py32_hal/timer/
mod.rs

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