From d23c71ea290828cbdf12b0ce64e9cd420e9038ab Mon Sep 17 00:00:00 2001 From: i509VCB Date: Tue, 20 May 2025 17:17:03 -0500 Subject: [PATCH 1/5] mspm0: generate interrupt group handlers --- embassy-mspm0/Cargo.toml | 4 +- embassy-mspm0/build.rs | 88 +++++++++++++++++++++++++++- embassy-mspm0/src/gpio.rs | 24 ++++++-- embassy-mspm0/src/int_group/c110x.rs | 25 -------- embassy-mspm0/src/int_group/g110x.rs | 47 --------------- embassy-mspm0/src/int_group/g150x.rs | 51 ---------------- embassy-mspm0/src/int_group/g151x.rs | 52 ---------------- embassy-mspm0/src/int_group/g310x.rs | 48 --------------- embassy-mspm0/src/int_group/g350x.rs | 51 ---------------- embassy-mspm0/src/int_group/g351x.rs | 52 ---------------- embassy-mspm0/src/int_group/l11xx.rs | 25 -------- embassy-mspm0/src/int_group/l12xx.rs | 49 ---------------- embassy-mspm0/src/int_group/l13xx.rs | 46 --------------- embassy-mspm0/src/int_group/l222x.rs | 49 ---------------- embassy-mspm0/src/lib.rs | 14 ----- examples/mspm0c1104/build.rs | 2 + examples/mspm0g3507/build.rs | 2 + examples/mspm0g3519/build.rs | 2 + examples/mspm0l1306/build.rs | 2 + examples/mspm0l2228/build.rs | 2 + 20 files changed, 117 insertions(+), 518 deletions(-) delete mode 100644 embassy-mspm0/src/int_group/c110x.rs delete mode 100644 embassy-mspm0/src/int_group/g110x.rs delete mode 100644 embassy-mspm0/src/int_group/g150x.rs delete mode 100644 embassy-mspm0/src/int_group/g151x.rs delete mode 100644 embassy-mspm0/src/int_group/g310x.rs delete mode 100644 embassy-mspm0/src/int_group/g350x.rs delete mode 100644 embassy-mspm0/src/int_group/g351x.rs delete mode 100644 embassy-mspm0/src/int_group/l11xx.rs delete mode 100644 embassy-mspm0/src/int_group/l12xx.rs delete mode 100644 embassy-mspm0/src/int_group/l13xx.rs delete mode 100644 embassy-mspm0/src/int_group/l222x.rs diff --git a/embassy-mspm0/Cargo.toml b/embassy-mspm0/Cargo.toml index 1b189e05a..6f767a3c0 100644 --- a/embassy-mspm0/Cargo.toml +++ b/embassy-mspm0/Cargo.toml @@ -46,14 +46,14 @@ cortex-m = "0.7.6" critical-section = "1.2.0" # mspm0-metapac = { version = "" } -mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-66a55c7bf38a2201ff48c299843e741f2d537f0b" } +mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-26a6f681eda4ef120e8cb614a1631727c848590f" } [build-dependencies] proc-macro2 = "1.0.94" quote = "1.0.40" # mspm0-metapac = { version = "", default-features = false, features = ["metadata"] } -mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-66a55c7bf38a2201ff48c299843e741f2d537f0b", default-features = false, features = ["metadata"] } +mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-26a6f681eda4ef120e8cb614a1631727c848590f", default-features = false, features = ["metadata"] } [features] default = ["rt"] diff --git a/embassy-mspm0/build.rs b/embassy-mspm0/build.rs index 094769992..6cd62895b 100644 --- a/embassy-mspm0/build.rs +++ b/embassy-mspm0/build.rs @@ -1,6 +1,7 @@ use std::cmp::Ordering; use std::collections::{BTreeSet, HashMap}; -use std::io::Write; +use std::fmt::Write; +use std::io::Write as _; use std::path::{Path, PathBuf}; use std::process::Command; use std::sync::LazyLock; @@ -16,12 +17,19 @@ mod common; fn main() { generate_code(); + interrupt_group_linker_magic(); } fn generate_code() { let mut cfgs = common::CfgSet::new(); common::set_target_cfgs(&mut cfgs); + #[cfg(any(feature = "rt"))] + println!( + "cargo:rustc-link-search={}", + PathBuf::from(env::var_os("OUT_DIR").unwrap()).display(), + ); + cfgs.declare_all(&["gpio_pb", "gpio_pc", "int_group1"]); let chip_name = match env::vars() @@ -58,6 +66,7 @@ fn generate_code() { g.extend(generate_interrupts()); g.extend(generate_peripheral_instances()); g.extend(generate_pin_trait_impls()); + g.extend(generate_groups()); let out_dir = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); let out_file = out_dir.join("_generated.rs").to_string_lossy().to_string(); @@ -123,6 +132,83 @@ fn get_chip_cfgs(chip_name: &str) -> Vec { cfgs } +/// Interrupt groups use a weakly linked symbols and #[linkage = "extern_weak"] is nightly we need to +/// do some linker magic to create weak linkage. +fn interrupt_group_linker_magic() { + let mut file = String::new(); + + for group in METADATA.interrupt_groups { + for interrupt in group.interrupts.iter() { + let name = interrupt.name; + + writeln!(&mut file, "PROVIDE({name} = DefaultHandler);").unwrap(); + } + } + + let out_dir = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + let out_file = out_dir.join("interrupt_group.x"); + fs::write(&out_file, file).unwrap(); +} + +fn generate_groups() -> TokenStream { + let group_vectors = METADATA.interrupt_groups.iter().map(|group| { + let vectors = group.interrupts.iter().map(|interrupt| { + let fn_name = Ident::new(interrupt.name, Span::call_site()); + + quote! { + pub(crate) fn #fn_name(); + } + }); + + quote! { #(#vectors)* } + }); + + let groups = METADATA.interrupt_groups.iter().map(|group| { + let interrupt_group_name = Ident::new(group.name, Span::call_site()); + let group_enum = Ident::new(&format!("Group{}", &group.name[5..]), Span::call_site()); + let group_number = Literal::u32_unsuffixed(group.number); + + let matches = group.interrupts.iter().map(|interrupt| { + let variant = Ident::new(&interrupt.name, Span::call_site()); + + quote! { + #group_enum::#variant => unsafe { group_vectors::#variant() }, + } + }); + + quote! { + #[cfg(feature = "rt")] + #[crate::pac::interrupt] + fn #interrupt_group_name() { + use crate::pac::#group_enum; + + let group = crate::pac::CPUSS.int_group(#group_number); + // MUST subtract by 1 since 0 is NO_INTR + let iidx = group.iidx().read().stat().to_bits() - 1; + + let Ok(group) = #group_enum::try_from(iidx as u8) else { + return; + }; + + match group { + #(#matches)* + } + } + } + }); + + quote! { + #(#groups)* + + #[cfg(feature = "rt")] + mod group_vectors { + extern "Rust" { + #(#group_vectors)* + } + } + } +} + #[derive(Debug, Clone)] struct Singleton { name: String, diff --git a/embassy-mspm0/src/gpio.rs b/embassy-mspm0/src/gpio.rs index 19a6230b6..738d51928 100644 --- a/embassy-mspm0/src/gpio.rs +++ b/embassy-mspm0/src/gpio.rs @@ -1119,24 +1119,36 @@ impl Iterator for BitIter { } } -// C110x has a dedicated interrupt just for GPIOA, as it does not have a GROUP1 interrupt. +// C110x and L110x have a dedicated interrupts just for GPIOA. +// +// These chips do not have a GROUP1 interrupt. #[cfg(all(feature = "rt", any(mspm0c110x, mspm0l110x)))] #[interrupt] fn GPIOA() { - gpioa_interrupt(); + irq_handler(pac::GPIOA, &PORTA_WAKERS); } -#[cfg(feature = "rt")] -pub(crate) fn gpioa_interrupt() { +// These symbols are weakly defined as DefaultHandler and are called by the interrupt group implementation. +// +// Defining these as no_mangle is required so that the linker will pick these over the default handler. + +#[cfg(all(feature = "rt", not(any(mspm0c110x, mspm0l110x))))] +#[no_mangle] +#[allow(non_snake_case)] +fn GPIOA() { irq_handler(pac::GPIOA, &PORTA_WAKERS); } #[cfg(all(feature = "rt", gpio_pb))] -pub(crate) fn gpiob_interrupt() { +#[no_mangle] +#[allow(non_snake_case)] +fn GPIOB() { irq_handler(pac::GPIOB, &PORTB_WAKERS); } #[cfg(all(feature = "rt", gpio_pc))] -pub(crate) fn gpioc_interrupt() { +#[allow(non_snake_case)] +#[no_mangle] +fn GPIOC() { irq_handler(pac::GPIOC, &PORTC_WAKERS); } diff --git a/embassy-mspm0/src/int_group/c110x.rs b/embassy-mspm0/src/int_group/c110x.rs deleted file mode 100644 index e6a9ddb99..000000000 --- a/embassy-mspm0/src/int_group/c110x.rs +++ /dev/null @@ -1,25 +0,0 @@ -use crate::pac; -use crate::pac::interrupt; - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP0() { - use mspm0_metapac::Group0; - - let group = pac::CPUSS.int_group(0); - - // TODO: Decompose to direct u8 - let iidx = group.iidx().read().stat().to_bits(); - - let Ok(group) = pac::Group0::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 0: {}", iidx); - return; - }; - - match group { - Group0::WWDT0 => todo!("implement WWDT0"), - Group0::DEBUGSS => todo!("implement DEBUGSS"), - Group0::FLASHCTL => todo!("implement FLASHCTL"), - Group0::SYSCTL => todo!("implement SYSCTL"), - } -} diff --git a/embassy-mspm0/src/int_group/g110x.rs b/embassy-mspm0/src/int_group/g110x.rs deleted file mode 100644 index 9f8ac4d7b..000000000 --- a/embassy-mspm0/src/int_group/g110x.rs +++ /dev/null @@ -1,47 +0,0 @@ -use crate::pac; -use crate::pac::interrupt; - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP0() { - use mspm0_metapac::Group0; - - let group = pac::CPUSS.int_group(0); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group0::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 0: {}", iidx); - return; - }; - - match group { - Group0::WWDT0 => todo!("implement WWDT0"), - Group0::WWDT1 => todo!("implement WWDT1"), - Group0::DEBUGSS => todo!("implement DEBUGSS"), - Group0::FLASHCTL => todo!("implement FLASHCTL"), - Group0::SYSCTL => todo!("implement SYSCTL"), - } -} - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP1() { - use mspm0_metapac::Group1; - - let group = pac::CPUSS.int_group(1); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group1::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 1: {}", iidx); - return; - }; - - match group { - Group1::GPIOA => crate::gpio::gpioa_interrupt(), - Group1::GPIOB => crate::gpio::gpiob_interrupt(), - } -} diff --git a/embassy-mspm0/src/int_group/g150x.rs b/embassy-mspm0/src/int_group/g150x.rs deleted file mode 100644 index 706ba2078..000000000 --- a/embassy-mspm0/src/int_group/g150x.rs +++ /dev/null @@ -1,51 +0,0 @@ -use crate::pac; -use crate::pac::interrupt; - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP0() { - use mspm0_metapac::Group0; - - let group = pac::CPUSS.int_group(0); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group0::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 0: {}", iidx); - return; - }; - - match group { - Group0::WWDT0 => todo!("implement WWDT0"), - Group0::WWDT1 => todo!("implement WWDT1"), - Group0::DEBUGSS => todo!("implement DEBUGSS"), - Group0::FLASHCTL => todo!("implement FLASHCTL"), - Group0::SYSCTL => todo!("implement SYSCTL"), - } -} - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP1() { - use mspm0_metapac::Group1; - - let group = pac::CPUSS.int_group(1); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group1::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 1: {}", iidx); - return; - }; - - match group { - Group1::GPIOA => crate::gpio::gpioa_interrupt(), - Group1::GPIOB => crate::gpio::gpiob_interrupt(), - Group1::COMP0 => todo!("implement COMP0"), - Group1::COMP1 => todo!("implement COMP1"), - Group1::COMP2 => todo!("implement COMP2"), - Group1::TRNG => todo!("implement TRNG"), - } -} diff --git a/embassy-mspm0/src/int_group/g151x.rs b/embassy-mspm0/src/int_group/g151x.rs deleted file mode 100644 index e785018a7..000000000 --- a/embassy-mspm0/src/int_group/g151x.rs +++ /dev/null @@ -1,52 +0,0 @@ -use crate::pac; -use crate::pac::interrupt; - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP0() { - use mspm0_metapac::Group0; - - let group = pac::CPUSS.int_group(0); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group0::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 0: {}", iidx); - return; - }; - - match group { - Group0::WWDT0 => todo!("implement WWDT0"), - Group0::WWDT1 => todo!("implement WWDT1"), - Group0::DEBUGSS => todo!("implement DEBUGSS"), - Group0::FLASHCTL => todo!("implement FLASHCTL"), - Group0::SYSCTL => todo!("implement SYSCTL"), - } -} - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP1() { - use mspm0_metapac::Group1; - - let group = pac::CPUSS.int_group(1); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group1::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 1: {}", iidx); - return; - }; - - match group { - Group1::GPIOA => crate::gpio::gpioa_interrupt(), - Group1::GPIOB => crate::gpio::gpiob_interrupt(), - Group1::COMP0 => todo!("implement COMP0"), - Group1::COMP1 => todo!("implement COMP1"), - Group1::COMP2 => todo!("implement COMP2"), - Group1::TRNG => todo!("implement TRNG"), - Group1::GPIOC => crate::gpio::gpioc_interrupt(), - } -} diff --git a/embassy-mspm0/src/int_group/g310x.rs b/embassy-mspm0/src/int_group/g310x.rs deleted file mode 100644 index ad508d3a2..000000000 --- a/embassy-mspm0/src/int_group/g310x.rs +++ /dev/null @@ -1,48 +0,0 @@ -use crate::pac; -use crate::pac::interrupt; - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP0() { - use mspm0_metapac::Group0; - - let group = pac::CPUSS.int_group(0); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group0::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 0: {}", iidx); - return; - }; - - match group { - Group0::WWDT0 => todo!("implement WWDT0"), - Group0::WWDT1 => todo!("implement WWDT1"), - Group0::DEBUGSS => todo!("implement DEBUGSS"), - Group0::FLASHCTL => todo!("implement FLASHCTL"), - Group0::SYSCTL => todo!("implement SYSCTL"), - } -} - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP1() { - use mspm0_metapac::Group1; - - let group = pac::CPUSS.int_group(1); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group1::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 1: {}", iidx); - return; - }; - - match group { - Group1::GPIOA => crate::gpio::gpioa_interrupt(), - Group1::GPIOB => crate::gpio::gpiob_interrupt(), - Group1::TRNG => todo!("implement TRNG"), - } -} diff --git a/embassy-mspm0/src/int_group/g350x.rs b/embassy-mspm0/src/int_group/g350x.rs deleted file mode 100644 index 706ba2078..000000000 --- a/embassy-mspm0/src/int_group/g350x.rs +++ /dev/null @@ -1,51 +0,0 @@ -use crate::pac; -use crate::pac::interrupt; - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP0() { - use mspm0_metapac::Group0; - - let group = pac::CPUSS.int_group(0); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group0::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 0: {}", iidx); - return; - }; - - match group { - Group0::WWDT0 => todo!("implement WWDT0"), - Group0::WWDT1 => todo!("implement WWDT1"), - Group0::DEBUGSS => todo!("implement DEBUGSS"), - Group0::FLASHCTL => todo!("implement FLASHCTL"), - Group0::SYSCTL => todo!("implement SYSCTL"), - } -} - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP1() { - use mspm0_metapac::Group1; - - let group = pac::CPUSS.int_group(1); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group1::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 1: {}", iidx); - return; - }; - - match group { - Group1::GPIOA => crate::gpio::gpioa_interrupt(), - Group1::GPIOB => crate::gpio::gpiob_interrupt(), - Group1::COMP0 => todo!("implement COMP0"), - Group1::COMP1 => todo!("implement COMP1"), - Group1::COMP2 => todo!("implement COMP2"), - Group1::TRNG => todo!("implement TRNG"), - } -} diff --git a/embassy-mspm0/src/int_group/g351x.rs b/embassy-mspm0/src/int_group/g351x.rs deleted file mode 100644 index e785018a7..000000000 --- a/embassy-mspm0/src/int_group/g351x.rs +++ /dev/null @@ -1,52 +0,0 @@ -use crate::pac; -use crate::pac::interrupt; - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP0() { - use mspm0_metapac::Group0; - - let group = pac::CPUSS.int_group(0); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group0::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 0: {}", iidx); - return; - }; - - match group { - Group0::WWDT0 => todo!("implement WWDT0"), - Group0::WWDT1 => todo!("implement WWDT1"), - Group0::DEBUGSS => todo!("implement DEBUGSS"), - Group0::FLASHCTL => todo!("implement FLASHCTL"), - Group0::SYSCTL => todo!("implement SYSCTL"), - } -} - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP1() { - use mspm0_metapac::Group1; - - let group = pac::CPUSS.int_group(1); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group1::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 1: {}", iidx); - return; - }; - - match group { - Group1::GPIOA => crate::gpio::gpioa_interrupt(), - Group1::GPIOB => crate::gpio::gpiob_interrupt(), - Group1::COMP0 => todo!("implement COMP0"), - Group1::COMP1 => todo!("implement COMP1"), - Group1::COMP2 => todo!("implement COMP2"), - Group1::TRNG => todo!("implement TRNG"), - Group1::GPIOC => crate::gpio::gpioc_interrupt(), - } -} diff --git a/embassy-mspm0/src/int_group/l11xx.rs b/embassy-mspm0/src/int_group/l11xx.rs deleted file mode 100644 index 426a80c13..000000000 --- a/embassy-mspm0/src/int_group/l11xx.rs +++ /dev/null @@ -1,25 +0,0 @@ -use crate::pac; -use crate::pac::interrupt; - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP0() { - use mspm0_metapac::Group0; - - let group = pac::CPUSS.int_group(0); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group0::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 0: {}", iidx); - return; - }; - - match group { - Group0::WWDT0 => todo!("implement WWDT0"), - Group0::DEBUGSS => todo!("implement DEBUGSS"), - Group0::FLASHCTL => todo!("implement FLASHCTL"), - Group0::SYSCTL => todo!("implement SYSCTL"), - } -} diff --git a/embassy-mspm0/src/int_group/l12xx.rs b/embassy-mspm0/src/int_group/l12xx.rs deleted file mode 100644 index eeb2ce70d..000000000 --- a/embassy-mspm0/src/int_group/l12xx.rs +++ /dev/null @@ -1,49 +0,0 @@ -use crate::pac; -use crate::pac::interrupt; - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP0() { - use mspm0_metapac::Group0; - - let group = pac::CPUSS.int_group(0); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group0::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 0: {}", iidx); - return; - }; - - match group { - Group0::WWDT0 => todo!("implement WWDT0"), - Group0::DEBUGSS => todo!("implement DEBUGSS"), - Group0::FLASHCTL => todo!("implement FLASHCTL"), - Group0::SYSCTL => todo!("implement SYSCTL"), - } -} - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP1() { - use mspm0_metapac::Group1; - - let group = pac::CPUSS.int_group(1); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group1::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 1: {}", iidx); - return; - }; - - match group { - Group1::GPIOA => crate::gpio::gpioa_interrupt(), - Group1::GPIOB => crate::gpio::gpiob_interrupt(), - Group1::COMP0 => todo!("implement COMP0"), - Group1::TRNG => todo!("implement TRNG"), - Group1::GPIOC => crate::gpio::gpioc_interrupt(), - } -} diff --git a/embassy-mspm0/src/int_group/l13xx.rs b/embassy-mspm0/src/int_group/l13xx.rs deleted file mode 100644 index 8be5adcad..000000000 --- a/embassy-mspm0/src/int_group/l13xx.rs +++ /dev/null @@ -1,46 +0,0 @@ -use crate::pac; -use crate::pac::interrupt; - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP0() { - use mspm0_metapac::Group0; - - let group = pac::CPUSS.int_group(0); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group0::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 0: {}", iidx); - return; - }; - - match group { - Group0::WWDT0 => todo!("implement WWDT0"), - Group0::DEBUGSS => todo!("implement DEBUGSS"), - Group0::FLASHCTL => todo!("implement FLASHCTL"), - Group0::SYSCTL => todo!("implement SYSCTL"), - } -} - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP1() { - use mspm0_metapac::Group1; - - let group = pac::CPUSS.int_group(1); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group1::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 1: {}", iidx); - return; - }; - - match group { - Group1::GPIOA => crate::gpio::gpioa_interrupt(), - Group1::COMP0 => todo!("implement COMP0"), - } -} diff --git a/embassy-mspm0/src/int_group/l222x.rs b/embassy-mspm0/src/int_group/l222x.rs deleted file mode 100644 index eeb2ce70d..000000000 --- a/embassy-mspm0/src/int_group/l222x.rs +++ /dev/null @@ -1,49 +0,0 @@ -use crate::pac; -use crate::pac::interrupt; - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP0() { - use mspm0_metapac::Group0; - - let group = pac::CPUSS.int_group(0); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group0::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 0: {}", iidx); - return; - }; - - match group { - Group0::WWDT0 => todo!("implement WWDT0"), - Group0::DEBUGSS => todo!("implement DEBUGSS"), - Group0::FLASHCTL => todo!("implement FLASHCTL"), - Group0::SYSCTL => todo!("implement SYSCTL"), - } -} - -#[cfg(feature = "rt")] -#[interrupt] -fn GROUP1() { - use mspm0_metapac::Group1; - - let group = pac::CPUSS.int_group(1); - - // Must subtract by 1 since NO_INTR is value 0 - let iidx = group.iidx().read().stat().to_bits() - 1; - - let Ok(group) = pac::Group1::try_from(iidx as u8) else { - debug!("Invalid IIDX for group 1: {}", iidx); - return; - }; - - match group { - Group1::GPIOA => crate::gpio::gpioa_interrupt(), - Group1::GPIOB => crate::gpio::gpiob_interrupt(), - Group1::COMP0 => todo!("implement COMP0"), - Group1::TRNG => todo!("implement TRNG"), - Group1::GPIOC => crate::gpio::gpioc_interrupt(), - } -} diff --git a/embassy-mspm0/src/lib.rs b/embassy-mspm0/src/lib.rs index f129e221b..7ff60e946 100644 --- a/embassy-mspm0/src/lib.rs +++ b/embassy-mspm0/src/lib.rs @@ -39,20 +39,6 @@ pub mod mode { #[cfg(feature = "_time-driver")] mod time_driver; -// Interrupt group handlers. -#[cfg_attr(mspm0c110x, path = "int_group/c110x.rs")] -#[cfg_attr(mspm0g110x, path = "int_group/g110x.rs")] -#[cfg_attr(mspm0g150x, path = "int_group/g150x.rs")] -#[cfg_attr(mspm0g350x, path = "int_group/g350x.rs")] -#[cfg_attr(mspm0g151x, path = "int_group/g151x.rs")] -#[cfg_attr(mspm0g351x, path = "int_group/g351x.rs")] -#[cfg_attr(mspm0g310x, path = "int_group/g310x.rs")] -#[cfg_attr(mspm0l110x, path = "int_group/l11xx.rs")] -#[cfg_attr(mspm0l122x, path = "int_group/l12xx.rs")] -#[cfg_attr(any(mspm0l130x, mspm0l134x), path = "int_group/l13xx.rs")] -#[cfg_attr(mspm0l222x, path = "int_group/l222x.rs")] -mod int_group; - pub(crate) mod _generated { #![allow(dead_code)] #![allow(unused_imports)] diff --git a/examples/mspm0c1104/build.rs b/examples/mspm0c1104/build.rs index 30691aa97..2d777c2d3 100644 --- a/examples/mspm0c1104/build.rs +++ b/examples/mspm0c1104/build.rs @@ -32,4 +32,6 @@ fn main() { println!("cargo:rustc-link-arg-bins=--nmagic"); println!("cargo:rustc-link-arg-bins=-Tlink.x"); println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); + // You must tell cargo to link interrupt groups if the rt feature is enabled. + println!("cargo:rustc-link-arg-bins=-Tinterrupt_group.x"); } diff --git a/examples/mspm0g3507/build.rs b/examples/mspm0g3507/build.rs index 30691aa97..2d777c2d3 100644 --- a/examples/mspm0g3507/build.rs +++ b/examples/mspm0g3507/build.rs @@ -32,4 +32,6 @@ fn main() { println!("cargo:rustc-link-arg-bins=--nmagic"); println!("cargo:rustc-link-arg-bins=-Tlink.x"); println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); + // You must tell cargo to link interrupt groups if the rt feature is enabled. + println!("cargo:rustc-link-arg-bins=-Tinterrupt_group.x"); } diff --git a/examples/mspm0g3519/build.rs b/examples/mspm0g3519/build.rs index 30691aa97..2d777c2d3 100644 --- a/examples/mspm0g3519/build.rs +++ b/examples/mspm0g3519/build.rs @@ -32,4 +32,6 @@ fn main() { println!("cargo:rustc-link-arg-bins=--nmagic"); println!("cargo:rustc-link-arg-bins=-Tlink.x"); println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); + // You must tell cargo to link interrupt groups if the rt feature is enabled. + println!("cargo:rustc-link-arg-bins=-Tinterrupt_group.x"); } diff --git a/examples/mspm0l1306/build.rs b/examples/mspm0l1306/build.rs index 30691aa97..2d777c2d3 100644 --- a/examples/mspm0l1306/build.rs +++ b/examples/mspm0l1306/build.rs @@ -32,4 +32,6 @@ fn main() { println!("cargo:rustc-link-arg-bins=--nmagic"); println!("cargo:rustc-link-arg-bins=-Tlink.x"); println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); + // You must tell cargo to link interrupt groups if the rt feature is enabled. + println!("cargo:rustc-link-arg-bins=-Tinterrupt_group.x"); } diff --git a/examples/mspm0l2228/build.rs b/examples/mspm0l2228/build.rs index 30691aa97..2d777c2d3 100644 --- a/examples/mspm0l2228/build.rs +++ b/examples/mspm0l2228/build.rs @@ -32,4 +32,6 @@ fn main() { println!("cargo:rustc-link-arg-bins=--nmagic"); println!("cargo:rustc-link-arg-bins=-Tlink.x"); println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); + // You must tell cargo to link interrupt groups if the rt feature is enabled. + println!("cargo:rustc-link-arg-bins=-Tinterrupt_group.x"); } From 8b65f9cf0f4095080297bf5c3e09334296da8076 Mon Sep 17 00:00:00 2001 From: i509VCB Date: Tue, 20 May 2025 17:29:28 -0500 Subject: [PATCH 2/5] mspm0: link interrupt groups in tests --- tests/mspm0/build.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/mspm0/build.rs b/tests/mspm0/build.rs index 57b592abf..0b58fb9e9 100644 --- a/tests/mspm0/build.rs +++ b/tests/mspm0/build.rs @@ -19,6 +19,8 @@ fn main() -> Result<(), Box> { println!("cargo:rustc-link-arg-bins=-Tlink_ram.x"); println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); println!("cargo:rustc-link-arg-bins=-Tteleprobe.x"); + // You must tell cargo to link interrupt groups if the rt feature is enabled. + println!("cargo:rustc-link-arg-bins=-Tinterrupt_group.x"); Ok(()) } From 0e47478f01335c735f8f27fa3a935776736e9afa Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 19 May 2025 16:38:34 +0200 Subject: [PATCH 3/5] nrf/rng: add Blocking/Async Mode param. This allows avoiding creating the irq handler if you're only going to use it in blocking mode. --- embassy-nrf/src/lib.rs | 24 +++++++++++++ embassy-nrf/src/rng.rs | 78 ++++++++++++++++++++++++++++-------------- 2 files changed, 76 insertions(+), 26 deletions(-) diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index 0c5dd059d..398bfed48 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -1039,3 +1039,27 @@ pub fn init(config: config::Config) -> Peripherals { peripherals } + +/// Operating modes for peripherals. +pub mod mode { + trait SealedMode {} + + /// Operating mode for a peripheral. + #[allow(private_bounds)] + pub trait Mode: SealedMode {} + + macro_rules! impl_mode { + ($name:ident) => { + impl SealedMode for $name {} + impl Mode for $name {} + }; + } + + /// Blocking mode. + pub struct Blocking; + /// Async mode. + pub struct Async; + + impl_mode!(Blocking); + impl_mode!(Async); +} diff --git a/embassy-nrf/src/rng.rs b/embassy-nrf/src/rng.rs index 7e42dc938..9d3130e6e 100644 --- a/embassy-nrf/src/rng.rs +++ b/embassy-nrf/src/rng.rs @@ -14,6 +14,7 @@ use embassy_hal_internal::{Peri, PeripheralType}; use embassy_sync::waitqueue::WakerRegistration; use crate::interrupt::typelevel::Interrupt; +use crate::mode::{Async, Blocking, Mode}; use crate::{interrupt, pac}; /// Interrupt handler. @@ -55,11 +56,31 @@ impl interrupt::typelevel::Handler for InterruptHandl /// A wrapper around an nRF RNG peripheral. /// /// It has a non-blocking API, and a blocking api through `rand`. -pub struct Rng<'d, T: Instance> { +pub struct Rng<'d, T: Instance, M: Mode> { _peri: Peri<'d, T>, + _phantom: PhantomData, } -impl<'d, T: Instance> Rng<'d, T> { +impl<'d, T: Instance> Rng<'d, T, Blocking> { + /// Creates a new RNG driver from the `RNG` peripheral and interrupt. + /// + /// SAFETY: The future returned from `fill_bytes` must not have its lifetime end without running its destructor, + /// e.g. using `mem::forget`. + /// + /// The synchronous API is safe. + pub fn new_blocking(rng: Peri<'d, T>) -> Self { + let this = Self { + _peri: rng, + _phantom: PhantomData, + }; + + this.stop(); + + this + } +} + +impl<'d, T: Instance> Rng<'d, T, Async> { /// Creates a new RNG driver from the `RNG` peripheral and interrupt. /// /// SAFETY: The future returned from `fill_bytes` must not have its lifetime end without running its destructor, @@ -70,7 +91,10 @@ impl<'d, T: Instance> Rng<'d, T> { rng: Peri<'d, T>, _irq: impl interrupt::typelevel::Binding> + 'd, ) -> Self { - let this = Self { _peri: rng }; + let this = Self { + _peri: rng, + _phantom: PhantomData, + }; this.stop(); this.disable_irq(); @@ -81,14 +105,6 @@ impl<'d, T: Instance> Rng<'d, T> { this } - fn stop(&self) { - T::regs().tasks_stop().write_value(1) - } - - fn start(&self) { - T::regs().tasks_start().write_value(1) - } - fn enable_irq(&self) { T::regs().intenset().write(|w| w.set_valrdy(true)); } @@ -97,16 +113,6 @@ impl<'d, T: Instance> Rng<'d, T> { T::regs().intenclr().write(|w| w.set_valrdy(true)); } - /// Enable or disable the RNG's bias correction. - /// - /// Bias correction removes any bias towards a '1' or a '0' in the bits generated. - /// However, this makes the generation of numbers slower. - /// - /// Defaults to disabled. - pub fn set_bias_correction(&self, enable: bool) { - T::regs().config().write(|w| w.set_dercen(enable)) - } - /// Fill the buffer with random bytes. pub async fn fill_bytes(&mut self, dest: &mut [u8]) { if dest.is_empty() { @@ -153,6 +159,26 @@ impl<'d, T: Instance> Rng<'d, T> { // Trigger the teardown drop(on_drop); } +} + +impl<'d, T: Instance, M: Mode> Rng<'d, T, M> { + fn stop(&self) { + T::regs().tasks_stop().write_value(1) + } + + fn start(&self) { + T::regs().tasks_start().write_value(1) + } + + /// Enable or disable the RNG's bias correction. + /// + /// Bias correction removes any bias towards a '1' or a '0' in the bits generated. + /// However, this makes the generation of numbers slower. + /// + /// Defaults to disabled. + pub fn set_bias_correction(&self, enable: bool) { + T::regs().config().write(|w| w.set_dercen(enable)) + } /// Fill the buffer with random bytes, blocking version. pub fn blocking_fill_bytes(&mut self, dest: &mut [u8]) { @@ -184,7 +210,7 @@ impl<'d, T: Instance> Rng<'d, T> { } } -impl<'d, T: Instance> Drop for Rng<'d, T> { +impl<'d, T: Instance, M: Mode> Drop for Rng<'d, T, M> { fn drop(&mut self) { self.stop(); critical_section::with(|cs| { @@ -195,7 +221,7 @@ impl<'d, T: Instance> Drop for Rng<'d, T> { } } -impl<'d, T: Instance> rand_core_06::RngCore for Rng<'d, T> { +impl<'d, T: Instance, M: Mode> rand_core_06::RngCore for Rng<'d, T, M> { fn fill_bytes(&mut self, dest: &mut [u8]) { self.blocking_fill_bytes(dest); } @@ -211,9 +237,9 @@ impl<'d, T: Instance> rand_core_06::RngCore for Rng<'d, T> { } } -impl<'d, T: Instance> rand_core_06::CryptoRng for Rng<'d, T> {} +impl<'d, T: Instance, M: Mode> rand_core_06::CryptoRng for Rng<'d, T, M> {} -impl<'d, T: Instance> rand_core_09::RngCore for Rng<'d, T> { +impl<'d, T: Instance, M: Mode> rand_core_09::RngCore for Rng<'d, T, M> { fn fill_bytes(&mut self, dest: &mut [u8]) { self.blocking_fill_bytes(dest); } @@ -225,7 +251,7 @@ impl<'d, T: Instance> rand_core_09::RngCore for Rng<'d, T> { } } -impl<'d, T: Instance> rand_core_09::CryptoRng for Rng<'d, T> {} +impl<'d, T: Instance, M: Mode> rand_core_09::CryptoRng for Rng<'d, T, M> {} /// Peripheral static state pub(crate) struct State { From 0bbde1f65964acccb52ca8913da0f99511d29336 Mon Sep 17 00:00:00 2001 From: Adam Morgan Date: Mon, 19 May 2025 16:02:20 -0600 Subject: [PATCH 4/5] Add support for rtc_v3h7rs --- embassy-stm32/src/rtc/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index b16c6fdca..49f423f37 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -25,7 +25,7 @@ use crate::time::Hertz; ), path = "v2.rs" )] -#[cfg_attr(any(rtc_v3, rtc_v3u5, rtc_v3l5), path = "v3.rs")] +#[cfg_attr(any(rtc_v3, rtc_v3u5, rtc_v3l5, rtc_v3h7rs), path = "v3.rs")] mod _version; #[allow(unused_imports)] pub use _version::*; From 3c025ff3772f6c20d53151a25b8cca9598bfcb2c Mon Sep 17 00:00:00 2001 From: Adam Morgan Date: Tue, 20 May 2025 09:17:38 -0600 Subject: [PATCH 5/5] Update stm32-metapac tag --- embassy-stm32/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 413c92cce..2ab4f9960 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -81,7 +81,7 @@ futures-util = { version = "0.3.30", default-features = false } sdio-host = "0.9.0" critical-section = "1.1" #stm32-metapac = { version = "16" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-7251801e3273011ce28a89e8f2e45eec2e419e26" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-27ef8fba3483187e852eaf3796d827259f61e8ec" } vcell = "0.1.3" nb = "1.0.0" @@ -110,7 +110,7 @@ proc-macro2 = "1.0.36" quote = "1.0.15" #stm32-metapac = { version = "16", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-7251801e3273011ce28a89e8f2e45eec2e419e26", default-features = false, features = ["metadata"] } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-27ef8fba3483187e852eaf3796d827259f61e8ec", default-features = false, features = ["metadata"] } [features] default = ["rt"]