1 | //! Timers, PWM, quadrature decoder. |
2 | |
3 | use core::marker::PhantomData; |
4 | |
5 | use embassy_hal_internal::Peripheral; |
6 | use embassy_sync::waitqueue::AtomicWaker; |
7 | |
8 | #[cfg (not(stm32l0))] |
9 | pub mod complementary_pwm; |
10 | pub mod input_capture; |
11 | pub mod low_level; |
12 | pub mod pwm_input; |
13 | pub mod qei; |
14 | pub mod simple_pwm; |
15 | |
16 | use crate::interrupt; |
17 | use crate::rcc::RccPeripheral; |
18 | |
19 | /// Timer channel. |
20 | #[derive (Clone, Copy)] |
21 | pub enum Channel { |
22 | /// Channel 1. |
23 | Ch1, |
24 | /// Channel 2. |
25 | Ch2, |
26 | /// Channel 3. |
27 | Ch3, |
28 | /// Channel 4. |
29 | Ch4, |
30 | } |
31 | |
32 | impl Channel { |
33 | /// Get the channel index (0..3) |
34 | 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 | /// Amount of bits of a timer. |
45 | #[derive (Clone, Copy, PartialEq, Eq, Debug)] |
46 | #[cfg_attr (feature = "defmt" , derive(defmt::Format))] |
47 | pub enum TimerBits { |
48 | /// 16 bits. |
49 | Bits16, |
50 | /// 32 bits. |
51 | #[cfg (not(stm32l0))] |
52 | Bits32, |
53 | } |
54 | |
55 | struct State { |
56 | up_waker: AtomicWaker, |
57 | cc_waker: [AtomicWaker; 4], |
58 | } |
59 | |
60 | impl State { |
61 | const fn new() -> Self { |
62 | Self { |
63 | up_waker: AtomicWaker::new(), |
64 | cc_waker: [const { AtomicWaker::new() }; 4], |
65 | } |
66 | } |
67 | } |
68 | |
69 | trait 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)] |
76 | pub 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. |
89 | pub trait BasicNoCr2Instance: CoreInstance {} |
90 | /// Basic timer instance. |
91 | pub trait BasicInstance: BasicNoCr2Instance {} |
92 | |
93 | /// General-purpose 16-bit timer with 1 channel instance. |
94 | pub 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. |
100 | pub 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. |
110 | trait 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)] |
123 | pub trait GeneralInstance4Channel: BasicInstance + GeneralInstance2Channel + General4ChBlankSealed {} |
124 | |
125 | /// General-purpose 32-bit timer with 4 channels instance. |
126 | pub trait GeneralInstance32bit4Channel: GeneralInstance4Channel {} |
127 | |
128 | /// Advanced 16-bit timer with 1 channel instance. |
129 | pub trait AdvancedInstance1Channel: BasicNoCr2Instance + GeneralInstance1Channel { |
130 | /// Communication interrupt for this timer. |
131 | type CommunicationInterrupt: interrupt::typelevel::Interrupt; |
132 | /// Break input interrupt for this timer. |
133 | type BreakInputInterrupt: interrupt::typelevel::Interrupt; |
134 | } |
135 | /// Advanced 16-bit timer with 2 channels instance. |
136 | |
137 | pub trait AdvancedInstance2Channel: BasicInstance + GeneralInstance2Channel + AdvancedInstance1Channel {} |
138 | |
139 | /// Advanced 16-bit timer with 4 channels instance. |
140 | pub trait AdvancedInstance4Channel: AdvancedInstance2Channel + GeneralInstance4Channel {} |
141 | |
142 | pin_trait!(Channel1Pin, GeneralInstance4Channel); |
143 | pin_trait!(Channel2Pin, GeneralInstance4Channel); |
144 | pin_trait!(Channel3Pin, GeneralInstance4Channel); |
145 | pin_trait!(Channel4Pin, GeneralInstance4Channel); |
146 | pin_trait!(ExternalTriggerPin, GeneralInstance4Channel); |
147 | |
148 | pin_trait!(Channel1ComplementaryPin, AdvancedInstance4Channel); |
149 | pin_trait!(Channel2ComplementaryPin, AdvancedInstance4Channel); |
150 | pin_trait!(Channel3ComplementaryPin, AdvancedInstance4Channel); |
151 | pin_trait!(Channel4ComplementaryPin, AdvancedInstance4Channel); |
152 | |
153 | pin_trait!(BreakInputPin, AdvancedInstance4Channel); |
154 | pin_trait!(BreakInput2Pin, AdvancedInstance4Channel); |
155 | |
156 | pin_trait!(BreakInputComparator1Pin, AdvancedInstance4Channel); |
157 | pin_trait!(BreakInputComparator2Pin, AdvancedInstance4Channel); |
158 | |
159 | pin_trait!(BreakInput2Comparator1Pin, AdvancedInstance4Channel); |
160 | pin_trait!(BreakInput2Comparator2Pin, AdvancedInstance4Channel); |
161 | |
162 | // Update Event trigger DMA for every timer |
163 | dma_trait!(UpDma, BasicInstance); |
164 | |
165 | dma_trait!(Ch1Dma, GeneralInstance4Channel); |
166 | dma_trait!(Ch2Dma, GeneralInstance4Channel); |
167 | dma_trait!(Ch3Dma, GeneralInstance4Channel); |
168 | dma_trait!(Ch4Dma, GeneralInstance4Channel); |
169 | |
170 | #[allow (unused)] |
171 | macro_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)] |
193 | macro_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)] |
202 | macro_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)] |
211 | macro_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 | // This macro only apply to "AdvancedInstance(s)", |
221 | // not "GeneralInstance4Channel" itself. |
222 | #[allow (unused)] |
223 | macro_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 | |
235 | foreach_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 | |
323 | /// Update interrupt handler. |
324 | pub struct UpdateInterruptHandler<T: CoreInstance> { |
325 | _phantom: PhantomData<T>, |
326 | } |
327 | |
328 | impl<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: TimCore = crate::pac::timer::TimCore::from_ptr(T::regs()); |
334 | |
335 | // Read TIM interrupt flags. |
336 | let sr: SrCore = regs.sr().read(); |
337 | |
338 | // Mask relevant interrupts (UIE). |
339 | let bits: u32 = sr.0 & 0x00000001; |
340 | |
341 | // Mask all the channels that fired. |
342 | regs.dier().modify(|w: &mut DierCore| w.0 &= !bits); |
343 | |
344 | // Wake the tasks |
345 | if sr.uif() { |
346 | T::state().up_waker.wake(); |
347 | } |
348 | } |
349 | } |
350 | |
351 | /// Capture/Compare interrupt handler. |
352 | pub struct CaptureCompareInterruptHandler<T: GeneralInstance1Channel> { |
353 | _phantom: PhantomData<T>, |
354 | } |
355 | |
356 | impl<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: TimGp16 = crate::pac::timer::TimGp16::from_ptr(T::regs()); |
364 | |
365 | // Read TIM interrupt flags. |
366 | let sr: SrGp16 = regs.sr().read(); |
367 | |
368 | // Mask relevant interrupts (CCIE). |
369 | let bits: u32 = sr.0 & 0x0000001E; |
370 | |
371 | // Mask all the channels that fired. |
372 | regs.dier().modify(|w: &mut DierGp16| w.0 &= !bits); |
373 | |
374 | // Wake the tasks |
375 | for ch: usize in 0..4 { |
376 | if sr.ccif(ch) { |
377 | T::state().cc_waker[ch].wake(); |
378 | } |
379 | } |
380 | } |
381 | } |
382 | |