{"record":{"id":"729ad0f0f1db5a89","repo":"embassy-rs/embassy","slug":"when-the-hse-is-used-as-cpu-system-bus-clock-or-cl","errorCode":null,"errorMessage":"When the HSE is used as cpu/system bus clock or clock source for any PLL, it is not allowed to be disabled","messagePattern":"When the HSE is used as cpu/system bus clock or clock source for any PLL, it is not allowed to be disabled","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"embassy-stm32/src/rcc/n6.rs","lineNumber":937,"sourceCode":"                    w.set_hsebyp(true);\n                    w.set_hseext(Hseext::Digital);\n                });\n            }\n        }\n        RCC.csr().write(|w| w.set_hseons(true));\n\n        // wait until the hse is ready\n        while !RCC.sr().read().hserdy() {}\n\n        Some(hse.freq)\n    } else if cpu_src == Cpusws::Hse\n        || sys_src == Syssws::Hse\n        || (pll1_src == Pllsel::Hse && rcc_sr.pllrdy(0))\n        || (pll2_src == Pllsel::Hse && rcc_sr.pllrdy(1))\n        || (pll3_src == Pllsel::Hse && rcc_sr.pllrdy(2))\n        || (pll4_src == Pllsel::Hse && rcc_sr.pllrdy(3))\n    {\n        panic!(\n            \"When the HSE is used as cpu/system bus clock or clock source for any PLL, it is not allowed to be disabled\"\n        );\n    } else {\n        debug!(\"HSE off\");\n\n        RCC.ccr().write(|w| w.set_hseonc(true));\n        RCC.hsecfgr().modify(|w| {\n            w.set_hseext(Hseext::Analog);\n            w.set_hsebyp(false);\n        });\n\n        // wait until the hse is disabled\n        while RCC.sr().read().hserdy() {}\n\n        None\n    };\n    // hse rtc configuration\n    let hse_rtc = hse.map(|freq| freq / (RCC.ccipr7().read().rtcpre().to_bits() + 1));","sourceCodeStart":919,"sourceCodeEnd":955,"githubUrl":"https://github.com/embassy-rs/embassy/blob/463a07b963419a1bfe61d5d597c44acb810afb8b/embassy-stm32/src/rcc/n6.rs#L919-L955","documentation":"embassy-stm32's HSE disable path for STM32N6 checks whether HSE is still in use as the cpu/system bus clock or as the input of any running PLL (pllrdy). If so, hardware rules forbid turning HSE off, and the driver panics instead of killing the active clock tree.","triggerScenarios":"Calling the HSE-off code path (e.g. deinit/low-power entry that disables HSE) while: sys clock source is HSE, or any of PLL1..PLL4 is running (pllrdy set) with HSE selected as its input.","commonSituations":"Entering Stop/standby-style low-power code that unconditionally disables HSE; runtime reconfiguration switching sysclk but leaving PLLs clocked from HSE; dropping an RCC config that assumed PLLs were already off.","solutions":["Switch sysclk to another source and disable/stop all PLLs using HSE before disabling HSE","Reorder the shutdown sequence: stop PLL1-4 first (wait pllrdy clear), then turn off HSE","If HSE must keep running, skip the HSE-disable step"],"exampleFix":"// before\ndisable_hse(); // PLL1 still running off HSE\n// after\nstop_pll(0); // clear PL1ON, wait PLL1RDY == 0\nswitch_sysclk_to_hsi();\ndisable_hse();","handlingStrategy":"validation","validationCode":"fn hse_in_use() -> bool {\n    // true if sysclk is HSE or any ready PLL is fed by HSE\n    sysclk_is(Syssws::Hse) || (0..4).any(|n| pll_ready(n) && pll_source(n) == Pllsel::Hse)\n}\nassert!(!hse_in_use(), \"stop PLLs / switch sysclk before disabling HSE\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Stop all PLLs and wait for pllrdy to clear before disabling their source oscillator","Switch sysclk to an independent source first","Document the shutdown ordering: PLLs -> sysclk -> oscillators"],"tags":["rust","embedded","rcc","hse","stm32n6","clock-config"],"backgroundTag":"conflicting-config-options","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"}