From 3ba8bb866a19a09f25e0b21419a068fd765a9033 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 25 Nov 2025 07:45:01 -0600 Subject: stm32: allow split irqs for time driver --- embassy-stm32/CHANGELOG.md | 1 + embassy-stm32/build.rs | 49 +++++++++++---- embassy-stm32/src/time_driver.rs | 126 +++------------------------------------ 3 files changed, 46 insertions(+), 130 deletions(-) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index a66b2d437..0f19b14b3 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +- fix: fix incorrect handling of split interrupts in timer driver - change: low power: store stop mode for dma channels - fix: Fixed ADC4 enable() for WBA - feat: allow use of anyadcchannel for adc4 diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 109571e8f..46d6290e7 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -9,7 +9,7 @@ use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote}; use stm32_metapac::metadata::ir::BitOffset; use stm32_metapac::metadata::{ - ALL_CHIPS, ALL_PERIPHERAL_VERSIONS, METADATA, MemoryRegion, MemoryRegionKind, PeripheralRccKernelClock, + ALL_CHIPS, ALL_PERIPHERAL_VERSIONS, METADATA, MemoryRegion, MemoryRegionKind, Peripheral, PeripheralRccKernelClock, PeripheralRccRegister, PeripheralRegisters, StopMode, }; @@ -133,6 +133,9 @@ fn main() { cfgs.enable("backup_sram") } + // compile a map of peripherals + let peripheral_map: BTreeMap<&str, &Peripheral> = METADATA.peripherals.iter().map(|p| (p.name, p)).collect(); + // generate one singleton per peripheral (with many exceptions...) for p in METADATA.peripherals { if let Some(r) = &p.registers { @@ -319,9 +322,33 @@ fn main() { _ => panic!("unknown time_driver {:?}", time_driver), }; - if !time_driver_singleton.is_empty() { + let time_driver_irq_decl = if !time_driver_singleton.is_empty() { cfgs.enable(format!("time_driver_{}", time_driver_singleton.to_lowercase())); - } + + let p = peripheral_map.get(time_driver_singleton).unwrap(); + let irqs: BTreeSet<_> = p + .interrupts + .iter() + .filter(|i| i.signal == "CC" || i.signal == "UP") + .map(|i| i.interrupt.to_ascii_uppercase()) + .collect(); + + irqs.iter() + .map(|i| { + let irq = format_ident!("{}", i); + quote! { + #[cfg(feature = "rt")] + #[interrupt] + fn #irq() { + crate::time_driver::get_driver().on_interrupt(); + } + } + }) + .collect() + } else { + TokenStream::new() + }; + for tim in [ "tim1", "tim2", "tim3", "tim4", "tim5", "tim8", "tim9", "tim12", "tim15", "tim20", "tim21", "tim22", "tim23", "tim24", @@ -371,6 +398,8 @@ fn main() { ); }); + g.extend(time_driver_irq_decl); + // ======== // Generate FLASH regions cfgs.declare("flash"); @@ -1862,7 +1891,7 @@ fn main() { flash_regions_table.push(row); } - let gpio_base = METADATA.peripherals.iter().find(|p| p.name == "GPIOA").unwrap().address as u32; + let gpio_base = peripheral_map.get("GPIOA").unwrap().address as u32; let gpio_stride = 0x400; for pin in METADATA.pins { @@ -1980,11 +2009,11 @@ fn main() { continue; } - let stop_mode = METADATA - .peripherals - .iter() - .find(|p| p.name == ch.dma) - .map(|p| p.rcc.as_ref().map(|rcc| rcc.stop_mode.clone()).unwrap_or_default()) + let dma_peri = peripheral_map.get(ch.dma).unwrap(); + let stop_mode = dma_peri + .rcc + .as_ref() + .map(|rcc| rcc.stop_mode.clone()) .unwrap_or_default(); let stop_mode = match stop_mode { @@ -2009,8 +2038,6 @@ fn main() { let dma = format_ident!("{}", ch.dma); let ch_num = ch.channel as usize; - - let dma_peri = METADATA.peripherals.iter().find(|p| p.name == ch.dma).unwrap(); let bi = dma_peri.registers.as_ref().unwrap(); let dma_info = match bi.kind { diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs index 0b75aef92..cfcf5f3fd 100644 --- a/embassy-stm32/src/time_driver.rs +++ b/embassy-stm32/src/time_driver.rs @@ -14,11 +14,11 @@ use stm32_metapac::timer::{TimGp16, regs}; use crate::interrupt::typelevel::Interrupt; use crate::pac::timer::vals; +use crate::peripherals; use crate::rcc::{self, SealedRccPeripheral}; #[cfg(feature = "low-power")] use crate::rtc::Rtc; use crate::timer::{CoreInstance, GeneralInstance1Channel}; -use crate::{interrupt, peripherals}; // NOTE regarding ALARM_COUNT: // @@ -56,121 +56,6 @@ type T = peripherals::TIM23; #[cfg(time_driver_tim24)] type T = peripherals::TIM24; -foreach_interrupt! { - (TIM1, timer, $block:ident, CC, $irq:ident) => { - #[cfg(time_driver_tim1)] - #[cfg(feature = "rt")] - #[interrupt] - fn $irq() { - DRIVER.on_interrupt() - } - }; - (TIM2, timer, $block:ident, CC, $irq:ident) => { - #[cfg(time_driver_tim2)] - #[cfg(feature = "rt")] - #[interrupt] - fn $irq() { - DRIVER.on_interrupt() - } - }; - (TIM3, timer, $block:ident, CC, $irq:ident) => { - #[cfg(time_driver_tim3)] - #[cfg(feature = "rt")] - #[interrupt] - fn $irq() { - DRIVER.on_interrupt() - } - }; - (TIM4, timer, $block:ident, CC, $irq:ident) => { - #[cfg(time_driver_tim4)] - #[cfg(feature = "rt")] - #[interrupt] - fn $irq() { - DRIVER.on_interrupt() - } - }; - (TIM5, timer, $block:ident, CC, $irq:ident) => { - #[cfg(time_driver_tim5)] - #[cfg(feature = "rt")] - #[interrupt] - fn $irq() { - DRIVER.on_interrupt() - } - }; - (TIM8, timer, $block:ident, CC, $irq:ident) => { - #[cfg(time_driver_tim8)] - #[cfg(feature = "rt")] - #[interrupt] - fn $irq() { - DRIVER.on_interrupt() - } - }; - (TIM9, timer, $block:ident, CC, $irq:ident) => { - #[cfg(time_driver_tim9)] - #[cfg(feature = "rt")] - #[interrupt] - fn $irq() { - DRIVER.on_interrupt() - } - }; - (TIM12, timer, $block:ident, CC, $irq:ident) => { - #[cfg(time_driver_tim12)] - #[cfg(feature = "rt")] - #[interrupt] - fn $irq() { - DRIVER.on_interrupt() - } - }; - (TIM15, timer, $block:ident, CC, $irq:ident) => { - #[cfg(time_driver_tim15)] - #[cfg(feature = "rt")] - #[interrupt] - fn $irq() { - DRIVER.on_interrupt() - } - }; - (TIM20, timer, $block:ident, CC, $irq:ident) => { - #[cfg(time_driver_tim20)] - #[cfg(feature = "rt")] - #[interrupt] - fn $irq() { - DRIVER.on_interrupt() - } - }; - (TIM21, timer, $block:ident, CC, $irq:ident) => { - #[cfg(time_driver_tim21)] - #[cfg(feature = "rt")] - #[interrupt] - fn $irq() { - DRIVER.on_interrupt() - } - }; - (TIM22, timer, $block:ident, CC, $irq:ident) => { - #[cfg(time_driver_tim22)] - #[cfg(feature = "rt")] - #[interrupt] - fn $irq() { - DRIVER.on_interrupt() - } - }; - (TIM23, timer, $block:ident, CC, $irq:ident) => { - #[cfg(time_driver_tim23)] - #[cfg(feature = "rt")] - #[interrupt] - fn $irq() { - DRIVER.on_interrupt() - } - }; - (TIM24, timer, $block:ident, CC, $irq:ident) => { - #[cfg(time_driver_tim24)] - #[cfg(feature = "rt")] - #[interrupt] - fn $irq() { - DRIVER.on_interrupt() - } - }; -} - fn regs_gp16() -> TimGp16 { unsafe { TimGp16::from_ptr(T::regs()) } } @@ -282,7 +167,11 @@ impl RtcDriver { r.cnt().write(|w| w.set_cnt(self.saved_count.load(Ordering::SeqCst))); ::CaptureCompareInterrupt::unpend(); - unsafe { ::CaptureCompareInterrupt::enable() }; + ::UpdateInterrupt::unpend(); + unsafe { + ::CaptureCompareInterrupt::enable(); + ::UpdateInterrupt::enable(); + } } fn init(&'static self, cs: CriticalSection) { @@ -290,7 +179,7 @@ impl RtcDriver { regs_gp16().cr1().modify(|w| w.set_cen(true)); } - fn on_interrupt(&self) { + pub(crate) fn on_interrupt(&self) { let r = regs_gp16(); critical_section::with(|cs| { @@ -508,7 +397,6 @@ impl Driver for RtcDriver { } } -#[cfg(feature = "low-power")] pub(crate) const fn get_driver() -> &'static RtcDriver { &DRIVER } -- cgit From dfd0d31ff61b2efa5561fb44fc08a6d7ea4e5d41 Mon Sep 17 00:00:00 2001 From: xoviat Date: Wed, 26 Nov 2025 09:26:55 -0600 Subject: remove rp test --- ci.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/ci.sh b/ci.sh index b4ed0dc18..cee761500 100755 --- a/ci.sh +++ b/ci.sh @@ -65,6 +65,7 @@ rm out/tests/pimoroni-pico-plus-2/pwm # flaky rm out/tests/rpi-pico/pwm rm out/tests/rpi-pico/cyw43-perf +rm out/tests/rpi-pico/uart_buffered # tests are implemented but the HIL test farm doesn't actually have these boards, yet rm -rf out/tests/stm32c071rb -- cgit