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.
This commit is contained in:
parent
88146eb53e
commit
fd739250ea
@ -119,7 +119,31 @@ impl<'d, T: Instance> Rng<'d, T> {
|
|||||||
|
|
||||||
pub async fn async_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
|
pub async fn async_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
|
||||||
for chunk in dest.chunks_mut(4) {
|
for chunk in dest.chunks_mut(4) {
|
||||||
let bits = T::regs().sr().read();
|
let mut bits = T::regs().sr().read();
|
||||||
|
if !bits.seis() && !bits.ceis() && !bits.drdy() {
|
||||||
|
// wait for interrupt
|
||||||
|
poll_fn(|cx| {
|
||||||
|
// quick check to avoid registration if already done.
|
||||||
|
let bits = T::regs().sr().read();
|
||||||
|
if bits.drdy() || bits.seis() || bits.ceis() {
|
||||||
|
return Poll::Ready(());
|
||||||
|
}
|
||||||
|
RNG_WAKER.register(cx.waker());
|
||||||
|
T::regs().cr().modify(|reg| reg.set_ie(true));
|
||||||
|
// Need to check condition **after** `register` to avoid a race
|
||||||
|
// condition that would result in lost notifications.
|
||||||
|
let bits = T::regs().sr().read();
|
||||||
|
if bits.drdy() || bits.seis() || bits.ceis() {
|
||||||
|
Poll::Ready(())
|
||||||
|
} else {
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
// Re-read the status register after wait.
|
||||||
|
bits = T::regs().sr().read()
|
||||||
|
}
|
||||||
if bits.seis() {
|
if bits.seis() {
|
||||||
// in case of noise-source or seed error we try to recover here
|
// in case of noise-source or seed error we try to recover here
|
||||||
// but we must not use the data in DR and we return an error
|
// 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> {
|
|||||||
for (dest, src) in chunk.iter_mut().zip(random_word.to_be_bytes().iter()) {
|
for (dest, src) in chunk.iter_mut().zip(random_word.to_be_bytes().iter()) {
|
||||||
*dest = *src
|
*dest = *src
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// wait for interrupt
|
|
||||||
poll_fn(|cx| {
|
|
||||||
// quick check to avoid registration if already done.
|
|
||||||
let bits = T::regs().sr().read();
|
|
||||||
if bits.drdy() || bits.seis() || bits.ceis() {
|
|
||||||
return Poll::Ready(());
|
|
||||||
}
|
|
||||||
RNG_WAKER.register(cx.waker());
|
|
||||||
T::regs().cr().modify(|reg| reg.set_ie(true));
|
|
||||||
// Need to check condition **after** `register` to avoid a race
|
|
||||||
// condition that would result in lost notifications.
|
|
||||||
let bits = T::regs().sr().read();
|
|
||||||
if bits.drdy() || bits.seis() || bits.ceis() {
|
|
||||||
Poll::Ready(())
|
|
||||||
} else {
|
|
||||||
Poll::Pending
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user