embassy-rs/embassy · error

must not select PLL source as DISABLE

Error message

must not select PLL source as DISABLE

What it means

During PLL initialization, embassy-stm32 requires the PLL clock source to be an actual oscillator (HSE, HSI, or MSI). `PllSource::Disable` exists only as a 'no PLL' placeholder, so selecting it as the source of a configured PLL is a configuration contradiction and the library panics via `panic!("must not select PLL source as DISABLE")`.

Solutions

  1. Set `pll.source` to `PllSource::Hse`, `PllSource::Hsi`, or `PllSource::Msi` in the rcc config.
  2. If no PLL is wanted, remove the `pll` field entirely (set it to None / omit it) instead of leaving source as Disable.
  3. If using HSE/HIS/MSI as source, ensure the corresponding oscillator is configured and enabled in the same rcc config (hse: Some(...), hsi: true, or msi config), since the source frequency is `unwrap!`ed.

Example fix

// before
pll: Some(PllConfig {
    source: PllSource::Disable,
    prediv: PllPreDiv::DIV1,
    mul: PllMul::MUL9,
    ..Default::default()
}),
// after
pll: Some(PllConfig {
    source: PllSource::Hse,
    prediv: PllPreDiv::DIV1,
    mul: PllMul::MUL9,
    ..Default::default()
}),
Defensive patterns

Strategy: validation

Validate before calling

if let Some(pll) = &config.rcc.pll {
    assert!(pll.source != PllSource::Disable, "rcc.pll.source must be Hse/Hsi/Msi, not Disable");
}

Type guard

fn pll_source_valid(pll: &PllConfig) -> bool {
    !matches!(pll.source, PllSource::Disable)
}

Prevention

When it happens

Trigger: Calling `init()` / `Config::default()` with an `rcc.pll` Some(PllConfig) whose `source` field is `PllSource::Disable`, i.e. configuring PLL dividers/mul but leaving the source at its default `Disable` value.

Common situations: Copying a PLL config snippet but forgetting to set `.source` to Hse/Hsi/Msi; constructing PllConfig programmatically with Default derive; refactoring board configs and dropping the source assignment.

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/1c3cb3dbc94cbb8c. Report an issue: GitHub.

Appendix: source

Thrown at embassy-stm32/src/rcc/l.rs:715

        pub msi: Option<Hertz>,
    }

    #[allow(unused)]
    #[derive(Default)]
    pub(super) struct PllOutput {
        pub p: Option<Hertz>,
        pub q: Option<Hertz>,
        pub r: Option<Hertz>,
    }

    pub(super) fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> PllOutput {
        // Disable PLL
        pll_enable(instance, false);

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

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

        let vco_freq = pll_src / pll.prediv * pll.mul;

        let p = pll.divp.map(|div| vco_freq / div);
        let q = pll.divq.map(|div| vco_freq / div);
        let r = pll.divr.map(|div| vco_freq / div);

        #[cfg(stm32l5)]
        if instance == PllInstance::Pllsai2 {
            assert!(q.is_none(), "PLLSAI2_Q is not available on L5");
            assert!(r.is_none(), "PLLSAI2_R is not available on L5");
        }

        macro_rules! write_fields {

View on GitHub (pinned to 463a07b963)