aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2025-11-25 07:45:01 -0600
committerxoviat <[email protected]>2025-11-25 07:45:01 -0600
commit3ba8bb866a19a09f25e0b21419a068fd765a9033 (patch)
tree47b46abc32c10767b4c171675c86d758cd60c825
parent5ffb3698541674d57fddb22044ac0f06397c6113 (diff)
stm32: allow split irqs for time driver
-rw-r--r--embassy-stm32/CHANGELOG.md1
-rw-r--r--embassy-stm32/build.rs49
-rw-r--r--embassy-stm32/src/time_driver.rs126
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
7 7
8## Unreleased - ReleaseDate 8## Unreleased - ReleaseDate
9 9
10- fix: fix incorrect handling of split interrupts in timer driver
10- change: low power: store stop mode for dma channels 11- change: low power: store stop mode for dma channels
11- fix: Fixed ADC4 enable() for WBA 12- fix: Fixed ADC4 enable() for WBA
12- feat: allow use of anyadcchannel for adc4 13- 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};
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}