mirror of
https://github.com/embassy-rs/embassy.git
synced 2025-09-28 12:50:37 +00:00
Merge pull request #4218 from embassy-rs/nrf-rng-mode
nrf/rng: add Blocking/Async Mode param.
This commit is contained in:
commit
7134e1a3a5
@ -1039,3 +1039,27 @@ pub fn init(config: config::Config) -> Peripherals {
|
|||||||
|
|
||||||
peripherals
|
peripherals
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Operating modes for peripherals.
|
||||||
|
pub mod mode {
|
||||||
|
trait SealedMode {}
|
||||||
|
|
||||||
|
/// Operating mode for a peripheral.
|
||||||
|
#[allow(private_bounds)]
|
||||||
|
pub trait Mode: SealedMode {}
|
||||||
|
|
||||||
|
macro_rules! impl_mode {
|
||||||
|
($name:ident) => {
|
||||||
|
impl SealedMode for $name {}
|
||||||
|
impl Mode for $name {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Blocking mode.
|
||||||
|
pub struct Blocking;
|
||||||
|
/// Async mode.
|
||||||
|
pub struct Async;
|
||||||
|
|
||||||
|
impl_mode!(Blocking);
|
||||||
|
impl_mode!(Async);
|
||||||
|
}
|
||||||
|
@ -14,6 +14,7 @@ use embassy_hal_internal::{Peri, PeripheralType};
|
|||||||
use embassy_sync::waitqueue::WakerRegistration;
|
use embassy_sync::waitqueue::WakerRegistration;
|
||||||
|
|
||||||
use crate::interrupt::typelevel::Interrupt;
|
use crate::interrupt::typelevel::Interrupt;
|
||||||
|
use crate::mode::{Async, Blocking, Mode};
|
||||||
use crate::{interrupt, pac};
|
use crate::{interrupt, pac};
|
||||||
|
|
||||||
/// Interrupt handler.
|
/// Interrupt handler.
|
||||||
@ -55,11 +56,31 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
|
|||||||
/// A wrapper around an nRF RNG peripheral.
|
/// A wrapper around an nRF RNG peripheral.
|
||||||
///
|
///
|
||||||
/// It has a non-blocking API, and a blocking api through `rand`.
|
/// It has a non-blocking API, and a blocking api through `rand`.
|
||||||
pub struct Rng<'d, T: Instance> {
|
pub struct Rng<'d, T: Instance, M: Mode> {
|
||||||
_peri: Peri<'d, T>,
|
_peri: Peri<'d, T>,
|
||||||
|
_phantom: PhantomData<M>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance> Rng<'d, T> {
|
impl<'d, T: Instance> Rng<'d, T, Blocking> {
|
||||||
|
/// Creates a new RNG driver from the `RNG` peripheral and interrupt.
|
||||||
|
///
|
||||||
|
/// SAFETY: The future returned from `fill_bytes` must not have its lifetime end without running its destructor,
|
||||||
|
/// e.g. using `mem::forget`.
|
||||||
|
///
|
||||||
|
/// The synchronous API is safe.
|
||||||
|
pub fn new_blocking(rng: Peri<'d, T>) -> Self {
|
||||||
|
let this = Self {
|
||||||
|
_peri: rng,
|
||||||
|
_phantom: PhantomData,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.stop();
|
||||||
|
|
||||||
|
this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d, T: Instance> Rng<'d, T, Async> {
|
||||||
/// Creates a new RNG driver from the `RNG` peripheral and interrupt.
|
/// Creates a new RNG driver from the `RNG` peripheral and interrupt.
|
||||||
///
|
///
|
||||||
/// SAFETY: The future returned from `fill_bytes` must not have its lifetime end without running its destructor,
|
/// SAFETY: The future returned from `fill_bytes` must not have its lifetime end without running its destructor,
|
||||||
@ -70,7 +91,10 @@ impl<'d, T: Instance> Rng<'d, T> {
|
|||||||
rng: Peri<'d, T>,
|
rng: Peri<'d, T>,
|
||||||
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let this = Self { _peri: rng };
|
let this = Self {
|
||||||
|
_peri: rng,
|
||||||
|
_phantom: PhantomData,
|
||||||
|
};
|
||||||
|
|
||||||
this.stop();
|
this.stop();
|
||||||
this.disable_irq();
|
this.disable_irq();
|
||||||
@ -81,14 +105,6 @@ impl<'d, T: Instance> Rng<'d, T> {
|
|||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stop(&self) {
|
|
||||||
T::regs().tasks_stop().write_value(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn start(&self) {
|
|
||||||
T::regs().tasks_start().write_value(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn enable_irq(&self) {
|
fn enable_irq(&self) {
|
||||||
T::regs().intenset().write(|w| w.set_valrdy(true));
|
T::regs().intenset().write(|w| w.set_valrdy(true));
|
||||||
}
|
}
|
||||||
@ -97,16 +113,6 @@ impl<'d, T: Instance> Rng<'d, T> {
|
|||||||
T::regs().intenclr().write(|w| w.set_valrdy(true));
|
T::regs().intenclr().write(|w| w.set_valrdy(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enable or disable the RNG's bias correction.
|
|
||||||
///
|
|
||||||
/// Bias correction removes any bias towards a '1' or a '0' in the bits generated.
|
|
||||||
/// However, this makes the generation of numbers slower.
|
|
||||||
///
|
|
||||||
/// Defaults to disabled.
|
|
||||||
pub fn set_bias_correction(&self, enable: bool) {
|
|
||||||
T::regs().config().write(|w| w.set_dercen(enable))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Fill the buffer with random bytes.
|
/// Fill the buffer with random bytes.
|
||||||
pub async fn fill_bytes(&mut self, dest: &mut [u8]) {
|
pub async fn fill_bytes(&mut self, dest: &mut [u8]) {
|
||||||
if dest.is_empty() {
|
if dest.is_empty() {
|
||||||
@ -153,6 +159,26 @@ impl<'d, T: Instance> Rng<'d, T> {
|
|||||||
// Trigger the teardown
|
// Trigger the teardown
|
||||||
drop(on_drop);
|
drop(on_drop);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d, T: Instance, M: Mode> Rng<'d, T, M> {
|
||||||
|
fn stop(&self) {
|
||||||
|
T::regs().tasks_stop().write_value(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn start(&self) {
|
||||||
|
T::regs().tasks_start().write_value(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Enable or disable the RNG's bias correction.
|
||||||
|
///
|
||||||
|
/// Bias correction removes any bias towards a '1' or a '0' in the bits generated.
|
||||||
|
/// However, this makes the generation of numbers slower.
|
||||||
|
///
|
||||||
|
/// Defaults to disabled.
|
||||||
|
pub fn set_bias_correction(&self, enable: bool) {
|
||||||
|
T::regs().config().write(|w| w.set_dercen(enable))
|
||||||
|
}
|
||||||
|
|
||||||
/// Fill the buffer with random bytes, blocking version.
|
/// Fill the buffer with random bytes, blocking version.
|
||||||
pub fn blocking_fill_bytes(&mut self, dest: &mut [u8]) {
|
pub fn blocking_fill_bytes(&mut self, dest: &mut [u8]) {
|
||||||
@ -184,7 +210,7 @@ impl<'d, T: Instance> Rng<'d, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance> Drop for Rng<'d, T> {
|
impl<'d, T: Instance, M: Mode> Drop for Rng<'d, T, M> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.stop();
|
self.stop();
|
||||||
critical_section::with(|cs| {
|
critical_section::with(|cs| {
|
||||||
@ -195,7 +221,7 @@ impl<'d, T: Instance> Drop for Rng<'d, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance> rand_core_06::RngCore for Rng<'d, T> {
|
impl<'d, T: Instance, M: Mode> rand_core_06::RngCore for Rng<'d, T, M> {
|
||||||
fn fill_bytes(&mut self, dest: &mut [u8]) {
|
fn fill_bytes(&mut self, dest: &mut [u8]) {
|
||||||
self.blocking_fill_bytes(dest);
|
self.blocking_fill_bytes(dest);
|
||||||
}
|
}
|
||||||
@ -211,9 +237,9 @@ impl<'d, T: Instance> rand_core_06::RngCore for Rng<'d, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance> rand_core_06::CryptoRng for Rng<'d, T> {}
|
impl<'d, T: Instance, M: Mode> rand_core_06::CryptoRng for Rng<'d, T, M> {}
|
||||||
|
|
||||||
impl<'d, T: Instance> rand_core_09::RngCore for Rng<'d, T> {
|
impl<'d, T: Instance, M: Mode> rand_core_09::RngCore for Rng<'d, T, M> {
|
||||||
fn fill_bytes(&mut self, dest: &mut [u8]) {
|
fn fill_bytes(&mut self, dest: &mut [u8]) {
|
||||||
self.blocking_fill_bytes(dest);
|
self.blocking_fill_bytes(dest);
|
||||||
}
|
}
|
||||||
@ -225,7 +251,7 @@ impl<'d, T: Instance> rand_core_09::RngCore for Rng<'d, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance> rand_core_09::CryptoRng for Rng<'d, T> {}
|
impl<'d, T: Instance, M: Mode> rand_core_09::CryptoRng for Rng<'d, T, M> {}
|
||||||
|
|
||||||
/// Peripheral static state
|
/// Peripheral static state
|
||||||
pub(crate) struct State {
|
pub(crate) struct State {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user