1
+ //! # Hardware random number generator.
2
+ //!
3
+ //!
4
+ //! The build in random number generator (RNG) of an STM32F4 uses analog noise to
5
+ //! proved random 32-bit values.
6
+ //!
7
+ //! Notes:
8
+ //! - It takes 40 periods of `RNG_CLK` to generate a new random value.
9
+ //! - The RNG requires the `PLL48_CLK` to be active ([more details](RngExt::constrain))
10
+ //!
11
+ //! For more details, see reference manual chapter 24.
12
+ //!
13
+ //! Minimal working example:
14
+ //! ```
15
+ //! let dp = stm32::Peripherals::take().unwrap();
16
+ //! let rcc = dp.RCC.constrain();
17
+ //! let clocks = rcc.cfgr.require_pll48clk().freeze();
18
+ //! let mut rand_source = dp.RNG.constrain(clocks);
19
+ //! let rand_val = rand_source.next_u32();
20
+ //! ```
21
+ //!
22
+ //! A full exaple can be found [in the examples folder on github](https://github.com/stm32-rs/stm32f4xx-hal/blob/master/examples/rng-display.rs)
1
23
use core:: cmp;
2
24
use core:: mem;
3
25
@@ -10,6 +32,7 @@ use core::num::NonZeroU32;
10
32
use core:: ops:: Shl ;
11
33
use rand_core:: RngCore ;
12
34
35
+ /// Random number generator specific errors
13
36
#[ derive( Debug , Eq , PartialEq , Copy , Clone ) ]
14
37
pub enum ErrorKind {
15
38
/// The RNG_CLK was not correctly detected (fRNG_CLK< fHCLK/16).
@@ -28,15 +51,36 @@ impl From<ErrorKind> for rand_core::Error {
28
51
}
29
52
}
30
53
54
+ /// Helper trait to implement the `constrain` method for the
55
+ /// [RNG peripheral](crate::stm32::RNG) which is how the [Rng] struct is
56
+ /// created.
57
+ ///
58
+ /// Usage:
59
+ /// ```
60
+ /// let dp = stm32::Peripherals::take().unwrap();
61
+ /// let rcc = dp.RCC.constrain();
62
+ /// let clocks = rcc.cfgr.require_pll48clk().freeze();
63
+ /// let mut rand_source = dp.RNG.constrain(clocks);
64
+ /// ```
31
65
pub trait RngExt {
66
+ /// Enables the hardware random generator and provides the [Rng] struct.
67
+ ///
68
+ /// The datasheet states, that the `RNG_CLK` must not be less than 1/16 HCLK
69
+ /// (HCLK is the CPU clock), otherwise all reads of the RNG would return a
70
+ /// ClockError (CECS error).
71
+ /// As the `RNG_CLK` always seems to be connected to the `PLL48_CLK` and the
72
+ /// maximum value of `HCLK` is 168MHz, this is always true as long as the `PLL48_CLK` is enabled.
73
+ /// This can be done with the [require_pll48clk](crate::rcc::CFGR::require_pll48clk) function.
74
+ ///
75
+ /// See reference manual section 24.4.2 for more details
76
+ ///
77
+ /// # Panics
78
+ ///
79
+ /// This function will panic if `PLL48_CLK < 1/16 HCLK`.
32
80
fn constrain ( self , clocks : Clocks ) -> Rng ;
33
81
}
34
82
35
83
impl RngExt for RNG {
36
- /// Enable RNG_CLK and the RNG peripheral.
37
- /// Note that clocks must already be configured such that RNG_CLK is not less than 1/16 HCLK,
38
- /// otherwise all reads of the RNG would return a ClockError (CECS error).
39
- /// This function will panic if pll48clk < 1/16 hclk.
40
84
fn constrain ( self , clocks : Clocks ) -> Rng {
41
85
let rcc = unsafe { & * pac:: RCC :: ptr ( ) } ;
42
86
@@ -58,6 +102,20 @@ impl RngExt for RNG {
58
102
}
59
103
}
60
104
105
+ /// Random number provider which provides access to all [rand_core::RngCore]
106
+ /// functions.
107
+ ///
108
+ /// Example use:
109
+ ///
110
+ /// ```
111
+ /// use rand_core::RngCore;
112
+ ///
113
+ /// // ...
114
+ ///
115
+ /// let mut rand_source = dp.RNG.constrain(clocks);
116
+ /// let rand_u32: u32 = rand_source.next_u32();
117
+ /// let rand_u64: u64 = rand_source.next_u64();
118
+ /// ```
61
119
pub struct Rng {
62
120
rb : RNG ,
63
121
}
@@ -80,6 +138,8 @@ impl Rng {
80
138
}
81
139
}
82
140
141
+ /// Releases ownership of the [RNG](crate::stm32::RNG) peripheral object
142
+ /// (after which `self` can't be used anymore).
83
143
pub fn release ( self ) -> RNG {
84
144
self . rb
85
145
}
0 commit comments