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

  1. Pass None for the optional frequency instead of Some(Hertz(0)).
  2. Fix the frequency computation so a real nonzero value is produced (check HSE crystal value / divisor math).
  3. 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

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)