diff options
| -rw-r--r-- | embassy-mspm0/Cargo.toml | 9 | ||||
| -rw-r--r-- | embassy-mspm0/build.rs | 403 | ||||
| -rw-r--r-- | embassy-mspm0/src/lib.rs | 19 | ||||
| -rw-r--r-- | embassy-mspm0/src/time_driver.rs | 3 |
4 files changed, 329 insertions, 105 deletions
diff --git a/embassy-mspm0/Cargo.toml b/embassy-mspm0/Cargo.toml index b747d270e..6aeafe932 100644 --- a/embassy-mspm0/Cargo.toml +++ b/embassy-mspm0/Cargo.toml | |||
| @@ -45,14 +45,14 @@ cortex-m = "0.7.6" | |||
| 45 | critical-section = "1.2.0" | 45 | critical-section = "1.2.0" |
| 46 | 46 | ||
| 47 | # mspm0-metapac = { version = "" } | 47 | # mspm0-metapac = { version = "" } |
| 48 | mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-9faa5239a8eab04946086158f2a7fdff5a6a179d" } | 48 | mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-119240dd23ef5748d2a7bef219ca298d37ba604a" } |
| 49 | 49 | ||
| 50 | [build-dependencies] | 50 | [build-dependencies] |
| 51 | proc-macro2 = "1.0.94" | 51 | proc-macro2 = "1.0.94" |
| 52 | quote = "1.0.40" | 52 | quote = "1.0.40" |
| 53 | 53 | ||
| 54 | # mspm0-metapac = { version = "", default-features = false, features = ["metadata"] } | 54 | # mspm0-metapac = { version = "", default-features = false, features = ["metadata"] } |
| 55 | mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-9faa5239a8eab04946086158f2a7fdff5a6a179d", default-features = false, features = ["metadata"] } | 55 | mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-119240dd23ef5748d2a7bef219ca298d37ba604a", default-features = false, features = ["metadata"] } |
| 56 | 56 | ||
| 57 | [features] | 57 | [features] |
| 58 | default = ["rt"] | 58 | default = ["rt"] |
| @@ -107,7 +107,10 @@ time-driver-timg9 = ["_time-driver"] | |||
| 107 | time-driver-timg10 = ["_time-driver"] | 107 | time-driver-timg10 = ["_time-driver"] |
| 108 | ## Use TIMG11 as time driver | 108 | ## Use TIMG11 as time driver |
| 109 | time-driver-timg11 = ["_time-driver"] | 109 | time-driver-timg11 = ["_time-driver"] |
| 110 | # TODO: Support TIMG12 and TIMG13 | 110 | ## Use TIMG12 as time driver |
| 111 | time-driver-timg12 = ["_time-driver"] | ||
| 112 | ## Use TIMG13 as time driver | ||
| 113 | time-driver-timg13 = ["_time-driver"] | ||
| 111 | ## Use TIMG14 as time driver | 114 | ## Use TIMG14 as time driver |
| 112 | time-driver-timg14 = ["_time-driver"] | 115 | time-driver-timg14 = ["_time-driver"] |
| 113 | ## Use TIMA0 as time driver | 116 | ## Use TIMA0 as time driver |
diff --git a/embassy-mspm0/build.rs b/embassy-mspm0/build.rs index 8c6dd4a5c..9025c337a 100644 --- a/embassy-mspm0/build.rs +++ b/embassy-mspm0/build.rs | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | use std::collections::HashMap; | 1 | use std::cmp::Ordering; |
| 2 | use std::collections::{BTreeSet, HashMap}; | ||
| 2 | use std::io::Write; | 3 | use std::io::Write; |
| 3 | use std::path::{Path, PathBuf}; | 4 | use std::path::{Path, PathBuf}; |
| 4 | use std::process::Command; | 5 | use std::process::Command; |
| @@ -23,48 +24,131 @@ fn generate_code() { | |||
| 23 | 24 | ||
| 24 | cfgs.declare_all(&["gpio_pb", "gpio_pc", "int_group1"]); | 25 | cfgs.declare_all(&["gpio_pb", "gpio_pc", "int_group1"]); |
| 25 | 26 | ||
| 26 | let mut singletons = Vec::new(); | 27 | let mut singletons = get_singletons(&mut cfgs); |
| 27 | 28 | ||
| 28 | // Generate singletons for GPIO pins. To only consider pins available on a family, use the name of | 29 | time_driver(&mut singletons, &mut cfgs); |
| 29 | // the pins from the pincm mappings. | 30 | |
| 30 | for pincm_mapping in METADATA.pincm_mappings.iter() { | 31 | let mut g = TokenStream::new(); |
| 31 | singletons.push(pincm_mapping.pin.to_string()); | 32 | |
| 33 | g.extend(generate_singletons(&singletons)); | ||
| 34 | g.extend(generate_pincm_mapping()); | ||
| 35 | g.extend(generate_pin()); | ||
| 36 | g.extend(generate_timers()); | ||
| 37 | g.extend(generate_interrupts()); | ||
| 38 | g.extend(generate_peripheral_instances()); | ||
| 39 | g.extend(generate_pin_trait_impls()); | ||
| 40 | |||
| 41 | let out_dir = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); | ||
| 42 | let out_file = out_dir.join("_generated.rs").to_string_lossy().to_string(); | ||
| 43 | fs::write(&out_file, g.to_string()).unwrap(); | ||
| 44 | rustfmt(&out_file); | ||
| 45 | } | ||
| 46 | |||
| 47 | #[derive(Debug, Clone)] | ||
| 48 | struct Singleton { | ||
| 49 | name: String, | ||
| 50 | |||
| 51 | cfg: Option<TokenStream>, | ||
| 52 | } | ||
| 53 | |||
| 54 | impl PartialEq for Singleton { | ||
| 55 | fn eq(&self, other: &Self) -> bool { | ||
| 56 | self.name == other.name | ||
| 32 | } | 57 | } |
| 58 | } | ||
| 33 | 59 | ||
| 34 | for peri in METADATA.peripherals { | 60 | impl Eq for Singleton {} |
| 35 | match peri.kind { | 61 | |
| 36 | // Specially generated. | 62 | impl PartialOrd for Singleton { |
| 37 | "gpio" => match peri.name { | 63 | fn partial_cmp(&self, other: &Self) -> Option<Ordering> { |
| 38 | "GPIOB" => cfgs.enable("gpio_pb"), | 64 | Some(self.cmp(other)) |
| 39 | "GPIOC" => cfgs.enable("gpio_pc"), | 65 | } |
| 40 | _ => (), | 66 | } |
| 41 | }, | 67 | |
| 68 | impl Ord for Singleton { | ||
| 69 | fn cmp(&self, other: &Self) -> Ordering { | ||
| 70 | self.name.cmp(&other.name) | ||
| 71 | } | ||
| 72 | } | ||
| 42 | 73 | ||
| 43 | // These peripherals are managed internally by the hal. | 74 | fn get_singletons(cfgs: &mut common::CfgSet) -> Vec<Singleton> { |
| 44 | "iomux" | "cpuss" => {} | 75 | let mut singletons = Vec::<Singleton>::new(); |
| 76 | |||
| 77 | for peripheral in METADATA.peripherals { | ||
| 78 | // Some peripherals do not generate a singleton, but generate a singleton for each pin. | ||
| 79 | let skip_peripheral_singleton = match peripheral.kind { | ||
| 80 | "gpio" => { | ||
| 81 | // Also enable ports that are present. | ||
| 82 | match peripheral.name { | ||
| 83 | "GPIOB" => cfgs.enable("gpio_pb"), | ||
| 84 | "GPIOC" => cfgs.enable("gpio_pc"), | ||
| 85 | _ => (), | ||
| 86 | } | ||
| 87 | |||
| 88 | true | ||
| 89 | } | ||
| 90 | |||
| 91 | // Each channel gets a singleton, handled separately. | ||
| 92 | "dma" => true, | ||
| 93 | |||
| 94 | // These peripherals do not exist as singletons, and have no signals but are managed | ||
| 95 | // by the HAL. | ||
| 96 | "iomux" | "cpuss" => true, | ||
| 45 | 97 | ||
| 46 | _ => singletons.push(peri.name.to_string()), | 98 | _ => false, |
| 99 | }; | ||
| 100 | |||
| 101 | if !skip_peripheral_singleton { | ||
| 102 | singletons.push(Singleton { | ||
| 103 | name: peripheral.name.to_string(), | ||
| 104 | cfg: None, | ||
| 105 | }); | ||
| 47 | } | 106 | } |
| 107 | |||
| 108 | let mut signals = BTreeSet::new(); | ||
| 109 | |||
| 110 | // Pick out each unique signal. There may be multiple instances of each signal due to | ||
| 111 | // iomux mappings. | ||
| 112 | for pin in peripheral.pins { | ||
| 113 | let signal = if peripheral.name.starts_with("GPIO") | ||
| 114 | || peripheral.name.starts_with("VREF") | ||
| 115 | || peripheral.name.starts_with("RTC") | ||
| 116 | { | ||
| 117 | pin.signal.to_string() | ||
| 118 | } else { | ||
| 119 | format!("{}_{}", peripheral.name, pin.signal) | ||
| 120 | }; | ||
| 121 | |||
| 122 | // We need to rename some signals to become valid Rust identifiers. | ||
| 123 | let signal = make_valid_identifier(&signal); | ||
| 124 | signals.insert(signal); | ||
| 125 | } | ||
| 126 | |||
| 127 | singletons.extend(signals); | ||
| 48 | } | 128 | } |
| 49 | 129 | ||
| 50 | time_driver(&singletons, &mut cfgs); | 130 | // DMA channels get their own singletons |
| 131 | for dma_channel in METADATA.dma_channels.iter() { | ||
| 132 | singletons.push(Singleton { | ||
| 133 | name: format!("DMA_CH{}", dma_channel.number), | ||
| 134 | cfg: None, | ||
| 135 | }); | ||
| 136 | } | ||
| 51 | 137 | ||
| 52 | // ======== | 138 | // TODO: Remove `/` signals from metapac (PA1/NRST on C110x for example) |
| 53 | // Write singletons | 139 | singletons.retain(|s| !s.name.contains('/')); |
| 54 | let mut g = TokenStream::new(); | ||
| 55 | 140 | ||
| 56 | let singleton_tokens: Vec<_> = singletons.iter().map(|s| format_ident!("{}", s)).collect(); | 141 | singletons.sort_by(|a, b| a.name.cmp(&b.name)); |
| 142 | singletons | ||
| 143 | } | ||
| 57 | 144 | ||
| 58 | g.extend(quote! { | 145 | fn make_valid_identifier(s: &str) -> Singleton { |
| 59 | embassy_hal_internal::peripherals_definition!(#(#singleton_tokens),*); | 146 | let name = s.replace('+', "_P").replace("-", "_N"); |
| 60 | }); | ||
| 61 | 147 | ||
| 62 | g.extend(quote! { | 148 | Singleton { name, cfg: None } |
| 63 | embassy_hal_internal::peripherals_struct!(#(#singleton_tokens),*); | 149 | } |
| 64 | }); | ||
| 65 | 150 | ||
| 66 | // ======== | 151 | fn generate_pincm_mapping() -> TokenStream { |
| 67 | // Generate GPIO pincm lookup tables. | ||
| 68 | let pincms = METADATA.pincm_mappings.iter().map(|mapping| { | 152 | let pincms = METADATA.pincm_mappings.iter().map(|mapping| { |
| 69 | let port_letter = mapping.pin.strip_prefix("P").unwrap(); | 153 | let port_letter = mapping.pin.strip_prefix("P").unwrap(); |
| 70 | let port_base = (port_letter.chars().next().unwrap() as u8 - b'A') * 32; | 154 | let port_base = (port_letter.chars().next().unwrap() as u8 - b'A') * 32; |
| @@ -81,7 +165,7 @@ fn generate_code() { | |||
| 81 | } | 165 | } |
| 82 | }); | 166 | }); |
| 83 | 167 | ||
| 84 | g.extend(quote! { | 168 | quote! { |
| 85 | #[doc = "Get the mapping from GPIO pin port to IOMUX PINCM index. This is required since the mapping from IO to PINCM index is not consistent across parts."] | 169 | #[doc = "Get the mapping from GPIO pin port to IOMUX PINCM index. This is required since the mapping from IO to PINCM index is not consistent across parts."] |
| 86 | pub(crate) fn gpio_pincm(pin_port: u8) -> u8 { | 170 | pub(crate) fn gpio_pincm(pin_port: u8) -> u8 { |
| 87 | match pin_port { | 171 | match pin_port { |
| @@ -89,9 +173,11 @@ fn generate_code() { | |||
| 89 | _ => unreachable!(), | 173 | _ => unreachable!(), |
| 90 | } | 174 | } |
| 91 | } | 175 | } |
| 92 | }); | 176 | } |
| 177 | } | ||
| 93 | 178 | ||
| 94 | for pincm_mapping in METADATA.pincm_mappings.iter() { | 179 | fn generate_pin() -> TokenStream { |
| 180 | let pin_impls = METADATA.pincm_mappings.iter().map(|pincm_mapping| { | ||
| 95 | let name = Ident::new(&pincm_mapping.pin, Span::call_site()); | 181 | let name = Ident::new(&pincm_mapping.pin, Span::call_site()); |
| 96 | let port_letter = pincm_mapping.pin.strip_prefix("P").unwrap(); | 182 | let port_letter = pincm_mapping.pin.strip_prefix("P").unwrap(); |
| 97 | let port_letter = port_letter.chars().next().unwrap(); | 183 | let port_letter = port_letter.chars().next().unwrap(); |
| @@ -101,78 +187,19 @@ fn generate_code() { | |||
| 101 | 187 | ||
| 102 | // TODO: Feature gate pins that can be used as NRST | 188 | // TODO: Feature gate pins that can be used as NRST |
| 103 | 189 | ||
| 104 | g.extend(quote! { | 190 | quote! { |
| 105 | impl_pin!(#name, crate::gpio::Port::#port, #pin_number); | 191 | impl_pin!(#name, crate::gpio::Port::#port, #pin_number); |
| 106 | }); | ||
| 107 | } | ||
| 108 | |||
| 109 | // Generate timers | ||
| 110 | for peripheral in METADATA.peripherals.iter().filter(|p| p.name.starts_with("TIM")) { | ||
| 111 | let name = Ident::new(&peripheral.name, Span::call_site()); | ||
| 112 | let timers = &*TIMERS; | ||
| 113 | |||
| 114 | let timer = timers.get(peripheral.name).expect("Timer does not exist"); | ||
| 115 | assert!(timer.bits == 16 || timer.bits == 32); | ||
| 116 | let bits = if timer.bits == 16 { | ||
| 117 | quote! { Bits16 } | ||
| 118 | } else { | ||
| 119 | quote! { Bits32 } | ||
| 120 | }; | ||
| 121 | |||
| 122 | g.extend(quote! { | ||
| 123 | impl_timer!(#name, #bits); | ||
| 124 | }); | ||
| 125 | } | ||
| 126 | |||
| 127 | // Generate interrupt module | ||
| 128 | let interrupts: Vec<Ident> = METADATA | ||
| 129 | .interrupts | ||
| 130 | .iter() | ||
| 131 | .map(|interrupt| Ident::new(interrupt.name, Span::call_site())) | ||
| 132 | .collect(); | ||
| 133 | |||
| 134 | g.extend(quote! { | ||
| 135 | embassy_hal_internal::interrupt_mod! { | ||
| 136 | #(#interrupts),* | ||
| 137 | } | ||
| 138 | }); | ||
| 139 | |||
| 140 | let group_interrupt_enables = METADATA | ||
| 141 | .interrupts | ||
| 142 | .iter() | ||
| 143 | .filter(|interrupt| interrupt.name.contains("GROUP")) | ||
| 144 | .map(|interrupt| { | ||
| 145 | let name = Ident::new(interrupt.name, Span::call_site()); | ||
| 146 | |||
| 147 | quote! { | ||
| 148 | crate::interrupt::typelevel::#name::enable(); | ||
| 149 | } | ||
| 150 | }); | ||
| 151 | |||
| 152 | // Generate interrupt enables for groups | ||
| 153 | g.extend(quote! { | ||
| 154 | pub fn enable_group_interrupts(_cs: critical_section::CriticalSection) { | ||
| 155 | use crate::interrupt::typelevel::Interrupt; | ||
| 156 | |||
| 157 | unsafe { | ||
| 158 | #(#group_interrupt_enables)* | ||
| 159 | } | ||
| 160 | } | 192 | } |
| 161 | }); | 193 | }); |
| 162 | 194 | ||
| 163 | let out_dir = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); | 195 | quote! { |
| 164 | let out_file = out_dir.join("_generated.rs").to_string_lossy().to_string(); | 196 | #(#pin_impls)* |
| 165 | fs::write(&out_file, g.to_string()).unwrap(); | 197 | } |
| 166 | rustfmt(&out_file); | ||
| 167 | } | 198 | } |
| 168 | 199 | ||
| 169 | fn time_driver(singletons: &[String], cfgs: &mut CfgSet) { | 200 | fn time_driver(singletons: &mut Vec<Singleton>, cfgs: &mut CfgSet) { |
| 170 | // Timer features | 201 | // Timer features |
| 171 | for (timer, desc) in TIMERS.iter() { | 202 | for (timer, _) in TIMERS.iter() { |
| 172 | if desc.bits != 16 { | ||
| 173 | continue; | ||
| 174 | } | ||
| 175 | |||
| 176 | let name = timer.to_lowercase(); | 203 | let name = timer.to_lowercase(); |
| 177 | cfgs.declare(&format!("time_driver_{}", name)); | 204 | cfgs.declare(&format!("time_driver_{}", name)); |
| 178 | } | 205 | } |
| @@ -192,7 +219,7 @@ fn time_driver(singletons: &[String], cfgs: &mut CfgSet) { | |||
| 192 | }; | 219 | }; |
| 193 | 220 | ||
| 194 | // Verify the selected timer is available | 221 | // Verify the selected timer is available |
| 195 | let singleton = match time_driver.as_ref().map(|x| x.as_ref()) { | 222 | let selected_timer = match time_driver.as_ref().map(|x| x.as_ref()) { |
| 196 | None => "", | 223 | None => "", |
| 197 | Some("timg0") => "TIMG0", | 224 | Some("timg0") => "TIMG0", |
| 198 | Some("timg1") => "TIMG1", | 225 | Some("timg1") => "TIMG1", |
| @@ -228,14 +255,186 @@ fn time_driver(singletons: &[String], cfgs: &mut CfgSet) { | |||
| 228 | "TIMA0", "TIMA1", | 255 | "TIMA0", "TIMA1", |
| 229 | ] | 256 | ] |
| 230 | .iter() | 257 | .iter() |
| 231 | .find(|tim| singletons.contains(&tim.to_string())) | 258 | .find(|tim| singletons.iter().any(|s| s.name == **tim)) |
| 232 | .expect("Could not find any timer") | 259 | .expect("Could not find any timer") |
| 233 | } | 260 | } |
| 234 | _ => panic!("unknown time_driver {:?}", time_driver), | 261 | _ => panic!("unknown time_driver {:?}", time_driver), |
| 235 | }; | 262 | }; |
| 236 | 263 | ||
| 237 | if !singleton.is_empty() { | 264 | if !selected_timer.is_empty() { |
| 238 | cfgs.enable(format!("time_driver_{}", singleton.to_lowercase())); | 265 | cfgs.enable(format!("time_driver_{}", selected_timer.to_lowercase())); |
| 266 | } | ||
| 267 | |||
| 268 | // Apply cfgs to each timer and it's pins | ||
| 269 | for singleton in singletons.iter_mut() { | ||
| 270 | if singleton.name.starts_with("TIM") { | ||
| 271 | // Remove suffixes for pin singletons. | ||
| 272 | let name = if singleton.name.contains("_CCP") { | ||
| 273 | singleton.name.split_once("_CCP").unwrap().0 | ||
| 274 | } else if singleton.name.contains("_FAULT") { | ||
| 275 | singleton.name.split_once("_FAULT").unwrap().0 | ||
| 276 | } else if singleton.name.contains("_IDX") { | ||
| 277 | singleton.name.split_once("_IDX").unwrap().0 | ||
| 278 | } else { | ||
| 279 | &singleton.name | ||
| 280 | }; | ||
| 281 | |||
| 282 | let feature = format!("time-driver-{}", name.to_lowercase()); | ||
| 283 | |||
| 284 | if singleton.name.contains(selected_timer) { | ||
| 285 | singleton.cfg = Some(quote! { #[cfg(not(all(feature = "time-driver-any", feature = #feature)))] }); | ||
| 286 | } else { | ||
| 287 | singleton.cfg = Some(quote! { #[cfg(not(feature = #feature))] }); | ||
| 288 | } | ||
| 289 | } | ||
| 290 | } | ||
| 291 | } | ||
| 292 | |||
| 293 | fn generate_singletons(singletons: &[Singleton]) -> TokenStream { | ||
| 294 | let singletons = singletons | ||
| 295 | .iter() | ||
| 296 | .map(|s| { | ||
| 297 | let cfg = s.cfg.clone().unwrap_or_default(); | ||
| 298 | |||
| 299 | let ident = format_ident!("{}", s.name); | ||
| 300 | |||
| 301 | quote! { | ||
| 302 | #cfg | ||
| 303 | #ident | ||
| 304 | } | ||
| 305 | }) | ||
| 306 | .collect::<Vec<_>>(); | ||
| 307 | |||
| 308 | quote! { | ||
| 309 | embassy_hal_internal::peripherals_definition!(#(#singletons),*); | ||
| 310 | embassy_hal_internal::peripherals_struct!(#(#singletons),*); | ||
| 311 | } | ||
| 312 | } | ||
| 313 | |||
| 314 | fn generate_timers() -> TokenStream { | ||
| 315 | // Generate timers | ||
| 316 | let timer_impls = METADATA | ||
| 317 | .peripherals | ||
| 318 | .iter() | ||
| 319 | .filter(|p| p.name.starts_with("TIM")) | ||
| 320 | .map(|peripheral| { | ||
| 321 | let name = Ident::new(&peripheral.name, Span::call_site()); | ||
| 322 | let timers = &*TIMERS; | ||
| 323 | |||
| 324 | let timer = timers.get(peripheral.name).expect("Timer does not exist"); | ||
| 325 | assert!(timer.bits == 16 || timer.bits == 32); | ||
| 326 | let bits = if timer.bits == 16 { | ||
| 327 | quote! { Bits16 } | ||
| 328 | } else { | ||
| 329 | quote! { Bits32 } | ||
| 330 | }; | ||
| 331 | |||
| 332 | quote! { | ||
| 333 | impl_timer!(#name, #bits); | ||
| 334 | } | ||
| 335 | }); | ||
| 336 | |||
| 337 | quote! { | ||
| 338 | #(#timer_impls)* | ||
| 339 | } | ||
| 340 | } | ||
| 341 | |||
| 342 | fn generate_interrupts() -> TokenStream { | ||
| 343 | // Generate interrupt module | ||
| 344 | let interrupts: Vec<Ident> = METADATA | ||
| 345 | .interrupts | ||
| 346 | .iter() | ||
| 347 | .map(|interrupt| Ident::new(interrupt.name, Span::call_site())) | ||
| 348 | .collect(); | ||
| 349 | |||
| 350 | let group_interrupt_enables = METADATA | ||
| 351 | .interrupts | ||
| 352 | .iter() | ||
| 353 | .filter(|interrupt| interrupt.name.contains("GROUP")) | ||
| 354 | .map(|interrupt| { | ||
| 355 | let name = Ident::new(interrupt.name, Span::call_site()); | ||
| 356 | |||
| 357 | quote! { | ||
| 358 | crate::interrupt::typelevel::#name::enable(); | ||
| 359 | } | ||
| 360 | }); | ||
| 361 | |||
| 362 | // Generate interrupt enables for groups | ||
| 363 | quote! { | ||
| 364 | embassy_hal_internal::interrupt_mod! { | ||
| 365 | #(#interrupts),* | ||
| 366 | } | ||
| 367 | |||
| 368 | pub fn enable_group_interrupts(_cs: critical_section::CriticalSection) { | ||
| 369 | use crate::interrupt::typelevel::Interrupt; | ||
| 370 | |||
| 371 | unsafe { | ||
| 372 | #(#group_interrupt_enables)* | ||
| 373 | } | ||
| 374 | } | ||
| 375 | } | ||
| 376 | } | ||
| 377 | |||
| 378 | fn generate_peripheral_instances() -> TokenStream { | ||
| 379 | let mut impls = Vec::<TokenStream>::new(); | ||
| 380 | |||
| 381 | for peripheral in METADATA.peripherals { | ||
| 382 | let peri = format_ident!("{}", peripheral.name); | ||
| 383 | |||
| 384 | // Will be filled in when uart implementation is finished | ||
| 385 | let _ = peri; | ||
| 386 | let tokens = match peripheral.kind { | ||
| 387 | // "uart" => Some(quote! { impl_uart_instance!(#peri); }), | ||
| 388 | _ => None, | ||
| 389 | }; | ||
| 390 | |||
| 391 | if let Some(tokens) = tokens { | ||
| 392 | impls.push(tokens); | ||
| 393 | } | ||
| 394 | } | ||
| 395 | |||
| 396 | quote! { | ||
| 397 | #(#impls)* | ||
| 398 | } | ||
| 399 | } | ||
| 400 | |||
| 401 | fn generate_pin_trait_impls() -> TokenStream { | ||
| 402 | let mut impls = Vec::<TokenStream>::new(); | ||
| 403 | |||
| 404 | for peripheral in METADATA.peripherals { | ||
| 405 | for pin in peripheral.pins { | ||
| 406 | // TODO: Remove `/` signals from metapac (PA1/NRST on C110x for example) | ||
| 407 | if pin.pin.contains('/') { | ||
| 408 | continue; | ||
| 409 | } | ||
| 410 | |||
| 411 | let key = (peripheral.kind, pin.signal); | ||
| 412 | |||
| 413 | let pin_name = format_ident!("{}", pin.pin); | ||
| 414 | let peri = format_ident!("{}", peripheral.name); | ||
| 415 | let pf = pin.pf; | ||
| 416 | |||
| 417 | // Will be filled in when uart implementation is finished | ||
| 418 | let _ = pin_name; | ||
| 419 | let _ = peri; | ||
| 420 | let _ = pf; | ||
| 421 | |||
| 422 | let tokens = match key { | ||
| 423 | // ("uart", "TX") => Some(quote! { impl_uart_tx_pin!(#peri, #pin_name, #pf); }), | ||
| 424 | // ("uart", "RX") => Some(quote! { impl_uart_rx_pin!(#peri, #pin_name, #pf); }), | ||
| 425 | // ("uart", "CTS") => Some(quote! { impl_uart_cts_pin!(#peri, #pin_name, #pf); }), | ||
| 426 | // ("uart", "RTS") => Some(quote! { impl_uart_rts_pin!(#peri, #pin_name, #pf); }), | ||
| 427 | _ => None, | ||
| 428 | }; | ||
| 429 | |||
| 430 | if let Some(tokens) = tokens { | ||
| 431 | impls.push(tokens); | ||
| 432 | } | ||
| 433 | } | ||
| 434 | } | ||
| 435 | |||
| 436 | quote! { | ||
| 437 | #(#impls)* | ||
| 239 | } | 438 | } |
| 240 | } | 439 | } |
| 241 | 440 | ||
diff --git a/embassy-mspm0/src/lib.rs b/embassy-mspm0/src/lib.rs index 1191b1010..f13245453 100644 --- a/embassy-mspm0/src/lib.rs +++ b/embassy-mspm0/src/lib.rs | |||
| @@ -8,6 +8,25 @@ pub(crate) mod fmt; | |||
| 8 | pub mod gpio; | 8 | pub mod gpio; |
| 9 | pub mod timer; | 9 | pub mod timer; |
| 10 | 10 | ||
| 11 | /// Operating modes for peripherals. | ||
| 12 | pub mod mode { | ||
| 13 | trait SealedMode {} | ||
| 14 | |||
| 15 | /// Operating mode for a peripheral. | ||
| 16 | #[allow(private_bounds)] | ||
| 17 | pub trait Mode: SealedMode {} | ||
| 18 | |||
| 19 | /// Blocking mode. | ||
| 20 | pub struct Blocking; | ||
| 21 | impl SealedMode for Blocking {} | ||
| 22 | impl Mode for Blocking {} | ||
| 23 | |||
| 24 | /// Async mode. | ||
| 25 | pub struct Async; | ||
| 26 | impl SealedMode for Async {} | ||
| 27 | impl Mode for Async {} | ||
| 28 | } | ||
| 29 | |||
| 11 | #[cfg(feature = "_time-driver")] | 30 | #[cfg(feature = "_time-driver")] |
| 12 | mod time_driver; | 31 | mod time_driver; |
| 13 | 32 | ||
diff --git a/embassy-mspm0/src/time_driver.rs b/embassy-mspm0/src/time_driver.rs index 937ce58d4..e80e89e55 100644 --- a/embassy-mspm0/src/time_driver.rs +++ b/embassy-mspm0/src/time_driver.rs | |||
| @@ -12,6 +12,9 @@ use mspm0_metapac::tim::{Counterregs16, Tim}; | |||
| 12 | use crate::peripherals; | 12 | use crate::peripherals; |
| 13 | use crate::timer::SealedTimer; | 13 | use crate::timer::SealedTimer; |
| 14 | 14 | ||
| 15 | #[cfg(any(time_driver_timg12, time_driver_timg13))] | ||
| 16 | compile_error!("TIMG12 and TIMG13 are not supported by the time driver yet"); | ||
| 17 | |||
| 15 | // Currently TIMG12 and TIMG13 are excluded because those are 32-bit timers. | 18 | // Currently TIMG12 and TIMG13 are excluded because those are 32-bit timers. |
| 16 | #[cfg(time_driver_timg0)] | 19 | #[cfg(time_driver_timg0)] |
| 17 | type T = peripherals::TIMG0; | 20 | type T = peripherals::TIMG0; |
