aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/time_driver.rs108
1 files changed, 43 insertions, 65 deletions
diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs
index 7efe0d3a5..98054e051 100644
--- a/embassy-stm32/src/time_driver.rs
+++ b/embassy-stm32/src/time_driver.rs
@@ -11,12 +11,12 @@ use embassy::time::TICKS_PER_SECOND;
11use stm32_metapac::timer::regs; 11use stm32_metapac::timer::regs;
12 12
13use crate::interrupt; 13use crate::interrupt;
14use crate::interrupt::{CriticalSection, Interrupt}; 14use crate::interrupt::CriticalSection;
15use crate::pac::timer::{vals, TimGp16}; 15use crate::pac::timer::vals;
16use crate::peripherals; 16use crate::peripherals;
17use crate::rcc::sealed::RccPeripheral; 17use crate::rcc::sealed::RccPeripheral;
18 18use crate::timer::sealed::Basic16bitInstance as BasicInstance;
19use self::sealed::Instance as _; 19use crate::timer::sealed::GeneralPurpose16bitInstance as Instance;
20 20
21const ALARM_COUNT: usize = 3; 21const ALARM_COUNT: usize = 3;
22 22
@@ -29,25 +29,35 @@ type T = peripherals::TIM4;
29#[cfg(time_driver_tim5)] 29#[cfg(time_driver_tim5)]
30type T = peripherals::TIM5; 30type T = peripherals::TIM5;
31 31
32#[cfg(time_driver_tim2)] 32crate::pac::interrupts! {
33#[interrupt] 33 (TIM2, timer, $block:ident, UP, $irq:ident) => {
34fn TIM2() { 34 #[cfg(time_driver_tim2)]
35 DRIVER.on_interrupt() 35 #[interrupt]
36} 36 fn $irq() {
37#[cfg(time_driver_tim3)] 37 DRIVER.on_interrupt()
38#[interrupt] 38 }
39fn TIM3() { 39 };
40 DRIVER.on_interrupt() 40 (TIM3, timer, $block:ident, UP, $irq:ident) => {
41} 41 #[cfg(time_driver_tim3)]
42#[cfg(time_driver_tim4)] 42 #[interrupt]
43#[interrupt] 43 fn $irq() {
44fn TIM4() { 44 DRIVER.on_interrupt()
45 DRIVER.on_interrupt() 45 }
46} 46 };
47#[cfg(time_driver_tim5)] 47 (TIM4, timer, $block:ident, UP, $irq:ident) => {
48#[interrupt] 48 #[cfg(time_driver_tim4)]
49fn TIM5() { 49 #[interrupt]
50 DRIVER.on_interrupt() 50 fn $irq() {
51 DRIVER.on_interrupt()
52 }
53 };
54 (TIM5, timer, $block:ident, UP, $irq:ident) => {
55 #[cfg(time_driver_tim5)]
56 #[interrupt]
57 fn $irq() {
58 DRIVER.on_interrupt()
59 }
60 };
51} 61}
52 62
53// Clock timekeeping works with something we call "periods", which are time intervals 63// Clock timekeeping works with something we call "periods", which are time intervals
@@ -93,6 +103,7 @@ impl AlarmState {
93} 103}
94 104
95struct RtcDriver { 105struct RtcDriver {
106 timer: T,
96 /// Number of 2^15 periods elapsed since boot. 107 /// Number of 2^15 periods elapsed since boot.
97 period: AtomicU32, 108 period: AtomicU32,
98 alarm_count: AtomicU8, 109 alarm_count: AtomicU8,
@@ -103,6 +114,7 @@ struct RtcDriver {
103const ALARM_STATE_NEW: AlarmState = AlarmState::new(); 114const ALARM_STATE_NEW: AlarmState = AlarmState::new();
104 115
105embassy::time_driver_impl!(static DRIVER: RtcDriver = RtcDriver { 116embassy::time_driver_impl!(static DRIVER: RtcDriver = RtcDriver {
117 timer: unsafe { core::mem::transmute(()) }, // steal is not const
106 period: AtomicU32::new(0), 118 period: AtomicU32::new(0),
107 alarm_count: AtomicU8::new(0), 119 alarm_count: AtomicU8::new(0),
108 alarms: Mutex::const_new(CriticalSectionRawMutex::new(), [ALARM_STATE_NEW; ALARM_COUNT]), 120 alarms: Mutex::const_new(CriticalSectionRawMutex::new(), [ALARM_STATE_NEW; ALARM_COUNT]),
@@ -110,10 +122,10 @@ embassy::time_driver_impl!(static DRIVER: RtcDriver = RtcDriver {
110 122
111impl RtcDriver { 123impl RtcDriver {
112 fn init(&'static self) { 124 fn init(&'static self) {
113 let r = T::regs(); 125 let r = self.timer.regs_gp16();
114 126
115 T::enable(); 127 <T as RccPeripheral>::enable();
116 T::reset(); 128 <T as RccPeripheral>::reset();
117 129
118 let timer_freq = T::frequency(); 130 let timer_freq = T::frequency();
119 131
@@ -142,7 +154,7 @@ impl RtcDriver {
142 // Enable CC0, disable others 154 // Enable CC0, disable others
143 r.dier().write(|w| w.set_ccie(0, true)); 155 r.dier().write(|w| w.set_ccie(0, true));
144 156
145 let irq: <T as sealed::Instance>::Interrupt = core::mem::transmute(()); 157 let irq: <T as BasicInstance>::Interrupt = core::mem::transmute(());
146 irq.unpend(); 158 irq.unpend();
147 irq.enable(); 159 irq.enable();
148 160
@@ -151,7 +163,7 @@ impl RtcDriver {
151 } 163 }
152 164
153 fn on_interrupt(&self) { 165 fn on_interrupt(&self) {
154 let r = T::regs(); 166 let r = self.timer.regs_gp16();
155 167
156 // NOTE(unsafe) Use critical section to access the methods 168 // NOTE(unsafe) Use critical section to access the methods
157 // XXX: reduce the size of this critical section ? 169 // XXX: reduce the size of this critical section ?
@@ -182,7 +194,7 @@ impl RtcDriver {
182 } 194 }
183 195
184 fn next_period(&self) { 196 fn next_period(&self) {
185 let r = T::regs(); 197 let r = self.timer.regs_gp16();
186 198
187 let period = self.period.fetch_add(1, Ordering::Relaxed) + 1; 199 let period = self.period.fetch_add(1, Ordering::Relaxed) + 1;
188 let t = (period as u64) << 15; 200 let t = (period as u64) << 15;
@@ -224,7 +236,7 @@ impl RtcDriver {
224 236
225impl Driver for RtcDriver { 237impl Driver for RtcDriver {
226 fn now(&self) -> u64 { 238 fn now(&self) -> u64 {
227 let r = T::regs(); 239 let r = self.timer.regs_gp16();
228 240
229 let period = self.period.load(Ordering::Relaxed); 241 let period = self.period.load(Ordering::Relaxed);
230 compiler_fence(Ordering::Acquire); 242 compiler_fence(Ordering::Acquire);
@@ -261,7 +273,7 @@ impl Driver for RtcDriver {
261 273
262 fn set_alarm(&self, alarm: AlarmHandle, timestamp: u64) { 274 fn set_alarm(&self, alarm: AlarmHandle, timestamp: u64) {
263 critical_section::with(|cs| { 275 critical_section::with(|cs| {
264 let r = T::regs(); 276 let r = self.timer.regs_gp16();
265 277
266 let n = alarm.id() as _; 278 let n = alarm.id() as _;
267 let alarm = self.get_alarm(cs, alarm); 279 let alarm = self.get_alarm(cs, alarm);
@@ -291,37 +303,3 @@ impl Driver for RtcDriver {
291pub(crate) fn init() { 303pub(crate) fn init() {
292 DRIVER.init() 304 DRIVER.init()
293} 305}
294
295// ------------------------------------------------------
296
297pub(crate) mod sealed {
298 use super::*;
299 pub trait Instance {
300 type Interrupt: Interrupt;
301
302 fn regs() -> TimGp16;
303 }
304}
305
306pub trait Instance: sealed::Instance + Sized + RccPeripheral + 'static {}
307
308macro_rules! impl_timer {
309 ($inst:ident) => {
310 impl sealed::Instance for peripherals::$inst {
311 type Interrupt = crate::interrupt::$inst;
312
313 fn regs() -> TimGp16 {
314 crate::pac::timer::TimGp16(crate::pac::$inst.0)
315 }
316 }
317
318 impl Instance for peripherals::$inst {}
319 };
320}
321
322crate::pac::peripherals!(
323 (timer, TIM2) => { impl_timer!(TIM2); };
324 (timer, TIM3) => { impl_timer!(TIM3); };
325 (timer, TIM4) => { impl_timer!(TIM4); };
326 (timer, TIM5) => { impl_timer!(TIM5); };
327);