{"record":{"id":"1dda3e85d8c47c29","repo":"embassy-rs/embassy","slug":"multiple-time-driver-xxx-cargo-features-enabled-1dda3e","errorCode":null,"errorMessage":"Multiple time-driver-xxx Cargo features enabled","messagePattern":"Multiple time-driver-xxx Cargo features enabled","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"embassy-stm32/build.rs","lineNumber":357,"sourceCode":"            )\n        }\n    }\n\n    // ========\n    // Handle time-driver-XXXX features.\n\n    let time_driver = match env::vars()\n        .map(|(a, _)| a)\n        .filter(|x| x.starts_with(\"CARGO_FEATURE_TIME_DRIVER_\"))\n        .get_one()\n    {\n        Ok(x) => Some(\n            x.strip_prefix(\"CARGO_FEATURE_TIME_DRIVER_\")\n                .unwrap()\n                .to_ascii_lowercase(),\n        ),\n        Err(GetOneError::None) => None,\n        Err(GetOneError::Multiple) => panic!(\"Multiple time-driver-xxx Cargo features enabled\"),\n    };\n\n    let time_driver_singleton: String = match time_driver.as_deref() {\n        None => String::new(),\n        Some(\"any\") => {\n            // The driver uses CC1 for the halfway-point interrupt and CC2 for the alarm,\n            // so basic and 1-channel timers are out. Rank the rest:\n            // 1. 32-bit timers first: the counter overflows far less often, so the driver\n            //    takes far fewer interrupts. Then less-featured first, to leave the more\n            //    capable timers to the user.\n            // 2. Within a category, larger TIM number first.\n            METADATA\n                .peripherals\n                .iter()\n                .filter(|p| singletons.contains(&p.name.to_string()))\n                .filter_map(|p| {\n                    let regs = p.registers.as_ref()?;\n                    if regs.kind != \"timer\" {","sourceCodeStart":339,"sourceCodeEnd":375,"githubUrl":"https://github.com/embassy-rs/embassy/blob/463a07b963419a1bfe61d5d597c44acb810afb8b/embassy-stm32/build.rs#L339-L375","documentation":"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.","triggerScenarios":"Enabling two or more time-driver features simultaneously (e.g. time-driver-tim2 + time-driver-tim3, or one of them plus time-driver-any).","commonSituations":"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.","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"],"exampleFix":"# before\nfeatures = [\"stm32f103c8\", \"time-driver-tim2\", \"time-driver-tim3\"]\n# after\nfeatures = [\"stm32f103c8\", \"time-driver-any\"]","handlingStrategy":"validation","validationCode":"# exactly one time-driver feature\nfeatures=$(cargo tree -f '{f}' -p embassy-stm32); echo \"$features\" | grep -oE 'time-driver-[a-z0-9]+' | sort -u | wc -l  # expect 1","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["build-script","cargo-features","time-driver","stm32"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"463a07b963419a1bfe61d5d597c44acb810afb8b","analyzedAt":"2026-09-10T13:38:26.660Z","contentChangedAt":"2026-09-10T13:38:26.660Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}