extern crate core;
#[cfg(feature = "unproven")]
use core::cmp;
use crate::rcc::{Clocks, Enable, AHB2};
use crate::stm32::RNG;
pub use rand_core::{CryptoRng, RngCore};
pub trait RngExt {
fn enable(self, ahb2: &mut AHB2, clocks: Clocks) -> Rng;
}
impl RngExt for RNG {
fn enable(self, ahb2: &mut AHB2, clocks: Clocks) -> Rng {
let msi = match clocks.msi() {
Some(msi) => msi == crate::rcc::MsiFreq::RANGE48M,
None => false,
};
let hsi = clocks.hsi48();
assert!(msi || hsi);
<RNG as Enable>::enable(ahb2);
while !RNG::is_enabled() {}
self.cr.modify(|_, w| w.rngen().set_bit());
Rng { rng: self }
}
}
pub struct Rng {
rng: RNG,
}
impl Rng {
pub fn free(self) -> RNG {
self.rng
}
pub fn get_random_data(&self) -> u32 {
while !self.is_data_ready() {}
self.possibly_invalid_random_data()
}
pub fn is_interrupt_enabled(&self) -> bool {
self.rng.cr.read().ie().bit()
}
pub fn is_enabled(&self) -> bool {
self.rng.cr.read().rngen().bit()
}
pub fn is_clock_error(&self) -> bool {
self.rng.sr.read().cecs().bit()
}
pub fn is_seed_error(&self) -> bool {
self.rng.sr.read().secs().bit()
}
pub fn is_data_ready(&self) -> bool {
self.rng.sr.read().drdy().bit()
}
pub fn possibly_invalid_random_data(&self) -> u32 {
self.rng.dr.read().rndata().bits()
}
}
impl RngCore for Rng {
fn next_u32(&mut self) -> u32 {
self.get_random_data()
}
fn next_u64(&mut self) -> u64 {
rand_core::impls::next_u64_via_u32(self)
}
fn fill_bytes(&mut self, dest: &mut [u8]) {
rand_core::impls::fill_bytes_via_next(self, dest)
}
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> {
Ok(self.fill_bytes(dest))
}
}
impl CryptoRng for Rng {}
#[derive(Debug)]
pub enum Error {}
#[cfg(feature = "unproven")]
impl crate::hal::blocking::rng::Read for Rng {
type Error = Error;
fn read(&mut self, buffer: &mut [u8]) -> Result<(), Self::Error> {
let mut i = 0usize;
while i < buffer.len() {
let random_word: u32 = self.get_random_data();
let bytes: [u8; 4] = random_word.to_ne_bytes();
let n = cmp::min(4, buffer.len() - i);
buffer[i..i + n].copy_from_slice(&bytes[..n]);
i += n;
}
Ok(())
}
}