embassy-rs/embassy · error
HSE is not ready to be selected as system clock source
Error message
HSE is not ready to be selected as system clock source
What it means
On STM32N6, before switching the system clock to HSE, the code checks `RCC.sr().hserdy()`. If the high-speed external oscillator is not ready, selecting it as the system bus clock source would clock the bus from a dead source, so the library panics.
Solutions
- Configure HSE (`hse: Some(Hse { mode, freq, ... })`) so it is started and awaited ready before the switch.
- If no HSE hardware exists, switch `config.sys` to Hsi, Msi, or Ic2.
- Check hardware (crystal, load capacitors, external clock present if bypass) so `hserdy` can set.
Example fix
// before
rcc: RccConfig { sys: SysClk::Hse, ..Default::default() }, // hse not configured
// after
rcc: RccConfig {
hse: Some(Hse { freq: MegaHertz::new(48), mode: HseMode::Bypass }),
sys: SysClk::Hse,
..Default::default()
}, Defensive patterns
Strategy: validation
Validate before calling
if config.rcc.sys == SysClk::Hse && config.rcc.hse.is_none() {
panic!("SysClk::Hse requires an hse config in rcc");
} Type guard
fn hse_ready_for_sys(rcc: &RccConfig) -> bool {
rcc.sys != SysClk::Hse || rcc.hse.is_some()
} Prevention
- Configure hse (mode + frequency) before selecting SysClk::Hse.
- Verify HSE hardware (crystal, load caps, bypass clock source) on the real board.
- If HSE is only intended to feed a PLL, don't also switch sysclk to HSE unless it is enabled.
When it happens
Trigger: Setting `config.sys = SysClk::Hse` while `hserdy()` is false — HSE never enabled in the rcc config, wrong crystal/bypass mode, or HSE hardware startup failure (bad crystal, load caps, no external clock in bypass).
Common situations: Boards without an HSE crystal where the config still selects HSE; bypass mode mismatched with actual clock input; HSE enabled only for PLL use but sysclk switched to HSE directly in a reinit that re-disables it.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- HSE is not ready to be selected as CPU clock source
- HSI is not ready to be selected as system clock source
- MSI is not ready to be selected as system clock source
- IC source was set to PLL , but it is not currently enabled
- HSI is not ready to be selected as CPU clock source
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/cc2b73692eea066b.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-stm32/src/rcc/n6.rs:372
match config.cpu {
CpuClk::Hsi if !RCC.sr().read().hsirdy() => panic!("HSI is not ready to be selected as CPU clock source"),
CpuClk::Msi if !RCC.sr().read().msirdy() => panic!("MSI is not ready to be selected as CPU clock source"),
CpuClk::Hse if !RCC.sr().read().hserdy() => panic!("HSE is not ready to be selected as CPU clock source"),
CpuClk::Ic1 if !ic_enabled(1) => panic!("IC1 is not ready to be selected as CPU clock source"),
_ => {}
}
// set source
let cpusw = Cpusw::from_bits(config.cpu.to_bits());
RCC.cfgr().modify(|w| w.set_cpusw(cpusw));
// wait for changes to take effect
while RCC.cfgr().read().cpusws() != Cpusws::from_bits(config.cpu.to_bits()) {}
// sysclk
debug!("configuring sysclk");
match config.sys {
SysClk::Hsi if !RCC.sr().read().hsirdy() => panic!("HSI is not ready to be selected as system clock source"),
SysClk::Msi if !RCC.sr().read().msirdy() => panic!("MSI is not ready to be selected as system clock source"),
SysClk::Hse if !RCC.sr().read().hserdy() => panic!("HSE is not ready to be selected as system clock source"),
SysClk::Ic2 if !ic_enabled(2) || !ic_enabled(6) || !ic_enabled(11) => panic!(
"IC2 is not ready to be selected as system clock source (make sure that IC6 and IC11 were configured as well)"
),
_ => {}
}
// switch the system bus clock
let syssw = Syssw::from_bits(config.sys.to_bits());
RCC.cfgr().modify(|w| w.set_syssw(syssw));
// wait for changes to be applied
while RCC.cfgr().read().syssws() != Syssws::from_bits(config.sys.to_bits()) {}
// decreasing dividers
debug!("configuring decreasing pclk dividers");
RCC.cfgr2().modify(|w| {
if config.ahb < w.hpre() {
debug!(" - AHB");
w.set_hpre(config.ahb);
}View on GitHub (pinned to 463a07b963)