1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
//! Support for the Random Number Generator (RNG) peripheral.
use cortex_m::interrupt::free;
use crate::{
pac::{RCC, RNG},
rcc_en_reset,
};
use cfg_if::cfg_if;
/// Represents a RNG peripheral.
pub struct Rng {
pub regs: RNG,
}
impl Rng {
/// Initialize a RNG peripheral, including configuration register writes, and enabling and resetting
/// its RCC peripheral clock.
pub fn new(regs: RNG) -> Self {
free(|_| {
let rcc = unsafe { &(*RCC::ptr()) };
cfg_if! {
if #[cfg(feature = "g0")] {
rcc_en_reset!(ahb1, rng, rcc);
} else if #[cfg(any(feature = "wb", feature = "wl"))] {
rcc_en_reset!(ahb3, rng, rcc);
} else {
rcc_en_reset!(ahb2, rng, rcc);
}
}
});
#[cfg(feature = "l5")]
regs.rng_cr.modify(|_, w| w.rngen().set_bit());
#[cfg(not(feature = "l5"))]
regs.cr.modify(|_, w| w.rngen().set_bit());
Self { regs }
}
/// Load a random number from the data register
pub fn read(&mut self) -> i32 {
// When data is not ready (DRDY=”0”) RNG_DR returns zero.
// It is recommended to always verify that RNG_DR is different from zero. Because when it is
// the case a seed error occurred between RNG_SR polling and RND_DR output reading (rare
// event).
// todo: CHeck for 0? Check for DREDY?
// https://github.com/stm32-rs/stm32-rs/issues/650 L5 error
#[cfg(feature = "l5")]
return self.regs.rng_dr.read().bits() as i32;
#[cfg(not(feature = "l5"))]
return self.regs.dr.read().bits() as i32;
}
/// Enable an interrupt. An interrupt isgenerated when a random number is ready or when an error
/// occurs. Therefore at each interrupt, check that: No error occured (SEIS and CEIS bits should be set
/// to 0 in the RNG_SR register. A random number is ready. The DRDY bit must be set to 1 in the
/// RNG_SR register.
pub fn enable_interrupt(&mut self) {
#[cfg(feature = "l5")]
self.regs.rng_cr.modify(|_, w| w.ie().set_bit());
#[cfg(not(feature = "l5"))]
self.regs.cr.modify(|_, w| w.ie().set_bit());
}
}