{"record":{"id":"4dfaf0da55ca6d40","repo":"embassy-rs/embassy","slug":"pll-source-is-not-ready","errorCode":null,"errorMessage":"PLL source is not ready","messagePattern":"PLL source is not ready","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"embassy-stm32/src/rcc/n6.rs","lineNumber":845,"sourceCode":"            // enable pll post divider output\n            cfgr3.modify(|w| {\n                w.set_pllmodssrst(true);\n                w.set_pllpdiven(true);\n            });\n            // enable the pll\n            debug!(\"PLL{}: enabling\", pll_index + 1);\n            RCC.csr().write(|w| w.set_pllons(pll_index, true));\n            // wait until ready\n            debug!(\"PLL{}: waiting for ready\", pll_index + 1);\n            while !RCC.sr().read().pllrdy(pll_index) {}\n            debug!(\"PLL{}: ready\", pll_index + 1);\n\n            pll_output(pll_config, input)\n        }\n        Some(Pll::Bypass { source }) => {\n            // check if source is ready\n            if !pll_source_ready(source.to_bits()) {\n                panic!(\"PLL source is not ready\")\n            }\n\n            // ensure pll is disabled\n            RCC.ccr().write(|w| w.set_pllonc(pll_index, true));\n            while RCC.sr().read().pllrdy(pll_index) {}\n\n            cfgr1.modify(|w| {\n                w.set_pllbyp(true);\n                w.set_pllsel(source);\n            });\n\n            pll_output(pll_config, input)\n        }\n        None => {\n            disable_pll(pll_index);\n\n            PllOutput::default()\n        }","sourceCodeStart":827,"sourceCodeEnd":863,"githubUrl":"https://github.com/embassy-rs/embassy/blob/463a07b963419a1bfe61d5d597c44acb810afb8b/embassy-stm32/src/rcc/n6.rs#L827-L863","documentation":"When enabling or reconfiguring a PLL on STM32N6, embassy-stm32 first verifies the chosen PLL input source (via pll_source_ready, which reads the source oscillator's ready flag in RCC.sr) is actually running. If the source oscillator is not ready it panics rather than waiting forever on a PLL that can never lock.","triggerScenarios":"init_config with a Pll::DivP or Pll::Bypass whose source oscillator (HSI/MSI/HSE) has not been enabled or has not stabilized when the PLL is configured — e.g. HSE given in config but its crystal/enable bits not set, or PLL::Bypass { source: Hse } while HSE is disabled.","commonSituations":"Requesting a PLL fed by HSE while the board has no HSE crystal or the HSE config was omitted; MSI/HSI turned off in the same config while still used as PLL input; very early init before oscillator startup.","solutions":["Enable and configure the PLL's source oscillator in the same rcc config (e.g. config.hse = Some(Hse...)) so it is started before the PLL","Or choose a different, already-enabled PLL source (HSI/MSI)","Check the board actually has the oscillator (HSE crystal) the config references"],"exampleFix":"// before\nconfig.pll1 = Some(Pll::DivP { source: Pllsel::Hse, .. }); // HSE not enabled\n// after\nconfig.hse = Some(Hse { freq: Megahertz::new(48), mode: HseMode::Oscillator });\nconfig.pll1 = Some(Pll::DivP { source: Pllsel::Hse, .. });","handlingStrategy":"validation","validationCode":"// before enabling a PLL on HSE, confirm HSE is on and ready\nlet sr = unsafe { (*stm32_metapac::RCC::ptr()).sr().read() };\nassert!(sr.hserdy(), \"enable HSE in rcc config before using it as PLL source\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always configure the PLL's source oscillator in the same rcc config","Verify the board physically has the HSE crystal if your config uses HSE","Check pll_source_ready semantics: the source must already be running, init will not start it for the PLL"],"tags":["rust","embedded","rcc","pll","stm32n6","clock-config"],"backgroundTag":"invalid-state-transition","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"}