embassy-rs/embassy · error

Invalid ahb5_pre for HSI/HSE sysclk: only DIV1 and DIV2 are…

Error message

Invalid ahb5_pre for HSI/HSE sysclk: only DIV1 and DIV2 are allowed

What it means

On STM32WBA, when the system clock source is HSI or HSE, the AHB5 prescaler can only be Div1 or Div2, implemented via the single HDIV5 bit. embassy-stm32's RCC init panics if config.ahb5_pre is set to any HPRE-style divider (Div4, Div8, ...) in this configuration, since the hardware has no encoding for it.

Solutions

  1. Set config.ahb5_pre to AHB5Prescaler::Div1 or AHB5Prescaler::Div2 while using HSI/HSE sysclk
  2. If you need deeper AHB5 division, switch sysclk to Sysclk::Pll1R so the full HPRE5 bits are used
  3. Pre-divide via PLL1 (feed HSI/HSE through PLL1 with a suitable divider) and clock from PLL1R instead

Example fix

// before
config.sysclk = Some(Sysclk::Hsi);
config.ahb5_pre = AHB5Prescaler::Div4; // panic
// after
config.sysclk = Some(Sysclk::Hsi);
config.ahb5_pre = AHB5Prescaler::Div1; // or Div2 only
Defensive patterns

Strategy: validation

Validate before calling

if matches!(config.sysclk, Some(Sysclk::Hsi) | Some(Sysclk::Hse)) {
    assert!(matches!(config.ahb5_pre, AHB5Prescaler::Div1 | AHB5Prescaler::Div2),
        "HSI/HSE sysclk allows only Div1/Div2 for AHB5");
}

Type guard

fn ahb5_pre_valid_for_hsi_hse(pre: &AHB5Prescaler) -> bool {
    matches!(pre, AHB5Prescaler::Div1 | AHB5Prescaler::Div2)
}

Prevention

When it happens

Trigger: rcc init with config.sysclk = Sysclk::Hsi or Sysclk::Hse and config.ahb5_pre = AHB5Prescaler::Div4 (or any divider other than Div1/Div2).

Common situations: Copying an AHB5 prescaler value from a PLL1R-based config and then switching sysclk to HSI/HSE; wanting a large AHB5 divide from the raw oscillator, which the hardware simply does not support.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at embassy-stm32/src/rcc/wba.rs:380

        w.set_sw(config.sys);
    });
    while RCC.cfgr1().read().sws() != config.sys {}

    RCC.cfgr2().modify(|w| {
        w.set_hpre(config.ahb_pre);
        w.set_ppre1(config.apb1_pre);
        w.set_ppre2(config.apb2_pre);
    });

    // Set AHB5 prescaler depending on sysclk source
    RCC.cfgr4().modify(|w| match config.sys {
        // When using HSI or HSE, use HDIV5 bit (0 = div1, 1 = div2)
        Sysclk::Hsi | Sysclk::Hse => {
            // Only Div1 and Div2 are valid for HDIV5, enforce this
            match config.ahb5_pre {
                AHB5Prescaler::Div1 => w.set_hdiv5(Hdiv5::Div1),
                AHB5Prescaler::Div2 => w.set_hdiv5(Hdiv5::Div2),
                _ => panic!("Invalid ahb5_pre for HSI/HSE sysclk: only DIV1 and DIV2 are allowed"),
            };
        }
        // When using PLL1, use HPRE5 bits [2:0]
        Sysclk::Pll1R => {
            w.set_hpre5(config.ahb5_pre);
        }
        _ => {}
    });

    let hclk5 = sys_clk / config.ahb5_pre;

    #[cfg(all(stm32wba, peri_usb_otg_hs))]
    let usb_refck = match config.mux.otghssel {
        Otghssel::Hse => hse,
        Otghssel::HseDiv2 => hse.map(|hse_val| hse_val / 2u8),
        Otghssel::Pll1P => pll1.p,
        Otghssel::Pll1PDiv2 => pll1.p.map(|pll1p_val| pll1p_val / 2u8),
    };

View on GitHub (pinned to 463a07b963)