rp: Add an RngCore impl based on ROSC.RANDOMBIT

This has the potential to not be random, but it should not be an issue
if default clock settings are used.
This commit is contained in:
Gabriel Smith 2022-11-29 20:46:04 -05:00
parent 8436c6180f
commit 71df28e269
3 changed files with 40 additions and 2 deletions

View File

@ -55,6 +55,7 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa
chrono = { version = "0.4", default-features = false, optional = true } chrono = { version = "0.4", default-features = false, optional = true }
embedded-io = { version = "0.4.0", features = ["async"], optional = true } embedded-io = { version = "0.4.0", features = ["async"], optional = true }
embedded-storage = { version = "0.3" } embedded-storage = { version = "0.3" }
rand_core = "0.6.4"
rp2040-pac2 = { git = "https://github.com/embassy-rs/rp2040-pac2", rev="017e3c9007b2d3b6965f0d85b5bf8ce3fa6d7364", features = ["rt"] } rp2040-pac2 = { git = "https://github.com/embassy-rs/rp2040-pac2", rev="017e3c9007b2d3b6965f0d85b5bf8ce3fa6d7364", features = ["rt"] }
#rp2040-pac2 = { path = "../../rp2040-pac2", features = ["rt"] } #rp2040-pac2 = { path = "../../rp2040-pac2", features = ["rt"] }

View File

@ -5,7 +5,7 @@ use crate::{pac, reset};
const XOSC_MHZ: u32 = 12; const XOSC_MHZ: u32 = 12;
/// safety: must be called exactly once at bootup /// safety: must be called exactly once at bootup
pub unsafe fn init() { pub(crate) unsafe fn init() {
// Reset everything except: // Reset everything except:
// - QSPI (we're using it to run this code!) // - QSPI (we're using it to run this code!)
// - PLLs (it may be suicide if that's what's clocking us) // - PLLs (it may be suicide if that's what's clocking us)
@ -196,3 +196,40 @@ unsafe fn configure_pll(p: pac::pll::Pll, refdiv: u32, vco_freq: u32, post_div1:
// Turn on post divider // Turn on post divider
p.pwr().modify(|w| w.set_postdivpd(false)); p.pwr().modify(|w| w.set_postdivpd(false));
} }
/// Random number generator based on the ROSC RANDOMBIT register.
///
/// This will not produce random values if the ROSC is stopped or run at some
/// harmonic of the bus frequency. With default clock settings these are not
/// issues.
pub struct RoscRng;
impl RoscRng {
fn next_u8() -> u8 {
let random_reg = pac::ROSC.randombit();
let mut acc = 0;
for _ in 0..u8::BITS {
acc <<= 1;
acc |= unsafe { random_reg.read().randombit() as u8 };
}
acc
}
}
impl rand_core::RngCore for RoscRng {
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> {
Ok(self.fill_bytes(dest))
}
fn next_u32(&mut self) -> u32 {
rand_core::impls::next_u32_via_fill(self)
}
fn next_u64(&mut self) -> u64 {
rand_core::impls::next_u64_via_fill(self)
}
fn fill_bytes(&mut self, dest: &mut [u8]) {
dest.fill_with(Self::next_u8)
}
}

View File

@ -21,7 +21,7 @@ pub mod uart;
#[cfg(feature = "nightly")] #[cfg(feature = "nightly")]
pub mod usb; pub mod usb;
mod clocks; pub mod clocks;
pub mod flash; pub mod flash;
mod reset; mod reset;