embassy-rs/embassy · error
Multiple stm32xx Cargo features enabled
Error message
Multiple stm32xx Cargo features enabled
What it means
embassy-stm32's build script requires exactly one chip target: it collects env vars starting with CARGO_FEATURE_STM32 (excluding CARGO_FEATURE_STM32_HRTIM) and asserts a single one. Multiple chip features cannot be unified into one generated codebase, so it panics.
Solutions
- Keep exactly one stm32xx chip feature enabled per build (fix Cargo.toml features array)
- Inspect `cargo tree -f '{p} {f}'` to find which crate pulls in the second chip feature and remove it
- Split multi-board projects into separate packages or use a Cargo workspace where each package has its own single chip feature
Example fix
# before features = ["stm32f103c8", "stm32f411ce"] # after features = ["stm32f103c8"]
Defensive patterns
Strategy: validation
Validate before calling
# ensure a single chip feature per build
cargo tree -f '{p} {f}' | grep -oE 'stm32[a-z0-9]+' | sort -u | wc -l # expect 1 Prevention
- One chip feature per package
- Separate packages per board in a workspace
- CI check for duplicated chip features via cargo tree
When it happens
Trigger: Cargo feature unification enables two chip features (e.g. stm32f103c8 + stm32f411ce) at once — usually because two crates in the same build each request a different chip, or a Cargo.toml lists two chip features.
Common situations: Same package used by binaries for different boards in one workspace; listing two chip features 'to be safe'; a dependency enabling a second chip feature.
Related errors
- Multiple stm32xx Cargo features enabled
- No stm32xx Cargo feature enabled
- No mspm0xx/mspsxx Cargo feature enabled
- Multiple mspm0xx/mspsxx Cargo features enabled
- Both 'single-bank' and 'dual-bank' features enabled
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/224ace08ebfd44ef.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-stm32/build.rs:59
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)