diff options
| -rw-r--r-- | embassy-stm32/src/rng.rs | 4 | ||||
| -rw-r--r-- | stm32-metapac/build.rs | 91 |
2 files changed, 72 insertions, 23 deletions
diff --git a/embassy-stm32/src/rng.rs b/embassy-stm32/src/rng.rs index 704f1a97b..c2248c84d 100644 --- a/embassy-stm32/src/rng.rs +++ b/embassy-stm32/src/rng.rs | |||
| @@ -24,6 +24,8 @@ pub struct Random<T: Instance> { | |||
| 24 | 24 | ||
| 25 | impl<T: Instance> Random<T> { | 25 | impl<T: Instance> Random<T> { |
| 26 | pub fn new(inner: impl Unborrow<Target = T>) -> Self { | 26 | pub fn new(inner: impl Unborrow<Target = T>) -> Self { |
| 27 | T::enable(); | ||
| 28 | T::reset(); | ||
| 27 | unborrow!(inner); | 29 | unborrow!(inner); |
| 28 | let mut random = Self { _inner: inner }; | 30 | let mut random = Self { _inner: inner }; |
| 29 | random.reset(); | 31 | random.reset(); |
| @@ -133,7 +135,7 @@ pub(crate) mod sealed { | |||
| 133 | } | 135 | } |
| 134 | } | 136 | } |
| 135 | 137 | ||
| 136 | pub trait Instance: sealed::Instance {} | 138 | pub trait Instance: sealed::Instance + crate::rcc::RccPeripheral {} |
| 137 | 139 | ||
| 138 | crate::pac::peripherals!( | 140 | crate::pac::peripherals!( |
| 139 | (rng, $inst:ident) => { | 141 | (rng, $inst:ident) => { |
diff --git a/stm32-metapac/build.rs b/stm32-metapac/build.rs index 008c9eb37..8118d8072 100644 --- a/stm32-metapac/build.rs +++ b/stm32-metapac/build.rs | |||
| @@ -105,6 +105,30 @@ macro_rules! {} {{ | |||
| 105 | .unwrap(); | 105 | .unwrap(); |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | fn find_reg_for_field<'c>( | ||
| 109 | rcc: &'c ir::IR, | ||
| 110 | reg_prefix: &str, | ||
| 111 | field_name: &str, | ||
| 112 | ) -> Option<(&'c str, &'c str)> { | ||
| 113 | rcc.fieldsets.iter().find_map(|(name, fieldset)| { | ||
| 114 | if name.starts_with(reg_prefix) { | ||
| 115 | fieldset | ||
| 116 | .fields | ||
| 117 | .iter() | ||
| 118 | .find_map(|field| { | ||
| 119 | if field_name == field.name { | ||
| 120 | return Some(field.name.as_str()); | ||
| 121 | } else { | ||
| 122 | None | ||
| 123 | } | ||
| 124 | }) | ||
| 125 | .map(|n| (name.as_str(), n)) | ||
| 126 | } else { | ||
| 127 | None | ||
| 128 | } | ||
| 129 | }) | ||
| 130 | } | ||
| 131 | |||
| 108 | fn main() { | 132 | fn main() { |
| 109 | let dir = "../stm32-data/data"; | 133 | let dir = "../stm32-data/data"; |
| 110 | 134 | ||
| @@ -131,6 +155,21 @@ fn main() { | |||
| 131 | peripherals: Vec::new(), | 155 | peripherals: Vec::new(), |
| 132 | }; | 156 | }; |
| 133 | 157 | ||
| 158 | // Load RCC register for chip | ||
| 159 | let rcc = chip.peripherals.iter().find_map(|(name, p)| { | ||
| 160 | if name == "RCC" { | ||
| 161 | p.block.as_ref().map(|block| { | ||
| 162 | let bi = BlockInfo::parse(block); | ||
| 163 | let rcc_reg_path = Path::new(&dir) | ||
| 164 | .join("registers") | ||
| 165 | .join(&format!("{}_{}.yaml", bi.module, bi.version)); | ||
| 166 | serde_yaml::from_reader(File::open(rcc_reg_path).unwrap()).unwrap() | ||
| 167 | }) | ||
| 168 | } else { | ||
| 169 | None | ||
| 170 | } | ||
| 171 | }); | ||
| 172 | |||
| 134 | let mut peripheral_versions: HashMap<String, String> = HashMap::new(); | 173 | let mut peripheral_versions: HashMap<String, String> = HashMap::new(); |
| 135 | let mut pin_table: Vec<Vec<String>> = Vec::new(); | 174 | let mut pin_table: Vec<Vec<String>> = Vec::new(); |
| 136 | let mut interrupt_table: Vec<Vec<String>> = Vec::new(); | 175 | let mut interrupt_table: Vec<Vec<String>> = Vec::new(); |
| @@ -217,30 +256,38 @@ fn main() { | |||
| 217 | }; | 256 | }; |
| 218 | assert_eq!(p.address, dma_base + dma_stride * dma_num); | 257 | assert_eq!(p.address, dma_base + dma_stride * dma_num); |
| 219 | } | 258 | } |
| 220 | "spi" => { | 259 | |
| 221 | if let Some(clock) = &p.clock { | 260 | _ => {} |
| 222 | // Workaround for APB1 register being split on some chip families. Assume | 261 | } |
| 223 | // first register until we can find a way to hint which register is used | 262 | |
| 224 | let reg = clock.to_ascii_lowercase(); | 263 | if let Some(clock) = &p.clock { |
| 225 | let (enable_reg, reset_reg) = if chip.family == "STM32H7" && clock == "APB1" | 264 | if let Some(rcc) = &rcc { |
| 226 | { | 265 | // Workaround for clock registers being split on some chip families. Assume fields are |
| 227 | (format!("{}lenr", reg), format!("{}lrstr", reg)) | 266 | // named after peripheral and look for first field matching and use that register. |
| 228 | } else if chip.family.starts_with("STM32L4") && clock == "APB1" { | 267 | let en = find_reg_for_field(&rcc, clock, &format!("{}EN", name)); |
| 229 | (format!("{}enr1", reg), format!("{}rstr1", reg)) | 268 | let rst = find_reg_for_field(&rcc, clock, &format!("{}RST", name)); |
| 230 | } else { | 269 | |
| 231 | (format!("{}enr", reg), format!("{}rstr", reg)) | 270 | match (en, rst) { |
| 232 | }; | 271 | (Some((enable_reg, enable_field)), Some((reset_reg, reset_field))) => { |
| 233 | let field = name.to_ascii_lowercase(); | 272 | peripheral_rcc_table.push(vec![ |
| 234 | peripheral_rcc_table.push(vec![ | 273 | name.clone(), |
| 235 | name.clone(), | 274 | enable_reg.to_ascii_lowercase(), |
| 236 | enable_reg, | 275 | reset_reg.to_ascii_lowercase(), |
| 237 | reset_reg, | 276 | format!("set_{}", enable_field.to_ascii_lowercase()), |
| 238 | format!("set_{}en", field), | 277 | format!("set_{}", reset_field.to_ascii_lowercase()), |
| 239 | format!("set_{}rst", field), | 278 | ]); |
| 240 | ]); | 279 | } |
| 280 | (None, Some(_)) => { | ||
| 281 | println!("Unable to find enable register for {}", name) | ||
| 282 | } | ||
| 283 | (Some(_), None) => { | ||
| 284 | println!("Unable to find reset register for {}", name) | ||
| 285 | } | ||
| 286 | (None, None) => { | ||
| 287 | println!("Unable to find enable and reset register for {}", name) | ||
| 288 | } | ||
| 241 | } | 289 | } |
| 242 | } | 290 | } |
| 243 | _ => {} | ||
| 244 | } | 291 | } |
| 245 | } | 292 | } |
| 246 | 293 | ||
