embassy-rs/embassy · error
time-driver-any requested, but the chip doesn't have a TIM…
Error message
time-driver-any requested, but the chip doesn't have a TIM with at least 2 capture/compare channels.
What it means
When the 'time-driver-any' feature is enabled, embassy-stm32's build script scans the chip's TIM peripherals for one with at least 2 capture/compare channels to back the internal time driver. If no such timer exists in the chip metadata, the build script panics. This is a compile-time error meaning the selected chip cannot supply a default time driver.
Solutions
- Pick an explicit time-driver timer feature (e.g. time-driver-tim2) matching a timer the chip actually has.
- Verify the selected chip's timer inventory in the datasheet / stm32-metapac.
- Use a chip variant with a standard TIM2/TIM3 if the application needs the built-in time driver.
- Provide your own time driver via embassy-time-driver instead of time-driver-any.
Example fix
# before
embassy-stm32 = { features = ["stm32wba52cg", "time-driver-any"] }
# after
embassy-stm32 = { features = ["stm32wba52cg", "time-driver-tim2"] } Defensive patterns
Strategy: validation
Validate before calling
# Verify the chip has a TIM with >=2 CC channels (e.g. TIM2/TIM3) and use an explicit driver:
# embassy-stm32 = { features = ["<chip>", "time-driver-tim2"] } Prevention
- Prefer explicit time-driver-timX features over time-driver-any on unusual chips.
- Confirm the timer exists in the chip's datasheet before selecting the feature.
- Do not put time-driver features into a shared base feature list for all targets.
When it happens
Trigger: Building with features embassy-stm32/time-driver-any on a chip whose TIM list contains no timer with >=2 CC channels (very small parts), or on a chip whose timers aren't named TIM*.
Common situations: Selecting a tiny/odd STM32 variant for a library default target; typos in the chip feature name resolving to an unsupported metapac entry; adding time-driver-any to a shared base feature set used by all targets in a workspace.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- Multiple time-driver-xxx Cargo features enabled
- 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/469ebdcb080b8dea.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-stm32/build.rs:391
.filter_map(|p| {
let regs = p.registers.as_ref()?;
if regs.kind != "timer" {
return None;
}
let category = match regs.block {
"TIM_GP32" => 0,
"TIM_2CH" => 1,
"TIM_2CH_CMP" => 2,
"TIM_GP16" => 3,
"TIM_ADV" => 4,
_ => return None,
};
let number: u32 = p.name.strip_prefix("TIM")?.parse().ok()?;
Some(((category, std::cmp::Reverse(number)), p.name))
})
.min_by_key(|(rank, _)| *rank)
.map(|(_, name)| name.to_string())
.expect("time-driver-any requested, but the chip doesn't have a TIM with at least 2 capture/compare channels.")
}
Some(x) => x.to_ascii_uppercase(),
};
let time_driver_irq_decl = if !time_driver_singleton.is_empty() {
cfgs.set(format!("time_driver_{}", time_driver_singleton.to_lowercase()), true);
let Some((p, regs)) = peripheral_map.get(time_driver_singleton.as_str()) else {
panic!("Tried to select {time_driver_singleton}, which is not available on this device");
};
// Tell the time driver how wide the timer's counter is.
if regs.kind == "timer" {
cfgs.enable(if regs.block == "TIM_GP32" {
"time_driver_32bit"
} else {
"time_driver_16bit"
});View on GitHub (pinned to 463a07b963)