embassy-rs/embassy · error
Hertz cannot be 0
Error message
Hertz cannot be 0
What it means
MaybeHertz's From<Option<Hertz>> impl panics when converting Some(Hertz(0)). A zero frequency is meaningless for clock configuration and typically indicates an unset or miscalculated clock, so the driver rejects it eagerly.
Solutions
- Pass None for the optional frequency instead of Some(Hertz(0)).
- Fix the frequency computation so a real nonzero value is produced (check HSE crystal value / divisor math).
- Add an early debug assertion on your computed frequencies before constructing the config.
Example fix
// before let freq: Option<Hertz> = Some(Hertz(0)); // after let freq: Option<Hertz> = None; // or Some(Hertz::mhz(16))
Defensive patterns
Strategy: validation
Validate before calling
fn checked_maybe(h: Option<Hertz>) -> Option<Hertz> { match h { Some(Hertz(0)) | None => None, other => other } } Type guard
fn is_valid_freq(f: Option<Hertz>) -> bool { !matches!(f, Some(Hertz(0))) } Prevention
- Map zero/absent frequencies to None instead of Some(Hertz(0)).
- Validate computed clock values are nonzero before building configs.
- Check HSE crystal constants and divisor math in board files.
When it happens
Trigger: Passing Some(Hertz(0)) anywhere the API accepts Option<Hertz> (e.g. optional clock frequencies in RCC/peripheral configs), usually because a computed frequency was 0 (disabled source, division by zero elsewhere, or uninitialized config).
Common situations: Clock frequency computed from an HSE value that is None/0; typo in a board file yielding 0 Hz; passing 0.mhz() wrapped in Some instead of None.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/39a178ec7b4117e3.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-stm32/src/time.rs:143
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
/// A variant on [Hertz] that acts as an `Option<Hertz>` that is smaller and repr C.
///
/// An `Option<Hertz>` can be `.into()`'d into this type and back.
/// The only restriction is that that [Hertz] cannot have the value 0 since that's
/// seen as the `None` variant.
pub struct MaybeHertz(u32);
impl MaybeHertz {
/// Same as calling the `.into()` function, but without type inference.
pub fn to_hertz(self) -> Option<Hertz> {
self.into()
}
}
impl From<Option<Hertz>> for MaybeHertz {
fn from(value: Option<Hertz>) -> Self {
match value {
Some(Hertz(0)) => panic!("Hertz cannot be 0"),
Some(Hertz(val)) => Self(val),
None => Self(0),
}
}
}
impl From<MaybeHertz> for Option<Hertz> {
fn from(value: MaybeHertz) -> Self {
match value {
MaybeHertz(0) => None,
MaybeHertz(val) => Some(Hertz(val)),
}
}
}
View on GitHub (pinned to 463a07b963)