@@ -5,9 +5,15 @@ use rand_core::TryRngCore;
55use crate :: { rcc:: Rcc , stm32:: RNG } ;
66use core:: { fmt:: Formatter , marker:: PhantomData } ;
77
8+ /// Error type for the RNG peripheral
89pub enum RngError {
10+ /// The DRDY bit is not set in the status register.
911 NotReady ,
12+ /// A noise source seed error was detected. [`seed_error_recovery()`]
13+ /// should be called to recover from the error.
1014 SeedError ,
15+ /// A clock error was detected. fRNGCLOCK is less than fHCLK/32
16+ /// The clock error condition is automatically cleared when the clock condition returns to normal.
1117 ClockError ,
1218}
1319
@@ -116,6 +122,27 @@ impl Rng<Running> {
116122 unsafe { ( * RNG :: ptr ( ) ) . sr ( ) . read ( ) . ceis ( ) . bit_is_set ( ) }
117123 }
118124
125+ /// Perform recovery sequence of a seed error from RM0440 26.3.7
126+ ///
127+ /// The SEIS bit is cleared, and 12 words and read and discarded from the DR register.
128+ ///
129+ /// If the recovery sequence was successful, the function returns `Ok(())`.
130+ /// If the SEIS bit is still set after the recovery sequence, [`RngError::SeedError`] is returned.
131+ pub fn seed_error_recovery ( & mut self ) -> Result < ( ) , RngError > {
132+ // Clear SEIS bit
133+ unsafe { ( * RNG :: ptr ( ) ) . sr ( ) . clear_bits ( |w| w. seis ( ) . clear_bit ( ) ) } ;
134+ // Read and discard 12 words from DR register
135+ for _ in 0 ..12 {
136+ unsafe { ( * RNG :: ptr ( ) ) . dr ( ) . read ( ) } ;
137+ }
138+ // Confirm SEIS is still clear
139+ if unsafe { ( * RNG :: ptr ( ) ) . sr ( ) . read ( ) . seis ( ) . bit_is_clear ( ) } {
140+ Ok ( ( ) )
141+ } else {
142+ Err ( RngError :: SeedError )
143+ }
144+ }
145+
119146 /// Blocking read of a random u32 from the RNG in polling mode.
120147 ///
121148 /// Returns an [`RngError`] if the RNG reports an error condition.
@@ -158,7 +185,9 @@ impl Rng<Running> {
158185 }
159186
160187 if status. drdy ( ) . bit_is_set ( ) {
161- // Data is ready. Read the DR register and return the value.
188+ // The data ready bit is set. Read the DR register and check if it is zero.
189+ // A zero read indicates a seed error between reading SR and DR registers
190+ // see RM0440 26.7.3 RNDATA description.
162191 match unsafe { ( * RNG :: ptr ( ) ) . dr ( ) . read ( ) . bits ( ) } {
163192 0 => Err ( RngError :: SeedError ) ,
164193 data => Ok ( data) ,
0 commit comments