stm32_hal2/rng.rs
1//! Support for the Random Number Generator (RNG) peripheral. This provides a simple
2//! API for accessing hardware-generated 32-bit random numbers, where constructing a `Rng` peripheral enables its
3//! peripheral clock, and provides some methods.
4//! Once this struct is constructed, the freestanding functions `read()`, and `reading_ready()` may be
5//! used to get a random number number, and check if a new one is available.
6
7use cfg_if::cfg_if;
8
9use crate::{
10 pac::{RCC, RNG},
11 util::rcc_en_reset,
12};
13
14/// Represents a RNG peripheral.
15pub struct Rng {
16 pub regs: RNG,
17}
18
19impl Rng {
20 /// Initialize a RNG peripheral, including configuration register writes, and enabling and resetting
21 /// its RCC peripheral clock.
22 pub fn new(regs: RNG) -> Self {
23 let rcc = unsafe { &(*RCC::ptr()) };
24
25 cfg_if! {
26 if #[cfg(feature = "g0")] {
27 rcc_en_reset!(ahb1, rng, rcc);
28 } else if #[cfg(any(feature = "wb", feature = "wl"))] {
29 rcc_en_reset!(ahb3, rng, rcc);
30 } else {
31 rcc_en_reset!(ahb2, rng, rcc);
32 }
33 }
34
35 regs.cr().modify(|_, w| w.rngen().bit(true));
36
37 Self { regs }
38 }
39
40 /// Load a random number from the data register
41 pub fn read(&mut self) -> i32 {
42 // When data is not ready (DRDY=”0”) RNG_DR returns zero.
43 // It is recommended to always verify that RNG_DR is different from zero. Because when it is
44 // the case a seed error occurred between RNG_SR polling and RND_DR output reading (rare
45 // event).
46 // todo: CHeck for 0? Check for DREDY?
47
48 self.regs.dr().read().bits() as i32
49 }
50
51 /// Return true if a reading is available.
52 pub fn reading_ready(&mut self) -> bool {
53 self.regs.sr().read().drdy().bit_is_set()
54 }
55
56 /// Enable an interrupt. An interrupt isgenerated when a random number is ready or when an error
57 /// occurs. Therefore at each interrupt, check that: No error occured (SEIS and CEIS bits should be set
58 /// to 0 in the RNG_SR register. A random number is ready. The DRDY bit must be set to 1 in the
59 /// RNG_SR register.
60 pub fn enable_interrupt(&mut self) {
61 self.regs.cr().modify(|_, w| w.ie().bit(true));
62 }
63}
64
65/// Gets a random value without needing to pass the `Rng` struct. Assumes it has been initialized,
66/// to enable it and its peripheral clock.
67pub fn read() -> i32 {
68 let regs = unsafe { &(*RNG::ptr()) };
69 regs.dr().read().bits() as i32
70}
71
72/// Return true if a reading is available.
73pub fn reading_ready() -> bool {
74 let regs = unsafe { &(*RNG::ptr()) };
75 regs.sr().read().drdy().bit_is_set()
76}