py32_hal/timer/
mod.rs

1//! Timers, PWM, quadrature decoder.
2
3// The following code is modified from embassy-stm32
4// https://github.com/embassy-rs/embassy/tree/main/embassy-stm32
5// Special thanks to the Embassy Project and its contributors for their work!
6
7use core::marker::PhantomData;
8
9use embassy_hal_internal::Peripheral;
10use embassy_sync::waitqueue::AtomicWaker;
11
12pub mod complementary_pwm;
13pub mod input_capture;
14pub mod low_level;
15pub mod pwm_input;
16pub mod qei;
17pub mod simple_pwm;
18
19use crate::interrupt;
20use crate::rcc::RccPeripheral;
21
22/// Timer channel.
23#[derive(Clone, Copy)]
24pub enum Channel {
25    /// Channel 1.
26    Ch1,
27    /// Channel 2.
28    Ch2,
29    /// Channel 3.
30    Ch3,
31    /// Channel 4.
32    Ch4,
33}
34
35impl Channel {
36    /// Get the channel index (0..3)
37    pub fn index(&self) -> usize {
38        match self {
39            Channel::Ch1 => 0,
40            Channel::Ch2 => 1,
41            Channel::Ch3 => 2,
42            Channel::Ch4 => 3,
43        }
44    }
45}
46
47/// Amount of bits of a timer.
48#[derive(Clone, Copy, PartialEq, Eq, Debug)]
49#[cfg_attr(feature = "defmt", derive(defmt::Format))]
50pub enum TimerBits {
51    /// 16 bits.
52    Bits16,
53    #[cfg(py32f072)]
54    /// 32 bits.
55    Bits32,
56}
57
58struct State {
59    up_waker: AtomicWaker,
60    cc_waker: [AtomicWaker; 4],
61}
62
63impl State {
64    const fn new() -> Self {
65        const NEW_AW: AtomicWaker = AtomicWaker::new();
66        Self {
67            up_waker: NEW_AW,
68            cc_waker: [NEW_AW; 4],
69        }
70    }
71}
72
73trait SealedInstance: RccPeripheral + Peripheral<P = Self> {
74    /// Async state for this timer
75    fn state() -> &'static State;
76}
77
78/// Core timer instance.
79#[allow(private_bounds)]
80pub trait CoreInstance: SealedInstance + 'static {
81    /// Update Interrupt for this timer.
82    type UpdateInterrupt: interrupt::typelevel::Interrupt;
83
84    /// Amount of bits this timer has.
85    const BITS: TimerBits;
86
87    /// Registers for this timer.
88    ///
89    /// This is a raw pointer to the register block. The actual register block layout varies depending on the timer type.
90    fn regs() -> *mut ();
91}
92/// Cut-down basic timer instance.
93pub trait BasicNoCr2Instance: CoreInstance {}
94/// Basic timer instance.
95pub trait BasicInstance: BasicNoCr2Instance {}
96
97/// General-purpose 16-bit timer with 1 channel instance.
98pub trait GeneralInstance1Channel: CoreInstance {
99    /// Capture compare interrupt for this timer.
100    type CaptureCompareInterrupt: interrupt::typelevel::Interrupt;
101}
102
103/// General-purpose 16-bit timer with 2 channels instance.
104pub trait GeneralInstance2Channel: GeneralInstance1Channel {
105    /// Trigger event interrupt for this timer.
106    type TriggerInterrupt: interrupt::typelevel::Interrupt;
107}
108
109// This trait add *extra* methods to GeneralInstance4Channel,
110// that GeneralInstance4Channel doesn't use, but the "AdvancedInstance"s need.
111// And it's a private trait, so it's content won't leak to outer namespace.
112//
113// If you want to add a new method to it, please leave a detail comment to explain it.
114trait General4ChBlankSealed {
115    // SimplePwm<'d, T> is implemented for T: GeneralInstance4Channel
116    // Advanced timers implement this trait, but the output needs to be
117    // enabled explicitly.
118    // To support general-purpose and advanced timers, this function is added
119    // here defaulting to noop and overwritten for advanced timers.
120    //
121    // Enable timer outputs.
122    fn enable_outputs(&self) {}
123}
124
125/// General-purpose 16-bit timer with 4 channels instance.
126#[allow(private_bounds)]
127pub trait GeneralInstance4Channel:
128    BasicInstance + GeneralInstance2Channel + General4ChBlankSealed
129{
130}
131
132/// General-purpose 32-bit timer with 4 channels instance.
133pub trait GeneralInstance32bit4Channel: GeneralInstance4Channel {}
134
135/// Advanced 16-bit timer with 1 channel instance.
136pub trait AdvancedInstance1Channel: BasicNoCr2Instance + GeneralInstance1Channel {
137    /// Communication interrupt for this timer.
138    type CommunicationInterrupt: interrupt::typelevel::Interrupt;
139    /// Break input interrupt for this timer.
140    type BreakInputInterrupt: interrupt::typelevel::Interrupt;
141}
142/// Advanced 16-bit timer with 2 channels instance.
143
144pub trait AdvancedInstance2Channel:
145    BasicInstance + GeneralInstance2Channel + AdvancedInstance1Channel
146{
147}
148
149/// Advanced 16-bit timer with 4 channels instance.
150pub trait AdvancedInstance4Channel: AdvancedInstance2Channel + GeneralInstance4Channel {}
151
152pin_trait!(Channel1Pin, GeneralInstance4Channel);
153pin_trait!(Channel2Pin, GeneralInstance4Channel);
154pin_trait!(Channel3Pin, GeneralInstance4Channel);
155pin_trait!(Channel4Pin, GeneralInstance4Channel);
156pin_trait!(ExternalTriggerPin, GeneralInstance4Channel);
157
158pin_trait!(Channel1ComplementaryPin, AdvancedInstance4Channel);
159pin_trait!(Channel2ComplementaryPin, AdvancedInstance4Channel);
160pin_trait!(Channel3ComplementaryPin, AdvancedInstance4Channel);
161pin_trait!(Channel4ComplementaryPin, AdvancedInstance4Channel);
162
163pin_trait!(BreakInputPin, AdvancedInstance4Channel);
164pin_trait!(BreakInput2Pin, AdvancedInstance4Channel);
165
166pin_trait!(BreakInputComparator1Pin, AdvancedInstance4Channel);
167pin_trait!(BreakInputComparator2Pin, AdvancedInstance4Channel);
168
169pin_trait!(BreakInput2Comparator1Pin, AdvancedInstance4Channel);
170pin_trait!(BreakInput2Comparator2Pin, AdvancedInstance4Channel);
171
172// // Update Event trigger DMA for every timer
173// dma_trait!(UpDma, BasicInstance);
174
175// dma_trait!(Ch1Dma, GeneralInstance4Channel);
176// dma_trait!(Ch2Dma, GeneralInstance4Channel);
177// dma_trait!(Ch3Dma, GeneralInstance4Channel);
178// dma_trait!(Ch4Dma, GeneralInstance4Channel);
179
180#[allow(unused)]
181macro_rules! impl_core_timer {
182    ($inst:ident, $bits:expr) => {
183        impl SealedInstance for crate::peripherals::$inst {
184            fn state() -> &'static State {
185                static STATE: State = State::new();
186                &STATE
187            }
188        }
189
190        impl CoreInstance for crate::peripherals::$inst {
191            type UpdateInterrupt = crate::_generated::peripheral_interrupts::$inst::UP;
192
193            const BITS: TimerBits = $bits;
194
195            fn regs() -> *mut () {
196                crate::pac::$inst.as_ptr()
197            }
198        }
199    };
200}
201
202#[allow(unused)]
203macro_rules! impl_general_1ch {
204    ($inst:ident) => {
205        impl GeneralInstance1Channel for crate::peripherals::$inst {
206            type CaptureCompareInterrupt = crate::_generated::peripheral_interrupts::$inst::CC;
207        }
208    };
209}
210
211#[allow(unused)]
212macro_rules! impl_general_2ch {
213    ($inst:ident) => {
214        impl GeneralInstance2Channel for crate::peripherals::$inst {
215            type TriggerInterrupt = crate::_generated::peripheral_interrupts::$inst::TRG;
216        }
217    };
218}
219
220#[allow(unused)]
221macro_rules! impl_advanced_1ch {
222    ($inst:ident) => {
223        impl AdvancedInstance1Channel for crate::peripherals::$inst {
224            type CommunicationInterrupt = crate::_generated::peripheral_interrupts::$inst::COM;
225            type BreakInputInterrupt = crate::_generated::peripheral_interrupts::$inst::BRK;
226        }
227    };
228}
229
230// This macro only apply to "AdvancedInstance(s)",
231// not "GeneralInstance4Channel" itself.
232#[allow(unused)]
233macro_rules! impl_general_4ch_blank_sealed {
234    ($inst:ident) => {
235        impl General4ChBlankSealed for crate::peripherals::$inst {
236            fn enable_outputs(&self) {
237                unsafe { crate::pac::timer::Tim1chCmp::from_ptr(Self::regs()) }
238                    .bdtr()
239                    .modify(|w| w.set_moe(true));
240            }
241        }
242    };
243}
244
245foreach_interrupt! {
246    ($inst:ident, timer, TIM_BASIC, UP, $irq:ident) => {
247        impl_core_timer!($inst, TimerBits::Bits16);
248        impl BasicNoCr2Instance for crate::peripherals::$inst {}
249        impl BasicInstance for crate::peripherals::$inst {}
250    };
251
252    ($inst:ident, timer, TIM_1CH, UP, $irq:ident) => {
253        impl_core_timer!($inst, TimerBits::Bits16);
254        impl BasicNoCr2Instance for crate::peripherals::$inst {}
255        impl BasicInstance for crate::peripherals::$inst {}
256        impl_general_1ch!($inst);
257        impl_general_2ch!($inst);
258        impl GeneralInstance4Channel for crate::peripherals::$inst {}
259        impl General4ChBlankSealed for crate::peripherals::$inst {}
260    };
261
262    ($inst:ident, timer, TIM_2CH, UP, $irq:ident) => {
263        impl_core_timer!($inst, TimerBits::Bits16);
264        impl BasicNoCr2Instance for crate::peripherals::$inst {}
265        impl BasicInstance for crate::peripherals::$inst {}
266        impl_general_1ch!($inst);
267        impl_general_2ch!($inst);
268        impl GeneralInstance4Channel for crate::peripherals::$inst {}
269        impl General4ChBlankSealed for crate::peripherals::$inst {}
270    };
271
272    ($inst:ident, timer, TIM_GP16, UP, $irq:ident) => {
273        impl_core_timer!($inst, TimerBits::Bits16);
274        impl BasicNoCr2Instance for crate::peripherals::$inst {}
275        impl BasicInstance for crate::peripherals::$inst {}
276        impl_general_1ch!($inst);
277        impl_general_2ch!($inst);
278        impl GeneralInstance4Channel for crate::peripherals::$inst {}
279        impl General4ChBlankSealed for crate::peripherals::$inst {}
280    };
281
282    ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => {
283        impl_core_timer!($inst, TimerBits::Bits32);
284        impl BasicNoCr2Instance for crate::peripherals::$inst {}
285        impl BasicInstance for crate::peripherals::$inst {}
286        impl_general_1ch!($inst);
287        impl_general_2ch!($inst);
288        impl GeneralInstance4Channel for crate::peripherals::$inst {}
289        impl GeneralInstance32bit4Channel for crate::peripherals::$inst {}
290        impl General4ChBlankSealed for crate::peripherals::$inst {}
291    };
292
293    ($inst:ident, timer, TIM_1CH_CMP, UP, $irq:ident) => {
294        impl_core_timer!($inst, TimerBits::Bits16);
295        impl BasicNoCr2Instance for crate::peripherals::$inst {}
296        impl BasicInstance for crate::peripherals::$inst {}
297        impl_general_1ch!($inst);
298        impl_general_2ch!($inst);
299        impl GeneralInstance4Channel for crate::peripherals::$inst {}
300        impl_general_4ch_blank_sealed!($inst);
301        impl_advanced_1ch!($inst);
302        impl AdvancedInstance2Channel for crate::peripherals::$inst {}
303        impl AdvancedInstance4Channel for crate::peripherals::$inst {}
304    };
305
306    ($inst:ident, timer, TIM_2CH_CMP, UP, $irq:ident) => {
307        impl_core_timer!($inst, TimerBits::Bits16);
308        impl BasicNoCr2Instance for crate::peripherals::$inst {}
309        impl BasicInstance for crate::peripherals::$inst {}
310        impl_general_1ch!($inst);
311        impl_general_2ch!($inst);
312        impl GeneralInstance4Channel for crate::peripherals::$inst {}
313        impl_general_4ch_blank_sealed!($inst);
314        impl_advanced_1ch!($inst);
315        impl AdvancedInstance2Channel for crate::peripherals::$inst {}
316        impl AdvancedInstance4Channel for crate::peripherals::$inst {}
317    };
318
319    ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => {
320        impl_core_timer!($inst, TimerBits::Bits16);
321        impl BasicNoCr2Instance for crate::peripherals::$inst {}
322        impl BasicInstance for crate::peripherals::$inst {}
323        impl_general_1ch!($inst);
324        impl_general_2ch!($inst);
325        impl GeneralInstance4Channel for crate::peripherals::$inst {}
326        impl_general_4ch_blank_sealed!($inst);
327        impl_advanced_1ch!($inst);
328        impl AdvancedInstance2Channel for crate::peripherals::$inst {}
329        impl AdvancedInstance4Channel for crate::peripherals::$inst {}
330    };
331}
332
333/// Update interrupt handler.
334pub struct UpdateInterruptHandler<T: CoreInstance> {
335    _phantom: PhantomData<T>,
336}
337
338impl<T: CoreInstance> interrupt::typelevel::Handler<T::UpdateInterrupt>
339    for UpdateInterruptHandler<T>
340{
341    unsafe fn on_interrupt() {
342        // #[cfg(feature = "low-power")]
343        // crate::low_power::on_wakeup_irq();
344
345        let regs = crate::pac::timer::TimCore::from_ptr(T::regs());
346
347        // Read TIM interrupt flags.
348        let sr = regs.sr().read();
349
350        // Mask relevant interrupts (UIE).
351        let bits = sr.0 & 0x00000001;
352
353        // Mask all the channels that fired.
354        regs.dier().modify(|w| w.0 &= !bits);
355
356        // Wake the tasks
357        if sr.uif() {
358            T::state().up_waker.wake();
359        }
360    }
361}
362
363/// Capture/Compare interrupt handler.
364pub struct CaptureCompareInterruptHandler<T: GeneralInstance1Channel> {
365    _phantom: PhantomData<T>,
366}
367
368impl<T: GeneralInstance1Channel> interrupt::typelevel::Handler<T::CaptureCompareInterrupt>
369    for CaptureCompareInterruptHandler<T>
370{
371    unsafe fn on_interrupt() {
372        // #[cfg(feature = "low-power")]
373        // crate::low_power::on_wakeup_irq();
374
375        let regs = crate::pac::timer::TimGp16::from_ptr(T::regs());
376
377        // Read TIM interrupt flags.
378        let sr = regs.sr().read();
379
380        // Mask relevant interrupts (CCIE).
381        let bits = sr.0 & 0x0000001E;
382
383        // Mask all the channels that fired.
384        regs.dier().modify(|w| w.0 &= !bits);
385
386        // Wake the tasks
387        for ch in 0..4 {
388            if sr.ccif(ch) {
389                T::state().cc_waker[ch].wake();
390            }
391        }
392    }
393}