diff --git a/embassy-stm32/src/rng.rs b/embassy-stm32/src/rng.rs index 305e2677..0afba3ba 100644 --- a/embassy-stm32/src/rng.rs +++ b/embassy-stm32/src/rng.rs @@ -19,11 +19,11 @@ pub enum Error { ClockError, } -pub struct Random { +pub struct Rng { _inner: T, } -impl Random { +impl Rng { pub fn new(inner: impl Unborrow) -> Self { T::enable(); T::reset(); @@ -49,7 +49,7 @@ impl Random { } } -impl RngCore for Random { +impl RngCore for Rng { fn next_u32(&mut self) -> u32 { loop { let bits = unsafe { T::regs().sr().read() }; @@ -80,9 +80,9 @@ impl RngCore for Random { } } -impl CryptoRng for Random {} +impl CryptoRng for Rng {} -impl traits::rng::Rng for Random { +impl traits::rng::Rng for Rng { type Error = Error; #[rustfmt::skip] type RngFuture<'a> where Self: 'a = impl Future> + 'a; @@ -128,28 +128,6 @@ impl traits::rng::Rng for Random { } } -impl traits::rng::Random for Random { - #[rustfmt::skip] - type NextFuture<'a> where Self: 'a = impl Future> + 'a; - - fn next<'a>(&'a mut self, range: u32) -> Self::NextFuture<'a> { - async move { - let t = (-(range as i32) % (range as i32)) as u32; - loop { - let mut buf = [0; 4]; - traits::rng::Rng::fill_bytes(self, &mut buf).await?; - let x = u32::from_le_bytes(buf); - let m = x as u64 * range as u64; - let l = m as u32; - if l < t { - continue; - } - return Ok((m >> 32) as u32); - } - } - } -} - pub(crate) mod sealed { use super::*; diff --git a/embassy-traits/src/rng.rs b/embassy-traits/src/rng.rs index 181faa51..3cc4b2a0 100644 --- a/embassy-traits/src/rng.rs +++ b/embassy-traits/src/rng.rs @@ -17,11 +17,60 @@ pub trait Rng { fn fill_bytes<'a>(&'a mut self, dest: &'a mut [u8]) -> Self::RngFuture<'a>; } -pub trait Random: Rng { - #[rustfmt::skip] - type NextFuture<'a>: Future::Error>> + 'a - where - Self: 'a; - - fn next<'a>(&'a mut self, range: u32) -> Self::NextFuture<'a>; +pub struct Random { + rng: T, +} + +impl Random { + pub fn new(rng: T) -> Self { + Self { rng } + } + + pub async fn next_u8<'a>(&'a mut self, range: u8) -> Result { + // Lemire's method + let t = (-(range as i8) % (range as i8)) as u8; + loop { + let mut buf = [0; 1]; + self.rng.fill_bytes(&mut buf).await?; + let x = u8::from_le_bytes(buf); + let m = x as u16 * range as u16; + let l = m as u8; + if l < t { + continue; + } + return Ok((m >> 8) as u8); + } + } + + pub async fn next_u16<'a>(&'a mut self, range: u16) -> Result { + // Lemire's method + let t = (-(range as i16) % (range as i16)) as u16; + loop { + let mut buf = [0; 2]; + self.rng.fill_bytes(&mut buf).await?; + let x = u16::from_le_bytes(buf); + let m = x as u32 * range as u32; + let l = m as u16; + if l < t { + continue; + } + return Ok((m >> 16) as u16); + } + } + + pub async fn next_u32<'a>(&'a mut self, range: u32) -> Result { + // Lemire's method + let t = (-(range as i32) % (range as i32)) as u32; + loop { + let mut buf = [0; 4]; + self.rng.fill_bytes(&mut buf).await?; + let x = u32::from_le_bytes(buf); + let m = x as u64 * range as u64; + let l = m as u32; + if l < t { + continue; + } + return Ok((m >> 32) as u32); + } + } } diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs index 4a9f261c..df493145 100644 --- a/examples/stm32h7/src/bin/eth.rs +++ b/examples/stm32h7/src/bin/eth.rs @@ -21,7 +21,7 @@ use embassy_net::{ }; use embassy_stm32::eth::lan8742a::LAN8742A; use embassy_stm32::eth::{Ethernet, State}; -use embassy_stm32::rng::Random; +use embassy_stm32::rng::Rng; use embassy_stm32::{interrupt, peripherals}; use heapless::Vec; use panic_probe as _; @@ -81,7 +81,7 @@ fn _embassy_rand(buf: &mut [u8]) { }); } -static mut RNG_INST: Option> = None; +static mut RNG_INST: Option> = None; static EXECUTOR: Forever = Forever::new(); static STATE: Forever> = Forever::new(); @@ -97,7 +97,7 @@ fn main() -> ! { let p = embassy_stm32::init(config()); - let rng = Random::new(p.RNG); + let rng = Rng::new(p.RNG); unsafe { RNG_INST.replace(rng); } diff --git a/examples/stm32h7/src/bin/rng.rs b/examples/stm32h7/src/bin/rng.rs index fea88c41..cf1b14ea 100644 --- a/examples/stm32h7/src/bin/rng.rs +++ b/examples/stm32h7/src/bin/rng.rs @@ -8,9 +8,9 @@ mod example_common; use embassy::executor::Spawner; use embassy::time::{Duration, Timer}; -use embassy::traits::rng::Random as _; use embassy_stm32::gpio::{Level, Output, Speed}; -use embassy_stm32::rng::Random; +use embassy_stm32::rng::Rng; +use embassy::traits::rng::Random; use embassy_stm32::Peripherals; use embedded_hal::digital::v2::OutputPin; use example_common::*; @@ -21,14 +21,14 @@ async fn main(_spawner: Spawner, p: Peripherals) { let mut led = Output::new(p.PB14, Level::High, Speed::Low); - let mut rng = Random::new(p.RNG); + let mut rng = Random::new(Rng::new(p.RNG)); loop { - info!("high {}", unwrap!(rng.next(16).await)); + info!("high {}", unwrap!(rng.next_u8(16).await)); unwrap!(led.set_high()); Timer::after(Duration::from_millis(500)).await; - info!("low {}", unwrap!(rng.next(16).await)); + info!("low {}", unwrap!(rng.next_u8(16).await)); unwrap!(led.set_low()); Timer::after(Duration::from_millis(500)).await; }