embassy-rs/embassy · error
Period cannot exceed
Error message
Period cannot exceed {} microseconds What it means
The watchdog period is stored in a 24-bit load register, and on RP2040 the counter decrements by 2 due to errata RP2040-E1, halving the effective maximum. `Watchdog::start`/`feed` computes the microsecond timeout and panics if it exceeds MAX_PERIOD (0xFFFFFF/2 us on RP2040, 0xFFFFFF us on RP235x) because the requested period cannot be represented in the hardware register.
Solutions
- Clamp or validate the watchdog timeout to <= 8_388_607 microseconds (8.386 s) on RP2040 before calling start
- Use a shorter watchdog period and feed it more frequently from a scheduled task
- Implement a software watchdog chain: hardware watchdog at a short period fed by a task that checks a longer logical deadline
- On RP235x you get the full 0xFFFFFF (~16.7 s) range since the errata is fixed
Example fix
// before watchdog.start(Duration::from_secs(15)); // panics on RP2040 // after const MAX_PERIOD_US: u64 = 0xFFFFFF / 2; let period = Duration::from_secs(15).min(Duration::from_micros(MAX_PERIOD_US)); watchdog.start(period); // ~8.39s max on RP2040
Defensive patterns
Strategy: validation
Validate before calling
fn watchdog_period_ok(d: std::time::Duration) -> bool {
const MAX_PERIOD_US: u64 = 0xFFFFFF / 2; // RP2040; RP235x: 0xFFFFFF
d.as_micros() <= MAX_PERIOD_US
} Try / catch
// panic in no_std: clamp before start watchdog.start(d.min(Duration::from_micros(0xFFFFFF / 2)));
Prevention
- Clamp watchdog timeouts to 8_388_607 us on RP2040 at the config boundary
- Remember RP2040-E1 halves the effective range versus RP235x
- Feed the watchdog from a task on a period well below the hardware limit
When it happens
Trigger: Calling `watchdog.start(Duration)` with a timeout whose microsecond value exceeds 8,388,607 us (~8.39 s) on RP2040 or 16,777,215 us (~16.78 s) on RP235x.
Common situations: Configuring a 10-second or 30-second watchdog on RP2040 assuming the full 24-bit range; porting RP235x watchdog timings back to RP2040 where the errata halves the limit; computing the timeout from a config value without clamping.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- Invalid watchdog scratch index
- Boot prepare error
- timer must be stopped before setting counter
- Failed to configure PLL_SYS
- Failed to configure PLL_USB
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/fc9ab53f3d2fba03.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-rp/src/watchdog.rs:91
// Configure which hardware will be reset by the watchdog
// (everything except ROSC, XOSC)
fn configure_wdog_reset_triggers(&self) {
let psm = pac::PSM;
psm.wdsel().write_value(pac::psm::regs::Wdsel(
0x0001ffff & !(0x01 << 0usize) & !(0x01 << 1usize),
));
}
/// Feed the watchdog timer
pub fn feed(&mut self, timeout: Duration) {
#[cfg(feature = "rp2040")]
const MAX_PERIOD: u32 = 0xFFFFFF / 2;
#[cfg(feature = "_rp235x")]
const MAX_PERIOD: u32 = 0xFFFFFF;
let timeout_us = timeout.as_micros();
if timeout_us > (MAX_PERIOD) as u64 {
panic!("Period cannot exceed {} microseconds", MAX_PERIOD);
}
let timeout_us = timeout_us as u32;
// Due to a logic error, the watchdog decrements by 2 and
// the load value must be compensated; see RP2040-E1
// This errata is fixed in the RP235x
let load_value = if cfg!(feature = "rp2040") {
timeout_us * 2
} else {
timeout_us
};
self.load_counter(load_value)
}
/// Start the watchdog timer
pub fn start(&mut self, initial_timeout: Duration) {
self.enable(false);View on GitHub (pinned to 463a07b963)