embassy-rs/embassy · error
pll ref_clk out of range
Error message
pll ref_clk out of range: {} hz What it means
After the prediv divider, the PLL reference clock (ref_clk) must fall within the hardware-supported ranges: up to 16 MHz, binned into Pllrge ranges (Range1..Range8). A ref_clk above 16 MHz cannot be encoded, so init_pll panics with the offending frequency. This happens before any output-divider math, so the config is rejected outright.
Solutions
- Increase config.prediv (DIVM) so in_clk / prediv is <= 16 MHz (ideally in the 2-16 MHz sweet spot).
- Recompute pll.mul/divp/divq values after changing prediv to keep the intended output frequencies.
- Prefer a reference in 4-8 MHz (Range4) or 8-16 MHz (Range8) for typical VCO configurations.
Example fix
// before
// 48 MHz HSI, prediv Div1 -> ref_clk 48 MHz -> panic
let pll = Pll { source: PllSource::Hsi, prediv: PllPreDiv::Div1, ..Default::default() };
// after
let pll = Pll { source: PllSource::Hsi, prediv: PllPreDiv::Div4, ..Default::default() }; // ref_clk = 12 MHz Defensive patterns
Strategy: validation
Validate before calling
let ref_hz = in_clk.0 / pll.prediv as u32;
assert!(ref_hz <= 16_000_000, "pll ref_clk {} Hz out of range, increase prediv", ref_hz); Prevention
- Always set DIVM/prediv explicitly; compute it from the source frequency rather than guessing.
- Target a 2-16 MHz reference for maximum VCO flexibility.
- Recompute mul/divp after any prediv change.
When it happens
Trigger: On H7/H5/WL-family RCC init, supplying a Pll whose input frequency divided by prediv (DIVM) exceeds 16 MHz — e.g. 48 MHz HSI with prediv Div1, or a 25 MHz HSE with too small a divider.
Common situations: Forgetting to set prediv/DIVM at all on a fast source; small prediv values with a 25/48 MHz crystal or HSI; porting configs from chips where larger ref clocks were tolerated.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- pll vco_clk out of range
- 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.
- must not set PllSource::Disable
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/cb335ed5ee43f970.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-stm32/src/rcc/h.rs:976
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;
#[cfg(any(stm32h743, stm32h730))]
let vco_clk = match config.fracn {
Some(fracn) => {
Hertz::hz((ref_clk.0 as f32 * ((config.mul.to_bits() + 1) as f32 + (fracn as f32 / 8192.0))) as u32)
}
None => ref_clk * config.mul,
};
#[cfg(not(any(stm32h743, stm32h730)))]
let vco_clk = ref_clk * config.mul;
let vco_range = if VCO_RANGE.contains(&vco_clk) {
Pllvcosel::MediumVcoView on GitHub (pinned to 463a07b963)