embassy-rs/embassy · error
RNG error persists after reset; check the RCC clock…
Error message
RNG error persists after reset; check the RCC clock configuration
What it means
The blocking RNG read polls for a valid random word; after repeated clock/health failures it resets the RNG peripheral and retries up to MAX_RESET_RETRIES. If errors still persist it panics, because the usual root cause is that the RNG peripheral clock does not meet the required frequency in the RCC configuration.
Solutions
- Fix the RCC config so the RNG peripheral clock is enabled and within the datasheet-required frequency range.
- Verify the RNG kernel clock source selection (e.g. HSI48/HSE/PLL output) matches your board's clock tree.
- If the hardware still errors, replace the chip or fall back to a software RNG / external entropy source.
Defensive patterns
Strategy: validation
Validate before calling
// Before using the RNG, confirm the kernel clock is enabled and fast enough // e.g. with embassy-stm32 rcc config: ensure rng clock source set and HSI48/PLL enabled. // let rng_clk = rcc.clocks.rng; // debug-log its value in a probe run
Try / catch
// Panic cannot be caught; wrap blocking reads at a higher level with a fallback:
match std::panic::catch_unwind(|| rng.blocking_next_u32()) {
Ok(w) => Some(w),
Err(_) => { log::error!("RNG hardware fault"); None /* use software RNG fallback */ }
} Prevention
- Always configure the RNG kernel clock source in RCC init (e.g. HSI48).
- Verify clock frequency meets the datasheet minimum for RNG.
- Test RNG output health early in bring-up before relying on it.
- Provide a software RNG fallback for fault-tolerant systems.
When it happens
Trigger: Calling blocking_next_u32 (or blocking fill via it) when poll_word() repeatedly returns None after full RNG resets — i.e. the RNG keeps signaling seed/clock errors.
Common situations: RNG kernel clock misconfigured (too slow or gated) in RCC init; running on a board where the RNG clock source is wrong; silicon health-error conditions.
Related errors
- MCLK frequency < 9.5 MHz is not compatible with the TRNG
- AHB frequency is too low
- must not select PLL source as DISABLE
- IC source was set to PLL , but it is not currently enabled
- LSE frequency more than 5% off from 32.768 kHz, cannot use…
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/1466d150704d42ce.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-stm32/src/rng.rs:418
/// Get a random u32.
///
/// This call is infallible: a seed or clock error is recovered by resetting
/// the RNG. If the error persists after `MAX_RESET_RETRIES` resets (almost
/// always a misconfigured RNG clock) it panics, since an infallible API has
/// no other way to surface the fault. Use [`fill_bytes`](Rng::<Async>::fill_bytes)
/// for a fallible path that returns [`Error`] instead.
pub fn blocking_next_u32(&mut self) -> u32 {
// Only resets are bounded, not poll iterations: a healthy RNG may take
// many reads to produce the first word, and that must not count as a
// failure.
let mut retries = 0;
loop {
if let Some(word) = self.poll_word() {
return word;
}
if retries >= MAX_RESET_RETRIES {
panic!("RNG error persists after reset; check the RCC clock configuration");
}
retries += 1;
self.reset();
}
}
/// Get a random u64
pub fn blocking_next_u64(&mut self) -> u64 {
let mut rand = self.blocking_next_u32() as u64;
rand |= (self.blocking_next_u32() as u64) << 32;
rand
}
/// Fill a slice with random bytes
pub fn blocking_fill_bytes(&mut self, dest: &mut [u8]) {
for chunk in dest.chunks_mut(4) {
let rand = self.blocking_next_u32();
for (slot, num) in chunk.iter_mut().zip(rand.to_ne_bytes().iter()) {View on GitHub (pinned to 463a07b963)