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, T: Instance, M: Mode> {
60 _peri: Peri<'d, T>,
61 _phantom: PhantomData<M>,
62}
63
64impl<'d, T: Instance> Rng<'d, T, Blocking> {
65 pub fn new_blocking(rng: Peri<'d, T>) -> Self {
72 let this = Self {
73 _peri: rng,
74 _phantom: PhantomData,
75 };
76
77 this.stop();
78
79 this
80 }
81}
82
83impl<'d, T: Instance> Rng<'d, T, Async> {
84 pub fn new(
91 rng: Peri<'d, T>,
92 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
93 ) -> Self {
94 let this = Self {
95 _peri: rng,
96 _phantom: PhantomData,
97 };
98
99 this.stop();
100 this.disable_irq();
101
102 T::Interrupt::unpend();
103 unsafe { T::Interrupt::enable() };
104
105 this
106 }
107
108 fn enable_irq(&self) {
109 T::regs().intenset().write(|w| w.set_valrdy(true));
110 }
111
112 fn disable_irq(&self) {
113 T::regs().intenclr().write(|w| w.set_valrdy(true));
114 }
115
116 pub async fn fill_bytes(&mut self, dest: &mut [u8]) {
118 if dest.is_empty() {
119 return; }
121
122 let range = dest.as_mut_ptr_range();
123 critical_section::with(|cs| {
126 let mut state = T::state().borrow_mut(cs);
127 state.ptr = range.start;
128 state.end = range.end;
129 });
130
131 self.enable_irq();
132 self.start();
133
134 let on_drop = OnDrop::new(|| {
135 self.stop();
136 self.disable_irq();
137
138 critical_section::with(|cs| {
139 let mut state = T::state().borrow_mut(cs);
140 state.ptr = ptr::null_mut();
141 state.end = ptr::null_mut();
142 });
143 });
144
145 poll_fn(|cx| {
146 critical_section::with(|cs| {
147 let mut s = T::state().borrow_mut(cs);
148 s.waker.register(cx.waker());
149 if s.ptr == s.end {
150 Poll::Ready(())
152 } else {
153 Poll::Pending
154 }
155 })
156 })
157 .await;
158
159 drop(on_drop);
161 }
162}
163
164impl<'d, T: Instance, M: Mode> Rng<'d, T, M> {
165 fn stop(&self) {
166 T::regs().tasks_stop().write_value(1)
167 }
168
169 fn start(&self) {
170 T::regs().tasks_start().write_value(1)
171 }
172
173 pub fn set_bias_correction(&self, enable: bool) {
180 T::regs().config().write(|w| w.set_dercen(enable))
181 }
182
183 pub fn blocking_fill_bytes(&mut self, dest: &mut [u8]) {
185 self.start();
186
187 for byte in dest.iter_mut() {
188 let regs = T::regs();
189 while regs.events_valrdy().read() == 0 {}
190 regs.events_valrdy().write_value(0);
191 *byte = regs.value().read().value();
192 }
193
194 self.stop();
195 }
196
197 pub fn blocking_next_u32(&mut self) -> u32 {
199 let mut bytes = [0; 4];
200 self.blocking_fill_bytes(&mut bytes);
201 u32::from_ne_bytes(bytes)
203 }
204
205 pub fn blocking_next_u64(&mut self) -> u64 {
207 let mut bytes = [0; 8];
208 self.blocking_fill_bytes(&mut bytes);
209 u64::from_ne_bytes(bytes)
210 }
211}
212
213impl<'d, T: Instance, M: Mode> Drop for Rng<'d, T, M> {
214 fn drop(&mut self) {
215 self.stop();
216 critical_section::with(|cs| {
217 let mut state = T::state().borrow_mut(cs);
218 state.ptr = ptr::null_mut();
219 state.end = ptr::null_mut();
220 });
221 }
222}
223
224impl<'d, T: Instance, M: Mode> rand_core_06::RngCore for Rng<'d, T, M> {
225 fn fill_bytes(&mut self, dest: &mut [u8]) {
226 self.blocking_fill_bytes(dest);
227 }
228 fn next_u32(&mut self) -> u32 {
229 self.blocking_next_u32()
230 }
231 fn next_u64(&mut self) -> u64 {
232 self.blocking_next_u64()
233 }
234 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core_06::Error> {
235 self.blocking_fill_bytes(dest);
236 Ok(())
237 }
238}
239
240impl<'d, T: Instance, M: Mode> rand_core_06::CryptoRng for Rng<'d, T, M> {}
241
242impl<'d, T: Instance, M: Mode> rand_core_09::RngCore for Rng<'d, T, M> {
243 fn fill_bytes(&mut self, dest: &mut [u8]) {
244 self.blocking_fill_bytes(dest);
245 }
246 fn next_u32(&mut self) -> u32 {
247 self.blocking_next_u32()
248 }
249 fn next_u64(&mut self) -> u64 {
250 self.blocking_next_u64()
251 }
252}
253
254impl<'d, T: Instance, M: Mode> rand_core_09::CryptoRng for Rng<'d, T, M> {}
255
256pub(crate) struct State {
258 inner: Mutex<RefCell<InnerState>>,
259}
260
261struct InnerState {
262 ptr: *mut u8,
263 end: *mut u8,
264 waker: WakerRegistration,
265}
266
267unsafe impl Send for InnerState {}
268
269impl State {
270 pub(crate) const fn new() -> Self {
271 Self {
272 inner: Mutex::new(RefCell::new(InnerState::new())),
273 }
274 }
275
276 fn borrow_mut<'cs>(&'cs self, cs: CriticalSection<'cs>) -> RefMut<'cs, InnerState> {
277 self.inner.borrow(cs).borrow_mut()
278 }
279}
280
281impl InnerState {
282 const fn new() -> Self {
283 Self {
284 ptr: ptr::null_mut(),
285 end: ptr::null_mut(),
286 waker: WakerRegistration::new(),
287 }
288 }
289}
290
291pub(crate) trait SealedInstance {
292 fn regs() -> pac::rng::Rng;
293 fn state() -> &'static State;
294}
295
296#[allow(private_bounds)]
298pub trait Instance: SealedInstance + PeripheralType + 'static + Send {
299 type Interrupt: interrupt::typelevel::Interrupt;
301}
302
303macro_rules! impl_rng {
304 ($type:ident, $pac_type:ident, $irq:ident) => {
305 impl crate::rng::SealedInstance for peripherals::$type {
306 fn regs() -> crate::pac::rng::Rng {
307 pac::$pac_type
308 }
309 fn state() -> &'static crate::rng::State {
310 static STATE: crate::rng::State = crate::rng::State::new();
311 &STATE
312 }
313 }
314 impl crate::rng::Instance for peripherals::$type {
315 type Interrupt = crate::interrupt::typelevel::$irq;
316 }
317 };
318}