embassy-rs/embassy · error
Multiple time-driver-xxx Cargo features enabled
Error message
Multiple time-driver-xxx Cargo features enabled
What it means
embassy-stm32 selects its time-driver timer via Cargo features 'time-driver-timX'/'time-driver-any'. The build script reads CARGO_FEATURE_TIME_DRIVER_* env vars and panics if more than one is set, because only one timer driver can be compiled in.
Solutions
- Keep exactly one time-driver-* feature enabled (use 'time-driver-any' if you have no specific timer requirement)
- Remove the extra time-driver features from Cargo.toml
- Check `cargo tree -f '{p} {f}'` to find which crate unifies in the second time-driver feature
Example fix
# before features = ["stm32f103c8", "time-driver-tim2", "time-driver-tim3"] # after features = ["stm32f103c8", "time-driver-any"]
Defensive patterns
Strategy: validation
Validate before calling
# exactly one time-driver feature
features=$(cargo tree -f '{f}' -p embassy-stm32); echo "$features" | grep -oE 'time-driver-[a-z0-9]+' | sort -u | wc -l # expect 1 Prevention
- Use time-driver-any unless a specific timer is needed
- Never list two time-driver-* features
- CI check via cargo tree for duplicated time drivers
When it happens
Trigger: Enabling two or more time-driver features simultaneously (e.g. time-driver-tim2 + time-driver-tim3, or one of them plus time-driver-any).
Common situations: Cargo feature unification from another crate in the workspace enabling a different time driver; manually adding a second time-driver feature 'to be safe'; merging Cargo.toml changes from two branches.
Related errors
- time-driver-any requested, but the chip doesn't have a TIM…
- Multiple time-driver-xxx Cargo features enabled
- unknown time_driver
- Multiple stm32xx Cargo features enabled
- No stm32xx Cargo feature enabled
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/1dda3e85d8c47c29.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-stm32/build.rs:357
)
}
}
// ========
// Handle time-driver-XXXX features.
let time_driver = match env::vars()
.map(|(a, _)| a)
.filter(|x| x.starts_with("CARGO_FEATURE_TIME_DRIVER_"))
.get_one()
{
Ok(x) => Some(
x.strip_prefix("CARGO_FEATURE_TIME_DRIVER_")
.unwrap()
.to_ascii_lowercase(),
),
Err(GetOneError::None) => None,
Err(GetOneError::Multiple) => panic!("Multiple time-driver-xxx Cargo features enabled"),
};
let time_driver_singleton: String = match time_driver.as_deref() {
None => String::new(),
Some("any") => {
// The driver uses CC1 for the halfway-point interrupt and CC2 for the alarm,
// so basic and 1-channel timers are out. Rank the rest:
// 1. 32-bit timers first: the counter overflows far less often, so the driver
// takes far fewer interrupts. Then less-featured first, to leave the more
// capable timers to the user.
// 2. Within a category, larger TIM number first.
METADATA
.peripherals
.iter()
.filter(|p| singletons.contains(&p.name.to_string()))
.filter_map(|p| {
let regs = p.registers.as_ref()?;
if regs.kind != "timer" {View on GitHub (pinned to 463a07b963)