embassy_stm32/timer/
mod.rs1use core::marker::PhantomData;
4
5use embassy_hal_internal::PeripheralType;
6use embassy_sync::waitqueue::AtomicWaker;
7
8#[cfg(not(stm32l0))]
9pub mod complementary_pwm;
10pub mod input_capture;
11pub mod low_level;
12pub mod one_pulse;
13pub mod pwm_input;
14pub mod qei;
15pub mod simple_pwm;
16
17use crate::interrupt;
18use crate::rcc::RccPeripheral;
19
20#[derive(Clone, Copy)]
22pub enum Channel {
23 Ch1,
25 Ch2,
27 Ch3,
29 Ch4,
31}
32
33impl Channel {
34 pub fn index(&self) -> usize {
36 match self {
37 Channel::Ch1 => 0,
38 Channel::Ch2 => 1,
39 Channel::Ch3 => 2,
40 Channel::Ch4 => 3,
41 }
42 }
43}
44
45pub enum Ch1 {}
47pub enum Ch2 {}
49pub enum Ch3 {}
51pub enum Ch4 {}
53
54#[allow(private_bounds)]
56pub trait TimerChannel: SealedTimerChannel {
57 const CHANNEL: Channel;
59}
60
61trait SealedTimerChannel {}
62
63impl TimerChannel for Ch1 {
64 const CHANNEL: Channel = Channel::Ch1;
65}
66
67impl TimerChannel for Ch2 {
68 const CHANNEL: Channel = Channel::Ch2;
69}
70
71impl TimerChannel for Ch3 {
72 const CHANNEL: Channel = Channel::Ch3;
73}
74
75impl TimerChannel for Ch4 {
76 const CHANNEL: Channel = Channel::Ch4;
77}
78
79impl SealedTimerChannel for Ch1 {}
80impl SealedTimerChannel for Ch2 {}
81impl SealedTimerChannel for Ch3 {}
82impl SealedTimerChannel for Ch4 {}
83
84#[derive(Clone, Copy)]
86pub enum BkIn {
87 BkIn1,
89 BkIn2,
91}
92
93impl BkIn {
94 pub fn index(&self) -> usize {
96 match self {
97 BkIn::BkIn1 => 0,
98 BkIn::BkIn2 => 1,
99 }
100 }
101}
102
103pub enum BkIn1 {}
105pub enum BkIn2 {}
107
108#[allow(private_bounds)]
110pub trait BreakInput: SealedBreakInput {
111 const INPUT: BkIn;
113}
114
115trait SealedBreakInput {}
116
117impl BreakInput for BkIn1 {
118 const INPUT: BkIn = BkIn::BkIn1;
119}
120
121impl BreakInput for BkIn2 {
122 const INPUT: BkIn = BkIn::BkIn2;
123}
124
125impl SealedBreakInput for BkIn1 {}
126impl SealedBreakInput for BkIn2 {}
127
128#[derive(Clone, Copy, PartialEq, Eq, Debug)]
130#[cfg_attr(feature = "defmt", derive(defmt::Format))]
131pub enum TimerBits {
132 Bits16,
134 #[cfg(not(stm32l0))]
136 Bits32,
137}
138
139struct State {
140 up_waker: AtomicWaker,
141 cc_waker: [AtomicWaker; 4],
142}
143
144impl State {
145 const fn new() -> Self {
146 Self {
147 up_waker: AtomicWaker::new(),
148 cc_waker: [const { AtomicWaker::new() }; 4],
149 }
150 }
151}
152
153trait SealedInstance: RccPeripheral + PeripheralType {
154 fn state() -> &'static State;
156}
157
158#[allow(private_bounds)]
160pub trait CoreInstance: SealedInstance + 'static {
161 type UpdateInterrupt: interrupt::typelevel::Interrupt;
163
164 const BITS: TimerBits;
166
167 fn regs() -> *mut ();
171}
172pub trait BasicNoCr2Instance: CoreInstance {}
174pub trait BasicInstance: BasicNoCr2Instance {}
176
177pub trait GeneralInstance1Channel: CoreInstance {
179 type CaptureCompareInterrupt: interrupt::typelevel::Interrupt;
181}
182
183pub trait GeneralInstance2Channel: GeneralInstance1Channel {
185 type TriggerInterrupt: interrupt::typelevel::Interrupt;
187}
188
189trait General4ChBlankSealed {
195 fn enable_outputs(&self) {}
203}
204
205#[allow(private_bounds)]
207pub trait GeneralInstance4Channel: BasicInstance + GeneralInstance2Channel + General4ChBlankSealed {}
208
209pub trait GeneralInstance32bit4Channel: GeneralInstance4Channel {}
211
212pub trait AdvancedInstance1Channel: BasicNoCr2Instance + GeneralInstance1Channel {
214 type CommunicationInterrupt: interrupt::typelevel::Interrupt;
216 type BreakInputInterrupt: interrupt::typelevel::Interrupt;
218}
219pub trait AdvancedInstance2Channel: BasicInstance + GeneralInstance2Channel + AdvancedInstance1Channel {}
222
223pub trait AdvancedInstance4Channel: AdvancedInstance2Channel + GeneralInstance4Channel {}
225
226pin_trait!(TimerPin, GeneralInstance4Channel, TimerChannel);
227pin_trait!(ExternalTriggerPin, GeneralInstance4Channel);
228
229pin_trait!(TimerComplementaryPin, AdvancedInstance4Channel, TimerChannel);
230
231pin_trait!(BreakInputPin, AdvancedInstance4Channel, BreakInput);
232
233pin_trait!(BreakInputComparator1Pin, AdvancedInstance4Channel, BreakInput);
234pin_trait!(BreakInputComparator2Pin, AdvancedInstance4Channel, BreakInput);
235
236dma_trait!(UpDma, BasicInstance);
238
239dma_trait!(Dma, GeneralInstance4Channel, TimerChannel);
240
241#[allow(unused)]
242macro_rules! impl_core_timer {
243 ($inst:ident, $bits:expr) => {
244 impl SealedInstance for crate::peripherals::$inst {
245 fn state() -> &'static State {
246 static STATE: State = State::new();
247 &STATE
248 }
249 }
250
251 impl CoreInstance for crate::peripherals::$inst {
252 type UpdateInterrupt = crate::_generated::peripheral_interrupts::$inst::UP;
253
254 const BITS: TimerBits = $bits;
255
256 fn regs() -> *mut () {
257 crate::pac::$inst.as_ptr()
258 }
259 }
260 };
261}
262
263#[allow(unused)]
264macro_rules! impl_general_1ch {
265 ($inst:ident) => {
266 impl GeneralInstance1Channel for crate::peripherals::$inst {
267 type CaptureCompareInterrupt = crate::_generated::peripheral_interrupts::$inst::CC;
268 }
269 };
270}
271
272#[allow(unused)]
273macro_rules! impl_general_2ch {
274 ($inst:ident) => {
275 impl GeneralInstance2Channel for crate::peripherals::$inst {
276 type TriggerInterrupt = crate::_generated::peripheral_interrupts::$inst::TRG;
277 }
278 };
279}
280
281#[allow(unused)]
282macro_rules! impl_advanced_1ch {
283 ($inst:ident) => {
284 impl AdvancedInstance1Channel for crate::peripherals::$inst {
285 type CommunicationInterrupt = crate::_generated::peripheral_interrupts::$inst::COM;
286 type BreakInputInterrupt = crate::_generated::peripheral_interrupts::$inst::BRK;
287 }
288 };
289}
290
291#[allow(unused)]
294macro_rules! impl_general_4ch_blank_sealed {
295 ($inst:ident) => {
296 impl General4ChBlankSealed for crate::peripherals::$inst {
297 fn enable_outputs(&self) {
298 unsafe { crate::pac::timer::Tim1chCmp::from_ptr(Self::regs()) }
299 .bdtr()
300 .modify(|w| w.set_moe(true));
301 }
302 }
303 };
304}
305
306foreach_interrupt! {
307 ($inst:ident, timer, TIM_BASIC, UP, $irq:ident) => {
308 impl_core_timer!($inst, TimerBits::Bits16);
309 impl BasicNoCr2Instance for crate::peripherals::$inst {}
310 impl BasicInstance for crate::peripherals::$inst {}
311 };
312
313 ($inst:ident, timer, TIM_1CH, UP, $irq:ident) => {
314 impl_core_timer!($inst, TimerBits::Bits16);
315 impl BasicNoCr2Instance for crate::peripherals::$inst {}
316 impl BasicInstance for crate::peripherals::$inst {}
317 impl_general_1ch!($inst);
318 impl_general_2ch!($inst);
319 impl GeneralInstance4Channel for crate::peripherals::$inst {}
320 impl General4ChBlankSealed for crate::peripherals::$inst {}
321 };
322
323 ($inst:ident, timer, TIM_2CH, UP, $irq:ident) => {
324 impl_core_timer!($inst, TimerBits::Bits16);
325 impl BasicNoCr2Instance for crate::peripherals::$inst {}
326 impl BasicInstance for crate::peripherals::$inst {}
327 impl_general_1ch!($inst);
328 impl_general_2ch!($inst);
329 impl GeneralInstance4Channel for crate::peripherals::$inst {}
330 impl General4ChBlankSealed for crate::peripherals::$inst {}
331 };
332
333 ($inst:ident, timer, TIM_GP16, UP, $irq:ident) => {
334 impl_core_timer!($inst, TimerBits::Bits16);
335 impl BasicNoCr2Instance for crate::peripherals::$inst {}
336 impl BasicInstance for crate::peripherals::$inst {}
337 impl_general_1ch!($inst);
338 impl_general_2ch!($inst);
339 impl GeneralInstance4Channel for crate::peripherals::$inst {}
340 impl General4ChBlankSealed for crate::peripherals::$inst {}
341 };
342
343 ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => {
344 impl_core_timer!($inst, TimerBits::Bits32);
345 impl BasicNoCr2Instance for crate::peripherals::$inst {}
346 impl BasicInstance for crate::peripherals::$inst {}
347 impl_general_1ch!($inst);
348 impl_general_2ch!($inst);
349 impl GeneralInstance4Channel for crate::peripherals::$inst {}
350 impl GeneralInstance32bit4Channel for crate::peripherals::$inst {}
351 impl General4ChBlankSealed for crate::peripherals::$inst {}
352 };
353
354 ($inst:ident, timer, TIM_1CH_CMP, UP, $irq:ident) => {
355 impl_core_timer!($inst, TimerBits::Bits16);
356 impl BasicNoCr2Instance for crate::peripherals::$inst {}
357 impl BasicInstance for crate::peripherals::$inst {}
358 impl_general_1ch!($inst);
359 impl_general_2ch!($inst);
360 impl GeneralInstance4Channel for crate::peripherals::$inst {}
361 impl_general_4ch_blank_sealed!($inst);
362 impl_advanced_1ch!($inst);
363 impl AdvancedInstance2Channel for crate::peripherals::$inst {}
364 impl AdvancedInstance4Channel for crate::peripherals::$inst {}
365 };
366
367 ($inst:ident, timer, TIM_2CH_CMP, UP, $irq:ident) => {
368 impl_core_timer!($inst, TimerBits::Bits16);
369 impl BasicNoCr2Instance for crate::peripherals::$inst {}
370 impl BasicInstance for crate::peripherals::$inst {}
371 impl_general_1ch!($inst);
372 impl_general_2ch!($inst);
373 impl GeneralInstance4Channel for crate::peripherals::$inst {}
374 impl_general_4ch_blank_sealed!($inst);
375 impl_advanced_1ch!($inst);
376 impl AdvancedInstance2Channel for crate::peripherals::$inst {}
377 impl AdvancedInstance4Channel for crate::peripherals::$inst {}
378 };
379
380 ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => {
381 impl_core_timer!($inst, TimerBits::Bits16);
382 impl BasicNoCr2Instance for crate::peripherals::$inst {}
383 impl BasicInstance for crate::peripherals::$inst {}
384 impl_general_1ch!($inst);
385 impl_general_2ch!($inst);
386 impl GeneralInstance4Channel for crate::peripherals::$inst {}
387 impl_general_4ch_blank_sealed!($inst);
388 impl_advanced_1ch!($inst);
389 impl AdvancedInstance2Channel for crate::peripherals::$inst {}
390 impl AdvancedInstance4Channel for crate::peripherals::$inst {}
391 };
392}
393
394pub struct UpdateInterruptHandler<T: CoreInstance> {
396 _phantom: PhantomData<T>,
397}
398
399impl<T: CoreInstance> interrupt::typelevel::Handler<T::UpdateInterrupt> for UpdateInterruptHandler<T> {
400 unsafe fn on_interrupt() {
401 #[cfg(feature = "low-power")]
402 crate::low_power::on_wakeup_irq();
403
404 let regs = crate::pac::timer::TimCore::from_ptr(T::regs());
405
406 let sr = regs.sr().read();
408
409 let bits = sr.0 & 0x00000001;
411
412 regs.dier().modify(|w| w.0 &= !bits);
414
415 if sr.uif() {
417 T::state().up_waker.wake();
418 }
419 }
420}
421
422pub struct CaptureCompareInterruptHandler<T: GeneralInstance1Channel> {
424 _phantom: PhantomData<T>,
425}
426
427impl<T: GeneralInstance1Channel> interrupt::typelevel::Handler<T::CaptureCompareInterrupt>
428 for CaptureCompareInterruptHandler<T>
429{
430 unsafe fn on_interrupt() {
431 #[cfg(feature = "low-power")]
432 crate::low_power::on_wakeup_irq();
433
434 let regs = crate::pac::timer::TimGp16::from_ptr(T::regs());
435
436 let sr = regs.sr().read();
438
439 let bits = sr.0 & 0x0000001E;
441
442 regs.dier().modify(|w| w.0 &= !bits);
444
445 for ch in 0..4 {
447 if sr.ccif(ch) {
448 T::state().cc_waker[ch].wake();
449 }
450 }
451 }
452}