embassy-rs/embassy · error

IC2 is not ready to be selected as system clock source…

Error message

IC2 is not ready to be selected as system clock source (make sure that IC6 and IC11 were configured as well)

What it means

This panic comes from embassy-stm32's STM32N6 RCC init when the requested system clock source is IC2 (an internal clock multiplexer output). IC2 is fed by IC6 and IC11, so the driver refuses to switch sysclk to IC2 unless intermediate clock units IC6 and IC11 have already been configured and enabled (ic_enabled checks). It fails fast rather than switching to a dead clock.

Solutions

  1. Configure IC6 and IC11 in the rcc config so they feed IC2 before selecting SysClk::Ic2 as the system clock source
  2. Or select a directly-ready source (SysClk::Hsi, SysClk::Msi, SysClk::Hse) instead of IC2
  3. Ensure the oscillator feeding the IC chain (e.g. PLL or HSE) is enabled first so ic_enabled(6)/ic_enabled(11) return true

Example fix

// before
config.sys = SysClk::Ic2; // IC6/IC11 not configured
// after
config.ic6 = Some(Ic6Config::from(pll1_p_output));
config.ic11 = Some(Ic11Config::from(hse_output));
config.sys = SysClk::Ic2;
Defensive patterns

Strategy: validation

Validate before calling

// STM32N6, before init with SysClk::Ic2
fn ic2_chain_ready() -> bool {
    let sr = unsafe { (*stm32_metapac::RCC::ptr()).sr().read() };
    // IC2 requires IC6 and IC11 enabled
    sr.ic6rdy() && sr.ic11rdy()
}
assert!(ic2_chain_ready(), "configure IC6/IC11 before selecting IC2 as sysclk");

Type guard

fn is_ic2_configurable(cfg: &Config) -> bool {
    cfg.ic6.is_some() && cfg.ic11.is_some()
}

Try / catch

// panics are fatal on embedded; wrap init in a halting hook instead
def_modinit_handler(|| {
    // log via UART/RTT, then safe-reset
    system_reset();
});

Prevention

When it happens

Trigger: Calling rcc init/init_config with SysClk::Ic2 while RCC.sr() reports IC6 or IC11 (or IC2 itself) not enabled — i.e. the IC6/IC11 intermediate clock units were never set up in the same clock tree configuration.

Common situations: Hand-writing a clock tree config for STM32N6 and selecting IC2 as sysclk without configuring the full IC6->IC11 chain; copying a clock config from another STM32 family where IC2 did not need intermediate units; typos or partially filled ClockTree structs in generated config code.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10). Data as JSON: /api/errors/00ec56b918fcdb54. Report an issue: GitHub.

Appendix: source

Thrown at embassy-stm32/src/rcc/n6.rs:373

        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);
        }
        if config.apb1 < w.ppre1() {

View on GitHub (pinned to 463a07b963)