embassy-rs/embassy · error
must not set PllSource::Disable
Error message
must not set PllSource::Disable
What it means
init_pll is only called for PLLs the user actually configured, and PllSource::Disable means 'this PLL is off'. Passing Disable inside a Pll config is contradictory — there is no input clock to divide — so init_pll panics immediately. Every configured PLL must give a real source: Hsi, Hse or Csi.
Solutions
- Remove the PLL from the Config (set the field to None) if it should be disabled — do not configure it with PllSource::Disable.
- Set source to PllSource::Hsi, Hse or Csi (whichever the board provides) in the Pll struct.
- Check constructors/builders for a default source of Disable being left in place.
Example fix
// before
let config = Config {
pll1: Some(Pll { source: PllSource::Disable, prediv: PllPreDiv::Div1, ..Default::default() }),
..Default::default()
};
// after
let config = Config {
pll1: Some(Pll { source: PllSource::Hse, prediv: PllPreDiv::Div1, ..Default::default() }),
..Default::default()
}; Defensive patterns
Strategy: validation
Validate before calling
fn configured(pll: &Option<Pll>) -> bool {
pll.as_ref().map_or(true, |p| p.source != PllSource::Disable)
}
assert!(configured(&config.pll1) && configured(&config.pll2) && configured(&config.pll3)); Prevention
- Use None (not PllSource::Disable) to express 'PLL off'.
- Audit builders/default() paths that may seed source: Disable into configured PLLs.
- Search your config-construction code for PllSource::Disable and remove those entries.
When it happens
Trigger: Constructing a Pll { source: PllSource::Disable, .. } and putting it into config.pll1/pll2/pll3 on H7/H5/WL-family targets, so init -> init_pll receives Disable.
Common situations: Building PLL configs programmatically where a default() starts with Disable and was never replaced; copy-pasting a 'disabled' placeholder struct into the config; generic code that fills Config pll fields unconditionally.
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
- must not select PLL source as DISABLE
- if PLL source is HSI, PLL prediv must be 2.
- if PLL source is PLL2, Config::pll2 must also be set.
- Source must be equal across all enabled PLLs.
- pll ref_clk out of range
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/289f89603867e98b.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-stm32/src/rcc/h.rs:963
#[allow(dead_code)]
t: Option<Hertz>,
}
fn disable_pll(num: usize) {
// Stop PLL
RCC.cr().modify(|w| w.set_pllon(num, false));
while RCC.cr().read().pllrdy(num) {}
// "To save power when PLL1 is not used, the value of PLL1M must be set to 0.""
#[cfg(any(stm32h7, stm32h7rs))]
RCC.pllckselr().write(|w| w.set_divm(num, PllPreDiv::from_bits(0)));
#[cfg(stm32h5)]
RCC.pllcfgr(num).write(|w| w.set_divm(PllPreDiv::from_bits(0)));
}
fn init_pll(num: usize, config: Pll, input: &PllInput) -> PllOutput {
let in_clk = match config.source {
PllSource::Disable => panic!("must not set PllSource::Disable"),
PllSource::Hsi => unwrap!(input.hsi),
PllSource::Hse => unwrap!(input.hse),
PllSource::Csi => unwrap!(input.csi),
};
let ref_clk = in_clk / config.prediv as u32;
let ref_range = match ref_clk.0 {
..=1_999_999 => Pllrge::Range1,
..=3_999_999 => Pllrge::Range2,
..=7_999_999 => Pllrge::Range4,
..=16_000_000 => Pllrge::Range8,
x => panic!("pll ref_clk out of range: {} hz", x),
};
// The smaller range (150 to 420 MHz) must
// be chosen when the reference clock frequency is lower than 2 MHz.
let wide_allowed = ref_range != Pllrge::Range1;View on GitHub (pinned to 463a07b963)