embassy-rs/embassy · error

No stm32xx Cargo feature enabled

Error message

No stm32xx Cargo feature enabled

What it means

embassy-stm32's build script generates chip-specific code and must know which STM32 chip to target. It reads env vars starting with CARGO_FEATURE_STM32 (excluding the HRTIM feature); if none exists it panics because no chip feature was enabled.

Solutions

  1. Enable exactly one chip feature in Cargo.toml, e.g. `embassy-stm32 = { version = "0.1", features = ["stm32wb15cc"] }`
  2. Run `cargo tree -f '{p} {f}'` to verify the feature list actually reaches embassy-stm32
  3. If building a support crate on top, re-export or require the user to enable a chip feature

Example fix

# before
embassy-stm32 = "0.1"
# after
embassy-stm32 = { version = "0.1", features = ["stm32h743zi"] }
Defensive patterns

Strategy: validation

Validate before calling

# CI check
cargo tree -f '{p} {f}' | grep -E 'embassy-stm32 .*stm32' || echo 'MISSING chip feature'

Prevention

When it happens

Trigger: Adding embassy-stm32 as a dependency without any stm32xx chip feature (e.g. `embassy-stm32 = "0.1"` with empty features array) and building.

Common situations: Forgetting the features list when adding the dependency; deleting features while debugging; a template or snippet with a placeholder chip name left unfilled.

Related errors


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

Appendix: source

Thrown at embassy-stm32/build.rs:58

fn main() {
    let mut cfgs = common::CfgSet::new();
    common::set_target_cfgs(&mut cfgs);

    if std::env::var("CARGO_FEATURE_RT").is_err()
        && std::env::var("CARGO_CFG_TARGET_OS") == Ok("none".to_string())
        && std::env::var("CARGO_CFG_TARGET_ARCH") == Ok("arm".to_string())
    {
        println!("cargo::warning=Building for bare-metal ARM without `rt` feature: interrupts will loop forever.");
    }

    let chip_name = match env::vars()
        .map(|(a, _)| a)
        .filter(|x| x.starts_with("CARGO_FEATURE_STM32") && x != "CARGO_FEATURE_STM32_HRTIM")
        .get_one()
    {
        Ok(x) => x,
        Err(GetOneError::None) => panic!("No stm32xx Cargo feature enabled"),
        Err(GetOneError::Multiple) => panic!("Multiple stm32xx Cargo features enabled"),
    }
    .strip_prefix("CARGO_FEATURE_")
    .unwrap()
    .to_ascii_lowercase();

    eprintln!("chip: {chip_name}");

    for p in METADATA.peripherals {
        if let Some(r) = &p.registers {
            // The AES driver enables the peripheral's clock, which the metadata does not
            // know for the AES of some chips (STM32L0, L1, F423): no driver there.
            if r.kind == "aes" && p.rcc.is_none() {
                continue;
            }
            cfgs.enable(r.kind);
            foreach_version_cfg(&mut cfgs, r.kind, r.version, |cfgs, cfg_name| {
                cfgs.enable(cfg_name);

View on GitHub (pinned to 463a07b963)