aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlle Sandberg <[email protected]>2023-08-28 11:27:56 +0200
committerOlle Sandberg <[email protected]>2023-08-28 11:44:05 +0200
commitfd739250ea8b830f06f8a78a272874faa888d42c (patch)
treeba1a707469dca2701c6464f8c438f671f80e3044
parent88146eb53e40ea2ab43c2db77f3f62c6d08c9b36 (diff)
stm32: fix wait for RNG data
If no data was available to read then the loop would wait for an interrupt and skip to the next chunk without writing the current one. This could cause the given slice to only be partially filled with random data. Fixed by moving the wait to before actually writing data to the chunk.
-rw-r--r--embassy-stm32/src/rng.rs46
1 files changed, 25 insertions, 21 deletions
diff --git a/embassy-stm32/src/rng.rs b/embassy-stm32/src/rng.rs
index 30816e436..0979dce8c 100644
--- a/embassy-stm32/src/rng.rs
+++ b/embassy-stm32/src/rng.rs
@@ -119,7 +119,31 @@ impl<'d, T: Instance> Rng<'d, T> {
119 119
120 pub async fn async_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { 120 pub async fn async_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
121 for chunk in dest.chunks_mut(4) { 121 for chunk in dest.chunks_mut(4) {
122 let bits = T::regs().sr().read(); 122 let mut bits = T::regs().sr().read();
123 if !bits.seis() && !bits.ceis() && !bits.drdy() {
124 // wait for interrupt
125 poll_fn(|cx| {
126 // quick check to avoid registration if already done.
127 let bits = T::regs().sr().read();
128 if bits.drdy() || bits.seis() || bits.ceis() {
129 return Poll::Ready(());
130 }
131 RNG_WAKER.register(cx.waker());
132 T::regs().cr().modify(|reg| reg.set_ie(true));
133 // Need to check condition **after** `register` to avoid a race
134 // condition that would result in lost notifications.
135 let bits = T::regs().sr().read();
136 if bits.drdy() || bits.seis() || bits.ceis() {
137 Poll::Ready(())
138 } else {
139 Poll::Pending
140 }
141 })
142 .await;
143
144 // Re-read the status register after wait.
145 bits = T::regs().sr().read()
146 }
123 if bits.seis() { 147 if bits.seis() {
124 // in case of noise-source or seed error we try to recover here 148 // in case of noise-source or seed error we try to recover here
125 // but we must not use the data in DR and we return an error 149 // but we must not use the data in DR and we return an error
@@ -143,26 +167,6 @@ impl<'d, T: Instance> Rng<'d, T> {
143 for (dest, src) in chunk.iter_mut().zip(random_word.to_be_bytes().iter()) { 167 for (dest, src) in chunk.iter_mut().zip(random_word.to_be_bytes().iter()) {
144 *dest = *src 168 *dest = *src
145 } 169 }
146 } else {
147 // wait for interrupt
148 poll_fn(|cx| {
149 // quick check to avoid registration if already done.
150 let bits = T::regs().sr().read();
151 if bits.drdy() || bits.seis() || bits.ceis() {
152 return Poll::Ready(());
153 }
154 RNG_WAKER.register(cx.waker());
155 T::regs().cr().modify(|reg| reg.set_ie(true));
156 // Need to check condition **after** `register` to avoid a race
157 // condition that would result in lost notifications.
158 let bits = T::regs().sr().read();
159 if bits.drdy() || bits.seis() || bits.ceis() {
160 Poll::Ready(())
161 } else {
162 Poll::Pending
163 }
164 })
165 .await;
166 } 170 }
167 } 171 }
168 172