diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 1ef92430f..87f9083b3 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -59,7 +59,7 @@ sdio-host = "0.5.0" embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } critical-section = "1.1" atomic-polyfill = "1.0.1" -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-735cab337aad6161f3d6bcf3e49cd1f034bc3130" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-8ee2862086886cd8ebaf5fd5e3bd6cfbe5baa840" } vcell = "0.1.3" bxcan = "0.7.0" nb = "1.0.0" @@ -78,7 +78,8 @@ critical-section = { version = "1.1", features = ["std"] } [build-dependencies] proc-macro2 = "1.0.36" quote = "1.0.15" -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-735cab337aad6161f3d6bcf3e49cd1f034bc3130", default-features = false, features = ["metadata"]} +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-8ee2862086886cd8ebaf5fd5e3bd6cfbe5baa840", default-features = false, features = ["metadata"]} + [features] default = ["rt"] @@ -134,6 +135,22 @@ time-driver-tim12 = ["_time-driver"] time-driver-tim15 = ["_time-driver"] +#! ## Analog Switch Pins (Pxy_C) on STM32H7 series +#! Get `PXY` and `PXY_C` singletons. Digital impls are on `PXY`, Analog impls are on `PXY_C` +#! If disabled, you get only the `PXY` singleton. It has both digital and analog impls. + +## Split PA0 +split-pa0 = ["_split-pins-enabled"] +## Split PA1 +split-pa1 = ["_split-pins-enabled"] +## Split PC2 +split-pc2 = ["_split-pins-enabled"] +## Split PC3 +split-pc3 = ["_split-pins-enabled"] + +## internal use only +_split-pins-enabled = [] + #! ## Chip-selection features #! Select your chip by specifying the model as a feature, e.g. `stm32c011d6`. #! Check the `Cargo.toml` for the latest list of supported chips. diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index ccc9210df..2c349e55e 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -81,6 +81,59 @@ fn main() { singletons.push(c.name.to_string()); } + let mut pin_set = std::collections::HashSet::new(); + for p in METADATA.peripherals { + for pin in p.pins { + pin_set.insert(pin.pin); + } + } + + struct SplitFeature { + feature_name: String, + pin_name_with_c: String, + pin_name_without_c: String, + } + + // Extra analog switch pins available on most H7 chips + let split_features: Vec = vec![ + #[cfg(feature = "split-pa0")] + SplitFeature { + feature_name: "split-pa0".to_string(), + pin_name_with_c: "PA0_C".to_string(), + pin_name_without_c: "PA0".to_string(), + }, + #[cfg(feature = "split-pa1")] + SplitFeature { + feature_name: "split-pa1".to_string(), + pin_name_with_c: "PA1_C".to_string(), + pin_name_without_c: "PA1".to_string(), + }, + #[cfg(feature = "split-pc2")] + SplitFeature { + feature_name: "split-pc2".to_string(), + pin_name_with_c: "PC2_C".to_string(), + pin_name_without_c: "PC2".to_string(), + }, + #[cfg(feature = "split-pc3")] + SplitFeature { + feature_name: "split-pc3".to_string(), + pin_name_with_c: "PC3_C".to_string(), + pin_name_without_c: "PC3".to_string(), + }, + ]; + + for split_feature in &split_features { + if pin_set.contains(split_feature.pin_name_with_c.as_str()) { + singletons.push(split_feature.pin_name_with_c.clone()); + } else { + panic!( + "'{}' feature invalid for this chip! No pin '{}' found.\n + Found pins: {:#?}", + split_feature.feature_name, split_feature.pin_name_with_c, pin_set + ) + } + } + // ======== // Handle time-driver-XXXX features. @@ -679,7 +732,16 @@ fn main() { let key = (regs.kind, pin.signal); if let Some(tr) = signals.get(&key) { let mut peri = format_ident!("{}", p.name); - let pin_name = format_ident!("{}", pin.pin); + + let pin_name = { + // If we encounter a _C pin but the split_feature for this pin is not enabled, skip it + if pin.pin.ends_with("_C") && !split_features.iter().any(|x| x.pin_name_with_c == pin.pin) { + continue; + } + + format_ident!("{}", pin.pin) + }; + let af = pin.af.unwrap_or(0); // MCO is special @@ -716,7 +778,13 @@ fn main() { } let peri = format_ident!("{}", p.name); - let pin_name = format_ident!("{}", pin.pin); + let pin_name = { + // If we encounter a _C pin but the split_feature for this pin is not enabled, skip it + if pin.pin.ends_with("_C") && !split_features.iter().any(|x| x.pin_name_with_c == pin.pin) { + continue; + } + format_ident!("{}", pin.pin) + }; // H7 has differential voltage measurements let ch: Option = if pin.signal.starts_with("INP") { @@ -866,13 +934,31 @@ fn main() { for pin_num in 0u32..16 { let pin_name = format!("P{}{}", port_letter, pin_num); + pins_table.push(vec![ - pin_name, + pin_name.clone(), p.name.to_string(), port_num.to_string(), pin_num.to_string(), format!("EXTI{}", pin_num), ]); + + // If we have the split pins, we need to do a little extra work: + // Add the "_C" variant to the table. The solution is not optimal, though. + // Adding them only when the corresponding GPIOx also appears. + // This should avoid unintended side-effects as much as possible. + #[cfg(feature = "_split-pins-enabled")] + for split_feature in &split_features { + if split_feature.pin_name_without_c == pin_name { + pins_table.push(vec![ + split_feature.pin_name_with_c.to_string(), + p.name.to_string(), + port_num.to_string(), + pin_num.to_string(), + format!("EXTI{}", pin_num), + ]); + } + } } } diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 2718c96da..9dd2f6163 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -191,6 +191,18 @@ pub fn init(config: Config) -> Peripherals { peripherals::FLASH::enable(); unsafe { + #[cfg(feature = "_split-pins-enabled")] + crate::pac::SYSCFG.pmcr().modify(|pmcr| { + #[cfg(feature = "split-pa0")] + pmcr.set_pa0so(true); + #[cfg(feature = "split-pa1")] + pmcr.set_pa1so(true); + #[cfg(feature = "split-pc2")] + pmcr.set_pc2so(true); + #[cfg(feature = "split-pc3")] + pmcr.set_pc3so(true); + }); + gpio::init(); dma::init( #[cfg(bdma)]