From bd759510baed2eacb381509c3afcfe0ade547d35 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 9 Jun 2021 13:40:34 +0200 Subject: [PATCH 1/4] Generate clock peripherals for all peripherals with register block Infers clock for a peripheral using the selected clock as a prefix, in order to work with split registers --- stm32-metapac/build.rs | 78 ++++++++++++++++++++++++++++++++---------- 1 file changed, 59 insertions(+), 19 deletions(-) diff --git a/stm32-metapac/build.rs b/stm32-metapac/build.rs index 008c9eb3..4c7c0e0d 100644 --- a/stm32-metapac/build.rs +++ b/stm32-metapac/build.rs @@ -105,6 +105,30 @@ macro_rules! {} {{ .unwrap(); } +fn find_reg_for_field<'c>( + rcc: &'c ir::IR, + reg_prefix: &str, + field_name: &str, +) -> Option<(&'c str, &'c str)> { + rcc.fieldsets.iter().find_map(|(name, fieldset)| { + if name.starts_with(reg_prefix) { + fieldset + .fields + .iter() + .find_map(|field| { + if field_name == field.name { + return Some(field.name.as_str()); + } else { + None + } + }) + .map(|n| (name.as_str(), n)) + } else { + None + } + }) +} + fn main() { let dir = "../stm32-data/data"; @@ -131,6 +155,16 @@ fn main() { peripherals: Vec::new(), }; + // Load RCC register for chip + let chip_family = chip.family.to_ascii_lowercase().clone(); + let rcc_family = chip_family.strip_prefix("stm32").unwrap(); + //.strip_prefix("stm32") + //.unwrap(); + let rcc_reg_path = Path::new(&dir) + .join("registers") + .join(&format!("rcc_{}.yaml", rcc_family)); + let mut rcc: ir::IR = serde_yaml::from_reader(File::open(rcc_reg_path).unwrap()).unwrap(); + let mut peripheral_versions: HashMap = HashMap::new(); let mut pin_table: Vec> = Vec::new(); let mut interrupt_table: Vec> = Vec::new(); @@ -217,30 +251,36 @@ fn main() { }; assert_eq!(p.address, dma_base + dma_stride * dma_num); } - "spi" => { - if let Some(clock) = &p.clock { - // Workaround for APB1 register being split on some chip families. Assume - // first register until we can find a way to hint which register is used - let reg = clock.to_ascii_lowercase(); - let (enable_reg, reset_reg) = if chip.family == "STM32H7" && clock == "APB1" - { - (format!("{}lenr", reg), format!("{}lrstr", reg)) - } else if chip.family.starts_with("STM32L4") && clock == "APB1" { - (format!("{}enr1", reg), format!("{}rstr1", reg)) - } else { - (format!("{}enr", reg), format!("{}rstr", reg)) - }; - let field = name.to_ascii_lowercase(); + + _ => {} + } + + if let Some(clock) = &p.clock { + // Workaround for clock registers being split on some chip families. Assume fields are + // named after peripheral and look for first field matching and use that register. + let en = find_reg_for_field(&rcc, clock, &format!("{}EN", name)); + let rst = find_reg_for_field(&rcc, clock, &format!("{}RST", name)); + + match (en, rst) { + (Some((enable_reg, enable_field)), Some((reset_reg, reset_field))) => { peripheral_rcc_table.push(vec![ name.clone(), - enable_reg, - reset_reg, - format!("set_{}en", field), - format!("set_{}rst", field), + enable_reg.to_ascii_lowercase(), + reset_reg.to_ascii_lowercase(), + format!("set_{}", enable_field.to_ascii_lowercase()), + format!("set_{}", reset_field.to_ascii_lowercase()), ]); } + (None, Some(_)) => { + println!("Unable to find enable register for {}", name) + } + (Some(_), None) => { + println!("Unable to find reset register for {}", name) + } + (None, None) => { + println!("Unable to find enable and reset register for {}", name) + } } - _ => {} } } From a92d6a372bea6b111fa1d2023b328942bae19e5f Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 9 Jun 2021 13:50:04 +0200 Subject: [PATCH 2/4] Cleanup and fix l4s --- stm32-metapac/build.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/stm32-metapac/build.rs b/stm32-metapac/build.rs index 4c7c0e0d..fe505c87 100644 --- a/stm32-metapac/build.rs +++ b/stm32-metapac/build.rs @@ -156,14 +156,12 @@ fn main() { }; // Load RCC register for chip - let chip_family = chip.family.to_ascii_lowercase().clone(); + let chip_family = chip.family.to_ascii_lowercase(); let rcc_family = chip_family.strip_prefix("stm32").unwrap(); - //.strip_prefix("stm32") - //.unwrap(); let rcc_reg_path = Path::new(&dir) .join("registers") - .join(&format!("rcc_{}.yaml", rcc_family)); - let mut rcc: ir::IR = serde_yaml::from_reader(File::open(rcc_reg_path).unwrap()).unwrap(); + .join(&format!("rcc_{}.yaml", &rcc_family[0..2])); + let rcc: ir::IR = serde_yaml::from_reader(File::open(rcc_reg_path).unwrap()).unwrap(); let mut peripheral_versions: HashMap = HashMap::new(); let mut pin_table: Vec> = Vec::new(); From f3d1ac6623cbd622122521154fdaf77f3e42e567 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 9 Jun 2021 13:54:53 +0200 Subject: [PATCH 3/4] Enable clock for RNG --- embassy-stm32/src/rng.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/embassy-stm32/src/rng.rs b/embassy-stm32/src/rng.rs index 704f1a97..c2248c84 100644 --- a/embassy-stm32/src/rng.rs +++ b/embassy-stm32/src/rng.rs @@ -24,6 +24,8 @@ pub struct Random { impl Random { pub fn new(inner: impl Unborrow) -> Self { + T::enable(); + T::reset(); unborrow!(inner); let mut random = Self { _inner: inner }; random.reset(); @@ -133,7 +135,7 @@ pub(crate) mod sealed { } } -pub trait Instance: sealed::Instance {} +pub trait Instance: sealed::Instance + crate::rcc::RccPeripheral {} crate::pac::peripherals!( (rng, $inst:ident) => { From 9a2adec5843894e6e25c3f671e4a852821345429 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Wed, 9 Jun 2021 18:48:32 +0200 Subject: [PATCH 4/4] Make RCC lookup optional --- stm32-metapac/build.rs | 65 ++++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/stm32-metapac/build.rs b/stm32-metapac/build.rs index fe505c87..8118d807 100644 --- a/stm32-metapac/build.rs +++ b/stm32-metapac/build.rs @@ -156,12 +156,19 @@ fn main() { }; // Load RCC register for chip - let chip_family = chip.family.to_ascii_lowercase(); - let rcc_family = chip_family.strip_prefix("stm32").unwrap(); - let rcc_reg_path = Path::new(&dir) - .join("registers") - .join(&format!("rcc_{}.yaml", &rcc_family[0..2])); - let rcc: ir::IR = serde_yaml::from_reader(File::open(rcc_reg_path).unwrap()).unwrap(); + let rcc = chip.peripherals.iter().find_map(|(name, p)| { + if name == "RCC" { + p.block.as_ref().map(|block| { + let bi = BlockInfo::parse(block); + let rcc_reg_path = Path::new(&dir) + .join("registers") + .join(&format!("{}_{}.yaml", bi.module, bi.version)); + serde_yaml::from_reader(File::open(rcc_reg_path).unwrap()).unwrap() + }) + } else { + None + } + }); let mut peripheral_versions: HashMap = HashMap::new(); let mut pin_table: Vec> = Vec::new(); @@ -254,29 +261,31 @@ fn main() { } if let Some(clock) = &p.clock { - // Workaround for clock registers being split on some chip families. Assume fields are - // named after peripheral and look for first field matching and use that register. - let en = find_reg_for_field(&rcc, clock, &format!("{}EN", name)); - let rst = find_reg_for_field(&rcc, clock, &format!("{}RST", name)); + if let Some(rcc) = &rcc { + // Workaround for clock registers being split on some chip families. Assume fields are + // named after peripheral and look for first field matching and use that register. + let en = find_reg_for_field(&rcc, clock, &format!("{}EN", name)); + let rst = find_reg_for_field(&rcc, clock, &format!("{}RST", name)); - match (en, rst) { - (Some((enable_reg, enable_field)), Some((reset_reg, reset_field))) => { - peripheral_rcc_table.push(vec![ - name.clone(), - enable_reg.to_ascii_lowercase(), - reset_reg.to_ascii_lowercase(), - format!("set_{}", enable_field.to_ascii_lowercase()), - format!("set_{}", reset_field.to_ascii_lowercase()), - ]); - } - (None, Some(_)) => { - println!("Unable to find enable register for {}", name) - } - (Some(_), None) => { - println!("Unable to find reset register for {}", name) - } - (None, None) => { - println!("Unable to find enable and reset register for {}", name) + match (en, rst) { + (Some((enable_reg, enable_field)), Some((reset_reg, reset_field))) => { + peripheral_rcc_table.push(vec![ + name.clone(), + enable_reg.to_ascii_lowercase(), + reset_reg.to_ascii_lowercase(), + format!("set_{}", enable_field.to_ascii_lowercase()), + format!("set_{}", reset_field.to_ascii_lowercase()), + ]); + } + (None, Some(_)) => { + println!("Unable to find enable register for {}", name) + } + (Some(_), None) => { + println!("Unable to find reset register for {}", name) + } + (None, None) => { + println!("Unable to find enable and reset register for {}", name) + } } } }