embassy-rs/embassy · error

must not select RESERVED_1 source as DISABLE

Error message

must not select RESERVED_1 source as DISABLE

What it means

init_pll panics when the PLL source is PllSource::_RESERVED_1, a reserved value in the RCC register enum. Reserved register encodings have no defined behavior per the reference manual, so the driver refuses to program them.

Solutions

  1. Set pll.source to PllSource::Hse or PllSource::Hsi.
  2. Do not construct the reserved variant directly; only obtain source values from the documented PllSource variants.
  3. Regenerate or fix any code-generation that emits _RESERVED_* variants into user configs.

Example fix

// before
source: PllSource::_RESERVED_1,
// after
source: PllSource::Hsi,
Defensive patterns

Strategy: validation

Validate before calling

assert!(!matches!(pll.source, PllSource::_RESERVED_1), "PLL source must not be reserved");

Type guard

fn pll_source_defined(s: PllSource) -> bool { matches!(s, PllSource::Hse | PllSource::Hsi | PllSource::Disable) }

Prevention

When it happens

Trigger: Constructing a PllConfig with pll.source set to PllSource::_RESERVED_1 (either manually or via an unsafe/transmuted value) and passing it through rcc init.

Common situations: Fiddling with register-level enums copied from reference manuals; type-punned or bit-converted configs; corrupted/incorrect generated code.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10). Data as JSON: /api/errors/776c5c977085459e. Report an issue: GitHub.

Appendix: source

Thrown at embassy-stm32/src/rcc/wba.rs:497

    pub r: Option<Hertz>,
}

fn pll_enable(enabled: bool) {
    RCC.cr().modify(|w| w.set_pllon(enabled));
    while RCC.cr().read().pllrdy() != enabled {}
}

fn init_pll(config: Option<Pll>, input: &PllInput, voltage_range: VoltageScale) -> PllOutput {
    // Disable PLL
    pll_enable(false);

    let Some(pll) = config else { return PllOutput::default() };

    let pre_src_freq = match pll.source {
        PllSource::Disable => panic!("must not select PLL source as DISABLE"),
        PllSource::Hse => unwrap!(input.hse),
        PllSource::Hsi => unwrap!(input.hsi),
        PllSource::_RESERVED_1 => panic!("must not select RESERVED_1 source as DISABLE"),
    };

    // Only divide by the HSE prescaler when the PLL source is HSE
    let src_freq = match pll.source {
        PllSource::Hse => {
            // read the prescaler bits and divide
            let hsepre = RCC.cr().read().hsepre();
            pre_src_freq / hsepre
        }
        _ => pre_src_freq,
    };

    // Calculate the reference clock, which is the source divided by m
    let ref_freq = src_freq / pll.prediv;
    // Check limits per RM0515 § 12.4.3
    assert!(Hertz::mhz(4) <= ref_freq && ref_freq <= Hertz::mhz(16));

    // Check PLL clocks per RM0515 § 12.4.5

View on GitHub (pinned to 463a07b963)