diff options
| author | Olle Sandberg <[email protected]> | 2023-08-28 11:27:56 +0200 |
|---|---|---|
| committer | Olle Sandberg <[email protected]> | 2023-08-28 11:44:05 +0200 |
| commit | fd739250ea8b830f06f8a78a272874faa888d42c (patch) | |
| tree | ba1a707469dca2701c6464f8c438f671f80e3044 | |
| parent | 88146eb53e40ea2ab43c2db77f3f62c6d08c9b36 (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.rs | 46 |
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 | ||
