{"record":{"id":"cb335ed5ee43f970","repo":"embassy-rs/embassy","slug":"pll-ref-clk-out-of-range-hz","errorCode":null,"errorMessage":"pll ref_clk out of range: {} hz","messagePattern":"pll ref_clk out of range: (.+?) hz","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"embassy-stm32/src/rcc/h.rs","lineNumber":976,"sourceCode":"    RCC.pllcfgr(num).write(|w| w.set_divm(PllPreDiv::from_bits(0)));\n}\n\nfn init_pll(num: usize, config: Pll, input: &PllInput) -> PllOutput {\n    let in_clk = match config.source {\n        PllSource::Disable => panic!(\"must not set PllSource::Disable\"),\n        PllSource::Hsi => unwrap!(input.hsi),\n        PllSource::Hse => unwrap!(input.hse),\n        PllSource::Csi => unwrap!(input.csi),\n    };\n\n    let ref_clk = in_clk / config.prediv as u32;\n\n    let ref_range = match ref_clk.0 {\n        ..=1_999_999 => Pllrge::Range1,\n        ..=3_999_999 => Pllrge::Range2,\n        ..=7_999_999 => Pllrge::Range4,\n        ..=16_000_000 => Pllrge::Range8,\n        x => panic!(\"pll ref_clk out of range: {} hz\", x),\n    };\n\n    // The smaller range (150 to 420 MHz) must\n    // be chosen when the reference clock frequency is lower than 2 MHz.\n    let wide_allowed = ref_range != Pllrge::Range1;\n\n    #[cfg(any(stm32h743, stm32h730))]\n    let vco_clk = match config.fracn {\n        Some(fracn) => {\n            Hertz::hz((ref_clk.0 as f32 * ((config.mul.to_bits() + 1) as f32 + (fracn as f32 / 8192.0))) as u32)\n        }\n        None => ref_clk * config.mul,\n    };\n    #[cfg(not(any(stm32h743, stm32h730)))]\n    let vco_clk = ref_clk * config.mul;\n\n    let vco_range = if VCO_RANGE.contains(&vco_clk) {\n        Pllvcosel::MediumVco","sourceCodeStart":958,"sourceCodeEnd":994,"githubUrl":"https://github.com/embassy-rs/embassy/blob/463a07b963419a1bfe61d5d597c44acb810afb8b/embassy-stm32/src/rcc/h.rs#L958-L994","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n// 48 MHz HSI, prediv Div1 -> ref_clk 48 MHz -> panic\nlet pll = Pll { source: PllSource::Hsi, prediv: PllPreDiv::Div1, ..Default::default() };\n// after\nlet pll = Pll { source: PllSource::Hsi, prediv: PllPreDiv::Div4, ..Default::default() }; // ref_clk = 12 MHz","handlingStrategy":"validation","validationCode":"let ref_hz = in_clk.0 / pll.prediv as u32;\nassert!(ref_hz <= 16_000_000, \"pll ref_clk {} Hz out of range, increase prediv\", ref_hz);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["rust","embedded","rcc","pll","frequency"],"backgroundTag":"value-out-of-range","analyzedSha":"463a07b963419a1bfe61d5d597c44acb810afb8b","analyzedAt":"2026-09-10T13:38:26.660Z","contentChangedAt":"2026-09-10T13:38:26.660Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}