diff options
| -rw-r--r-- | embassy-mspm0/Cargo.toml | 9 | ||||
| -rw-r--r-- | embassy-mspm0/build.rs | 397 | ||||
| -rw-r--r-- | embassy-mspm0/src/lib.rs | 19 | ||||
| -rw-r--r-- | embassy-mspm0/src/time_driver.rs | 3 |
4 files changed, 322 insertions, 106 deletions
diff --git a/embassy-mspm0/Cargo.toml b/embassy-mspm0/Cargo.toml index e63a86103..28a8e7724 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..39d8b2f8a 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,128 @@ 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 { | ||
| 36 | // Specially generated. | ||
| 37 | "gpio" => match peri.name { | ||
| 38 | "GPIOB" => cfgs.enable("gpio_pb"), | ||
| 39 | "GPIOC" => cfgs.enable("gpio_pc"), | ||
| 40 | _ => (), | ||
| 41 | }, | ||
| 42 | 61 | ||
| 43 | // These peripherals are managed internally by the hal. | 62 | impl PartialOrd for Singleton { |
| 44 | "iomux" | "cpuss" => {} | 63 | fn partial_cmp(&self, other: &Self) -> Option<Ordering> { |
| 64 | Some(self.cmp(other)) | ||
| 65 | } | ||
| 66 | } | ||
| 45 | 67 | ||
| 46 | _ => singletons.push(peri.name.to_string()), | 68 | impl Ord for Singleton { |
| 47 | } | 69 | fn cmp(&self, other: &Self) -> Ordering { |
| 70 | self.name.cmp(&other.name) | ||
| 48 | } | 71 | } |
| 72 | } | ||
| 49 | 73 | ||
| 50 | time_driver(&singletons, &mut cfgs); | 74 | fn get_singletons(cfgs: &mut common::CfgSet) -> Vec<Singleton> { |
| 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 | } | ||
| 51 | 90 | ||
| 52 | // ======== | 91 | // Each channel gets a singleton, handled separately. |
| 53 | // Write singletons | 92 | "dma" => true, |
| 54 | let mut g = TokenStream::new(); | ||
| 55 | 93 | ||
| 56 | let singleton_tokens: Vec<_> = singletons.iter().map(|s| format_ident!("{}", s)).collect(); | 94 | // These peripherals do not exist as singletons, and have no signals but are managed |
| 95 | // by the HAL. | ||
| 96 | "iomux" | "cpuss" => true, | ||
| 57 | 97 | ||
| 58 | g.extend(quote! { | 98 | _ => false, |
| 59 | embassy_hal_internal::peripherals_definition!(#(#singleton_tokens),*); | 99 | }; |
| 60 | }); | ||
| 61 | 100 | ||
| 62 | g.extend(quote! { | 101 | if !skip_peripheral_singleton { |
| 63 | embassy_hal_internal::peripherals_struct!(#(#singleton_tokens),*); | 102 | singletons.push(Singleton { |
| 64 | }); | 103 | name: peripheral.name.to_string(), |
| 104 | cfg: None, | ||
| 105 | }); | ||
| 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); | ||
| 128 | } | ||
| 129 | |||
| 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 | } | ||
| 65 | 137 | ||
| 66 | // ======== | 138 | singletons.sort_by(|a, b| a.name.cmp(&b.name)); |
| 67 | // Generate GPIO pincm lookup tables. | 139 | singletons |
| 140 | } | ||
| 141 | |||
| 142 | fn make_valid_identifier(s: &str) -> Singleton { | ||
| 143 | let name = s.replace('+', "_P").replace("-", "_N"); | ||
| 144 | |||
| 145 | Singleton { name, cfg: None } | ||
| 146 | } | ||
| 147 | |||
| 148 | fn generate_pincm_mapping() -> TokenStream { | ||
| 68 | let pincms = METADATA.pincm_mappings.iter().map(|mapping| { | 149 | let pincms = METADATA.pincm_mappings.iter().map(|mapping| { |
| 69 | let port_letter = mapping.pin.strip_prefix("P").unwrap(); | 150 | let port_letter = mapping.pin.strip_prefix("P").unwrap(); |
| 70 | let port_base = (port_letter.chars().next().unwrap() as u8 - b'A') * 32; | 151 | let port_base = (port_letter.chars().next().unwrap() as u8 - b'A') * 32; |
| @@ -81,7 +162,7 @@ fn generate_code() { | |||
| 81 | } | 162 | } |
| 82 | }); | 163 | }); |
| 83 | 164 | ||
| 84 | g.extend(quote! { | 165 | 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."] | 166 | #[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 { | 167 | pub(crate) fn gpio_pincm(pin_port: u8) -> u8 { |
| 87 | match pin_port { | 168 | match pin_port { |
| @@ -89,9 +170,11 @@ fn generate_code() { | |||
| 89 | _ => unreachable!(), | 170 | _ => unreachable!(), |
| 90 | } | 171 | } |
| 91 | } | 172 | } |
| 92 | }); | 173 | } |
| 174 | } | ||
| 93 | 175 | ||
| 94 | for pincm_mapping in METADATA.pincm_mappings.iter() { | 176 | fn generate_pin() -> TokenStream { |
| 177 | let pin_impls = METADATA.pincm_mappings.iter().map(|pincm_mapping| { | ||
| 95 | let name = Ident::new(&pincm_mapping.pin, Span::call_site()); | 178 | let name = Ident::new(&pincm_mapping.pin, Span::call_site()); |
| 96 | let port_letter = pincm_mapping.pin.strip_prefix("P").unwrap(); | 179 | let port_letter = pincm_mapping.pin.strip_prefix("P").unwrap(); |
| 97 | let port_letter = port_letter.chars().next().unwrap(); | 180 | let port_letter = port_letter.chars().next().unwrap(); |
| @@ -101,78 +184,19 @@ fn generate_code() { | |||
| 101 | 184 | ||
| 102 | // TODO: Feature gate pins that can be used as NRST | 185 | // TODO: Feature gate pins that can be used as NRST |
| 103 | 186 | ||
| 104 | g.extend(quote! { | 187 | quote! { |
| 105 | impl_pin!(#name, crate::gpio::Port::#port, #pin_number); | 188 | 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 | } | 189 | } |
| 161 | }); | 190 | }); |
| 162 | 191 | ||
| 163 | let out_dir = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); | 192 | quote! { |
| 164 | let out_file = out_dir.join("_generated.rs").to_string_lossy().to_string(); | 193 | #(#pin_impls)* |
| 165 | fs::write(&out_file, g.to_string()).unwrap(); | 194 | } |
| 166 | rustfmt(&out_file); | ||
| 167 | } | 195 | } |
| 168 | 196 | ||
| 169 | fn time_driver(singletons: &[String], cfgs: &mut CfgSet) { | 197 | fn time_driver(singletons: &mut Vec<Singleton>, cfgs: &mut CfgSet) { |
| 170 | // Timer features | 198 | // Timer features |
| 171 | for (timer, desc) in TIMERS.iter() { | 199 | for (timer, _) in TIMERS.iter() { |
| 172 | if desc.bits != 16 { | ||
| 173 | continue; | ||
| 174 | } | ||
| 175 | |||
| 176 | let name = timer.to_lowercase(); | 200 | let name = timer.to_lowercase(); |
| 177 | cfgs.declare(&format!("time_driver_{}", name)); | 201 | cfgs.declare(&format!("time_driver_{}", name)); |
| 178 | } | 202 | } |
| @@ -192,7 +216,7 @@ fn time_driver(singletons: &[String], cfgs: &mut CfgSet) { | |||
| 192 | }; | 216 | }; |
| 193 | 217 | ||
| 194 | // Verify the selected timer is available | 218 | // Verify the selected timer is available |
| 195 | let singleton = match time_driver.as_ref().map(|x| x.as_ref()) { | 219 | let selected_timer = match time_driver.as_ref().map(|x| x.as_ref()) { |
| 196 | None => "", | 220 | None => "", |
| 197 | Some("timg0") => "TIMG0", | 221 | Some("timg0") => "TIMG0", |
| 198 | Some("timg1") => "TIMG1", | 222 | Some("timg1") => "TIMG1", |
| @@ -228,14 +252,181 @@ fn time_driver(singletons: &[String], cfgs: &mut CfgSet) { | |||
| 228 | "TIMA0", "TIMA1", | 252 | "TIMA0", "TIMA1", |
| 229 | ] | 253 | ] |
| 230 | .iter() | 254 | .iter() |
| 231 | .find(|tim| singletons.contains(&tim.to_string())) | 255 | .find(|tim| singletons.iter().any(|s| s.name == **tim)) |
| 232 | .expect("Could not find any timer") | 256 | .expect("Could not find any timer") |
| 233 | } | 257 | } |
| 234 | _ => panic!("unknown time_driver {:?}", time_driver), | 258 | _ => panic!("unknown time_driver {:?}", time_driver), |
| 235 | }; | 259 | }; |
| 236 | 260 | ||
| 237 | if !singleton.is_empty() { | 261 | if !selected_timer.is_empty() { |
| 238 | cfgs.enable(format!("time_driver_{}", singleton.to_lowercase())); | 262 | cfgs.enable(format!("time_driver_{}", selected_timer.to_lowercase())); |
| 263 | } | ||
| 264 | |||
| 265 | // Apply cfgs to each timer and it's pins | ||
| 266 | for singleton in singletons.iter_mut() { | ||
| 267 | if singleton.name.starts_with("TIM") { | ||
| 268 | // Remove suffixes for pin singletons. | ||
| 269 | let name = if singleton.name.contains("_CCP") { | ||
| 270 | singleton.name.split_once("_CCP").unwrap().0 | ||
| 271 | } else if singleton.name.contains("_FAULT") { | ||
| 272 | singleton.name.split_once("_FAULT").unwrap().0 | ||
| 273 | } else if singleton.name.contains("_IDX") { | ||
| 274 | singleton.name.split_once("_IDX").unwrap().0 | ||
| 275 | } else { | ||
| 276 | &singleton.name | ||
| 277 | }; | ||
| 278 | |||
| 279 | let feature = format!("time-driver-{}", name.to_lowercase()); | ||
| 280 | |||
| 281 | if singleton.name.contains(selected_timer) { | ||
| 282 | singleton.cfg = Some(quote! { #[cfg(not(all(feature = "time-driver-any", feature = #feature)))] }); | ||
| 283 | } else { | ||
| 284 | singleton.cfg = Some(quote! { #[cfg(not(feature = #feature))] }); | ||
| 285 | } | ||
| 286 | } | ||
| 287 | } | ||
| 288 | } | ||
| 289 | |||
| 290 | fn generate_singletons(singletons: &[Singleton]) -> TokenStream { | ||
| 291 | let singletons = singletons | ||
| 292 | .iter() | ||
| 293 | .map(|s| { | ||
| 294 | let cfg = s.cfg.clone().unwrap_or_default(); | ||
| 295 | |||
| 296 | let ident = format_ident!("{}", s.name); | ||
| 297 | |||
| 298 | quote! { | ||
| 299 | #cfg | ||
| 300 | #ident | ||
| 301 | } | ||
| 302 | }) | ||
| 303 | .collect::<Vec<_>>(); | ||
| 304 | |||
| 305 | quote! { | ||
| 306 | embassy_hal_internal::peripherals_definition!(#(#singletons),*); | ||
| 307 | embassy_hal_internal::peripherals_struct!(#(#singletons),*); | ||
| 308 | } | ||
| 309 | } | ||
| 310 | |||
| 311 | fn generate_timers() -> TokenStream { | ||
| 312 | // Generate timers | ||
| 313 | let timer_impls = METADATA | ||
| 314 | .peripherals | ||
| 315 | .iter() | ||
| 316 | .filter(|p| p.name.starts_with("TIM")) | ||
| 317 | .map(|peripheral| { | ||
| 318 | let name = Ident::new(&peripheral.name, Span::call_site()); | ||
| 319 | let timers = &*TIMERS; | ||
| 320 | |||
| 321 | let timer = timers.get(peripheral.name).expect("Timer does not exist"); | ||
| 322 | assert!(timer.bits == 16 || timer.bits == 32); | ||
| 323 | let bits = if timer.bits == 16 { | ||
| 324 | quote! { Bits16 } | ||
| 325 | } else { | ||
| 326 | quote! { Bits32 } | ||
| 327 | }; | ||
| 328 | |||
| 329 | quote! { | ||
| 330 | impl_timer!(#name, #bits); | ||
| 331 | } | ||
| 332 | }); | ||
| 333 | |||
| 334 | quote! { | ||
| 335 | #(#timer_impls)* | ||
| 336 | } | ||
| 337 | } | ||
| 338 | |||
| 339 | fn generate_interrupts() -> TokenStream { | ||
| 340 | // Generate interrupt module | ||
| 341 | let interrupts: Vec<Ident> = METADATA | ||
| 342 | .interrupts | ||
| 343 | .iter() | ||
| 344 | .map(|interrupt| Ident::new(interrupt.name, Span::call_site())) | ||
| 345 | .collect(); | ||
| 346 | |||
| 347 | let group_interrupt_enables = METADATA | ||
| 348 | .interrupts | ||
| 349 | .iter() | ||
| 350 | .filter(|interrupt| interrupt.name.contains("GROUP")) | ||
| 351 | .map(|interrupt| { | ||
| 352 | let name = Ident::new(interrupt.name, Span::call_site()); | ||
| 353 | |||
| 354 | quote! { | ||
| 355 | crate::interrupt::typelevel::#name::enable(); | ||
| 356 | } | ||
| 357 | }); | ||
| 358 | |||
| 359 | // Generate interrupt enables for groups | ||
| 360 | quote! { | ||
| 361 | embassy_hal_internal::interrupt_mod! { | ||
| 362 | #(#interrupts),* | ||
| 363 | } | ||
| 364 | |||
| 365 | pub fn enable_group_interrupts(_cs: critical_section::CriticalSection) { | ||
| 366 | use crate::interrupt::typelevel::Interrupt; | ||
| 367 | |||
| 368 | unsafe { | ||
| 369 | #(#group_interrupt_enables)* | ||
| 370 | } | ||
| 371 | } | ||
| 372 | } | ||
| 373 | } | ||
| 374 | |||
| 375 | fn generate_peripheral_instances() -> TokenStream { | ||
| 376 | let mut impls = Vec::<TokenStream>::new(); | ||
| 377 | |||
| 378 | for peripheral in METADATA.peripherals { | ||
| 379 | let peri = format_ident!("{}", peripheral.name); | ||
| 380 | |||
| 381 | // Will be filled in when uart implementation is finished | ||
| 382 | let _ = peri; | ||
| 383 | let tokens = match peripheral.kind { | ||
| 384 | // "uart" => Some(quote! { impl_uart_instance!(#peri); }), | ||
| 385 | _ => None, | ||
| 386 | }; | ||
| 387 | |||
| 388 | if let Some(tokens) = tokens { | ||
| 389 | impls.push(tokens); | ||
| 390 | } | ||
| 391 | } | ||
| 392 | |||
| 393 | quote! { | ||
| 394 | #(#impls)* | ||
| 395 | } | ||
| 396 | } | ||
| 397 | |||
| 398 | fn generate_pin_trait_impls() -> TokenStream { | ||
| 399 | let mut impls = Vec::<TokenStream>::new(); | ||
| 400 | |||
| 401 | for peripheral in METADATA.peripherals { | ||
| 402 | for pin in peripheral.pins { | ||
| 403 | let key = (peripheral.kind, pin.signal); | ||
| 404 | |||
| 405 | let pin_name = format_ident!("{}", pin.pin); | ||
| 406 | let peri = format_ident!("{}", peripheral.name); | ||
| 407 | let pf = pin.pf; | ||
| 408 | |||
| 409 | // Will be filled in when uart implementation is finished | ||
| 410 | let _ = pin_name; | ||
| 411 | let _ = peri; | ||
| 412 | let _ = pf; | ||
| 413 | |||
| 414 | let tokens = match key { | ||
| 415 | // ("uart", "TX") => Some(quote! { impl_uart_tx_pin!(#peri, #pin_name, #pf); }), | ||
| 416 | // ("uart", "RX") => Some(quote! { impl_uart_rx_pin!(#peri, #pin_name, #pf); }), | ||
| 417 | // ("uart", "CTS") => Some(quote! { impl_uart_cts_pin!(#peri, #pin_name, #pf); }), | ||
| 418 | // ("uart", "RTS") => Some(quote! { impl_uart_rts_pin!(#peri, #pin_name, #pf); }), | ||
| 419 | _ => None, | ||
| 420 | }; | ||
| 421 | |||
| 422 | if let Some(tokens) = tokens { | ||
| 423 | impls.push(tokens); | ||
| 424 | } | ||
| 425 | } | ||
| 426 | } | ||
| 427 | |||
| 428 | quote! { | ||
| 429 | #(#impls)* | ||
| 239 | } | 430 | } |
| 240 | } | 431 | } |
| 241 | 432 | ||
diff --git a/embassy-mspm0/src/lib.rs b/embassy-mspm0/src/lib.rs index 3128bb3c7..1df85a520 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; |
