embassy-rs/embassy · error
TRNG: consecutive health check failures. Increase…
Error message
TRNG: {} consecutive health check failures. Increase Config::sample_count. What it means
The RP235x hardware TRNG runs entropy health checks on every random number generation. When the EHR valid flag never asserts and the health-check status reports failure MAX_HEALTH_CHECK_RETRIES times consecutively, the blocking wait gives up and panics, telling the user to raise `Config::sample_count`. Repeated health-check failures indicate the entropy source is producing insufficient/unhealthy samples for the current sample_count setting.
Solutions
- Increase `Config::sample_count` (raise it substantially, e.g. multiply by 2-10) so the health check accumulates enough entropy before validation
- Retry generation at a higher level with backoff, since failures can be transient under marginal conditions
- Check power supply and clock configuration — unstable analog supply degrades the entropy source and can cause persistent health-check failures
- If failures persist across sample_count increases, treat the TRNG as faulty and route through a software RNG seeded from a different source
Example fix
// before
let mut trng = Trng::new(p.TRNG, Config { sample_count: 100 });
let n = trng.blocking_next_u32();
// after
let mut trng = Trng::new(p.TRNG, Config { sample_count: 2000 });
let n = trng.blocking_next_u32(); Defensive patterns
Strategy: validation
Validate before calling
fn cfg_ok(cfg: &Config) -> Result<(), &'static str> {
if cfg.sample_count < 1000 { Err("sample_count too low for reliable TRNG health checks") } else { Ok(()) }
} Try / catch
// panics in no_std; validate config and use the async API with retry instead of blocking defensive: tune sample_count upward until health checks pass reliably
Prevention
- Start with conservative (large) sample_count values and only reduce after field testing
- Log health-check failure counts via handle_health_check_status equivalents before hitting the cap
- Watch for environmental causes: brownouts, noisy supplies, extreme temperatures
When it happens
Trigger: Calling `blocking_next_u32`, `blocking_next_u64`, or `blocking_fill_bytes` on the TRNG when the hardware health check fails MAX_HEALTH_CHECK_RETRIES consecutive times — usually because Config::sample_count is too low for the chip's noise source (e.g. default sample count too small at current clock/temperature conditions).
Common situations: RP235x boards with the TRNG configured with a small sample_count; noisy power/clock conditions weakening the ring-oscillator entropy; code copied from examples with aggressive (small) sample counts to speed up generation.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- MCLK frequency < 9.5 MHz is not compatible with the TRNG
- ErevidIsZero
- heartbeat from esp32 stopped
- PHY did not respond
- Passphrase is too short or too long
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/f32008bfd7a0021f.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-rp/src/trng.rs:330
/// Unmask all interrupt sources. The interrupt handler masks them when it fires.
fn unmask_irq(&self) {
self.info.regs.rng_imr().write(|w| {
w.set_ehr_valid_int_mask(false);
w.set_autocorr_err_int_mask(false);
w.set_crngt_err_int_mask(false);
w.set_vn_err_int_mask(false);
});
}
fn blocking_wait_for_successful_generation(&self) {
let regs = self.info.regs;
let mut failures = 0;
while regs.trng_valid().read().ehr_valid().not() {
if self.handle_health_check_status() {
failures += 1;
if failures >= MAX_HEALTH_CHECK_RETRIES {
panic!(
"TRNG: {} consecutive health check failures. Increase Config::sample_count.",
MAX_HEALTH_CHECK_RETRIES
);
}
}
}
}
/// Read out a completed block. Reading `EHR_DATA5` clears the result registers
/// and starts the next generation.
fn read_ehr_registers_into_array(&mut self, buffer: &mut [u8; TRNG_BLOCK_SIZE_BYTES]) {
let regs = self.info.regs;
let ehr_data_regs = [
regs.ehr_data0(),
regs.ehr_data1(),
regs.ehr_data2(),
regs.ehr_data3(),
regs.ehr_data4(),View on GitHub (pinned to 463a07b963)