aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2025-11-26 15:29:43 +0000
committerGitHub <[email protected]>2025-11-26 15:29:43 +0000
commit9879f8de1e5c1af80218d61837ed71d7c19c3fe8 (patch)
tree485dff5586903be2dd67ecb33b7bc32f12719120
parent9fa4f7309895bab81eb0e398d8f457ee528aad69 (diff)
parentdfd0d31ff61b2efa5561fb44fc08a6d7ea4e5d41 (diff)
Merge pull request #4940 from xoviat/time
stm32: allow split irqs for time driver
-rwxr-xr-xci.sh1
-rw-r--r--embassy-stm32/CHANGELOG.md1
-rw-r--r--embassy-stm32/build.rs49
-rw-r--r--embassy-stm32/src/time_driver.rs126
4 files changed, 47 insertions, 130 deletions
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
65# flaky 65# flaky
66rm out/tests/rpi-pico/pwm 66rm out/tests/rpi-pico/pwm
67rm out/tests/rpi-pico/cyw43-perf 67rm out/tests/rpi-pico/cyw43-perf
68rm out/tests/rpi-pico/uart_buffered
68 69
69# tests are implemented but the HIL test farm doesn't actually have these boards, yet 70# tests are implemented but the HIL test farm doesn't actually have these boards, yet
70rm -rf out/tests/stm32c071rb 71rm -rf out/tests/stm32c071rb
diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md
index 5c31b5a11..4c38b0add 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
7 7
8## Unreleased - ReleaseDate 8## Unreleased - ReleaseDate
9 9
10- fix: fix incorrect handling of split interrupts in timer driver
10- feat: allow granular stop for regular usart 11- feat: allow granular stop for regular usart
11- feat: Add continuous waveform method to SimplePWM 12- feat: Add continuous waveform method to SimplePWM
12- change: remove waveform timer method 13- change: remove waveform timer method
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};
9use quote::{format_ident, quote}; 9use quote::{format_ident, quote};
10use stm32_metapac::metadata::ir::BitOffset; 10use stm32_metapac::metadata::ir::BitOffset;
11use stm32_metapac::metadata::{ 11use stm32_metapac::metadata::{
12 ALL_CHIPS, ALL_PERIPHERAL_VERSIONS, METADATA, MemoryRegion, MemoryRegionKind, PeripheralRccKernelClock, 12 ALL_CHIPS, ALL_PERIPHERAL_VERSIONS, METADATA, MemoryRegion, MemoryRegionKind, Peripheral, PeripheralRccKernelClock,
13 PeripheralRccRegister, PeripheralRegisters, StopMode, 13 PeripheralRccRegister, PeripheralRegisters, StopMode,
14}; 14};
15 15
@@ -133,6 +133,9 @@ fn main() {
133 cfgs.enable("backup_sram") 133 cfgs.enable("backup_sram")
134 } 134 }
135 135
136 // compile a map of peripherals
137 let peripheral_map: BTreeMap<&str, &Peripheral> = METADATA.peripherals.iter().map(|p| (p.name, p)).collect();
138
136 // generate one singleton per peripheral (with many exceptions...) 139 // generate one singleton per peripheral (with many exceptions...)
137 for p in METADATA.peripherals { 140 for p in METADATA.peripherals {
138 if let Some(r) = &p.registers { 141 if let Some(r) = &p.registers {
@@ -319,9 +322,33 @@ fn main() {
319 _ => panic!("unknown time_driver {:?}", time_driver), 322 _ => panic!("unknown time_driver {:?}", time_driver),
320 }; 323 };
321 324
322 if !time_driver_singleton.is_empty() { 325 let time_driver_irq_decl = if !time_driver_singleton.is_empty() {
323 cfgs.enable(format!("time_driver_{}", time_driver_singleton.to_lowercase())); 326 cfgs.enable(format!("time_driver_{}", time_driver_singleton.to_lowercase()));
324 } 327
328 let p = peripheral_map.get(time_driver_singleton).unwrap();
329 let irqs: BTreeSet<_> = p
330 .interrupts
331 .iter()
332 .filter(|i| i.signal == "CC" || i.signal == "UP")
333 .map(|i| i.interrupt.to_ascii_uppercase())
334 .collect();
335
336 irqs.iter()
337 .map(|i| {
338 let irq = format_ident!("{}", i);
339 quote! {
340 #[cfg(feature = "rt")]
341 #[interrupt]
342 fn #irq() {
343 crate::time_driver::get_driver().on_interrupt();
344 }
345 }
346 })
347 .collect()
348 } else {
349 TokenStream::new()
350 };
351
325 for tim in [ 352 for tim in [
326 "tim1", "tim2", "tim3", "tim4", "tim5", "tim8", "tim9", "tim12", "tim15", "tim20", "tim21", "tim22", "tim23", 353 "tim1", "tim2", "tim3", "tim4", "tim5", "tim8", "tim9", "tim12", "tim15", "tim20", "tim21", "tim22", "tim23",
327 "tim24", 354 "tim24",
@@ -371,6 +398,8 @@ fn main() {
371 ); 398 );
372 }); 399 });
373 400
401 g.extend(time_driver_irq_decl);
402
374 // ======== 403 // ========
375 // Generate FLASH regions 404 // Generate FLASH regions
376 cfgs.declare("flash"); 405 cfgs.declare("flash");
@@ -1862,7 +1891,7 @@ fn main() {
1862 flash_regions_table.push(row); 1891 flash_regions_table.push(row);
1863 } 1892 }
1864 1893
1865 let gpio_base = METADATA.peripherals.iter().find(|p| p.name == "GPIOA").unwrap().address as u32; 1894 let gpio_base = peripheral_map.get("GPIOA").unwrap().address as u32;
1866 let gpio_stride = 0x400; 1895 let gpio_stride = 0x400;
1867 1896
1868 for pin in METADATA.pins { 1897 for pin in METADATA.pins {
@@ -1980,11 +2009,11 @@ fn main() {
1980 continue; 2009 continue;
1981 } 2010 }
1982 2011
1983 let stop_mode = METADATA 2012 let dma_peri = peripheral_map.get(ch.dma).unwrap();
1984 .peripherals 2013 let stop_mode = dma_peri
1985 .iter() 2014 .rcc
1986 .find(|p| p.name == ch.dma) 2015 .as_ref()
1987 .map(|p| p.rcc.as_ref().map(|rcc| rcc.stop_mode.clone()).unwrap_or_default()) 2016 .map(|rcc| rcc.stop_mode.clone())
1988 .unwrap_or_default(); 2017 .unwrap_or_default();
1989 2018
1990 let stop_mode = match stop_mode { 2019 let stop_mode = match stop_mode {
@@ -2009,8 +2038,6 @@ fn main() {
2009 2038
2010 let dma = format_ident!("{}", ch.dma); 2039 let dma = format_ident!("{}", ch.dma);
2011 let ch_num = ch.channel as usize; 2040 let ch_num = ch.channel as usize;
2012
2013 let dma_peri = METADATA.peripherals.iter().find(|p| p.name == ch.dma).unwrap();
2014 let bi = dma_peri.registers.as_ref().unwrap(); 2041 let bi = dma_peri.registers.as_ref().unwrap();
2015 2042
2016 let dma_info = match bi.kind { 2043 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};
14 14
15use crate::interrupt::typelevel::Interrupt; 15use crate::interrupt::typelevel::Interrupt;
16use crate::pac::timer::vals; 16use crate::pac::timer::vals;
17use crate::peripherals;
17use crate::rcc::{self, SealedRccPeripheral}; 18use crate::rcc::{self, SealedRccPeripheral};
18#[cfg(feature = "low-power")] 19#[cfg(feature = "low-power")]
19use crate::rtc::Rtc; 20use crate::rtc::Rtc;
20use crate::timer::{CoreInstance, GeneralInstance1Channel}; 21use crate::timer::{CoreInstance, GeneralInstance1Channel};
21use crate::{interrupt, peripherals};
22 22
23// NOTE regarding ALARM_COUNT: 23// NOTE regarding ALARM_COUNT:
24// 24//
@@ -56,121 +56,6 @@ type T = peripherals::TIM23;
56#[cfg(time_driver_tim24)] 56#[cfg(time_driver_tim24)]
57type T = peripherals::TIM24; 57type T = peripherals::TIM24;
58 58
59foreach_interrupt! {
60 (TIM1, timer, $block:ident, CC, $irq:ident) => {
61 #[cfg(time_driver_tim1)]
62 #[cfg(feature = "rt")]
63 #[interrupt]
64 fn $irq() {
65 DRIVER.on_interrupt()
66 }
67 };
68 (TIM2, timer, $block:ident, CC, $irq:ident) => {
69 #[cfg(time_driver_tim2)]
70 #[cfg(feature = "rt")]
71 #[interrupt]
72 fn $irq() {
73 DRIVER.on_interrupt()
74 }
75 };
76 (TIM3, timer, $block:ident, CC, $irq:ident) => {
77 #[cfg(time_driver_tim3)]
78 #[cfg(feature = "rt")]
79 #[interrupt]
80 fn $irq() {
81 DRIVER.on_interrupt()
82 }
83 };
84 (TIM4, timer, $block:ident, CC, $irq:ident) => {
85 #[cfg(time_driver_tim4)]
86 #[cfg(feature = "rt")]
87 #[interrupt]
88 fn $irq() {
89 DRIVER.on_interrupt()
90 }
91 };
92 (TIM5, timer, $block:ident, CC, $irq:ident) => {
93 #[cfg(time_driver_tim5)]
94 #[cfg(feature = "rt")]
95 #[interrupt]
96 fn $irq() {
97 DRIVER.on_interrupt()
98 }
99 };
100 (TIM8, timer, $block:ident, CC, $irq:ident) => {
101 #[cfg(time_driver_tim8)]
102 #[cfg(feature = "rt")]
103 #[interrupt]
104 fn $irq() {
105 DRIVER.on_interrupt()
106 }
107 };
108 (TIM9, timer, $block:ident, CC, $irq:ident) => {
109 #[cfg(time_driver_tim9)]
110 #[cfg(feature = "rt")]
111 #[interrupt]
112 fn $irq() {
113 DRIVER.on_interrupt()
114 }
115 };
116 (TIM12, timer, $block:ident, CC, $irq:ident) => {
117 #[cfg(time_driver_tim12)]
118 #[cfg(feature = "rt")]
119 #[interrupt]
120 fn $irq() {
121 DRIVER.on_interrupt()
122 }
123 };
124 (TIM15, timer, $block:ident, CC, $irq:ident) => {
125 #[cfg(time_driver_tim15)]
126 #[cfg(feature = "rt")]
127 #[interrupt]
128 fn $irq() {
129 DRIVER.on_interrupt()
130 }
131 };
132 (TIM20, timer, $block:ident, CC, $irq:ident) => {
133 #[cfg(time_driver_tim20)]
134 #[cfg(feature = "rt")]
135 #[interrupt]
136 fn $irq() {
137 DRIVER.on_interrupt()
138 }
139 };
140 (TIM21, timer, $block:ident, CC, $irq:ident) => {
141 #[cfg(time_driver_tim21)]
142 #[cfg(feature = "rt")]
143 #[interrupt]
144 fn $irq() {
145 DRIVER.on_interrupt()
146 }
147 };
148 (TIM22, timer, $block:ident, CC, $irq:ident) => {
149 #[cfg(time_driver_tim22)]
150 #[cfg(feature = "rt")]
151 #[interrupt]
152 fn $irq() {
153 DRIVER.on_interrupt()
154 }
155 };
156 (TIM23, timer, $block:ident, CC, $irq:ident) => {
157 #[cfg(time_driver_tim23)]
158 #[cfg(feature = "rt")]
159 #[interrupt]
160 fn $irq() {
161 DRIVER.on_interrupt()
162 }
163 };
164 (TIM24, timer, $block:ident, CC, $irq:ident) => {
165 #[cfg(time_driver_tim24)]
166 #[cfg(feature = "rt")]
167 #[interrupt]
168 fn $irq() {
169 DRIVER.on_interrupt()
170 }
171 };
172}
173
174fn regs_gp16() -> TimGp16 { 59fn regs_gp16() -> TimGp16 {
175 unsafe { TimGp16::from_ptr(T::regs()) } 60 unsafe { TimGp16::from_ptr(T::regs()) }
176} 61}
@@ -282,7 +167,11 @@ impl RtcDriver {
282 r.cnt().write(|w| w.set_cnt(self.saved_count.load(Ordering::SeqCst))); 167 r.cnt().write(|w| w.set_cnt(self.saved_count.load(Ordering::SeqCst)));
283 168
284 <T as GeneralInstance1Channel>::CaptureCompareInterrupt::unpend(); 169 <T as GeneralInstance1Channel>::CaptureCompareInterrupt::unpend();
285 unsafe { <T as GeneralInstance1Channel>::CaptureCompareInterrupt::enable() }; 170 <T as CoreInstance>::UpdateInterrupt::unpend();
171 unsafe {
172 <T as GeneralInstance1Channel>::CaptureCompareInterrupt::enable();
173 <T as CoreInstance>::UpdateInterrupt::enable();
174 }
286 } 175 }
287 176
288 fn init(&'static self, cs: CriticalSection) { 177 fn init(&'static self, cs: CriticalSection) {
@@ -290,7 +179,7 @@ impl RtcDriver {
290 regs_gp16().cr1().modify(|w| w.set_cen(true)); 179 regs_gp16().cr1().modify(|w| w.set_cen(true));
291 } 180 }
292 181
293 fn on_interrupt(&self) { 182 pub(crate) fn on_interrupt(&self) {
294 let r = regs_gp16(); 183 let r = regs_gp16();
295 184
296 critical_section::with(|cs| { 185 critical_section::with(|cs| {
@@ -508,7 +397,6 @@ impl Driver for RtcDriver {
508 } 397 }
509} 398}
510 399
511#[cfg(feature = "low-power")]
512pub(crate) const fn get_driver() -> &'static RtcDriver { 400pub(crate) const fn get_driver() -> &'static RtcDriver {
513 &DRIVER 401 &DRIVER
514} 402}