embassy_stm32/timer/
mod.rs1use core::marker::PhantomData;
4
5use embassy_hal_internal::Peripheral;
6use embassy_sync::waitqueue::AtomicWaker;
7
8#[cfg(not(stm32l0))]
9pub mod complementary_pwm;
10pub mod input_capture;
11pub mod low_level;
12pub mod pwm_input;
13pub mod qei;
14pub mod simple_pwm;
15
16use crate::interrupt;
17use crate::rcc::RccPeripheral;
18
19#[derive(Clone, Copy)]
21pub enum Channel {
22 Ch1,
24 Ch2,
26 Ch3,
28 Ch4,
30}
31
32impl Channel {
33 pub fn index(&self) -> usize {
35 match self {
36 Channel::Ch1 => 0,
37 Channel::Ch2 => 1,
38 Channel::Ch3 => 2,
39 Channel::Ch4 => 3,
40 }
41 }
42}
43
44#[derive(Clone, Copy, PartialEq, Eq, Debug)]
46#[cfg_attr(feature = "defmt", derive(defmt::Format))]
47pub enum TimerBits {
48 Bits16,
50 #[cfg(not(stm32l0))]
52 Bits32,
53}
54
55struct State {
56 up_waker: AtomicWaker,
57 cc_waker: [AtomicWaker; 4],
58}
59
60impl State {
61 const fn new() -> Self {
62 Self {
63 up_waker: AtomicWaker::new(),
64 cc_waker: [const { AtomicWaker::new() }; 4],
65 }
66 }
67}
68
69trait SealedInstance: RccPeripheral + Peripheral<P = Self> {
70 fn state() -> &'static State;
72}
73
74#[allow(private_bounds)]
76pub trait CoreInstance: SealedInstance + 'static {
77 type UpdateInterrupt: interrupt::typelevel::Interrupt;
79
80 const BITS: TimerBits;
82
83 fn regs() -> *mut ();
87}
88pub trait BasicNoCr2Instance: CoreInstance {}
90pub trait BasicInstance: BasicNoCr2Instance {}
92
93pub trait GeneralInstance1Channel: CoreInstance {
95 type CaptureCompareInterrupt: interrupt::typelevel::Interrupt;
97}
98
99pub trait GeneralInstance2Channel: GeneralInstance1Channel {
101 type TriggerInterrupt: interrupt::typelevel::Interrupt;
103}
104
105trait General4ChBlankSealed {
111 fn enable_outputs(&self) {}
119}
120
121#[allow(private_bounds)]
123pub trait GeneralInstance4Channel: BasicInstance + GeneralInstance2Channel + General4ChBlankSealed {}
124
125pub trait GeneralInstance32bit4Channel: GeneralInstance4Channel {}
127
128pub trait AdvancedInstance1Channel: BasicNoCr2Instance + GeneralInstance1Channel {
130 type CommunicationInterrupt: interrupt::typelevel::Interrupt;
132 type BreakInputInterrupt: interrupt::typelevel::Interrupt;
134}
135pub trait AdvancedInstance2Channel: BasicInstance + GeneralInstance2Channel + AdvancedInstance1Channel {}
138
139pub trait AdvancedInstance4Channel: AdvancedInstance2Channel + GeneralInstance4Channel {}
141
142pin_trait!(Channel1Pin, GeneralInstance4Channel);
143pin_trait!(Channel2Pin, GeneralInstance4Channel);
144pin_trait!(Channel3Pin, GeneralInstance4Channel);
145pin_trait!(Channel4Pin, GeneralInstance4Channel);
146pin_trait!(ExternalTriggerPin, GeneralInstance4Channel);
147
148pin_trait!(Channel1ComplementaryPin, AdvancedInstance4Channel);
149pin_trait!(Channel2ComplementaryPin, AdvancedInstance4Channel);
150pin_trait!(Channel3ComplementaryPin, AdvancedInstance4Channel);
151pin_trait!(Channel4ComplementaryPin, AdvancedInstance4Channel);
152
153pin_trait!(BreakInputPin, AdvancedInstance4Channel);
154pin_trait!(BreakInput2Pin, AdvancedInstance4Channel);
155
156pin_trait!(BreakInputComparator1Pin, AdvancedInstance4Channel);
157pin_trait!(BreakInputComparator2Pin, AdvancedInstance4Channel);
158
159pin_trait!(BreakInput2Comparator1Pin, AdvancedInstance4Channel);
160pin_trait!(BreakInput2Comparator2Pin, AdvancedInstance4Channel);
161
162dma_trait!(UpDma, BasicInstance);
164
165dma_trait!(Ch1Dma, GeneralInstance4Channel);
166dma_trait!(Ch2Dma, GeneralInstance4Channel);
167dma_trait!(Ch3Dma, GeneralInstance4Channel);
168dma_trait!(Ch4Dma, GeneralInstance4Channel);
169
170#[allow(unused)]
171macro_rules! impl_core_timer {
172 ($inst:ident, $bits:expr) => {
173 impl SealedInstance for crate::peripherals::$inst {
174 fn state() -> &'static State {
175 static STATE: State = State::new();
176 &STATE
177 }
178 }
179
180 impl CoreInstance for crate::peripherals::$inst {
181 type UpdateInterrupt = crate::_generated::peripheral_interrupts::$inst::UP;
182
183 const BITS: TimerBits = $bits;
184
185 fn regs() -> *mut () {
186 crate::pac::$inst.as_ptr()
187 }
188 }
189 };
190}
191
192#[allow(unused)]
193macro_rules! impl_general_1ch {
194 ($inst:ident) => {
195 impl GeneralInstance1Channel for crate::peripherals::$inst {
196 type CaptureCompareInterrupt = crate::_generated::peripheral_interrupts::$inst::CC;
197 }
198 };
199}
200
201#[allow(unused)]
202macro_rules! impl_general_2ch {
203 ($inst:ident) => {
204 impl GeneralInstance2Channel for crate::peripherals::$inst {
205 type TriggerInterrupt = crate::_generated::peripheral_interrupts::$inst::TRG;
206 }
207 };
208}
209
210#[allow(unused)]
211macro_rules! impl_advanced_1ch {
212 ($inst:ident) => {
213 impl AdvancedInstance1Channel for crate::peripherals::$inst {
214 type CommunicationInterrupt = crate::_generated::peripheral_interrupts::$inst::COM;
215 type BreakInputInterrupt = crate::_generated::peripheral_interrupts::$inst::BRK;
216 }
217 };
218}
219
220#[allow(unused)]
223macro_rules! impl_general_4ch_blank_sealed {
224 ($inst:ident) => {
225 impl General4ChBlankSealed for crate::peripherals::$inst {
226 fn enable_outputs(&self) {
227 unsafe { crate::pac::timer::Tim1chCmp::from_ptr(Self::regs()) }
228 .bdtr()
229 .modify(|w| w.set_moe(true));
230 }
231 }
232 };
233}
234
235foreach_interrupt! {
236 ($inst:ident, timer, TIM_BASIC, UP, $irq:ident) => {
237 impl_core_timer!($inst, TimerBits::Bits16);
238 impl BasicNoCr2Instance for crate::peripherals::$inst {}
239 impl BasicInstance for crate::peripherals::$inst {}
240 };
241
242 ($inst:ident, timer, TIM_1CH, 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 impl_general_1ch!($inst);
247 impl_general_2ch!($inst);
248 impl GeneralInstance4Channel for crate::peripherals::$inst {}
249 impl General4ChBlankSealed for crate::peripherals::$inst {}
250 };
251
252 ($inst:ident, timer, TIM_2CH, 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_GP16, 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_GP32, UP, $irq:ident) => {
273 impl_core_timer!($inst, TimerBits::Bits32);
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 GeneralInstance32bit4Channel for crate::peripherals::$inst {}
280 impl General4ChBlankSealed for crate::peripherals::$inst {}
281 };
282
283 ($inst:ident, timer, TIM_1CH_CMP, UP, $irq:ident) => {
284 impl_core_timer!($inst, TimerBits::Bits16);
285 impl BasicNoCr2Instance for crate::peripherals::$inst {}
286 impl BasicInstance for crate::peripherals::$inst {}
287 impl_general_1ch!($inst);
288 impl_general_2ch!($inst);
289 impl GeneralInstance4Channel for crate::peripherals::$inst {}
290 impl_general_4ch_blank_sealed!($inst);
291 impl_advanced_1ch!($inst);
292 impl AdvancedInstance2Channel for crate::peripherals::$inst {}
293 impl AdvancedInstance4Channel for crate::peripherals::$inst {}
294 };
295
296 ($inst:ident, timer, TIM_2CH_CMP, UP, $irq:ident) => {
297 impl_core_timer!($inst, TimerBits::Bits16);
298 impl BasicNoCr2Instance for crate::peripherals::$inst {}
299 impl BasicInstance for crate::peripherals::$inst {}
300 impl_general_1ch!($inst);
301 impl_general_2ch!($inst);
302 impl GeneralInstance4Channel for crate::peripherals::$inst {}
303 impl_general_4ch_blank_sealed!($inst);
304 impl_advanced_1ch!($inst);
305 impl AdvancedInstance2Channel for crate::peripherals::$inst {}
306 impl AdvancedInstance4Channel for crate::peripherals::$inst {}
307 };
308
309 ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => {
310 impl_core_timer!($inst, TimerBits::Bits16);
311 impl BasicNoCr2Instance for crate::peripherals::$inst {}
312 impl BasicInstance for crate::peripherals::$inst {}
313 impl_general_1ch!($inst);
314 impl_general_2ch!($inst);
315 impl GeneralInstance4Channel for crate::peripherals::$inst {}
316 impl_general_4ch_blank_sealed!($inst);
317 impl_advanced_1ch!($inst);
318 impl AdvancedInstance2Channel for crate::peripherals::$inst {}
319 impl AdvancedInstance4Channel for crate::peripherals::$inst {}
320 };
321}
322
323pub struct UpdateInterruptHandler<T: CoreInstance> {
325 _phantom: PhantomData<T>,
326}
327
328impl<T: CoreInstance> interrupt::typelevel::Handler<T::UpdateInterrupt> for UpdateInterruptHandler<T> {
329 unsafe fn on_interrupt() {
330 #[cfg(feature = "low-power")]
331 crate::low_power::on_wakeup_irq();
332
333 let regs = crate::pac::timer::TimCore::from_ptr(T::regs());
334
335 let sr = regs.sr().read();
337
338 let bits = sr.0 & 0x00000001;
340
341 regs.dier().modify(|w| w.0 &= !bits);
343
344 if sr.uif() {
346 T::state().up_waker.wake();
347 }
348 }
349}
350
351pub struct CaptureCompareInterruptHandler<T: GeneralInstance1Channel> {
353 _phantom: PhantomData<T>,
354}
355
356impl<T: GeneralInstance1Channel> interrupt::typelevel::Handler<T::CaptureCompareInterrupt>
357 for CaptureCompareInterruptHandler<T>
358{
359 unsafe fn on_interrupt() {
360 #[cfg(feature = "low-power")]
361 crate::low_power::on_wakeup_irq();
362
363 let regs = crate::pac::timer::TimGp16::from_ptr(T::regs());
364
365 let sr = regs.sr().read();
367
368 let bits = sr.0 & 0x0000001E;
370
371 regs.dier().modify(|w| w.0 &= !bits);
373
374 for ch in 0..4 {
376 if sr.ccif(ch) {
377 T::state().cc_waker[ch].wake();
378 }
379 }
380 }
381}