diff options
Diffstat (limited to 'embassy-mspm0/build.rs')
| -rw-r--r-- | embassy-mspm0/build.rs | 116 |
1 files changed, 97 insertions, 19 deletions
diff --git a/embassy-mspm0/build.rs b/embassy-mspm0/build.rs index d294bc422..ac40adbdf 100644 --- a/embassy-mspm0/build.rs +++ b/embassy-mspm0/build.rs | |||
| @@ -16,21 +16,22 @@ use quote::{format_ident, quote}; | |||
| 16 | mod common; | 16 | mod common; |
| 17 | 17 | ||
| 18 | fn main() { | 18 | fn main() { |
| 19 | generate_code(); | ||
| 20 | interrupt_group_linker_magic(); | ||
| 21 | } | ||
| 22 | |||
| 23 | fn generate_code() { | ||
| 24 | let mut cfgs = common::CfgSet::new(); | 19 | let mut cfgs = common::CfgSet::new(); |
| 25 | common::set_target_cfgs(&mut cfgs); | 20 | common::set_target_cfgs(&mut cfgs); |
| 26 | 21 | ||
| 22 | generate_code(&mut cfgs); | ||
| 23 | select_gpio_features(&mut cfgs); | ||
| 24 | interrupt_group_linker_magic(); | ||
| 25 | } | ||
| 26 | |||
| 27 | fn generate_code(cfgs: &mut CfgSet) { | ||
| 27 | #[cfg(any(feature = "rt"))] | 28 | #[cfg(any(feature = "rt"))] |
| 28 | println!( | 29 | println!( |
| 29 | "cargo:rustc-link-search={}", | 30 | "cargo:rustc-link-search={}", |
| 30 | PathBuf::from(env::var_os("OUT_DIR").unwrap()).display(), | 31 | PathBuf::from(env::var_os("OUT_DIR").unwrap()).display(), |
| 31 | ); | 32 | ); |
| 32 | 33 | ||
| 33 | cfgs.declare_all(&["gpio_pb", "gpio_pc", "int_group1"]); | 34 | cfgs.declare_all(&["gpio_pb", "gpio_pc", "int_group1", "unicomm"]); |
| 34 | 35 | ||
| 35 | let chip_name = match env::vars() | 36 | let chip_name = match env::vars() |
| 36 | .map(|(a, _)| a) | 37 | .map(|(a, _)| a) |
| @@ -53,9 +54,9 @@ fn generate_code() { | |||
| 53 | cfgs.declare_all(&get_chip_cfgs(&chip)); | 54 | cfgs.declare_all(&get_chip_cfgs(&chip)); |
| 54 | } | 55 | } |
| 55 | 56 | ||
| 56 | let mut singletons = get_singletons(&mut cfgs); | 57 | let mut singletons = get_singletons(cfgs); |
| 57 | 58 | ||
| 58 | time_driver(&mut singletons, &mut cfgs); | 59 | time_driver(&mut singletons, cfgs); |
| 59 | 60 | ||
| 60 | let mut g = TokenStream::new(); | 61 | let mut g = TokenStream::new(); |
| 61 | 62 | ||
| @@ -68,7 +69,7 @@ fn generate_code() { | |||
| 68 | g.extend(generate_pin_trait_impls()); | 69 | g.extend(generate_pin_trait_impls()); |
| 69 | g.extend(generate_groups()); | 70 | g.extend(generate_groups()); |
| 70 | g.extend(generate_dma_channel_count()); | 71 | g.extend(generate_dma_channel_count()); |
| 71 | g.extend(generate_adc_constants(&mut cfgs)); | 72 | g.extend(generate_adc_constants(cfgs)); |
| 72 | 73 | ||
| 73 | let out_dir = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); | 74 | let out_dir = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); |
| 74 | let out_file = out_dir.join("_generated.rs").to_string_lossy().to_string(); | 75 | let out_file = out_dir.join("_generated.rs").to_string_lossy().to_string(); |
| @@ -115,6 +116,14 @@ fn get_chip_cfgs(chip_name: &str) -> Vec<String> { | |||
| 115 | cfgs.push("mspm0g351x".to_string()); | 116 | cfgs.push("mspm0g351x".to_string()); |
| 116 | } | 117 | } |
| 117 | 118 | ||
| 119 | if chip_name.starts_with("mspm0g518") { | ||
| 120 | cfgs.push("mspm0g518x".to_string()); | ||
| 121 | } | ||
| 122 | |||
| 123 | if chip_name.starts_with("mspm0h321") { | ||
| 124 | cfgs.push("mspm0h321x".to_string()); | ||
| 125 | } | ||
| 126 | |||
| 118 | if chip_name.starts_with("mspm0l110") { | 127 | if chip_name.starts_with("mspm0l110") { |
| 119 | cfgs.push("mspm0l110x".to_string()); | 128 | cfgs.push("mspm0l110x".to_string()); |
| 120 | } | 129 | } |
| @@ -189,8 +198,15 @@ fn generate_groups() -> TokenStream { | |||
| 189 | use crate::pac::#group_enum; | 198 | use crate::pac::#group_enum; |
| 190 | 199 | ||
| 191 | let group = crate::pac::CPUSS.int_group(#group_number); | 200 | let group = crate::pac::CPUSS.int_group(#group_number); |
| 192 | // MUST subtract by 1 since 0 is NO_INTR | 201 | let stat = group.iidx().read().stat(); |
| 193 | let iidx = group.iidx().read().stat().to_bits() - 1; | 202 | |
| 203 | // check for spurious interrupts | ||
| 204 | if stat == crate::pac::cpuss::vals::Iidx::NO_INTR { | ||
| 205 | return; | ||
| 206 | } | ||
| 207 | |||
| 208 | // MUST subtract by 1 because NO_INTR offsets IIDX values. | ||
| 209 | let iidx = stat.to_bits() - 1; | ||
| 194 | 210 | ||
| 195 | let Ok(group) = #group_enum::try_from(iidx as u8) else { | 211 | let Ok(group) = #group_enum::try_from(iidx as u8) else { |
| 196 | return; | 212 | return; |
| @@ -208,7 +224,7 @@ fn generate_groups() -> TokenStream { | |||
| 208 | 224 | ||
| 209 | #[cfg(feature = "rt")] | 225 | #[cfg(feature = "rt")] |
| 210 | mod group_vectors { | 226 | mod group_vectors { |
| 211 | extern "Rust" { | 227 | unsafe extern "Rust" { |
| 212 | #(#group_vectors)* | 228 | #(#group_vectors)* |
| 213 | } | 229 | } |
| 214 | } | 230 | } |
| @@ -288,6 +304,15 @@ fn get_singletons(cfgs: &mut common::CfgSet) -> Vec<Singleton> { | |||
| 288 | // by the HAL. | 304 | // by the HAL. |
| 289 | "iomux" | "cpuss" => true, | 305 | "iomux" | "cpuss" => true, |
| 290 | 306 | ||
| 307 | // Unicomm instances get their own singletons, but we need to enable a cfg for unicomm drivers. | ||
| 308 | "unicomm" => { | ||
| 309 | cfgs.enable("unicomm"); | ||
| 310 | false | ||
| 311 | } | ||
| 312 | |||
| 313 | // TODO: Remove after TIMB is fixed | ||
| 314 | "tim" if peripheral.name.starts_with("TIMB") => true, | ||
| 315 | |||
| 291 | _ => false, | 316 | _ => false, |
| 292 | }; | 317 | }; |
| 293 | 318 | ||
| @@ -411,6 +436,8 @@ fn time_driver(singletons: &mut Vec<Singleton>, cfgs: &mut CfgSet) { | |||
| 411 | // Verify the selected timer is available | 436 | // Verify the selected timer is available |
| 412 | let selected_timer = match time_driver.as_ref().map(|x| x.as_ref()) { | 437 | let selected_timer = match time_driver.as_ref().map(|x| x.as_ref()) { |
| 413 | None => "", | 438 | None => "", |
| 439 | // TODO: Fix TIMB0 | ||
| 440 | // Some("timb0") => "TIMB0", | ||
| 414 | Some("timg0") => "TIMG0", | 441 | Some("timg0") => "TIMG0", |
| 415 | Some("timg1") => "TIMG1", | 442 | Some("timg1") => "TIMG1", |
| 416 | Some("timg2") => "TIMG2", | 443 | Some("timg2") => "TIMG2", |
| @@ -428,16 +455,17 @@ fn time_driver(singletons: &mut Vec<Singleton>, cfgs: &mut CfgSet) { | |||
| 428 | Some("tima1") => "TIMA1", | 455 | Some("tima1") => "TIMA1", |
| 429 | Some("any") => { | 456 | Some("any") => { |
| 430 | // Order of timer candidates: | 457 | // Order of timer candidates: |
| 431 | // 1. 16-bit, 2 channel | 458 | // 1. Basic timers |
| 432 | // 2. 16-bit, 2 channel with shadow registers | 459 | // 2. 16-bit, 2 channel |
| 433 | // 3. 16-bit, 4 channel | 460 | // 3. 16-bit, 2 channel with shadow registers |
| 434 | // 4. 16-bit with QEI | 461 | // 4. 16-bit, 4 channel |
| 435 | // 5. Advanced timers | 462 | // 5. 16-bit with QEI |
| 463 | // 6. Advanced timers | ||
| 436 | // | 464 | // |
| 437 | // TODO: Select RTC first if available | ||
| 438 | // TODO: 32-bit timers are not considered yet | 465 | // TODO: 32-bit timers are not considered yet |
| 439 | [ | 466 | [ |
| 440 | // 16-bit, 2 channel | 467 | // basic timers. No PWM pins |
| 468 | // "TIMB0", // 16-bit, 2 channel | ||
| 441 | "TIMG0", "TIMG1", "TIMG2", "TIMG3", // 16-bit, 2 channel with shadow registers | 469 | "TIMG0", "TIMG1", "TIMG2", "TIMG3", // 16-bit, 2 channel with shadow registers |
| 442 | "TIMG4", "TIMG5", "TIMG6", "TIMG7", // 16-bit, 4 channel | 470 | "TIMG4", "TIMG5", "TIMG6", "TIMG7", // 16-bit, 4 channel |
| 443 | "TIMG14", // 16-bit with QEI | 471 | "TIMG14", // 16-bit with QEI |
| @@ -507,6 +535,8 @@ fn generate_timers() -> TokenStream { | |||
| 507 | .peripherals | 535 | .peripherals |
| 508 | .iter() | 536 | .iter() |
| 509 | .filter(|p| p.name.starts_with("TIM")) | 537 | .filter(|p| p.name.starts_with("TIM")) |
| 538 | // TODO: Fix TIMB when used at time driver. | ||
| 539 | .filter(|p| !p.name.starts_with("TIMB")) | ||
| 510 | .map(|peripheral| { | 540 | .map(|peripheral| { |
| 511 | let name = Ident::new(&peripheral.name, Span::call_site()); | 541 | let name = Ident::new(&peripheral.name, Span::call_site()); |
| 512 | let timers = &*TIMERS; | 542 | let timers = &*TIMERS; |
| @@ -579,6 +609,7 @@ fn generate_peripheral_instances() -> TokenStream { | |||
| 579 | "i2c" => Some(quote! { impl_i2c_instance!(#peri, #fifo_size); }), | 609 | "i2c" => Some(quote! { impl_i2c_instance!(#peri, #fifo_size); }), |
| 580 | "wwdt" => Some(quote! { impl_wwdt_instance!(#peri); }), | 610 | "wwdt" => Some(quote! { impl_wwdt_instance!(#peri); }), |
| 581 | "adc" => Some(quote! { impl_adc_instance!(#peri); }), | 611 | "adc" => Some(quote! { impl_adc_instance!(#peri); }), |
| 612 | "mathacl" => Some(quote! { impl_mathacl_instance!(#peri); }), | ||
| 582 | _ => None, | 613 | _ => None, |
| 583 | }; | 614 | }; |
| 584 | 615 | ||
| @@ -646,6 +677,35 @@ fn generate_pin_trait_impls() -> TokenStream { | |||
| 646 | } | 677 | } |
| 647 | } | 678 | } |
| 648 | 679 | ||
| 680 | fn select_gpio_features(cfgs: &mut CfgSet) { | ||
| 681 | cfgs.declare_all(&[ | ||
| 682 | "gpioa_interrupt", | ||
| 683 | "gpioa_group", | ||
| 684 | "gpiob_interrupt", | ||
| 685 | "gpiob_group", | ||
| 686 | "gpioc_group", | ||
| 687 | ]); | ||
| 688 | |||
| 689 | for interrupt in METADATA.interrupts.iter() { | ||
| 690 | match interrupt.name { | ||
| 691 | "GPIOA" => cfgs.enable("gpioa_interrupt"), | ||
| 692 | "GPIOB" => cfgs.enable("gpiob_interrupt"), | ||
| 693 | _ => (), | ||
| 694 | } | ||
| 695 | } | ||
| 696 | |||
| 697 | for group in METADATA.interrupt_groups.iter() { | ||
| 698 | for interrupt in group.interrupts { | ||
| 699 | match interrupt.name { | ||
| 700 | "GPIOA" => cfgs.enable("gpioa_group"), | ||
| 701 | "GPIOB" => cfgs.enable("gpiob_group"), | ||
| 702 | "GPIOC" => cfgs.enable("gpioc_group"), | ||
| 703 | _ => (), | ||
| 704 | } | ||
| 705 | } | ||
| 706 | } | ||
| 707 | } | ||
| 708 | |||
| 649 | /// rustfmt a given path. | 709 | /// rustfmt a given path. |
| 650 | /// Failures are logged to stderr and ignored. | 710 | /// Failures are logged to stderr and ignored. |
| 651 | fn rustfmt(path: impl AsRef<Path>) { | 711 | fn rustfmt(path: impl AsRef<Path>) { |
| @@ -688,6 +748,24 @@ struct TimerDesc { | |||
| 688 | const TIMERS: LazyLock<HashMap<String, TimerDesc>> = LazyLock::new(|| { | 748 | const TIMERS: LazyLock<HashMap<String, TimerDesc>> = LazyLock::new(|| { |
| 689 | let mut map = HashMap::new(); | 749 | let mut map = HashMap::new(); |
| 690 | map.insert( | 750 | map.insert( |
| 751 | "TIMB0".into(), | ||
| 752 | TimerDesc { | ||
| 753 | bits: 16, | ||
| 754 | prescaler: true, | ||
| 755 | repeat_counter: false, | ||
| 756 | ccp_channels_internal: 2, | ||
| 757 | ccp_channels_external: 2, | ||
| 758 | external_pwm_channels: 0, | ||
| 759 | phase_load: false, | ||
| 760 | shadow_load: false, | ||
| 761 | shadow_ccs: false, | ||
| 762 | deadband: false, | ||
| 763 | fault_handler: false, | ||
| 764 | qei_hall: false, | ||
| 765 | }, | ||
| 766 | ); | ||
| 767 | |||
| 768 | map.insert( | ||
| 691 | "TIMG0".into(), | 769 | "TIMG0".into(), |
| 692 | TimerDesc { | 770 | TimerDesc { |
| 693 | bits: 16, | 771 | bits: 16, |
