1#![macro_use]
4
5use core::cell::{RefCell, RefMut};
6use core::future::poll_fn;
7use core::marker::PhantomData;
8use core::ptr;
9use core::task::Poll;
10
11use critical_section::{CriticalSection, Mutex};
12use embassy_hal_internal::drop::OnDrop;
13use embassy_hal_internal::{Peri, PeripheralType};
14use embassy_sync::waitqueue::WakerRegistration;
15
16use crate::interrupt::typelevel::Interrupt;
17use crate::mode::{Async, Blocking, Mode};
18use crate::{interrupt, pac};
19
20pub struct InterruptHandler<T: Instance> {
22 _phantom: PhantomData<T>,
23}
24
25impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
26 unsafe fn on_interrupt() {
27 let r = T::regs();
28
29 r.events_valrdy().write_value(0);
31
32 critical_section::with(|cs| {
35 let mut state = T::state().borrow_mut(cs);
36 if !state.ptr.is_null() && state.ptr != state.end {
39 unsafe {
44 *state.ptr = r.value().read().value();
45 state.ptr = state.ptr.add(1);
46 }
47
48 if state.ptr == state.end {
49 state.waker.wake();
50 }
51 }
52 });
53 }
54}
55
56pub struct Rng<'d, M: Mode> {
60 r: pac::rng::Rng,
61 state: &'static State,
62 _phantom: PhantomData<(&'d (), M)>,
63}
64
65impl<'d> Rng<'d, Blocking> {
66 pub fn new_blocking<T: Instance>(_rng: Peri<'d, T>) -> Self {
73 let this = Self {
74 r: T::regs(),
75 state: T::state(),
76 _phantom: PhantomData,
77 };
78
79 this.stop();
80
81 this
82 }
83}
84
85impl<'d> Rng<'d, Async> {
86 pub fn new<T: Instance>(
93 _rng: Peri<'d, T>,
94 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
95 ) -> Self {
96 let this = Self {
97 r: T::regs(),
98 state: T::state(),
99 _phantom: PhantomData,
100 };
101
102 this.stop();
103 this.disable_irq();
104
105 T::Interrupt::unpend();
106 unsafe { T::Interrupt::enable() };
107
108 this
109 }
110
111 fn enable_irq(&self) {
112 self.r.intenset().write(|w| w.set_valrdy(true));
113 }
114
115 fn disable_irq(&self) {
116 self.r.intenclr().write(|w| w.set_valrdy(true));
117 }
118
119 pub async fn fill_bytes(&mut self, dest: &mut [u8]) {
121 if dest.is_empty() {
122 return; }
124
125 let range = dest.as_mut_ptr_range();
126 let state = self.state;
127 critical_section::with(|cs| {
130 let mut state = state.borrow_mut(cs);
131 state.ptr = range.start;
132 state.end = range.end;
133 });
134
135 self.enable_irq();
136 self.start();
137
138 let on_drop = OnDrop::new(|| {
139 self.stop();
140 self.disable_irq();
141
142 critical_section::with(|cs| {
143 let mut state = state.borrow_mut(cs);
144 state.ptr = ptr::null_mut();
145 state.end = ptr::null_mut();
146 });
147 });
148
149 poll_fn(|cx| {
150 critical_section::with(|cs| {
151 let mut s = state.borrow_mut(cs);
152 s.waker.register(cx.waker());
153 if s.ptr == s.end {
154 Poll::Ready(())
156 } else {
157 Poll::Pending
158 }
159 })
160 })
161 .await;
162
163 drop(on_drop);
165 }
166}
167
168impl<'d, M: Mode> Rng<'d, M> {
169 fn stop(&self) {
170 self.r.tasks_stop().write_value(1)
171 }
172
173 fn start(&self) {
174 self.r.tasks_start().write_value(1)
175 }
176
177 pub fn set_bias_correction(&self, enable: bool) {
184 self.r.config().write(|w| w.set_dercen(enable))
185 }
186
187 pub fn blocking_fill_bytes(&mut self, dest: &mut [u8]) {
189 self.start();
190
191 for byte in dest.iter_mut() {
192 let regs = self.r;
193 while regs.events_valrdy().read() == 0 {}
194 regs.events_valrdy().write_value(0);
195 *byte = regs.value().read().value();
196 }
197
198 self.stop();
199 }
200
201 pub fn blocking_next_u32(&mut self) -> u32 {
203 let mut bytes = [0; 4];
204 self.blocking_fill_bytes(&mut bytes);
205 u32::from_ne_bytes(bytes)
207 }
208
209 pub fn blocking_next_u64(&mut self) -> u64 {
211 let mut bytes = [0; 8];
212 self.blocking_fill_bytes(&mut bytes);
213 u64::from_ne_bytes(bytes)
214 }
215}
216
217impl<'d, M: Mode> Drop for Rng<'d, M> {
218 fn drop(&mut self) {
219 self.stop();
220 critical_section::with(|cs| {
221 let mut state = self.state.borrow_mut(cs);
222 state.ptr = ptr::null_mut();
223 state.end = ptr::null_mut();
224 });
225 }
226}
227
228impl<'d, M: Mode> rand_core_06::RngCore for Rng<'d, M> {
229 fn fill_bytes(&mut self, dest: &mut [u8]) {
230 self.blocking_fill_bytes(dest);
231 }
232 fn next_u32(&mut self) -> u32 {
233 self.blocking_next_u32()
234 }
235 fn next_u64(&mut self) -> u64 {
236 self.blocking_next_u64()
237 }
238 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core_06::Error> {
239 self.blocking_fill_bytes(dest);
240 Ok(())
241 }
242}
243
244impl<'d, M: Mode> rand_core_06::CryptoRng for Rng<'d, M> {}
245
246impl<'d, M: Mode> rand_core_09::RngCore for Rng<'d, M> {
247 fn fill_bytes(&mut self, dest: &mut [u8]) {
248 self.blocking_fill_bytes(dest);
249 }
250 fn next_u32(&mut self) -> u32 {
251 self.blocking_next_u32()
252 }
253 fn next_u64(&mut self) -> u64 {
254 self.blocking_next_u64()
255 }
256}
257
258impl<'d, M: Mode> rand_core_09::CryptoRng for Rng<'d, M> {}
259
260pub(crate) struct State {
262 inner: Mutex<RefCell<InnerState>>,
263}
264
265struct InnerState {
266 ptr: *mut u8,
267 end: *mut u8,
268 waker: WakerRegistration,
269}
270
271unsafe impl Send for InnerState {}
272
273impl State {
274 pub(crate) const fn new() -> Self {
275 Self {
276 inner: Mutex::new(RefCell::new(InnerState::new())),
277 }
278 }
279
280 fn borrow_mut<'cs>(&'cs self, cs: CriticalSection<'cs>) -> RefMut<'cs, InnerState> {
281 self.inner.borrow(cs).borrow_mut()
282 }
283}
284
285impl InnerState {
286 const fn new() -> Self {
287 Self {
288 ptr: ptr::null_mut(),
289 end: ptr::null_mut(),
290 waker: WakerRegistration::new(),
291 }
292 }
293}
294
295pub(crate) trait SealedInstance {
296 fn regs() -> pac::rng::Rng;
297 fn state() -> &'static State;
298}
299
300#[allow(private_bounds)]
302pub trait Instance: SealedInstance + PeripheralType + 'static + Send {
303 type Interrupt: interrupt::typelevel::Interrupt;
305}
306
307macro_rules! impl_rng {
308 ($type:ident, $pac_type:ident, $irq:ident) => {
309 impl crate::rng::SealedInstance for peripherals::$type {
310 fn regs() -> crate::pac::rng::Rng {
311 pac::$pac_type
312 }
313 fn state() -> &'static crate::rng::State {
314 static STATE: crate::rng::State = crate::rng::State::new();
315 &STATE
316 }
317 }
318 impl crate::rng::Instance for peripherals::$type {
319 type Interrupt = crate::interrupt::typelevel::$irq;
320 }
321 };
322}