nrf/rng: make available on all chips, use Instance trait, switch to new interrupt binding.
This commit is contained in:
parent
96788ac93a
commit
d113fcfe32
12 changed files with 154 additions and 76 deletions
|
@ -142,6 +142,8 @@ impl_twis!(TWI0, TWIS0, TWIM0_TWIS0_TWI0);
|
||||||
|
|
||||||
impl_qdec!(QDEC, QDEC, QDEC);
|
impl_qdec!(QDEC, QDEC, QDEC);
|
||||||
|
|
||||||
|
impl_rng!(RNG, RNG, RNG);
|
||||||
|
|
||||||
impl_timer!(TIMER0, TIMER0, TIMER0);
|
impl_timer!(TIMER0, TIMER0, TIMER0);
|
||||||
impl_timer!(TIMER1, TIMER1, TIMER1);
|
impl_timer!(TIMER1, TIMER1, TIMER1);
|
||||||
impl_timer!(TIMER2, TIMER2, TIMER2);
|
impl_timer!(TIMER2, TIMER2, TIMER2);
|
||||||
|
|
|
@ -152,6 +152,8 @@ impl_pdm!(PDM, PDM, PDM);
|
||||||
|
|
||||||
impl_qdec!(QDEC, QDEC, QDEC);
|
impl_qdec!(QDEC, QDEC, QDEC);
|
||||||
|
|
||||||
|
impl_rng!(RNG, RNG, RNG);
|
||||||
|
|
||||||
impl_timer!(TIMER0, TIMER0, TIMER0);
|
impl_timer!(TIMER0, TIMER0, TIMER0);
|
||||||
impl_timer!(TIMER1, TIMER1, TIMER1);
|
impl_timer!(TIMER1, TIMER1, TIMER1);
|
||||||
impl_timer!(TIMER2, TIMER2, TIMER2);
|
impl_timer!(TIMER2, TIMER2, TIMER2);
|
||||||
|
|
|
@ -154,6 +154,8 @@ impl_pdm!(PDM, PDM, PDM);
|
||||||
|
|
||||||
impl_qdec!(QDEC, QDEC, QDEC);
|
impl_qdec!(QDEC, QDEC, QDEC);
|
||||||
|
|
||||||
|
impl_rng!(RNG, RNG, RNG);
|
||||||
|
|
||||||
impl_timer!(TIMER0, TIMER0, TIMER0);
|
impl_timer!(TIMER0, TIMER0, TIMER0);
|
||||||
impl_timer!(TIMER1, TIMER1, TIMER1);
|
impl_timer!(TIMER1, TIMER1, TIMER1);
|
||||||
impl_timer!(TIMER2, TIMER2, TIMER2);
|
impl_timer!(TIMER2, TIMER2, TIMER2);
|
||||||
|
|
|
@ -155,6 +155,8 @@ impl_timer!(TIMER3, TIMER3, TIMER3, extended);
|
||||||
|
|
||||||
impl_qdec!(QDEC, QDEC, QDEC);
|
impl_qdec!(QDEC, QDEC, QDEC);
|
||||||
|
|
||||||
|
impl_rng!(RNG, RNG, RNG);
|
||||||
|
|
||||||
impl_pin!(P0_00, 0, 0);
|
impl_pin!(P0_00, 0, 0);
|
||||||
impl_pin!(P0_01, 0, 1);
|
impl_pin!(P0_01, 0, 1);
|
||||||
impl_pin!(P0_02, 0, 2);
|
impl_pin!(P0_02, 0, 2);
|
||||||
|
|
|
@ -175,6 +175,8 @@ impl_pdm!(PDM, PDM, PDM);
|
||||||
|
|
||||||
impl_qdec!(QDEC, QDEC, QDEC);
|
impl_qdec!(QDEC, QDEC, QDEC);
|
||||||
|
|
||||||
|
impl_rng!(RNG, RNG, RNG);
|
||||||
|
|
||||||
impl_timer!(TIMER0, TIMER0, TIMER0);
|
impl_timer!(TIMER0, TIMER0, TIMER0);
|
||||||
impl_timer!(TIMER1, TIMER1, TIMER1);
|
impl_timer!(TIMER1, TIMER1, TIMER1);
|
||||||
impl_timer!(TIMER2, TIMER2, TIMER2);
|
impl_timer!(TIMER2, TIMER2, TIMER2);
|
||||||
|
|
|
@ -201,6 +201,8 @@ impl_pdm!(PDM, PDM, PDM);
|
||||||
|
|
||||||
impl_qdec!(QDEC, QDEC, QDEC);
|
impl_qdec!(QDEC, QDEC, QDEC);
|
||||||
|
|
||||||
|
impl_rng!(RNG, RNG, RNG);
|
||||||
|
|
||||||
impl_timer!(TIMER0, TIMER0, TIMER0);
|
impl_timer!(TIMER0, TIMER0, TIMER0);
|
||||||
impl_timer!(TIMER1, TIMER1, TIMER1);
|
impl_timer!(TIMER1, TIMER1, TIMER1);
|
||||||
impl_timer!(TIMER2, TIMER2, TIMER2);
|
impl_timer!(TIMER2, TIMER2, TIMER2);
|
||||||
|
|
|
@ -212,6 +212,8 @@ impl_pdm!(PDM, PDM, PDM);
|
||||||
|
|
||||||
impl_qdec!(QDEC, QDEC, QDEC);
|
impl_qdec!(QDEC, QDEC, QDEC);
|
||||||
|
|
||||||
|
impl_rng!(RNG, RNG, RNG);
|
||||||
|
|
||||||
impl_pin!(P0_00, 0, 0);
|
impl_pin!(P0_00, 0, 0);
|
||||||
impl_pin!(P0_01, 0, 1);
|
impl_pin!(P0_01, 0, 1);
|
||||||
impl_pin!(P0_02, 0, 2);
|
impl_pin!(P0_02, 0, 2);
|
||||||
|
|
|
@ -127,6 +127,9 @@ embassy_hal_common::peripherals! {
|
||||||
// SAADC
|
// SAADC
|
||||||
SAADC,
|
SAADC,
|
||||||
|
|
||||||
|
// RNG
|
||||||
|
RNG,
|
||||||
|
|
||||||
// PWM
|
// PWM
|
||||||
PWM0,
|
PWM0,
|
||||||
PWM1,
|
PWM1,
|
||||||
|
@ -252,6 +255,8 @@ impl_timer!(TIMER0, TIMER0, TIMER0);
|
||||||
impl_timer!(TIMER1, TIMER1, TIMER1);
|
impl_timer!(TIMER1, TIMER1, TIMER1);
|
||||||
impl_timer!(TIMER2, TIMER2, TIMER2);
|
impl_timer!(TIMER2, TIMER2, TIMER2);
|
||||||
|
|
||||||
|
impl_rng!(RNG, RNG, RNG);
|
||||||
|
|
||||||
impl_pin!(P0_00, 0, 0);
|
impl_pin!(P0_00, 0, 0);
|
||||||
impl_pin!(P0_01, 0, 1);
|
impl_pin!(P0_01, 0, 1);
|
||||||
impl_pin!(P0_02, 0, 2);
|
impl_pin!(P0_02, 0, 2);
|
||||||
|
|
|
@ -61,7 +61,7 @@ pub mod pwm;
|
||||||
pub mod qdec;
|
pub mod qdec;
|
||||||
#[cfg(any(feature = "nrf52840", feature = "_nrf5340-app"))]
|
#[cfg(any(feature = "nrf52840", feature = "_nrf5340-app"))]
|
||||||
pub mod qspi;
|
pub mod qspi;
|
||||||
#[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))]
|
#[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf9160")))]
|
||||||
pub mod rng;
|
pub mod rng;
|
||||||
#[cfg(not(any(feature = "nrf52820", feature = "_nrf5340-net")))]
|
#[cfg(not(any(feature = "nrf52820", feature = "_nrf5340-net")))]
|
||||||
pub mod saadc;
|
pub mod saadc;
|
||||||
|
|
|
@ -1,83 +1,48 @@
|
||||||
//! Random Number Generator (RNG) driver.
|
//! Random Number Generator (RNG) driver.
|
||||||
|
|
||||||
|
#![macro_use]
|
||||||
|
|
||||||
use core::future::poll_fn;
|
use core::future::poll_fn;
|
||||||
|
use core::marker::PhantomData;
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
use core::sync::atomic::{AtomicPtr, Ordering};
|
use core::sync::atomic::{AtomicPtr, Ordering};
|
||||||
use core::task::Poll;
|
use core::task::Poll;
|
||||||
|
|
||||||
|
use embassy_cortex_m::interrupt::Interrupt;
|
||||||
use embassy_hal_common::drop::OnDrop;
|
use embassy_hal_common::drop::OnDrop;
|
||||||
use embassy_hal_common::{into_ref, PeripheralRef};
|
use embassy_hal_common::{into_ref, PeripheralRef};
|
||||||
use embassy_sync::waitqueue::AtomicWaker;
|
use embassy_sync::waitqueue::AtomicWaker;
|
||||||
|
|
||||||
use crate::interrupt::InterruptExt;
|
use crate::interrupt::InterruptExt;
|
||||||
use crate::peripherals::RNG;
|
use crate::{interrupt, Peripheral};
|
||||||
use crate::{interrupt, pac, Peripheral};
|
|
||||||
|
|
||||||
impl RNG {
|
/// Interrupt handler.
|
||||||
fn regs() -> &'static pac::rng::RegisterBlock {
|
pub struct InterruptHandler<T: Instance> {
|
||||||
unsafe { &*pac::RNG::ptr() }
|
_phantom: PhantomData<T>,
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static STATE: State = State {
|
impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
|
||||||
ptr: AtomicPtr::new(ptr::null_mut()),
|
unsafe fn on_interrupt() {
|
||||||
end: AtomicPtr::new(ptr::null_mut()),
|
let s = T::state();
|
||||||
waker: AtomicWaker::new(),
|
let r = T::regs();
|
||||||
};
|
|
||||||
|
|
||||||
struct State {
|
|
||||||
ptr: AtomicPtr<u8>,
|
|
||||||
end: AtomicPtr<u8>,
|
|
||||||
waker: AtomicWaker,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A wrapper around an nRF RNG peripheral.
|
|
||||||
///
|
|
||||||
/// It has a non-blocking API, and a blocking api through `rand`.
|
|
||||||
pub struct Rng<'d> {
|
|
||||||
irq: PeripheralRef<'d, interrupt::RNG>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'d> Rng<'d> {
|
|
||||||
/// 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(_rng: impl Peripheral<P = RNG> + 'd, irq: impl Peripheral<P = interrupt::RNG> + 'd) -> Self {
|
|
||||||
into_ref!(irq);
|
|
||||||
|
|
||||||
let this = Self { irq };
|
|
||||||
|
|
||||||
this.stop();
|
|
||||||
this.disable_irq();
|
|
||||||
|
|
||||||
this.irq.set_handler(Self::on_interrupt);
|
|
||||||
this.irq.unpend();
|
|
||||||
this.irq.enable();
|
|
||||||
|
|
||||||
this
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_interrupt(_: *mut ()) {
|
|
||||||
// Clear the event.
|
// Clear the event.
|
||||||
RNG::regs().events_valrdy.reset();
|
r.events_valrdy.reset();
|
||||||
|
|
||||||
// Mutate the slice within a critical section,
|
// Mutate the slice within a critical section,
|
||||||
// so that the future isn't dropped in between us loading the pointer and actually dereferencing it.
|
// so that the future isn't dropped in between us loading the pointer and actually dereferencing it.
|
||||||
let (ptr, end) = critical_section::with(|_| {
|
let (ptr, end) = critical_section::with(|_| {
|
||||||
let ptr = STATE.ptr.load(Ordering::Relaxed);
|
let ptr = s.ptr.load(Ordering::Relaxed);
|
||||||
// We need to make sure we haven't already filled the whole slice,
|
// We need to make sure we haven't already filled the whole slice,
|
||||||
// in case the interrupt fired again before the executor got back to the future.
|
// in case the interrupt fired again before the executor got back to the future.
|
||||||
let end = STATE.end.load(Ordering::Relaxed);
|
let end = s.end.load(Ordering::Relaxed);
|
||||||
if !ptr.is_null() && ptr != end {
|
if !ptr.is_null() && ptr != end {
|
||||||
// If the future was dropped, the pointer would have been set to null,
|
// If the future was dropped, the pointer would have been set to null,
|
||||||
// so we're still good to mutate the slice.
|
// so we're still good to mutate the slice.
|
||||||
// The safety contract of `Rng::new` means that the future can't have been dropped
|
// The safety contract of `Rng::new` means that the future can't have been dropped
|
||||||
// without calling its destructor.
|
// without calling its destructor.
|
||||||
unsafe {
|
unsafe {
|
||||||
*ptr = RNG::regs().value.read().value().bits();
|
*ptr = r.value.read().value().bits();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(ptr, end)
|
(ptr, end)
|
||||||
|
@ -90,15 +55,15 @@ impl<'d> Rng<'d> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let new_ptr = unsafe { ptr.add(1) };
|
let new_ptr = unsafe { ptr.add(1) };
|
||||||
match STATE
|
match s
|
||||||
.ptr
|
.ptr
|
||||||
.compare_exchange(ptr, new_ptr, Ordering::Relaxed, Ordering::Relaxed)
|
.compare_exchange(ptr, new_ptr, Ordering::Relaxed, Ordering::Relaxed)
|
||||||
{
|
{
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
let end = STATE.end.load(Ordering::Relaxed);
|
let end = s.end.load(Ordering::Relaxed);
|
||||||
// It doesn't matter if `end` was changed under our feet, because then this will just be false.
|
// It doesn't matter if `end` was changed under our feet, because then this will just be false.
|
||||||
if new_ptr == end {
|
if new_ptr == end {
|
||||||
STATE.waker.wake();
|
s.waker.wake();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
|
@ -107,21 +72,53 @@ impl<'d> Rng<'d> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A wrapper around an nRF RNG peripheral.
|
||||||
|
///
|
||||||
|
/// It has a non-blocking API, and a blocking api through `rand`.
|
||||||
|
pub struct Rng<'d, T: Instance> {
|
||||||
|
_peri: PeripheralRef<'d, T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d, T: Instance> Rng<'d, T> {
|
||||||
|
/// 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(
|
||||||
|
rng: impl Peripheral<P = T> + 'd,
|
||||||
|
_irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
|
) -> Self {
|
||||||
|
into_ref!(rng);
|
||||||
|
|
||||||
|
let this = Self { _peri: rng };
|
||||||
|
|
||||||
|
this.stop();
|
||||||
|
this.disable_irq();
|
||||||
|
|
||||||
|
unsafe { T::Interrupt::steal() }.unpend();
|
||||||
|
unsafe { T::Interrupt::steal() }.enable();
|
||||||
|
|
||||||
|
this
|
||||||
|
}
|
||||||
|
|
||||||
fn stop(&self) {
|
fn stop(&self) {
|
||||||
RNG::regs().tasks_stop.write(|w| unsafe { w.bits(1) })
|
T::regs().tasks_stop.write(|w| unsafe { w.bits(1) })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start(&self) {
|
fn start(&self) {
|
||||||
RNG::regs().tasks_start.write(|w| unsafe { w.bits(1) })
|
T::regs().tasks_start.write(|w| unsafe { w.bits(1) })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enable_irq(&self) {
|
fn enable_irq(&self) {
|
||||||
RNG::regs().intenset.write(|w| w.valrdy().set());
|
T::regs().intenset.write(|w| w.valrdy().set());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn disable_irq(&self) {
|
fn disable_irq(&self) {
|
||||||
RNG::regs().intenclr.write(|w| w.valrdy().clear());
|
T::regs().intenclr.write(|w| w.valrdy().clear());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enable or disable the RNG's bias correction.
|
/// Enable or disable the RNG's bias correction.
|
||||||
|
@ -131,7 +128,7 @@ impl<'d> Rng<'d> {
|
||||||
///
|
///
|
||||||
/// Defaults to disabled.
|
/// Defaults to disabled.
|
||||||
pub fn set_bias_correction(&self, enable: bool) {
|
pub fn set_bias_correction(&self, enable: bool) {
|
||||||
RNG::regs().config.write(|w| w.dercen().bit(enable))
|
T::regs().config.write(|w| w.dercen().bit(enable))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fill the buffer with random bytes.
|
/// Fill the buffer with random bytes.
|
||||||
|
@ -140,11 +137,13 @@ impl<'d> Rng<'d> {
|
||||||
return; // Nothing to fill
|
return; // Nothing to fill
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let s = T::state();
|
||||||
|
|
||||||
let range = dest.as_mut_ptr_range();
|
let range = dest.as_mut_ptr_range();
|
||||||
// Even if we've preempted the interrupt, it can't preempt us again,
|
// Even if we've preempted the interrupt, it can't preempt us again,
|
||||||
// so we don't need to worry about the order we write these in.
|
// so we don't need to worry about the order we write these in.
|
||||||
STATE.ptr.store(range.start, Ordering::Relaxed);
|
s.ptr.store(range.start, Ordering::Relaxed);
|
||||||
STATE.end.store(range.end, Ordering::Relaxed);
|
s.end.store(range.end, Ordering::Relaxed);
|
||||||
|
|
||||||
self.enable_irq();
|
self.enable_irq();
|
||||||
self.start();
|
self.start();
|
||||||
|
@ -154,16 +153,16 @@ impl<'d> Rng<'d> {
|
||||||
self.disable_irq();
|
self.disable_irq();
|
||||||
|
|
||||||
// The interrupt is now disabled and can't preempt us anymore, so the order doesn't matter here.
|
// The interrupt is now disabled and can't preempt us anymore, so the order doesn't matter here.
|
||||||
STATE.ptr.store(ptr::null_mut(), Ordering::Relaxed);
|
s.ptr.store(ptr::null_mut(), Ordering::Relaxed);
|
||||||
STATE.end.store(ptr::null_mut(), Ordering::Relaxed);
|
s.end.store(ptr::null_mut(), Ordering::Relaxed);
|
||||||
});
|
});
|
||||||
|
|
||||||
poll_fn(|cx| {
|
poll_fn(|cx| {
|
||||||
STATE.waker.register(cx.waker());
|
s.waker.register(cx.waker());
|
||||||
|
|
||||||
// The interrupt will never modify `end`, so load it first and then get the most up-to-date `ptr`.
|
// The interrupt will never modify `end`, so load it first and then get the most up-to-date `ptr`.
|
||||||
let end = STATE.end.load(Ordering::Relaxed);
|
let end = s.end.load(Ordering::Relaxed);
|
||||||
let ptr = STATE.ptr.load(Ordering::Relaxed);
|
let ptr = s.ptr.load(Ordering::Relaxed);
|
||||||
|
|
||||||
if ptr == end {
|
if ptr == end {
|
||||||
// We're done.
|
// We're done.
|
||||||
|
@ -183,7 +182,7 @@ impl<'d> Rng<'d> {
|
||||||
self.start();
|
self.start();
|
||||||
|
|
||||||
for byte in dest.iter_mut() {
|
for byte in dest.iter_mut() {
|
||||||
let regs = RNG::regs();
|
let regs = T::regs();
|
||||||
while regs.events_valrdy.read().bits() == 0 {}
|
while regs.events_valrdy.read().bits() == 0 {}
|
||||||
regs.events_valrdy.reset();
|
regs.events_valrdy.reset();
|
||||||
*byte = regs.value.read().value().bits();
|
*byte = regs.value.read().value().bits();
|
||||||
|
@ -193,13 +192,16 @@ impl<'d> Rng<'d> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d> Drop for Rng<'d> {
|
impl<'d, T: Instance> Drop for Rng<'d, T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.irq.disable()
|
self.stop();
|
||||||
|
let s = T::state();
|
||||||
|
s.ptr.store(ptr::null_mut(), Ordering::Relaxed);
|
||||||
|
s.end.store(ptr::null_mut(), Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d> rand_core::RngCore for Rng<'d> {
|
impl<'d, T: Instance> rand_core::RngCore for Rng<'d, T> {
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
@ -223,4 +225,53 @@ impl<'d> rand_core::RngCore for Rng<'d> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d> rand_core::CryptoRng for Rng<'d> {}
|
impl<'d, T: Instance> rand_core::CryptoRng for Rng<'d, T> {}
|
||||||
|
|
||||||
|
pub(crate) mod sealed {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
/// Peripheral static state
|
||||||
|
pub struct State {
|
||||||
|
pub ptr: AtomicPtr<u8>,
|
||||||
|
pub end: AtomicPtr<u8>,
|
||||||
|
pub waker: AtomicWaker,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl State {
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
ptr: AtomicPtr::new(ptr::null_mut()),
|
||||||
|
end: AtomicPtr::new(ptr::null_mut()),
|
||||||
|
waker: AtomicWaker::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Instance {
|
||||||
|
fn regs() -> &'static crate::pac::rng::RegisterBlock;
|
||||||
|
fn state() -> &'static State;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// RNG peripheral instance.
|
||||||
|
pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send {
|
||||||
|
/// Interrupt for this peripheral.
|
||||||
|
type Interrupt: Interrupt;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_rng {
|
||||||
|
($type:ident, $pac_type:ident, $irq:ident) => {
|
||||||
|
impl crate::rng::sealed::Instance for peripherals::$type {
|
||||||
|
fn regs() -> &'static crate::pac::rng::RegisterBlock {
|
||||||
|
unsafe { &*pac::$pac_type::ptr() }
|
||||||
|
}
|
||||||
|
fn state() -> &'static crate::rng::sealed::State {
|
||||||
|
static STATE: crate::rng::sealed::State = crate::rng::sealed::State::new();
|
||||||
|
&STATE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl crate::rng::Instance for peripherals::$type {
|
||||||
|
type Interrupt = crate::interrupt::$irq;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -3,15 +3,19 @@
|
||||||
#![feature(type_alias_impl_trait)]
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_nrf::interrupt;
|
|
||||||
use embassy_nrf::rng::Rng;
|
use embassy_nrf::rng::Rng;
|
||||||
|
use embassy_nrf::{bind_interrupts, peripherals, rng};
|
||||||
use rand::Rng as _;
|
use rand::Rng as _;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
RNG => rng::InterruptHandler<peripherals::RNG>;
|
||||||
|
});
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let p = embassy_nrf::init(Default::default());
|
let p = embassy_nrf::init(Default::default());
|
||||||
let mut rng = Rng::new(p.RNG, interrupt::take!(RNG));
|
let mut rng = Rng::new(p.RNG, Irqs);
|
||||||
|
|
||||||
// Async API
|
// Async API
|
||||||
let mut bytes = [0; 4];
|
let mut bytes = [0; 4];
|
||||||
|
|
|
@ -10,7 +10,7 @@ use embassy_net::tcp::TcpSocket;
|
||||||
use embassy_net::{Stack, StackResources};
|
use embassy_net::{Stack, StackResources};
|
||||||
use embassy_nrf::rng::Rng;
|
use embassy_nrf::rng::Rng;
|
||||||
use embassy_nrf::usb::{Driver, HardwareVbusDetect};
|
use embassy_nrf::usb::{Driver, HardwareVbusDetect};
|
||||||
use embassy_nrf::{interrupt, pac, peripherals};
|
use embassy_nrf::{bind_interrupts, interrupt, pac, peripherals, rng};
|
||||||
use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState};
|
use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState};
|
||||||
use embassy_usb::class::cdc_ncm::{CdcNcmClass, State};
|
use embassy_usb::class::cdc_ncm::{CdcNcmClass, State};
|
||||||
use embassy_usb::{Builder, Config, UsbDevice};
|
use embassy_usb::{Builder, Config, UsbDevice};
|
||||||
|
@ -18,6 +18,10 @@ use embedded_io::asynch::Write;
|
||||||
use static_cell::StaticCell;
|
use static_cell::StaticCell;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
RNG => rng::InterruptHandler<peripherals::RNG>;
|
||||||
|
});
|
||||||
|
|
||||||
type MyDriver = Driver<'static, peripherals::USBD, HardwareVbusDetect>;
|
type MyDriver = Driver<'static, peripherals::USBD, HardwareVbusDetect>;
|
||||||
|
|
||||||
macro_rules! singleton {
|
macro_rules! singleton {
|
||||||
|
@ -108,7 +112,7 @@ async fn main(spawner: Spawner) {
|
||||||
//});
|
//});
|
||||||
|
|
||||||
// Generate random seed
|
// Generate random seed
|
||||||
let mut rng = Rng::new(p.RNG, interrupt::take!(RNG));
|
let mut rng = Rng::new(p.RNG, Irqs);
|
||||||
let mut seed = [0; 8];
|
let mut seed = [0; 8];
|
||||||
rng.blocking_fill_bytes(&mut seed);
|
rng.blocking_fill_bytes(&mut seed);
|
||||||
let seed = u64::from_le_bytes(seed);
|
let seed = u64::from_le_bytes(seed);
|
||||||
|
|
Loading…
Reference in a new issue