use core::fmt;
use core::task::{Poll, ready};
use crate::ral::trng;
use crate::ral::{modify_reg, read_reg, write_reg};
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)]
pub enum SampleMode {
VonNeumann = trng::MCTL::SAMP_MODE::RW::SAMP_MODE_0,
Raw = trng::MCTL::SAMP_MODE::RW::SAMP_MODE_1,
VonNeumannRaw = trng::MCTL::SAMP_MODE::RW::SAMP_MODE_2,
}
impl Default for SampleMode {
fn default() -> Self {
Self::VonNeumannRaw
}
}
pub struct Trng {
reg: trng::TRNG,
block: [u32; 16],
index: usize,
}
impl fmt::Debug for Trng {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("TRNG")
.field("block", &self.block)
.field("index", &self.index)
.finish()
}
}
#[cfg(feature = "defmt")]
impl defmt::Format for Trng {
fn format(&self, f: defmt::Formatter) {
defmt::write!(f, "Trng {{ block: {}, index: {} }}", self.block, self.index)
}
}
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct RetryCount(u32);
impl RetryCount {
pub const DEFAULT: u32 = 15;
pub fn new(retry_count: u32) -> Option<Self> {
(1..=15)
.contains(&retry_count)
.then_some(RetryCount(retry_count))
}
}
impl Default for RetryCount {
fn default() -> Self {
RetryCount(Self::DEFAULT)
}
}
impl Trng {
pub fn new(reg: trng::TRNG, sample_mode: SampleMode, retry_count: RetryCount) -> Self {
modify_reg!(trng, reg, MCTL, PRGM: 1);
modify_reg!(trng, reg, MCTL, RST_DEF: 1);
write_reg!(trng, reg, SCMISC, RTY_CT: retry_count.0, LRUN_MAX: 34);
write_reg!(trng, reg, SCML, MONO_MAX: 1384, MONO_RNG: 268); write_reg!(trng, reg, SCR1L, RUN1_MAX: 405, RUN1_RNG: 178); write_reg!(trng, reg, SCR2L, RUN2_MAX: 220, RUN2_RNG: 122); write_reg!(trng, reg, SCR3L, RUN3_MAX: 125, RUN3_RNG: 88); write_reg!(trng, reg, SCR4L, RUN4_MAX: 75, RUN4_RNG: 64); write_reg!(trng, reg, SCR5L, RUN5_MAX: 47, RUN5_RNG: 46); write_reg!(trng, reg, SCR6PL, RUN6P_MAX: 47, RUN6P_RNG: 46);
write_reg!(trng, reg, PKRMAX, PKR_MAX: 26912); write_reg!(trng, reg, PKRRNG, PKR_RNG: 2467);
write_reg!(trng, reg, FRQMAX, FRQ_MAX: 25600); write_reg!(trng, reg, FRQMIN, FRQ_MIN: 1600);
write_reg!(trng, reg, SDCTL, SAMP_SIZE: 2500, ENT_DLY: 3200); write_reg!(trng, reg, SBLIM, SB_LIM: 63);
modify_reg!(trng, reg, MCTL, SAMP_MODE: sample_mode as u32);
modify_reg!(trng, reg, MCTL, PRGM: 0);
read_reg!(trng, reg, ENT[15]);
Self {
reg,
block: [0; 16],
index: 16, }
}
pub fn next_u32(&mut self) -> Poll<Result<u32, Error>> {
ready!(self.retrieve_if_needed())?;
let data = self.block[self.index];
self.index += 1;
Poll::Ready(Ok(data))
}
fn retrieve_if_needed(&mut self) -> Poll<Result<(), Error>> {
if self.index >= self.block.len() {
ready!(self.retrieve())?;
self.index = 0;
}
Poll::Ready(Ok(()))
}
fn retrieve(&mut self) -> Poll<Result<(), Error>> {
let mctl = read_reg!(trng, self.reg, MCTL);
if (mctl & trng::MCTL::ERR::mask) != 0 {
let flags = self.get_error_flags();
write_reg!(trng, self.reg, MCTL, mctl); return Poll::Ready(Err(Error(flags)));
}
if (mctl & trng::MCTL::ENT_VAL::mask) == 0 {
return Poll::Pending; }
for idx in 0..self.reg.ENT.len() {
self.block[idx] = read_reg!(trng, self.reg, ENT[idx]);
}
read_reg!(trng, self.reg, ENT[0]);
Poll::Ready(Ok(()))
}
fn get_error_flags(&self) -> ErrorFlags {
let status = read_reg!(trng, self.reg, STATUS) & 0xFFFF;
let mut flags = ErrorFlags::from_bits_truncate(status);
flags.set(
ErrorFlags::FCT_FAIL,
read_reg!(trng, self.reg, MCTL, FCT_FAIL) == 1,
);
flags
}
pub fn release_disabled(self) -> trng::TRNG {
modify_reg!(trng, self.reg, MCTL, PRGM: 1);
while read_reg!(trng, self.reg, MCTL, TSTOP_OK) == 0 {
core::hint::spin_loop();
}
self.reg
}
}
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Error(pub ErrorFlags);
bitflags::bitflags! {
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ErrorFlags : u32 {
const TF1BR0 = 1 << 0;
const TF1BR1 = 1 << 1;
const TF2BR0 = 1 << 2;
const TF2BR1 = 1 << 3;
const TF3BR0 = 1 << 4;
const TF3BR1 = 1 << 5;
const TF4BR0 = 1 << 6;
const TF4BR1 = 1 << 7;
const TF5BR0 = 1 << 8;
const TF5BR1 = 1 << 9;
const TF6PBR0 = 1 << 10;
const TF6PBR1 = 1 << 11;
const TFSB = 1 << 12;
const TFLR = 1 << 13;
const TFP = 1 << 14;
const TFMB = 1 << 15;
const FCT_FAIL = 1 << 16;
}
}
#[cfg(feature = "defmt")]
impl defmt::Format for ErrorFlags {
fn format(&self, f: defmt::Formatter) {
defmt::write!(f, "ErrorFlags({=u32:#x})", self.bits());
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "An error occurred in the TRNG module")
}
}
#[cfg(test)]
mod tests {
use super::RetryCount;
#[test]
fn retry_count() {
assert!(RetryCount::new(0).is_none());
for count in 1..16 {
assert!(RetryCount::new(count).is_some());
}
assert!(RetryCount::new(16).is_none());
}
}