1use crate::peripherals::Trng;
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub enum TrngError {
19 NoData,
21 Timeout,
23}
24
25pub struct TrngDriver<'d> {
27 _trng: Trng<'d>,
28}
29
30impl<'d> TrngDriver<'d> {
31 pub fn new(trng: Trng<'d>) -> Self {
33 Self { _trng: trng }
34 }
35
36 fn regs(&self) -> &'static ws63_pac::trng::RegisterBlock {
37 unsafe { &*Trng::ptr() }
39 }
40
41 pub fn data_ready(&self) -> bool {
43 self.regs().trng_fifo_ready().read().bits() & 0x01 != 0
44 }
45
46 pub fn done(&self) -> bool {
48 self.regs().trng_fifo_ready().read().bits() & 0x02 != 0
49 }
50
51 pub fn read(&self) -> Result<u32, TrngError> {
55 if !self.data_ready() {
56 return Err(TrngError::NoData);
57 }
58 Ok(self.regs().trng_fifo_data().read().bits())
59 }
60
61 pub fn read_blocking(&self) -> Result<u32, TrngError> {
68 for _ in 0..1_000_000 {
69 if self.data_ready() {
70 return Ok(self.regs().trng_fifo_data().read().bits());
71 }
72 core::hint::spin_loop();
73 }
74 Err(TrngError::Timeout)
75 }
76
77 pub fn fill_bytes(&self, buf: &mut [u8]) -> Result<(), TrngError> {
82 let mut i = 0;
83 while i < buf.len() {
84 let word = self.read_blocking()?;
85 let bytes = word.to_le_bytes();
86 for &b in &bytes {
87 if i < buf.len() {
88 buf[i] = b;
89 i += 1;
90 }
91 }
92 }
93 Ok(())
94 }
95
96 pub fn fill_words(&self, buf: &mut [u32]) -> Result<(), TrngError> {
100 for word in buf.iter_mut() {
101 *word = self.read_blocking()?;
102 }
103 Ok(())
104 }
105
106 pub fn set_sample_clock(&mut self, external: bool) {
110 unsafe {
111 self.regs().trng_fro_sample_clk_sel().write(|w| w.bits(if external { 1 } else { 0 }));
112 }
113 }
114
115 pub fn set_divider(&mut self, div: u8) {
120 unsafe {
121 self.regs().trng_fro_div_cnt().write(|w| w.bits(div as u32));
122 }
123 }
124
125 pub fn data_status(&self) -> u32 {
127 self.regs().trng_data_st().read().bits()
128 }
129}
130
131#[cfg(test)]
134mod tests {
135 use super::*;
136
137 #[test]
138 fn test_trng_error_type_variants() {
139 assert_ne!(TrngError::NoData as u8, TrngError::Timeout as u8);
140 }
141
142 #[test]
143 fn test_trng_data_ready_bit() {
144 let ready: u32 = 0x01;
146 assert!((ready & 0x01) != 0); let not_ready: u32 = 0x00;
148 assert!((not_ready & 0x01) == 0); }
150
151 #[test]
152 fn test_trng_done_bit() {
153 let done: u32 = 0x02;
155 assert!((done & 0x02) != 0); let not_done: u32 = 0x00;
157 assert!((not_done & 0x02) == 0); }
159
160 #[test]
161 fn test_trng_read_blocking_timeout_logic() {
162 let max_retries = 10u32;
164 let mut data_ready = false;
165 let mut retries = 0;
166 let result = loop {
167 if data_ready {
168 break Ok(42u32);
169 }
170 if retries >= max_retries {
171 break Err(TrngError::Timeout);
172 }
173 retries += 1;
174 };
175 assert_eq!(result, Err(TrngError::Timeout));
176 assert_eq!(retries, 10);
177 }
178
179 #[test]
180 fn test_trng_read_blocking_success_first_try() {
181 let data_ready = true;
182 let result = if data_ready { Ok(0xDEAD_BEEFu32) } else { Err(TrngError::Timeout) };
183 assert_eq!(result.unwrap(), 0xDEAD_BEEF);
184 }
185}