From 71df28e269ae3157b4b07df7f270b2a81c08803e Mon Sep 17 00:00:00 2001 From: Gabriel Smith Date: Tue, 29 Nov 2022 20:46:04 -0500 Subject: [PATCH] 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. --- embassy-rp/Cargo.toml | 1 + embassy-rp/src/clocks.rs | 39 ++++++++++++++++++++++++++++++++++++++- embassy-rp/src/lib.rs | 2 +- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index daa60f9c5..284d458c6 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -55,6 +55,7 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa chrono = { version = "0.4", default-features = false, optional = true } embedded-io = { version = "0.4.0", features = ["async"], optional = true } 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 = { path = "../../rp2040-pac2", features = ["rt"] } diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs index 1c446f389..85c9bbb7a 100644 --- a/embassy-rp/src/clocks.rs +++ b/embassy-rp/src/clocks.rs @@ -5,7 +5,7 @@ use crate::{pac, reset}; const XOSC_MHZ: u32 = 12; /// safety: must be called exactly once at bootup -pub unsafe fn init() { +pub(crate) unsafe fn init() { // Reset everything except: // - QSPI (we're using it to run this code!) // - 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 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) + } +} diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index e5b07c903..d21b5f7b0 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs @@ -21,7 +21,7 @@ pub mod uart; #[cfg(feature = "nightly")] pub mod usb; -mod clocks; +pub mod clocks; pub mod flash; mod reset;