aboutsummaryrefslogtreecommitdiff
path: root/embassy-nrf
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2025-05-19 16:38:34 +0200
committerDario Nieuwenhuis <[email protected]>2025-05-21 12:39:52 +0200
commit0e47478f01335c735f8f27fa3a935776736e9afa (patch)
tree89e9184d44b567a8a4c8de871cc1645090c11e9f /embassy-nrf
parent7cbc9058bc726900571a7858c581f60cd8cb0266 (diff)
nrf/rng: add Blocking/Async Mode param.
This allows avoiding creating the irq handler if you're only going to use it in blocking mode.
Diffstat (limited to 'embassy-nrf')
-rw-r--r--embassy-nrf/src/lib.rs24
-rw-r--r--embassy-nrf/src/rng.rs78
2 files changed, 76 insertions, 26 deletions
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs
index 0c5dd059d..398bfed48 100644
--- a/embassy-nrf/src/lib.rs
+++ b/embassy-nrf/src/lib.rs
@@ -1039,3 +1039,27 @@ pub fn init(config: config::Config) -> Peripherals {
1039 1039
1040 peripherals 1040 peripherals
1041} 1041}
1042
1043/// Operating modes for peripherals.
1044pub mod mode {
1045 trait SealedMode {}
1046
1047 /// Operating mode for a peripheral.
1048 #[allow(private_bounds)]
1049 pub trait Mode: SealedMode {}
1050
1051 macro_rules! impl_mode {
1052 ($name:ident) => {
1053 impl SealedMode for $name {}
1054 impl Mode for $name {}
1055 };
1056 }
1057
1058 /// Blocking mode.
1059 pub struct Blocking;
1060 /// Async mode.
1061 pub struct Async;
1062
1063 impl_mode!(Blocking);
1064 impl_mode!(Async);
1065}
diff --git a/embassy-nrf/src/rng.rs b/embassy-nrf/src/rng.rs
index 7e42dc938..9d3130e6e 100644
--- a/embassy-nrf/src/rng.rs
+++ b/embassy-nrf/src/rng.rs
@@ -14,6 +14,7 @@ use embassy_hal_internal::{Peri, PeripheralType};
14use embassy_sync::waitqueue::WakerRegistration; 14use embassy_sync::waitqueue::WakerRegistration;
15 15
16use crate::interrupt::typelevel::Interrupt; 16use crate::interrupt::typelevel::Interrupt;
17use crate::mode::{Async, Blocking, Mode};
17use crate::{interrupt, pac}; 18use crate::{interrupt, pac};
18 19
19/// Interrupt handler. 20/// Interrupt handler.
@@ -55,11 +56,31 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
55/// A wrapper around an nRF RNG peripheral. 56/// A wrapper around an nRF RNG peripheral.
56/// 57///
57/// It has a non-blocking API, and a blocking api through `rand`. 58/// It has a non-blocking API, and a blocking api through `rand`.
58pub struct Rng<'d, T: Instance> { 59pub struct Rng<'d, T: Instance, M: Mode> {
59 _peri: Peri<'d, T>, 60 _peri: Peri<'d, T>,
61 _phantom: PhantomData<M>,
60} 62}
61 63
62impl<'d, T: Instance> Rng<'d, T> { 64impl<'d, T: Instance> Rng<'d, T, Blocking> {
65 /// Creates a new RNG driver from the `RNG` peripheral and interrupt.
66 ///
67 /// SAFETY: The future returned from `fill_bytes` must not have its lifetime end without running its destructor,
68 /// e.g. using `mem::forget`.
69 ///
70 /// The synchronous API is safe.
71 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> {
63 /// Creates a new RNG driver from the `RNG` peripheral and interrupt. 84 /// Creates a new RNG driver from the `RNG` peripheral and interrupt.
64 /// 85 ///
65 /// SAFETY: The future returned from `fill_bytes` must not have its lifetime end without running its destructor, 86 /// 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> {
70 rng: Peri<'d, T>, 91 rng: Peri<'d, T>,
71 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 92 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
72 ) -> Self { 93 ) -> Self {
73 let this = Self { _peri: rng }; 94 let this = Self {
95 _peri: rng,
96 _phantom: PhantomData,
97 };
74 98
75 this.stop(); 99 this.stop();
76 this.disable_irq(); 100 this.disable_irq();
@@ -81,14 +105,6 @@ impl<'d, T: Instance> Rng<'d, T> {
81 this 105 this
82 } 106 }
83 107
84 fn stop(&self) {
85 T::regs().tasks_stop().write_value(1)
86 }
87
88 fn start(&self) {
89 T::regs().tasks_start().write_value(1)
90 }
91
92 fn enable_irq(&self) { 108 fn enable_irq(&self) {
93 T::regs().intenset().write(|w| w.set_valrdy(true)); 109 T::regs().intenset().write(|w| w.set_valrdy(true));
94 } 110 }
@@ -97,16 +113,6 @@ impl<'d, T: Instance> Rng<'d, T> {
97 T::regs().intenclr().write(|w| w.set_valrdy(true)); 113 T::regs().intenclr().write(|w| w.set_valrdy(true));
98 } 114 }
99 115
100 /// Enable or disable the RNG's bias correction.
101 ///
102 /// Bias correction removes any bias towards a '1' or a '0' in the bits generated.
103 /// However, this makes the generation of numbers slower.
104 ///
105 /// Defaults to disabled.
106 pub fn set_bias_correction(&self, enable: bool) {
107 T::regs().config().write(|w| w.set_dercen(enable))
108 }
109
110 /// Fill the buffer with random bytes. 116 /// Fill the buffer with random bytes.
111 pub async fn fill_bytes(&mut self, dest: &mut [u8]) { 117 pub async fn fill_bytes(&mut self, dest: &mut [u8]) {
112 if dest.is_empty() { 118 if dest.is_empty() {
@@ -153,6 +159,26 @@ impl<'d, T: Instance> Rng<'d, T> {
153 // Trigger the teardown 159 // Trigger the teardown
154 drop(on_drop); 160 drop(on_drop);
155 } 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 /// Enable or disable the RNG's bias correction.
174 ///
175 /// Bias correction removes any bias towards a '1' or a '0' in the bits generated.
176 /// However, this makes the generation of numbers slower.
177 ///
178 /// Defaults to disabled.
179 pub fn set_bias_correction(&self, enable: bool) {
180 T::regs().config().write(|w| w.set_dercen(enable))
181 }
156 182
157 /// Fill the buffer with random bytes, blocking version. 183 /// Fill the buffer with random bytes, blocking version.
158 pub fn blocking_fill_bytes(&mut self, dest: &mut [u8]) { 184 pub fn blocking_fill_bytes(&mut self, dest: &mut [u8]) {
@@ -184,7 +210,7 @@ impl<'d, T: Instance> Rng<'d, T> {
184 } 210 }
185} 211}
186 212
187impl<'d, T: Instance> Drop for Rng<'d, T> { 213impl<'d, T: Instance, M: Mode> Drop for Rng<'d, T, M> {
188 fn drop(&mut self) { 214 fn drop(&mut self) {
189 self.stop(); 215 self.stop();
190 critical_section::with(|cs| { 216 critical_section::with(|cs| {
@@ -195,7 +221,7 @@ impl<'d, T: Instance> Drop for Rng<'d, T> {
195 } 221 }
196} 222}
197 223
198impl<'d, T: Instance> rand_core_06::RngCore for Rng<'d, T> { 224impl<'d, T: Instance, M: Mode> rand_core_06::RngCore for Rng<'d, T, M> {
199 fn fill_bytes(&mut self, dest: &mut [u8]) { 225 fn fill_bytes(&mut self, dest: &mut [u8]) {
200 self.blocking_fill_bytes(dest); 226 self.blocking_fill_bytes(dest);
201 } 227 }
@@ -211,9 +237,9 @@ impl<'d, T: Instance> rand_core_06::RngCore for Rng<'d, T> {
211 } 237 }
212} 238}
213 239
214impl<'d, T: Instance> rand_core_06::CryptoRng for Rng<'d, T> {} 240impl<'d, T: Instance, M: Mode> rand_core_06::CryptoRng for Rng<'d, T, M> {}
215 241
216impl<'d, T: Instance> rand_core_09::RngCore for Rng<'d, T> { 242impl<'d, T: Instance, M: Mode> rand_core_09::RngCore for Rng<'d, T, M> {
217 fn fill_bytes(&mut self, dest: &mut [u8]) { 243 fn fill_bytes(&mut self, dest: &mut [u8]) {
218 self.blocking_fill_bytes(dest); 244 self.blocking_fill_bytes(dest);
219 } 245 }
@@ -225,7 +251,7 @@ impl<'d, T: Instance> rand_core_09::RngCore for Rng<'d, T> {
225 } 251 }
226} 252}
227 253
228impl<'d, T: Instance> rand_core_09::CryptoRng for Rng<'d, T> {} 254impl<'d, T: Instance, M: Mode> rand_core_09::CryptoRng for Rng<'d, T, M> {}
229 255
230/// Peripheral static state 256/// Peripheral static state
231pub(crate) struct State { 257pub(crate) struct State {