aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/timer/mod.rs
diff options
context:
space:
mode:
authorBruno Bousquet <[email protected]>2024-05-06 02:47:42 -0400
committerBruno Bousquet <[email protected]>2024-05-06 02:47:42 -0400
commit55c8d3f4743bc653c1659dc3e961df86afe7d3db (patch)
tree3ec6a5afaf16d4a7aa38fd532a661e597a832acd /embassy-stm32/src/timer/mod.rs
parentb662dfb1838a72d243e939da9349c68c8fef5bdc (diff)
add async capture
Diffstat (limited to 'embassy-stm32/src/timer/mod.rs')
-rw-r--r--embassy-stm32/src/timer/mod.rs93
1 files changed, 92 insertions, 1 deletions
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index 9a1fbcd61..4b4929aeb 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -1,5 +1,8 @@
1//! Timers, PWM, quadrature decoder. 1//! Timers, PWM, quadrature decoder.
2 2
3use core::marker::PhantomData;
4use embassy_sync::waitqueue::AtomicWaker;
5
3#[cfg(not(stm32l0))] 6#[cfg(not(stm32l0))]
4pub mod complementary_pwm; 7pub mod complementary_pwm;
5pub mod input_capture; 8pub mod input_capture;
@@ -46,8 +49,29 @@ pub enum TimerBits {
46 Bits32, 49 Bits32,
47} 50}
48 51
52struct State {
53 up_waker: AtomicWaker,
54 cc_waker: [AtomicWaker; 4],
55}
56
57impl State {
58 const fn new() -> Self {
59 const NEW_AW: AtomicWaker = AtomicWaker::new();
60 Self {
61 up_waker: NEW_AW,
62 cc_waker: [NEW_AW; 4],
63 }
64 }
65}
66
67trait SealedInstance: RccPeripheral {
68 /// Async state for this timer
69 fn state() -> &'static State;
70}
71
49/// Core timer instance. 72/// Core timer instance.
50pub trait CoreInstance: RccPeripheral + 'static { 73#[allow(private_bounds)]
74pub trait CoreInstance: SealedInstance + 'static {
51 /// Update Interrupt for this timer. 75 /// Update Interrupt for this timer.
52 type UpdateInterrupt: interrupt::typelevel::Interrupt; 76 type UpdateInterrupt: interrupt::typelevel::Interrupt;
53 77
@@ -144,6 +168,13 @@ dma_trait!(Ch4Dma, GeneralInstance4Channel);
144#[allow(unused)] 168#[allow(unused)]
145macro_rules! impl_core_timer { 169macro_rules! impl_core_timer {
146 ($inst:ident, $bits:expr) => { 170 ($inst:ident, $bits:expr) => {
171 impl SealedInstance for crate::peripherals::$inst {
172 fn state() -> &'static State {
173 static STATE: State = State::new();
174 &STATE
175 }
176 }
177
147 impl CoreInstance for crate::peripherals::$inst { 178 impl CoreInstance for crate::peripherals::$inst {
148 type UpdateInterrupt = crate::_generated::peripheral_interrupts::$inst::UP; 179 type UpdateInterrupt = crate::_generated::peripheral_interrupts::$inst::UP;
149 180
@@ -286,3 +317,63 @@ foreach_interrupt! {
286 impl AdvancedInstance4Channel for crate::peripherals::$inst {} 317 impl AdvancedInstance4Channel for crate::peripherals::$inst {}
287 }; 318 };
288} 319}
320
321/// Update interrupt handler.
322pub struct UpdateInterruptHandler<T: CoreInstance> {
323 _phantom: PhantomData<T>,
324}
325
326impl<T: CoreInstance> interrupt::typelevel::Handler<T::UpdateInterrupt> for UpdateInterruptHandler<T> {
327 unsafe fn on_interrupt() {
328 #[cfg(feature = "low-power")]
329 crate::low_power::on_wakeup_irq();
330
331 let regs = crate::pac::timer::TimCore::from_ptr(T::regs());
332
333 // Read TIM interrupt flags.
334 let sr = regs.sr().read();
335
336 // Mask relevant interrupts (UIE).
337 let bits = sr.0 & 0x00000001;
338
339 // Mask all the channels that fired.
340 regs.dier().modify(|w| w.0 &= !bits);
341
342 // Wake the tasks
343 if sr.uif() {
344 T::state().up_waker.wake();
345 }
346 }
347}
348
349/// Capture/Compare interrupt handler.
350pub struct CaptureCompareInterruptHandler<T: GeneralInstance1Channel> {
351 _phantom: PhantomData<T>,
352}
353
354impl<T: GeneralInstance1Channel> interrupt::typelevel::Handler<T::CaptureCompareInterrupt>
355 for CaptureCompareInterruptHandler<T>
356{
357 unsafe fn on_interrupt() {
358 #[cfg(feature = "low-power")]
359 crate::low_power::on_wakeup_irq();
360
361 let regs = crate::pac::timer::TimGp16::from_ptr(T::regs());
362
363 // Read TIM interrupt flags.
364 let sr = regs.sr().read();
365
366 // Mask relevant interrupts (CCIE).
367 let bits = sr.0 & 0x0000001E;
368
369 // Mask all the channels that fired.
370 regs.dier().modify(|w| w.0 &= !bits);
371
372 // Wake the tasks
373 for ch in 0..4 {
374 if sr.ccif(ch) {
375 T::state().cc_waker[ch].wake();
376 }
377 }
378 }
379}