stm32_hal2/timer.rs
1//! Provides support for basic timer functionality. Includes initialization, interrupts,
2//! and PWM features. Also supports capture compare, output compare, burst DMA, and getting the current uptime using
3//! an overflowing wrapper. (In seconds, milliseconds, or microseconds)
4//!
5//! Low-power timers (LPTIM) and high-presolution timers (HRTIM) are not yet supported.
6
7// todo: WB and WL should support pwm features
8
9#[cfg(feature = "monotonic")]
10use core;
11#[cfg(not(any(
12 feature = "f401",
13 feature = "f410",
14 feature = "f411",
15 feature = "f413",
16 feature = "g031",
17 feature = "g041",
18 feature = "g070",
19 feature = "g030",
20 feature = "wb",
21 feature = "wl"
22)))]
23use core::ops::Deref;
24use core::{
25 sync::atomic::{AtomicU32, Ordering},
26 time::Duration,
27};
28
29use cfg_if::cfg_if;
30use num_traits::float::FloatCore; // To round floats.
31use paste::paste;
32#[cfg(feature = "monotonic")]
33use rtic_monotonic::Monotonic;
34
35#[cfg(any(feature = "f3", feature = "l4"))]
36use crate::dma::DmaInput;
37#[cfg(not(any(feature = "f4", feature = "l552")))]
38use crate::dma::{self, ChannelCfg, DmaChannel};
39#[cfg(feature = "c0")]
40use crate::pac::DMA as DMA1;
41#[cfg(not(feature = "c0"))]
42use crate::pac::DMA1;
43#[cfg(not(any(
44 feature = "f401",
45 feature = "f410",
46 feature = "f411",
47 feature = "f413",
48 feature = "g031",
49 feature = "g041",
50 feature = "g070",
51 feature = "g030",
52 feature = "g051",
53 feature = "c0",
54 feature = "wb",
55 feature = "wl"
56)))]
57use crate::util::RccPeriph;
58// todo: LPTIM (low-power timers) and HRTIM (high-resolution timers). And Advanced control functionality
59use crate::{
60 clocks::Clocks,
61 error::{Error, Result},
62 instant::Instant,
63 pac::{self, RCC},
64 util::rcc_en_reset,
65};
66
67// This `TICK_OVERFLOW_COUNT` must be incremented in firmware in the timer's update interrupt.
68pub static TICK_OVERFLOW_COUNT: AtomicU32 = AtomicU32::new(0);
69
70// todo: Low power timer enabling etc. eg on L4, RCC_APB1Enr1().LPTIM1EN
71
72#[cfg_attr(feature = "defmt", derive(defmt::Format))]
73#[derive(Debug, Clone, Copy, Eq, PartialEq)]
74pub enum TimerError {
75 /// Used for when attempting to set a timer period that is out of range.
76 ValueError,
77}
78
79#[derive(Clone, Copy)]
80#[repr(u8)]
81/// This bit-field selects the trigger input to be used to synchronize the counter.
82/// Sets SMCR register, TS field.
83pub enum InputTrigger {
84 ///Internal Trigger 0 (ITR0)
85 Internal0 = 0b00000,
86 Internal1 = 0b00001,
87 Internal2 = 0b00010,
88 Internal3 = 0b00011,
89 /// TI1 Edge Detector (TI1F_ED)
90 Ti1Edge = 0b00100,
91 FilteredTimerInput1 = 0b00101,
92 FilteredTimerInput2 = 0b00110,
93 ExternalTriggerInput = 0b00111,
94 Internal4 = 0b01000,
95 Internal5 = 0b01001,
96 Internal6 = 0b01010,
97 Internal7 = 0b01011,
98 Internal8 = 0b01100,
99 Internal9 = 0b01101,
100 Internal10 = 0b01110,
101 Internal11 = 0b01111,
102 Internal12 = 0b10000,
103 Internal13 = 0b10001,
104}
105
106#[derive(Clone, Copy)]
107#[repr(u8)]
108/// When external signals are selected the active edge of the trigger signal (TRGI) is linked to
109/// the polarity selected on the external input (see Input Control register and Control Register
110/// description. Sets SMCR register, SMS field.
111pub enum InputSlaveMode {
112 /// Slave mode disabled - if CEN = ‘1 then the prescaler is clocked directly by the internal
113 /// clock
114 Disabled = 0b0000,
115 /// Encoder mode 1 - Counter counts up/down on TI1FP1 edge depending on TI2FP2
116 /// level
117 Encoder1 = 0b0001,
118 /// Encoder mode 2 - Counter counts up/down on TI2FP2 edge depending on TI1FP1
119 /// level.
120 Encoder2 = 0b0010,
121 /// Encoder mode 3 - Counter counts up/down on both TI1FP1 and TI2FP2 edges
122 /// depending on the level of the other input.
123 Encoder3 = 0b0011,
124 /// Reset mode - Rising edge of the selected trigger input (TRGI) reinitializes the counter
125 /// and generates an update of the registers.
126 Reset = 0b0100,
127 /// Gated Mode - The counter clock is enabled when the trigger input (TRGI) is high. The
128 /// counter stops (but is not reset) as soon as the trigger becomes low. Both start and stop of
129 /// the counter are controlled.
130 Gated = 0b0101,
131 /// Trigger Mode - The counter starts at a rising edge of the trigger TRGI (but it is not
132 /// reset). Only the start of the counter is controlled.
133 Trigger = 0b0110,
134 /// External Clock Mode 1 - Rising edges of the selected trigger (TRGI) clock the counter.
135 ExternalClock1 = 0b0111,
136 /// Combined reset + trigger mode - Rising edge of the selected trigger input (TRGI)
137 /// reinitializes the counter, generates an update of the registers and starts the counter.
138 CombinedResetTrigger = 0b1000,
139}
140
141#[derive(Clone, Copy)]
142#[repr(u8)]
143/// These bits allow selected information to be sent in master mode to slave timers for
144/// synchronization (TRGO). Sets CR2 register, MMS field.
145pub enum MasterModeSelection {
146 /// Tthe UG bit from the TIMx_EGR register is used as trigger output (TRGO). If the
147 /// reset is generated by the trigger input (slave mode controller configured in reset mode) then
148 /// the signal on TRGO is delayed compared to the actual reset.
149 Reset = 0b000,
150 /// the Counter Enable signal CNT_EN is used as trigger output (TRGO). It is
151 /// useful to start several timers at the same time or to control a window in which a slave timer is
152 /// enable. The Counter Enable signal is generated by a logic AND between CEN control bit
153 /// and the trigger input when configured in gated mode. When the Counter Enable signal is
154 /// controlled by the trigger input, there is a delay on TRGO, except if the master/slave mode is
155 /// selected (see the MSM bit description in TIMx_SMCR register).
156 Enable = 0b001,
157 /// The update event is selected as trigger output (TRGO). For instance a master
158 /// timer can then be used as a prescaler for a slave timer.
159 Update = 0b010,
160 /// Compare Pulse - The trigger output send a positive pulse when the CC1IF flag is to be
161 /// set (even if it was already high), as soon as a capture or a compare match occurred.
162 /// (TRGO).
163 ComparePulse = 0b011,
164 /// OC1REF signal is used as trigger output (TRGO)
165 Compare1 = 0b100,
166 /// OC2REF signal is used as trigger output (TRGO)
167 Compare2 = 0b101,
168 /// OC3REF signal is used as trigger output (TRGO)
169 Compare3 = 0b110,
170 /// OC4REF signal is used as trigger output (TRGO)
171 Compare4 = 0b111,
172}
173
174/// Timer interrupt
175pub enum TimerInterrupt {
176 /// Update interrupt can be used for a timeout. DIER UIE to set, ... to clear
177 Update,
178 /// Trigger. DIER TIE to set, ... to clear
179 Trigger,
180 /// Capture/Compare. CC1IE to set, ... to clear
181 CaptureCompare1,
182 /// Capture/Compare. CC2IE to set, ... to clear
183 CaptureCompare2,
184 /// Capture/Compare. CC3IE to set, ... to clear
185 CaptureCompare3,
186 /// Capture/Compare. CC4IE to set, ... to clear
187 CaptureCompare4,
188 /// Update DMA. DIER UDE to set, ... to clear
189 UpdateDma,
190 /// Drigger. TDE to set, ... to clear
191 TriggerDma,
192 /// Capture/Compare. CC1DE to set, ... to clear
193 CaptureCompare1Dma,
194 /// Capture/Compare. CC2DE to set, ... to clear
195 CaptureCompare2Dma,
196 /// Capture/Compare. CC3DE to set, ... to clear
197 CaptureCompare3Dma,
198 /// Capture/Compare. CC4DE to set, ... to clear
199 CaptureCompare4Dma,
200}
201
202/// Output alignment. Sets `TIMx_CR1` register, `CMS` field.
203#[derive(Clone, Copy)]
204pub enum Alignment {
205 /// Edge-aligned mode. The counter counts up or down depending on the direction bit
206 /// (DIR).
207 Edge = 0b00,
208 /// Center-aligned mode 1. The counter counts up and down alternatively. Output compare
209 /// interrupt flags of channels configured in output (CCxS=00 in TIMx_CCMRx register) are set
210 /// only when the counter is counting down.
211 Center1 = 0b01,
212 /// Center-aligned mode 2. The counter counts up and down alternatively. Output compare
213 /// interrupt flags of channels configured in output (CCxS=00 in TIMx_CCMRx register) are set
214 /// only when the counter is counting up.
215 Center2 = 0b10,
216 /// Center-aligned mode 3. The counter counts up and down alternatively. Output compare
217 /// interrupt flags of channels configured in output (CCxS=00 in TIMx_CCMRx register) are set
218 /// both when the counter is counting up or down.
219 Center3 = 0b11,
220}
221
222/// Timer channel
223#[derive(Clone, Copy)]
224pub enum TimChannel {
225 C1,
226 C2,
227 C3,
228 #[cfg(not(feature = "wl"))]
229 C4,
230}
231
232/// Timer count direction. Defaults to `Up`.
233#[repr(u8)]
234#[derive(Clone, Copy)]
235pub enum CountDir {
236 Up = 0,
237 Down = 1,
238}
239
240/// Capture/Compare selection.
241/// This field defines the direction of the channel (input/output) as well as the used input.
242/// It affects the TIMx_CCMR1 register, CCxS fields.
243///
244/// Note that the the specific timer input source varies depending on the channel.
245/// `InputTiPrimary` always matches the associated channel (e.g. TI1 for CH1, TI2 for CH2, etc),
246/// while `InputTiSecondary` is TI2 for CH1, TI1 for CH2, TI4 for CH3, and TI3 for CH4.
247#[repr(u8)]
248#[derive(Clone, Copy)]
249pub enum CaptureCompare {
250 Output = 0b00,
251 InputTiPrimary = 0b01,
252 InputTiSecondary = 0b10,
253 InputTrc = 0b11,
254}
255
256/// Capture/Compare output polarity. Defaults to `ActiveHigh` in hardware. Sets TIMx_CCER register,
257/// CCxP and CCXNP fields.
258#[derive(Clone, Copy)]
259pub enum Polarity {
260 ActiveHigh,
261 ActiveLow,
262}
263
264impl Polarity {
265 /// For use with `set_bit()`.
266 fn bit(&self) -> bool {
267 match self {
268 Self::ActiveHigh => false,
269 Self::ActiveLow => true,
270 }
271 }
272}
273
274#[derive(Clone, Copy)]
275#[repr(u8)]
276/// See F303 ref man, section 21.4.7. H745 RM, section 41.4.8. Sets TIMx_CCMR1 register, OC1M field.
277/// These bits define the behavior of the output reference signal OC1REF from which OC1 and
278/// OC1N are derived. OC1REF is active high whereas OC1 and OC1N active level depends
279/// on CC1P and CC1NP bits.
280pub enum OutputCompare {
281 /// Frozen - The comparison between the output compare register TIMx_CCR1 and the
282 /// counter TIMx_CNT has no effect on the outputs.(this mode is used to generate a timing
283 /// base).
284 Frozen = 0b0000,
285 /// Set channel 1 to active level on match. OC1REF signal is forced high when the
286 /// counter TIMx_CNT matches the capture/compare register 1 (TIMx_CCR1).
287 Active = 0b0001,
288 /// Set channel 1 to inactive level on match. OC1REF signal is forced low when the
289 /// counter TIMx_CNT matches the capture/compare register 1 (TIMx_CCR1).
290 /// 0011: Toggle - OC1REF toggles when TIMx_CNT=TIMx_CCR1.
291 Inactive = 0b0010,
292 /// tim_oc1ref toggles when TIMx_CNT=TIMx_CCR1.
293 Toggle = 0b0011,
294 /// Force inactive level - OC1REF is forced low.
295 ForceInactive = 0b0100,
296 /// Force active level - OC1REF is forced high.
297 ForceActive = 0b0101,
298 /// PWM mode 1 - In upcounting, channel 1 is active as long as TIMx_CNT<TIMx_CCR1
299 /// else inactive. In downcounting, channel 1 is inactive (OC1REF=‘0) as long as
300 /// TIMx_CNT>TIMx_CCR1 else active (OC1REF=1).
301 Pwm1 = 0b0110,
302 /// PWM mode 2 - In upcounting, channel 1 is inactive as long as
303 /// TIMx_CNT<TIMx_CCR1 else active. In downcounting, channel 1 is active as long as
304 /// TIMx_CNT>TIMx_CCR1 else inactive.
305 Pwm2 = 0b0111,
306 /// Retriggerable OPM mode 1 - In up-counting mode, the channel is active until a trigger
307 /// event is detected (on TRGI signal). Then, a comparison is performed as in PWM mode 1
308 /// and the channels becomes inactive again at the next update. In down-counting mode, the
309 /// channel is inactive until a trigger event is detected (on TRGI signal). Then, a comparison is
310 /// performed as in PWM mode 1 and the channels becomes inactive again at the next update.
311 RetriggerableOpmMode1 = 0b1000,
312 /// Retriggerable OPM mode 2 - In up-counting mode, the channel is inactive until a
313 /// trigger event is detected (on TRGI signal). Then, a comparison is performed as in PWM
314 /// mode 2 and the channels becomes inactive again at the next update. In down-counting
315 /// mode, the channel is active until a trigger event is detected (on TRGI signal). Then, a
316 /// comparison is performed as in PWM mode 1 and the channels becomes active again at the
317 /// next update.
318 RetriggerableOpmMode2 = 0b1001,
319 /// Combined PWM mode 1 - OC1REF has the same behavior as in PWM mode 1.
320 /// OC1REFC is the logical OR between OC1REF and OC2REF.
321 CombinedPwm1 = 0b1100,
322 /// Combined PWM mode 2 - OC1REF has the same behavior as in PWM mode 2.
323 /// OC1REFC is the logical AND between OC1REF and OC2REF.
324 CombinedPwm2 = 0b1101,
325 /// Asymmetric PWM mode 1 - OC1REF has the same behavior as in PWM mode 1.
326 /// OC1REFC outputs OC1REF when the counter is counting up, OC2REF when it is counting
327 /// down.
328 AsymmetricPwm1 = 0b1110,
329 /// Asymmetric PWM mode 2 - OC1REF has the same behavior as in PWM mode 2.
330 /// /// OC1REFC outputs OC1REF when the counter is counting up, OC2REF when it is counting
331 /// down
332 AsymmetricPwm2 = 0b1111,
333}
334
335/// Update Request source. This bit is set and cleared by software to select the UEV event sources.
336/// Sets `TIMx_CR1` register, `URS` field.
337#[derive(Clone, Copy)]
338#[repr(u8)]
339pub enum UpdateReqSrc {
340 /// Any of the following events generate an update interrupt or DMA request.
341 /// These events can be:
342 /// – Counter overflow/underflow
343 /// – Setting the UG bit
344 /// – Update generation through the slave mode controller
345 Any = 0,
346 /// Only counter overflow/underflow generates an update interrupt or DMA request.
347 OverUnderFlow = 1,
348}
349
350/// Capture/Compaer DMA selection.
351/// Sets `TIMx_CR2` register, `CCDS` field.
352#[derive(Clone, Copy)]
353#[repr(u8)]
354pub enum CaptureCompareDma {
355 /// CCx DMA request sent when CCx event occur
356 Ccx = 0,
357 /// CCx DMA request sent when update event occurs
358 Update = 1,
359}
360
361/// Initial configuration data for Timer peripherals.
362#[derive(Clone)]
363pub struct TimerConfig {
364 /// If `one_pulse_mode` is true, the counter stops counting at the next update event
365 /// (clearing the bit CEN). If false, Counter is not stopped at update event. Defaults to false.
366 /// Sets `TIMx_CR` register, `OPM` field.
367 pub one_pulse_mode: bool,
368 /// Update request source. Ie, counter overflow/underflow only, or any. defaults to any.
369 pub update_request_source: UpdateReqSrc,
370 /// Set `true` to buffer the preload. Useful when changing period and duty while the timer is running.
371 /// Default to false.
372 pub auto_reload_preload: bool,
373 /// Select center or edge alignment. Defaults to edge.
374 pub alignment: Alignment,
375 /// Sets when CCx DMA requests occur. Defaults to on CCx event.
376 pub capture_compare_dma: CaptureCompareDma,
377 /// Timer counting direction. Defaults to up.
378 pub direction: CountDir,
379}
380
381impl Default for TimerConfig {
382 fn default() -> Self {
383 Self {
384 one_pulse_mode: false,
385 update_request_source: UpdateReqSrc::Any,
386 auto_reload_preload: false,
387 alignment: Alignment::Edge,
388 capture_compare_dma: CaptureCompareDma::Ccx,
389 direction: CountDir::Up,
390 }
391 }
392}
393
394/// Represents a General Purpose or Advanced Control timer.
395pub struct Timer<TIM> {
396 /// Register block for the specific timer.
397 pub regs: TIM,
398 /// Our config stucture, for configuration that is written to the timer hardware on initialization
399 /// via the constructor.
400 pub cfg: TimerConfig,
401 /// Associated timer clock speed in Hz.
402 clock_speed: u32,
403 // #[cfg(feature = "monotonic")]
404 // /// Used to indicate the timer has expired, and running time counts (eg the `time_elapsed()` method) properly
405 // /// increment.
406 // pub wrap_count: u32,
407 // #[cfg(feature = "monotonic")]
408 /// Updated in the constructor and `set_freq` fns. Used for mapping timer ticks to time (eg in
409 /// seconds, us etc)
410 ns_per_tick: u64,
411 period: f32, // In seconds. Used for overflow tracking. Updated when `ns_per_tick` is.
412}
413
414macro_rules! make_timer {
415 ($TIMX:ident, $tim:ident, $apb:expr, $res:ident) => {
416 impl Timer<pac::$TIMX> {
417 paste! {
418 /// Initialize a Timer peripheral, including enabling and resetting
419 /// its RCC peripheral clock.
420 ///
421 /// Sets prescaler and auto-reload based on the requested frequency.
422 /// Use `new_timx_manual` to set the prescaler and auto-reload directly.
423 pub fn [<new_ $tim>](regs: pac::$TIMX, freq: f32, cfg: TimerConfig, clocks: &Clocks) -> Self {
424 let mut result = Self::new_internal(regs, cfg, clocks);
425
426 result.set_freq(freq).ok();
427 result.set_dir();
428
429 // Trigger an update event to load the prescaler value to the clock
430 // NOTE(write): uses all bits in this register. This also clears the interrupt flag,
431 // which the EGER update will generate.
432 result.reinitialize();
433
434 result
435 }
436
437 /// Initialize a Timer peripheral, including enabling and resetting
438 /// its RCC peripheral clock.
439 pub fn [<new_ $tim _manual>](regs: pac::$TIMX, psc: u16, arr: u32, cfg: TimerConfig, clocks: &Clocks) -> Self {
440 let mut result = Self::new_internal(regs, cfg, clocks);
441
442 result.set_prescaler(psc);
443 result.set_auto_reload(arr);
444 result.set_dir();
445
446 // Trigger an update event to load the prescaler value to the clock
447 // NOTE(write): uses all bits in this register. This also clears the interrupt flag,
448 // which the EGER update will generate.
449 result.reinitialize();
450
451 result
452 }
453
454 #[inline]
455 fn new_internal(regs: pac::$TIMX, cfg: TimerConfig, clocks: &Clocks) -> Self {
456 let rcc = unsafe { &(*RCC::ptr()) };
457
458 // `freq` is in Hz.
459 rcc_en_reset!([<apb $apb>], $tim, rcc);
460
461 #[cfg(not(feature = "c0"))]
462 let clock_speed = clocks.[<apb $apb _timer>]();
463 #[cfg(feature = "c0")]
464 let clock_speed = clocks.apb1_timer(); // C0 only has one APB
465
466 regs.cr1().modify(|_, w| {
467 #[cfg(not(feature = "f373"))]
468 w.opm().bit(cfg.one_pulse_mode);
469 w.urs().bit(cfg.update_request_source as u8 != 0);
470 w.arpe().bit(cfg.auto_reload_preload)
471 });
472
473 #[cfg(not(any(feature = "f373", feature = "c0")))]
474 regs.cr2().modify(|_, w| {
475 w.ccds().bit(cfg.capture_compare_dma as u8 != 0)
476 });
477
478 Timer {
479 clock_speed,
480 cfg,
481 regs,
482 // #[cfg(feature = "monotonic")]
483 // wrap_count: 0,
484 // #[cfg(feature = "monotonic")]
485 ns_per_tick: 0, // set in `new_timx`
486 period: 0., // set in `new_timx`
487 }
488 }
489 }
490
491 /// Enable a specific type of Timer interrupt.
492 pub fn enable_interrupt(&mut self, interrupt: TimerInterrupt) {
493 match interrupt {
494 TimerInterrupt::Update => self.regs.dier().modify(|_, w| w.uie().bit(true)),
495 // todo: Only DIER is in PAC, or some CCs. PAC BUG? Only avail on some timers/MCUs?
496 // TimerInterrupt::Trigger => self.regs.dier().modify(|_, w| w.tie().bit(true)),
497 // TimerInterrupt::CaptureCompare1 => self.regs.dier().modify(|_, w| w.cc1ie().bit(true)),
498 // TimerInterrupt::CaptureCompare2 => self.regs.dier().modify(|_, w| w.cc2ie().bit(true)),
499 // TimerInterrupt::CaptureCompare3 => self.regs.dier().modify(|_, w| w.cc3ie().bit(true)),
500 // TimerInterrupt::CaptureCompare4 => self.regs.dier().modify(|_, w| w.cc4ie().bit(true)),
501 #[cfg(not(feature = "f3"))] // todo: Not working on some variants
502 TimerInterrupt::UpdateDma => self.regs.dier().modify(|_, w| w.ude().bit(true)),
503 // TimerInterrupt::TriggerDma => self.regs.dier().modify(|_, w| w.tde().bit(true)),
504 // TimerInterrupt::CaptureCompare1Dma => self.regs.dier().modify(|_, w| w.cc1de().bit(true)),
505 // TimerInterrupt::CaptureCompare2Dma => self.regs.dier().modify(|_, w| w.ccd2de().bit(true)),
506 // TimerInterrupt::CaptureCompare3Dma => self.regs.dier().modify(|_, w| w.cc3de().bit(true)),
507 // TimerInterrupt::CaptureCompare4Dma => self.regs.dier().modify(|_, w| w.cc4de().bit(true)),
508 _ => unimplemented!("TODO TEMP PROBLEMS"),
509 };
510 }
511
512 /// Disable a specific type of Timer interrupt.
513 pub fn disable_interrupt(&mut self, interrupt: TimerInterrupt) {
514 match interrupt {
515 TimerInterrupt::Update => self.regs.dier().modify(|_, w| w.uie().clear_bit()),
516 // todo: Only DIER is in PAC, or some CCs. PAC BUG? Only avail on some timers/MCUs?
517 // TimerInterrupt::Trigger => self.regs.dier().modify(|_, w| w.tie().clear_bit()),
518 // TimerInterrupt::CaptureCompare1 => self.regs.dier().modify(|_, w| w.cc1ie().clear_bit()),
519 // TimerInterrupt::CaptureCompare2 => self.regs.dier().modify(|_, w| w.cc2ie().clear_bit()),
520 // TimerInterrupt::CaptureCompare3 => self.regs.dier().modify(|_, w| w.cc3ie().clear_bit()),
521 // TimerInterrupt::CaptureCompare4 => self.regs.dier().modify(|_, w| w.cc4ie().clear_bit()),
522 #[cfg(not(feature = "f3"))] // todo: Not working on some variants
523 TimerInterrupt::UpdateDma => self.regs.dier().modify(|_, w| w.ude().clear_bit()),
524 // TimerInterrupt::TriggerDma => self.regs.dier().modify(|_, w| w.tde().clear_bit()),
525 // TimerInterrupt::CaptureCompare1Dma => self.regs.dier().modify(|_, w| w.cc1de().clear_bit()),
526 // TimerInterrupt::CaptureCompare2Dma => self.regs.dier().modify(|_, w| w.ccd2de().clear_bit()),
527 // TimerInterrupt::CaptureCompare3Dma => self.regs.dier().modify(|_, w| w.cc3de().clear_bit()),
528 // TimerInterrupt::CaptureCompare4Dma => self.regs.dier().modify(|_, w| w.cc4de().clear_bit()),
529 _ => unimplemented!("TODO TEMP PROBLEMS"),
530 };
531 }
532
533 /// Clears interrupt associated with this timer.
534 ///
535 /// If the interrupt is not cleared, it will immediately retrigger after
536 /// the ISR has finished. For examlpe, place this at the top of your timer's
537 /// interrupt handler.
538 pub fn clear_interrupt(&mut self, interrupt: TimerInterrupt) {
539 // Note that unlike other clear interrupt functions, for this, we clear the bit instead
540 // of setting it. Due to the way our SVDs are set up not working well with this atomic clear,
541 // we need to make sure we write 1s to the rest of the bits.
542 // todo: Overcapture flags for each CC? DMA interrupts?
543 #[cfg(feature = "c0")]
544 let bits = 0xffff;
545 #[cfg(not(feature = "c0"))]
546 let bits = 0xffff_ffff;
547
548 unsafe {
549 match interrupt {
550 TimerInterrupt::Update => self
551 .regs
552 .sr()
553 .write(|w| w.bits(bits).uif().clear_bit()),
554 // todo: Only DIER is in PAC, or some CCs. PAC BUG? Only avail on some timers?
555 // TimerInterrupt::Trigger => self.regs.sr().write(|w| w.bits(bits).tif().clear_bit()),
556 // TimerInterrupt::CaptureCompare1 => self.regs.sr().write(|w| w.bits(bits).cc1if().clear_bit()),
557 // TimerInterrupt::CaptureCompare2 => self.regs.sr().write(|w| w.bits(bits).cc2if().clear_bit()),
558 // TimerInterrupt::CaptureCompare3 => self.regs.sr().write(|w| w.bits(bits).cc3if().clear_bit()),
559 // TimerInterrupt::CaptureCompare4 => self.regs.sr().write(|w| w.bits(bits).cc4if().clear_bit()),
560 _ => unimplemented!(
561 "Clearing DMA flags is unimplemented using this function."
562 ),
563 };
564 }
565 }
566
567 /// Enable (start) the timer.
568 pub fn enable(&mut self) {
569 self.regs.cr1().modify(|_,w| w.cen().bit(true));
570 }
571
572 /// Disable (stop) the timer.
573 pub fn disable(&mut self) {
574 self.regs.cr1().modify(|_, w| w.cen().clear_bit());
575 }
576
577 /// Check if the timer is enabled.
578 pub fn is_enabled(&self) -> bool {
579 self.regs.cr1().read().cen().bit_is_set()
580 }
581
582 #[cfg(not(feature = "c0"))]
583 /// Print the (raw) contents of the status register.
584 pub fn read_status(&self) -> u32 {
585 unsafe { self.regs.sr().read().bits() }
586 }
587
588 #[cfg(feature = "c0")]
589 /// Print the (raw) contents of the status register.
590 pub fn read_status(&self) -> u16 {
591 unsafe { self.regs.sr().read().bits().try_into().unwrap() }
592 }
593
594 /// Set the timer frequency, in Hz. Overrides the period or frequency set
595 /// in the constructor.
596 pub fn set_freq(&mut self, mut freq: f32) -> Result<()> {
597 assert!(freq > 0.);
598 // todo: Take into account the `timxsw` bit in RCC CFGR3, which may also
599 // todo require an adjustment to freq.
600 match self.cfg.alignment {
601 Alignment::Edge => (),
602 _ => freq *= 2.,
603 }
604
605 let (psc, arr) = calc_freq_vals(freq, self.clock_speed)?;
606
607 self.regs.arr().write(|w| unsafe { w.bits(arr.into()) });
608 self.regs.psc().write(|w| unsafe { w.bits(psc.into()) });
609
610 // (PSC+1)*(ARR+1) = TIMclk/Updatefrequency = TIMclk * period
611 // period = (PSC+1)*(ARR+1) / TIMclk
612 // Calculate this based on our actual ARR and PSC values; don't use
613 // the requested frequency or period.
614 let arr_f32 = arr as f32;
615 let period_secs = (psc as f32 + 1.) * ( arr_f32 + 1.) / self.clock_speed as f32;
616 self.ns_per_tick = (period_secs / arr_f32 * 1_000_000_000.) as u64;
617 self.period = period_secs;
618
619 Ok(())
620 }
621
622 /// Set the timer period, in seconds. Overrides the period or frequency set
623 /// in the constructor.
624 pub fn set_period(&mut self, period: f32) -> Result<()> {
625 assert!(period > 0.);
626 self.set_freq(1. / period)
627 }
628
629 /// Set the auto-reload register value. Used for adjusting frequency.
630 pub fn set_auto_reload(&mut self, arr: u32) {
631 // todo: Could be u16 or u32 depending on timer resolution,
632 // todo but this works for now.
633 #[cfg(not(feature = "c0"))]
634 self.regs.arr().write(|w| unsafe { w.bits(arr.into()) });
635 #[cfg(feature = "c0")]
636 self.regs.arr().write(|w| unsafe { w.bits((arr as u32).try_into().unwrap()) });
637 }
638
639 /// Set the prescaler value. Used for adjusting frequency.
640 pub fn set_prescaler(&mut self, psc: u16) {
641 self.regs.psc().write(|w| unsafe { w.bits(psc.into()) });
642 }
643
644 /// Reset the countdown; set the counter to 0.
645 pub fn reset_count(&mut self) {
646 self.regs.cnt().write(|w| unsafe { w.bits(0) });
647 }
648
649 /// UIF Flag in SR register is set when CNT reg is overflow / underflow
650 ///
651 pub fn get_uif(&self ) -> bool {
652 self.regs.sr().read().uif().bit_is_set()
653 }
654
655 pub fn clear_uif(&mut self) {
656 #[cfg(feature = "c0")]
657 let bits = 0xffff;
658 #[cfg(not(feature = "c0"))]
659 let bits = 0xffff_ffff;
660
661 unsafe {
662 self.regs
663 .sr()
664 .write(|w| w.bits(bits).uif().clear_bit());
665 }
666 }
667
668 /// Re-initialize the counter and generates an update of the registers. Note that the prescaler
669 /// counter is cleared too (anyway the prescaler ratio is not affected). The counter is cleared.
670 /// When changing timer frequency (or period) via PSC, you may need to run this. Alternatively, change
671 /// the freq in an update ISR.
672 /// Note from RM, PSC reg: PSC contains the value to be loaded in the active prescaler
673 /// register at each update event
674 /// (including when the counter is cleared through UG bit of TIMx_EGR register or through
675 /// trigger controller when configured in “reset mode”).'
676 /// If you're doing something where the updates can wait a cycle, this isn't required. (eg PWM
677 /// with changing duty period).
678 pub fn reinitialize(&mut self) {
679 self.regs.egr().write(|w| w.ug().bit(true));
680 self.clear_interrupt(TimerInterrupt::Update);
681 }
682
683 /// Read the current counter value.
684 pub fn read_count(&self) -> u32 {
685 // todo: This depends on resolution. We read the whole
686 // todo res and pass a u32 just in case.
687 // self.regs.cnt().read().cnt().bits()
688 self.regs.cnt().read().bits()
689 }
690
691
692 /// Enables PWM output for a given channel and output compare, with an initial duty cycle, in Hz.
693 pub fn enable_pwm_output(
694 &mut self,
695 channel: TimChannel,
696 compare: OutputCompare,
697 duty: f32,
698 ) {
699 self.set_capture_compare_output(channel, CaptureCompare::Output);
700 self.set_preload(channel, true);
701 self.set_output_compare(channel, compare);
702 self.set_duty(channel, (self.get_max_duty() as f32 * duty) as $res);
703 self.enable_capture_compare(channel);
704 }
705
706 /// Return the integer associated with the maximum duty period.
707 pub fn get_max_duty(&self) -> $res {
708 #[cfg(feature = "g0")]
709 return self.regs.arr().read().bits().try_into().unwrap();
710 #[cfg(not(feature = "g0"))]
711 self.regs.arr().read().arr().bits().try_into().unwrap()
712 }
713
714 /// See G4 RM, section 29.4.24: Dma burst mode. "The TIMx timers have the capability to
715 /// generate multiple DMA requests upon a single event.
716 /// The main purpose is to be able to re-program part of the timer multiple times without
717 /// software overhead, but it can also be used to read several registers in a row, at regular
718 /// intervals." This may be used to create arbitrary waveforms by modifying the CCR register
719 /// (base address = 13-16, for CCR1-4), or for implementing duty-cycle based digital protocols.
720 #[cfg(not(any(feature = "g0", feature = "f", feature = "l552", feature = "l4")))]
721 pub unsafe fn write_dma_burst(
722 &mut self,
723 buf: &[u16],
724 base_address: u8,
725 burst_len: u8,
726 dma_channel: DmaChannel,
727 channel_cfg: ChannelCfg,
728 ds_32_bits: bool,
729 dma_periph: dma::DmaPeriph,
730 ) -> Result<()> {
731 // Note: F3 and L4 are unsupported here, since I'm not sure how to select teh
732 // correct Timer channel.
733
734 // todo: Should we disable the timer here?
735
736 let (ptr, len) = (buf.as_ptr(), buf.len());
737
738 // todo: For F3 and L4, manually set channel using PAC for now. Currently
739 // todo we don't have a way here to pick the timer. Could do it with a new macro arg.
740
741 // L44 RM, Table 41. "DMA1 requests for each channel"
742 // #[cfg(any(feature = "f3", feature = "l4"))]
743 // let dma_channel = match tim_channel {
744 // // SaiChannel::A => DmaInput::Sai1A.dma1_channel(),
745 // };
746 //
747 // #[cfg(feature = "l4")]
748 // match tim_channel {
749 // SaiChannel::B => dma.channel_select(DmaInput::Sai1B),
750 // };
751
752 // RM:
753 // This example is for the case where every CCRx register has to be updated once. If every
754 // CCRx register is to be updated twice for example, the number of data to transfer should be
755 // 6. Let's take the example of a buffer in the RAM containing data1, data2, data3, data4, data5
756 // and data6. The data is transferred to the CCRx registers as follows: on the first update DMA
757 // request, data1 is transferred to CCR2, data2 is transferred to CCR3, data3 is transferred to
758 // CCR4 and on the second update DMA request, data4 is transferred to CCR2, data5 is
759 // transferred to CCR3 and data6 is transferred to CCR4.
760
761 // 1. Configure the corresponding DMA channel as follows:
762 // –DMA channel peripheral address is the DMAR register address
763 let periph_addr = unsafe { &self.regs.dmar() as *const _ as u32 };
764 // –DMA channel memory address is the address of the buffer in the RAM containing
765 // the data to be transferred by DMA into CCRx registers.
766
767 // Number of data to transfer is our buffer len number of registers we're editing, x
768 // number of half-words written to each reg.
769 let num_data = len as u32;
770
771 // 2.
772 // Configure the DCR register by configuring the DBA and DBL bit fields as follows:
773 // DBL = 3 transfers, DBA = 0xE.
774
775 // The DBL[4:0] bits in the TIMx_DCR register set the DMA burst length. The timer recognizes
776 // a burst transfer when a read or a write access is done to the TIMx_DMAR address), i.e. the
777 // number of transfers (either in half-words or in bytes).
778 // The DBA[4:0] bits in the TIMx_DCR registers define the DMA base address for DMA
779 // transfers (when read/write access are done through the TIMx_DMAR address). DBA is
780 // defined as an offset starting from the address of the TIMx_CR1 register:
781 // Example:
782 // 00000: TIMx_CR1
783 // 00001: TIMx_CR2
784 // 00010: TIMx_SMCR
785 self.regs.dcr().modify(|_, w| unsafe {
786 w.dba().bits(base_address);
787 w.dbl().bits(burst_len as u8 - 1)
788 });
789
790 // 3. Enable the TIMx update DMA request (set the UDE bit in the DIER register).
791 // note: Leaving this to application code for now.
792 // self.enable_interrupt(TimerInterrupt::UpdateDma);
793
794 // 4. Enable TIMx
795 self.enable();
796
797 // 5. Enable the DMA channel
798 match dma_periph {
799 dma::DmaPeriph::Dma1 => {
800 let mut regs = unsafe { &(*DMA1::ptr()) };
801 dma::cfg_channel(
802 &mut regs,
803 dma_channel,
804 periph_addr,
805 ptr as u32,
806 num_data,
807 dma::Direction::ReadFromMem,
808 // Note: This may only be relevant if modifying a reg that changes for 32-bit
809 // timers, like AAR and CCRx
810 if ds_32_bits { dma::DataSize::S32} else { dma::DataSize::S16 },
811 dma::DataSize::S16,
812 channel_cfg,
813 )?;
814 }
815 #[cfg(dma2)]
816 dma::DmaPeriph::Dma2 => {
817 let mut regs = unsafe { &(*pac::DMA2::ptr()) };
818 dma::cfg_channel(
819 &mut regs,
820 dma_channel,
821 periph_addr,
822 ptr as u32,
823 num_data,
824 dma::Direction::ReadFromMem,
825 // Note: This may only be relevant if modifying a reg that changes for 32-bit
826 // timers, like AAR and CCRx
827 if ds_32_bits { dma::DataSize::S32} else { dma::DataSize::S16 },
828 dma::DataSize::S16,
829 channel_cfg,
830 )?;
831 }
832 }
833 Ok(())
834 }
835
836 #[cfg(not(any(feature = "g0", feature = "f", feature = "l552", feature = "l4")))]
837 pub unsafe fn read_dma_burst(
838 // todo: Experimenting with input capture.
839 &mut self,
840 buf: &mut [u16],
841 base_address: u8,
842 burst_len: u8,
843 dma_channel: DmaChannel,
844 channel_cfg: ChannelCfg,
845 ds_32_bits: bool,
846 dma_periph: dma::DmaPeriph,
847 ) -> Result<()> {
848 let (ptr, len) = (buf.as_mut_ptr(), buf.len());
849
850 let periph_addr = unsafe { &self.regs.dmar() as *const _ as u32 };
851
852 let num_data = len as u32;
853
854 self.regs.dcr().modify(|_, w| unsafe {
855 w.dba().bits(base_address);
856 w.dbl().bits(burst_len as u8 - 1)
857 });
858
859 self.enable();
860
861 match dma_periph {
862 dma::DmaPeriph::Dma1 => {
863 #[cfg(not(feature = "c0"))]
864 let mut regs = unsafe { &(*pac::DMA1::ptr()) };
865 #[cfg(feature = "c0")]
866 let mut regs = unsafe { &(*pac::DMA::ptr()) };
867
868 dma::cfg_channel(
869 &mut regs,
870 dma_channel,
871 periph_addr,
872 ptr as u32,
873 num_data,
874 dma::Direction::ReadFromPeriph,
875 // Note: This may only be relevant if modifying a reg that changes for 32-bit
876 // timers, like AAR and CCRx
877 if ds_32_bits { dma::DataSize::S32} else { dma::DataSize::S16 },
878 dma::DataSize::S16,
879 channel_cfg,
880 )?;
881 }
882 #[cfg(dma2)]
883 dma::DmaPeriph::Dma2 => {
884 let mut regs = unsafe { &(*pac::DMA2::ptr()) };
885 dma::cfg_channel(
886 &mut regs,
887 dma_channel,
888 periph_addr,
889 ptr as u32,
890 num_data,
891 dma::Direction::ReadFromPeriph,
892 // Note: This may only be relevant if modifying a reg that changes for 32-bit
893 // timers, like AAR and CCRx
894 if ds_32_bits { dma::DataSize::S32} else { dma::DataSize::S16 },
895 dma::DataSize::S16,
896 channel_cfg,
897 )?;
898 }
899 }
900 Ok(())
901 }
902
903 /// Get the time elapsed since the start of the timer, taking overflow wraps into account.
904 ///
905 /// Important: the value returned here will only be correct if the ARR and PSC are set
906 /// only using the constructor, `set_freq`, or `set_period` methods.
907 pub fn now(&mut self) -> Instant {
908 // let wrap_count = self.wrap_count;
909 let wrap_count = TICK_OVERFLOW_COUNT.load(Ordering::Acquire);
910
911 let ticks = (self.read_count() as u64 + wrap_count as u64 *
912 self.get_max_duty() as u64);
913 let count_ns = ticks as i128 * self.ns_per_tick as i128;
914
915 Instant::new(count_ns)
916 }
917
918 pub fn elapsed(&mut self, since: Instant) -> Duration {
919 self.now() - since
920 }
921 }
922
923 #[cfg(feature = "monotonic")]
924 impl Monotonic for Timer<pac::$TIMX> {
925 type Instant = Instant;
926 type Duration = core::time::Duration;
927
928 const DISABLE_INTERRUPT_ON_EMPTY_QUEUE: bool = false;
929
930 fn now(&mut self) -> Self::Instant {
931 self.time_elapsed()
932 }
933
934 /// We use the compare 1 channel for this.
935 /// todo: Support wrapping?
936 fn set_compare(&mut self, instant: Self::Instant) {
937 self.regs
938 .ccr1()
939 .write(|w| unsafe { w.ccr().bits(((instant.count_ns as f32 / self.ns_per_tick) as u16).into()) });
940 }
941
942 /// We use the compare 1 channel for this.
943 /// todo: Support wrapping?
944 fn clear_compare_flag(&mut self) {
945 self.regs.sr().modify(|_, w| w.cc1if().clear_bit());
946 }
947
948 fn zero() -> Self::Instant {
949 Instant::default()
950 }
951
952 unsafe fn reset(&mut self) {
953 self.reset_count();
954 TICK_OVERFLOW_COUNT.store(0, Ordering::Release);
955 }
956
957 fn on_interrupt(&mut self) {
958 // self.wrap_count += 1;
959 TICK_OVERFLOW_COUNT.fetch_add(1, Ordering::Relaxed);
960 }
961 fn enable_timer(&mut self) {
962 self.enable();
963 }
964 fn disable_timer(&mut self) {
965 self.disable();
966 }
967
968 /// Print the (raw) contents of the status register.
969 pub fn read_status(&self) -> u32 {
970 unsafe { self.regs.isr().read().bits() }
971 }
972 }
973
974 // cfg_if! {
975 // if #[cfg(feature = "embedded_hal")] {
976 // // use embedded_hal::{
977 // // blocking::delay::{DelayMs, DelayUs},
978 // // timer::CountDown,
979 // // };
980 // // use embedded_time::{rate::Hertz, duration};
981 // // use void::Void;
982 // }
983 // }
984
985 // #[cfg(feature = "embedded_hal")]
986 // // #[cfg_attr(docsrs, doc(cfg(feature = "embedded_hal")))]
987 // impl DelayMs<u32> for Timer<pac::$TIMX> {
988 // fn delay_ms(&mut self, ms: u32) {
989 // let ms_to_s = ms as f32 / 1_000.;
990 // self.set_freq(1. / (ms_to_s)).ok();
991 // self.reset_count();
992 // self.enable();
993 // while self.get_uif() == false {}
994 // self.clear_uif();
995 // self.disable();
996 // }
997 // }
998 //
999 // #[cfg(feature = "embedded_hal")]
1000 // // #[cfg_attr(docsrs, doc(cfg(feature = "embedded_hal")))]
1001 // impl DelayMs<u16> for Timer<pac::$TIMX> {
1002 // fn delay_ms(&mut self, ms: u16) {
1003 // self.delay_ms(ms as u32)
1004 // }
1005 // }
1006 //
1007 // #[cfg(feature = "embedded_hal")]
1008 // // #[cfg_attr(docsrs, doc(cfg(feature = "embedded_hal")))]
1009 // impl DelayMs<u8> for Timer<pac::$TIMX> {
1010 // fn delay_ms(&mut self, ms: u8) {
1011 // self.delay_ms(ms as u32)
1012 // }
1013 // }
1014 //
1015 // #[cfg(feature = "embedded_hal")]
1016 // // #[cfg_attr(docsrs, doc(cfg(feature = "embedded_hal")))]
1017 // impl DelayUs<u32> for Timer<pac::$TIMX> {
1018 // fn delay_us(&mut self, us: u32) {
1019 // let us_to_s = us as f32 / 1_000_000.;
1020 // self.set_freq(1. / (us_to_s)).ok();
1021 // self.reset_count();
1022 // self.enable();
1023 // while self.get_uif() == false {}
1024 // self.clear_uif();
1025 // self.disable();
1026 // }
1027 // }
1028 //
1029 // #[cfg(feature = "embedded_hal")]
1030 // // #[cfg_attr(docsrs, doc(cfg(feature = "embedded_hal")))]
1031 // impl DelayUs<u16> for Timer<pac::$TIMX> {
1032 // fn delay_us(&mut self, us: u16) {
1033 // self.delay_us(us as u32);
1034 // }
1035 // }
1036 //
1037 // #[cfg(feature = "embedded_hal")]
1038 // // #[cfg_attr(docsrs, doc(cfg(feature = "embedded_hal")))]
1039 // impl DelayUs<u8> for Timer<pac::$TIMX> {
1040 // fn delay_us(&mut self, us: u8) {
1041 // self.delay_us(us as u32);
1042 // }
1043 // }
1044
1045 // /// Implementation of the embedded-hal CountDown trait
1046 // /// To use Countdown it is prefered to configure new timer in Oneshot mode :
1047 // ///
1048 // /// Example :
1049 // /// llet tim16_conf = TimerConfig {
1050 // /// one_pulse_mode: true,
1051 // /// ..Default::default()
1052 // /// };
1053 // ///
1054 // /// Creation of timer. Here the freq arg value is not important, the freq
1055 // /// will be changed for each CountDown start timer depends on delay wanted.
1056 // ///
1057 // /// let mut tim16: Timer<TIM16> = Timer::new_tim16(dp.TIM16, 1000., tim16_conf, &clocks);
1058 // ///
1059 // ///
1060 // #[cfg(feature = "embedded_hal")]
1061 // impl CountDown for Timer<pac::$TIMX>
1062 // {
1063 // type Time = duration::Generic<u32>;
1064 //
1065 // fn start<T>(&mut self, timeout: T)
1066 // where
1067 // T: Into<Self::Time>,
1068 // {
1069 //
1070 // //Disable timer and clear flag uif
1071 // self.disable();
1072 // self.clear_uif();
1073 //
1074 // //Get timeout
1075 // let timeout: Self::Time = timeout.into();
1076 //
1077 // let denom = timeout.scaling_factor().denominator();
1078 //
1079 // //Prevent a division by zero
1080 // if *denom != 0 {
1081 // //Convert time to seconds
1082 // let time_to_s = timeout.integer() as f32 / *denom as f32;
1083 //
1084 // //Configure timer
1085 // self.set_freq(1. / (time_to_s)).ok();
1086 // self.reset_count();
1087 // //Update event to setup prescale and reload registers
1088 // self.reinitialize();
1089 // self.clear_uif();
1090 //
1091 // //start the timer
1092 // self.enable();
1093 // }
1094 //
1095 // }
1096 //
1097 // /// Wait until the timer has elapsed
1098 // /// and than clear the event.
1099 // fn wait(&mut self) -> nb::Result<(), Void> {
1100 // if !self.get_uif() {
1101 // Err(nb::Error::WouldBlock)
1102 // } else {
1103 // self.clear_uif();
1104 // self.disable();
1105 // Ok(())
1106 // }
1107 // }
1108 // }
1109 }
1110}
1111
1112macro_rules! cc_slave_mode {
1113 ($TIMX:ident) => {
1114 impl Timer<pac::$TIMX> {
1115 /// Set input slave mode and input trigger. See `InputSlaveMode` and `InputTrigger` documentation for more details.
1116 /// Use `set_input_capture` to configure input channels if required.
1117 ///
1118 /// Note: Some modes (e.g. encoder modes) are unavailable on some timers. Consult the reference manual for specifics.
1119 pub fn set_input_slave_mode(
1120 &mut self,
1121 slave_mode: InputSlaveMode,
1122 trigger: InputTrigger,
1123 ) {
1124 self.regs.smcr().modify(|_, w| unsafe {
1125 w.sms().bits(slave_mode as u8).ts().bits(trigger as u8)
1126 });
1127 }
1128 }
1129 };
1130}
1131
1132// We use macros to support the varying number of capture compare channels available on
1133// different timers.
1134// Note that there's lots of DRY between these implementations.
1135macro_rules! cc_4_channels {
1136 ($TIMX:ident, $res:ident $(, $bdtr:ident)?) => {
1137 impl Timer<pac::$TIMX> {
1138 /// Function that allows us to set direction only on timers that have this option.
1139 pub fn set_dir(&mut self) {
1140 self.regs
1141 .cr1()
1142 .modify(|_, w| w.dir().bit(self.cfg.direction as u8 != 0));
1143 self.regs
1144 .cr1()
1145 .modify(|_, w| unsafe { w.cms().bits(self.cfg.alignment as u8) });
1146 }
1147
1148 /// Set up input capture, eg for PWM input.
1149 /// L4 RM, section 26.3.8. H723 RM, section 43.3.7.
1150 ///
1151 /// Note: Does not handle TISEL (timer input selection register), ICxPS (input capture prescaler),
1152 /// and ICxF (input capture filter) - you must set these manually using the PAC if hardware defaults are not appropriate.
1153 #[cfg(not(any(
1154 feature = "f",
1155 feature = "l4x5",
1156 feature = "l5",
1157 feature = "g0",
1158 feature = "wb"
1159 )))]
1160 pub fn set_input_capture(
1161 &mut self,
1162 channel: TimChannel,
1163 mode: CaptureCompare,
1164 ccp: Polarity,
1165 ccnp: Polarity,
1166 ) {
1167 // 2. Select the active input for TIMx_CCR1: write the CC1S bits to 01 in the TIMx_CCMR1
1168 // register.
1169 self.set_capture_compare_input(channel, mode);
1170
1171 // 1. Select the proper TI1x source (internal or external) with the TI1SEL[3:0] bits in the
1172 // TIMx_TISEL register.
1173 // Leaving it at its default value of 0 selects the timer input, which we'll hard-code
1174 // for now.
1175 // let tisel = 0b0000;
1176
1177 // 3.
1178 // Program the needed input filter duration in relation with the signal connected to the
1179 // timer (when the input is one of the tim_tix (ICxF bits in the TIMx_CCMRx register). Let’s
1180 // imagine that, when toggling, the input signal is not stable during at must 5 internal clock
1181 // cycles. We must program a filter duration longer than these 5 clock cycles. We can
1182 // validate a transition on tim_ti1 when 8 consecutive samples with the new level have
1183 // been detected (sampled at fDTS frequency). Then write IC1F bits to 0011 in the
1184 // TIMx_CCMR1 register.
1185 // let filter = 0b0000;
1186
1187 match channel {
1188 TimChannel::C1 => {
1189 // self.regs.tisel.modify(|_, w| unsafe { w.ti1sel().bits(tisel) });
1190
1191 // 4. Select the active polarity for TI1FP1 (used both for capture in TIMx_CCR1 and counter
1192 // clear): write the CC1P and CC1NP bits to ‘0’ (active on rising edge).
1193 // (Note: We could use the `set_polarity` and `set_complementary_polarity` methods, but
1194 // this allows us to combine them in a single reg write.)
1195 self.regs.ccer().modify(|_, w| {
1196 w.cc1p().bit(ccp.bit());
1197 w.cc1np().bit(ccnp.bit())
1198 });
1199
1200 // 5.
1201 // Program the input prescaler. In our example, we wish the capture to be performed at
1202 // each valid transition, so the prescaler is disabled (write IC1PS bits to 00 in the
1203 // TIMx_CCMR1 register).
1204 // self.regs.ccmr1_input().modify(|_, w| unsafe {
1205 // // todo: PAC ommission?
1206 // // w.ic1psc().bits(0b00);
1207 // w.ic1f().bits(filter)
1208 // });
1209 }
1210 TimChannel::C2 => {
1211 // self.regs.tisel.modify(|_, w| unsafe { w.ti2sel().bits(tisel) });
1212
1213 self.regs.ccer().modify(|_, w| {
1214 w.cc2p().bit(ccp.bit());
1215 w.cc2np().bit(ccnp.bit())
1216 });
1217
1218 // self.regs.ccmr1_input().modify(|_, w| unsafe {
1219 // w.ic2psc().bits(0b00);
1220 // w.ic2f().bits(filter)
1221 // });
1222 }
1223 TimChannel::C3 => {
1224 // self.regs.tisel.modify(|_, w| unsafe { w.ti3sel().bits(tisel) });
1225
1226 self.regs.ccer().modify(|_, w| {
1227 w.cc3p().bit(ccp.bit());
1228 w.cc3np().bit(ccnp.bit())
1229 });
1230
1231 // self.regs.ccmr2_input().modify(|_, w| unsafe {
1232 // w.ic3psc().bits(0b00);
1233 // w.ic3f().bits(filter)
1234 // });
1235 }
1236 #[cfg(not(feature = "wl"))]
1237 TimChannel::C4 => {
1238 // self.regs.tisel.modify(|_, w| unsafe { w.ti4sel().bits(tisel) });
1239
1240 self.regs.ccer().modify(|_, w| {
1241 #[cfg(not(any(feature = "f4", feature = "l4")))]
1242 w.cc4np().bit(ccnp.bit());
1243 w.cc4p().bit(ccp.bit())
1244 });
1245
1246 // self.regs.ccmr2_input().modify(|_, w| unsafe {
1247 // w.ic4psc().bits(0b00);
1248 // w.ic4f().bits(filter)
1249 // });
1250 }
1251 }
1252
1253 // 6. Enable capture from the counter into the capture register by setting the CC1E bit in the
1254 // TIMx_CCER register.
1255 self.enable_capture_compare(channel);
1256
1257 // 7.If needed, enable the related interrupt request by setting the CC1IE bit in the
1258 // TIMx_DIER register, and/or the DMA request by setting the CC1DE bit in the
1259 // TIMx_DIER register.
1260 }
1261
1262 // todo: more advanced PWM modes. Asymmetric, combined, center-aligned etc.
1263
1264 /// Set Output Compare Mode. See docs on the `OutputCompare` enum.
1265 pub fn set_output_compare(&mut self, channel: TimChannel, mode: OutputCompare) {
1266 match channel {
1267 TimChannel::C1 => {
1268 self.regs.ccmr1_output().modify(|_, w| unsafe {
1269 #[cfg(not(any(feature = "f", feature = "l5", feature = "wb")))]
1270 w.oc1m_3().bit((mode as u8) >> 3 != 0);
1271 w.oc1m().bits((mode as u8) & 0b111)
1272 });
1273 }
1274 TimChannel::C2 => {
1275 self.regs.ccmr1_output().modify(|_, w| unsafe {
1276 #[cfg(not(any(feature = "f", feature = "l5", feature = "wb")))]
1277 w.oc2m_3().bit((mode as u8) >> 3 != 0);
1278 w.oc2m().bits((mode as u8) & 0b111)
1279 });
1280 }
1281 TimChannel::C3 => {
1282 self.regs.ccmr2_output().modify(|_, w| unsafe {
1283 #[cfg(not(any(feature = "f", feature = "l5", feature = "wb")))]
1284 w.oc3m_3().bit((mode as u8) >> 3 != 0);
1285 w.oc3m().bits((mode as u8) & 0b111)
1286 });
1287 }
1288 #[cfg(not(feature = "wl"))]
1289 TimChannel::C4 => {
1290 self.regs.ccmr2_output().modify(|_, w| unsafe {
1291 #[cfg(not(any(
1292 feature = "f3",
1293 feature = "f4",
1294 feature = "l5",
1295 feature = "wb",
1296 feature = "h7"
1297 )))]
1298 w.oc4m_3().bit((mode as u8) >> 3 != 0);
1299 w.oc4m().bits((mode as u8) & 0b111)
1300 });
1301 }
1302 }
1303 }
1304
1305 /// Return the set duty period for a given channel. Divide by `get_max_duty()`
1306 /// to find the portion of the duty cycle used.
1307 pub fn get_duty(&self, channel: TimChannel) -> $res {
1308 cfg_if! {
1309 if #[cfg(any(feature = "wb", feature = "wl"))] {
1310 (match channel {
1311 TimChannel::C1 => self.regs.ccr1().read().bits(),
1312 TimChannel::C2 => self.regs.ccr2().read().bits(),
1313 TimChannel::C3 => self.regs.ccr3().read().bits(),
1314 #[cfg(not(feature = "wl"))]
1315 TimChannel::C4 => self.regs.ccr4().read().bits(),
1316 }) as $res
1317 } else {
1318 match channel {
1319 TimChannel::C1 => self.regs.ccr1().read().ccr().bits().into(),
1320 TimChannel::C2 => self.regs.ccr2().read().ccr().bits().into(),
1321 TimChannel::C3 => self.regs.ccr3().read().ccr().bits().into(),
1322 #[cfg(not(feature = "wl"))]
1323 TimChannel::C4 => self.regs.ccr4().read().ccr().bits().into(),
1324 }
1325 }
1326 }
1327 }
1328
1329 /// Set the duty cycle, as a portion of ARR (`get_max_duty()`). Note that this
1330 /// needs to be re-run if you change ARR at any point.
1331 pub fn set_duty(&mut self, channel: TimChannel, duty: $res) {
1332 unsafe {
1333 match channel {
1334 TimChannel::C1 => self
1335 .regs
1336 .ccr1()
1337 .write(|w| w.ccr().bits(duty.try_into().unwrap())),
1338 TimChannel::C2 => self
1339 .regs
1340 .ccr2()
1341 .write(|w| w.ccr().bits(duty.try_into().unwrap())),
1342 TimChannel::C3 => self
1343 .regs
1344 .ccr3()
1345 .write(|w| w.ccr().bits(duty.try_into().unwrap())),
1346 #[cfg(not(feature = "wl"))]
1347 TimChannel::C4 => self
1348 .regs
1349 .ccr4()
1350 .write(|w| w.ccr().bits(duty.try_into().unwrap())),
1351 };
1352 }
1353 }
1354
1355 /// Set timer alignment to Edge, or one of 3 center modes.
1356 /// STM32F303 ref man, section 21.4.1:
1357 /// Bits 6:5 CMS: Center-aligned mode selection
1358 /// 00: Edge-aligned mode. The counter counts up or down depending on the direction bit
1359 /// (DIR).
1360 /// 01: Center-aligned mode 1. The counter counts up and down alternatively. Output compare
1361 /// interrupt flags of channels configured in output (CCxS=00 in TIMx_CCMRx register) are set
1362 /// only when the counter is counting down.
1363 /// 10: Center-aligned mode 2. The counter counts up and down alternatively. Output compare
1364 /// interrupt flags of channels configured in output (CCxS=00 in TIMx_CCMRx register) are set
1365 /// only when the counter is counting up.
1366 /// 11: Center-aligned mode 3. The counter counts up and down alternatively. Output compare
1367 /// interrupt flags of channels configured in output (CCxS=00 in TIMx_CCMRx register) are set
1368 /// both when the counter is counting up or down.
1369 pub fn set_alignment(&mut self, alignment: Alignment) {
1370 self.regs
1371 .cr1()
1372 .modify(|_, w| unsafe { w.cms().bits(alignment as u8) });
1373 self.cfg.alignment = alignment;
1374 }
1375
1376 /// Set output polarity. See docs on the `Polarity` enum.
1377 pub fn set_polarity(&mut self, channel: TimChannel, polarity: Polarity) {
1378 match channel {
1379 TimChannel::C1 => self.regs.ccer().modify(|_, w| w.cc1p().bit(polarity.bit())),
1380 TimChannel::C2 => self.regs.ccer().modify(|_, w| w.cc2p().bit(polarity.bit())),
1381 TimChannel::C3 => self.regs.ccer().modify(|_, w| w.cc3p().bit(polarity.bit())),
1382 #[cfg(not(feature = "wl"))]
1383 TimChannel::C4 => self.regs.ccer().modify(|_, w| w.cc4p().bit(polarity.bit())),
1384 };
1385 }
1386
1387 /// Set complementary output polarity. See docs on the `Polarity` enum.
1388 pub fn set_complementary_polarity(&mut self, channel: TimChannel, polarity: Polarity) {
1389 match channel {
1390 TimChannel::C1 => self
1391 .regs
1392 .ccer()
1393 .modify(|_, w| w.cc1np().bit(polarity.bit())),
1394 TimChannel::C2 => self
1395 .regs
1396 .ccer()
1397 .modify(|_, w| w.cc2np().bit(polarity.bit())),
1398 TimChannel::C3 => self
1399 .regs
1400 .ccer()
1401 .modify(|_, w| w.cc3np().bit(polarity.bit())),
1402 #[cfg(not(any(feature = "f4", feature = "wl", feature = "l4")))]
1403 TimChannel::C4 => self
1404 .regs
1405 .ccer()
1406 .modify(|_, w| w.cc4np().bit(polarity.bit())),
1407 #[cfg(any(feature = "f4", feature = "wl", feature = "l4"))] // PAC ommission
1408 _ => panic!(),
1409 };
1410 }
1411 /// Disables capture compare on a specific channel.
1412 pub fn disable_capture_compare(&mut self, channel: TimChannel) {
1413 match channel {
1414 TimChannel::C1 => self.regs.ccer().modify(|_, w| w.cc1e().clear_bit()),
1415 TimChannel::C2 => self.regs.ccer().modify(|_, w| w.cc2e().clear_bit()),
1416 TimChannel::C3 => self.regs.ccer().modify(|_, w| w.cc3e().clear_bit()),
1417 #[cfg(not(feature = "wl"))]
1418 TimChannel::C4 => self.regs.ccer().modify(|_, w| w.cc4e().clear_bit()),
1419 };
1420 }
1421
1422 /// Enables capture compare on a specific channel.
1423 pub fn enable_capture_compare(&mut self, channel: TimChannel) {
1424 match channel {
1425 TimChannel::C1 => self.regs.ccer().modify(|_, w| w.cc1e().bit(true)),
1426 TimChannel::C2 => self.regs.ccer().modify(|_, w| w.cc2e().bit(true)),
1427 TimChannel::C3 => self.regs.ccer().modify(|_, w| w.cc3e().bit(true)),
1428 #[cfg(not(feature = "wl"))]
1429 TimChannel::C4 => self.regs.ccer().modify(|_, w| w.cc4e().bit(true)),
1430 };
1431 }
1432
1433 /// Set Capture Compare mode in output mode. See docs on the `CaptureCompare` enum.
1434 ///
1435 /// Note: Also sets MOE bit BDTR register for timers that have it.
1436 pub fn set_capture_compare_output(
1437 &mut self,
1438 channel: TimChannel,
1439 mode: CaptureCompare,
1440 ) {
1441 // Note: CC1S bits are writable only when the channel is OFF (CC1E = 0 in TIMx_CCER)
1442 self.disable_capture_compare(channel);
1443
1444 match channel {
1445 TimChannel::C1 => self
1446 .regs
1447 .ccmr1_output()
1448 .modify(unsafe { |_, w| w.cc1s().bits(mode as u8) }),
1449 TimChannel::C2 => self
1450 .regs
1451 .ccmr1_output()
1452 .modify(unsafe { |_, w| w.cc2s().bits(mode as u8) }),
1453 TimChannel::C3 => self
1454 .regs
1455 .ccmr2_output()
1456 .modify(unsafe { |_, w| w.cc3s().bits(mode as u8) }),
1457 #[cfg(not(feature = "wl"))]
1458 TimChannel::C4 => self
1459 .regs
1460 .ccmr2_output()
1461 .modify(unsafe { |_, w| w.cc4s().bits(mode as u8) }),
1462 };
1463
1464 $(
1465 self.regs.$bdtr().modify(|_, w| w.moe().set_bit());
1466 )?
1467 }
1468
1469 /// Set Capture Compare mode in input mode. See docs on the `CaptureCompare` enum.
1470 pub fn set_capture_compare_input(&mut self, channel: TimChannel, mode: CaptureCompare) {
1471 // Note: CC1S bits are writable only when the channel is OFF (CC1E = 0 in TIMx_CCER)
1472 self.disable_capture_compare(channel);
1473
1474 match channel {
1475 TimChannel::C1 => self
1476 .regs
1477 .ccmr1_input()
1478 .modify(unsafe { |_, w| w.cc1s().bits(mode as u8) }),
1479 TimChannel::C2 => self
1480 .regs
1481 .ccmr1_input()
1482 .modify(unsafe { |_, w| w.cc2s().bits(mode as u8) }),
1483 TimChannel::C3 => self
1484 .regs
1485 .ccmr2_input()
1486 .modify(unsafe { |_, w| w.cc3s().bits(mode as u8) }),
1487 #[cfg(not(feature = "wl"))]
1488 TimChannel::C4 => self
1489 .regs
1490 .ccmr2_input()
1491 .modify(unsafe { |_, w| w.cc4s().bits(mode as u8) }),
1492 };
1493 }
1494
1495 /// Set preload mode.
1496 /// OC1PE: Output Compare 1 preload enable
1497 /// 0: Preload register on TIMx_CCR1 disabled. TIMx_CCR1 can be written at anytime, the
1498 /// new value is taken in account immediately.
1499 /// 1: Preload register on TIMx_CCR1 enabled. Read/Write operations access the preload
1500 /// register. TIMx_CCR1 preload value is loaded in the active register at each update event.
1501 /// Note: 1: These bits can not be modified as long as LOCK level 3 has been programmed
1502 /// (LOCK bits in TIMx_BDTR register) and CC1S=’00’ (the channel is configured in
1503 /// output).
1504 /// 2: The PWM mode can be used without validating the preload register only in one
1505 /// pulse mode (OPM bit set in TIMx_CR1 register). Else the behavior is not guaranteed.
1506 ///
1507 /// Setting preload is required to enable PWM.
1508 pub fn set_preload(&mut self, channel: TimChannel, value: bool) {
1509 match channel {
1510 TimChannel::C1 => self.regs.ccmr1_output().modify(|_, w| w.oc1pe().bit(value)),
1511 TimChannel::C2 => self.regs.ccmr1_output().modify(|_, w| w.oc2pe().bit(value)),
1512 TimChannel::C3 => self.regs.ccmr2_output().modify(|_, w| w.oc3pe().bit(value)),
1513 #[cfg(not(feature = "wl"))]
1514 TimChannel::C4 => self.regs.ccmr2_output().modify(|_, w| w.oc4pe().bit(value)),
1515 };
1516
1517 // "As the preload registers are transferred to the shadow registers only when an update event
1518 // occurs, before starting the counter, you have to initialize all the registers by setting the UG
1519 // bit in the TIMx_EGR register."
1520 self.reinitialize();
1521 }
1522 }
1523 };
1524}
1525
1526#[cfg(any(feature = "g0", feature = "g4", feature = "c0"))]
1527macro_rules! cc_2_channels {
1528 ($TIMX:ident, $res:ident $(, $bdtr:ident)?) => {
1529 impl Timer<pac::$TIMX> {
1530 /// Function that allows us to set direction only on timers that have this option.
1531 fn set_dir(&mut self) {
1532 // self.regs.cr1().modify(|_, w| w.dir().bit(self.cfg.direction as u8 != 0));
1533 }
1534
1535 // todo: more advanced PWM modes. Asymmetric, combined, center-aligned etc.
1536
1537 /// Set up input capture, eg for PWM input.
1538 /// L4 RM, section 26.3.8. H723 RM, section 43.3.7.
1539 ///
1540 /// Note: Does not handle TISEL (timer input selection register), ICxPS (input capture prescaler),
1541 /// and ICxF (input capture filter) - you must set these manually using the PAC if hardware defaults are not appropriate.
1542 #[cfg(not(any(feature = "f", feature = "l4x5", feature = "l5", feature = "g0")))]
1543 pub fn set_input_capture(
1544 &mut self,
1545 channel: TimChannel,
1546 mode: CaptureCompare,
1547 ccp: Polarity,
1548 ccnp: Polarity,
1549 ) {
1550 self.set_capture_compare_input(channel, mode);
1551
1552 match channel {
1553 TimChannel::C1 => {
1554 self.regs.ccer().modify(|_, w| {
1555 w.cc1p().bit(ccp.bit());
1556 w.cc1np().bit(ccnp.bit())
1557 });
1558 }
1559 TimChannel::C2 => {
1560 #[cfg(not(feature = "c0"))]
1561 self.regs.ccer().modify(|_, w| {
1562 w.cc2p().bit(ccp.bit());
1563 w.cc2np().bit(ccnp.bit())
1564 });
1565 }
1566 _ => panic!()
1567 }
1568
1569 // self.regs.smcr().modify(|_, w| unsafe {
1570 // w.ts().bits(trigger as u8);
1571 // w.sms().bits(slave_mode as u8)
1572 // });
1573
1574 self.enable_capture_compare(channel);
1575 }
1576
1577 /// Set Output Compare Mode. See docs on the `OutputCompare` enum.
1578 pub fn set_output_compare(&mut self, channel: TimChannel, mode: OutputCompare) {
1579 match channel {
1580 TimChannel::C1 => {
1581 self.regs.ccmr1_output().modify(|_, w| unsafe {
1582 #[cfg(not(any(feature = "f4", feature = "l5", feature = "wb")))]
1583 w.oc1m_3().bit((mode as u8) >> 3 != 0);
1584 w.oc1m().bits((mode as u8) & 0b111)
1585
1586 });
1587 }
1588 TimChannel::C2 => {
1589 self.regs.ccmr1_output().modify(|_, w| unsafe {
1590 #[cfg(not(any(feature = "f4", feature = "l5", feature = "wb")))]
1591 w.oc2m_3().bit((mode as u8) >> 3 != 0);
1592 w.oc2m().bits((mode as u8) & 0b111)
1593
1594 });
1595 }
1596 _ => panic!()
1597 }
1598
1599 $(
1600 self.regs.$bdtr().modify(|_, w| w.moe().set_bit());
1601 )?
1602 }
1603
1604 /// Return the set duty period for a given channel. Divide by `get_max_duty()`
1605 /// to find the portion of the duty cycle used.
1606 pub fn get_duty(&self, channel: TimChannel) -> $res {
1607 cfg_if! {
1608 if #[cfg(feature = "g0")] {
1609 match channel {
1610 TimChannel::C1 => self.regs.ccr1().read().bits().try_into().unwrap(),
1611 TimChannel::C2 => self.regs.ccr2().read().bits().try_into().unwrap(),
1612 _ => panic!()
1613 }
1614 } else if #[cfg(any(feature = "wb", feature = "wl", feature = "l5"))] {
1615 match channel {
1616 TimChannel::C1 => self.regs.ccr1().read().ccr1().bits(),
1617 TimChannel::C2 => self.regs.ccr2().read().ccr2().bits(),
1618 _ => panic!()
1619 }
1620 } else {
1621 match channel {
1622 TimChannel::C1 => self.regs.ccr1().read().ccr().bits().try_into().unwrap(),
1623 TimChannel::C2 => self.regs.ccr2().read().ccr().bits().try_into().unwrap(),
1624 _ => panic!()
1625 }
1626 }
1627 }
1628 }
1629
1630 /// Set the duty cycle, as a portion of ARR (`get_max_duty()`). Note that this
1631 /// needs to be re-run if you change ARR at any point.
1632 pub fn set_duty(&mut self, channel: TimChannel, duty: $res) {
1633 cfg_if! {
1634 if #[cfg(feature = "g0")] {
1635 match channel {
1636 // TimChannel::C1 => self.regs.ccr1().write(|w| w.ccr1().bits(duty.try_into().unwrap())),
1637 // TimChannel::C2 => self.regs.ccr2().write(|w| w.ccr2().bits(duty.try_into().unwrap())),
1638 _ => panic!()
1639 };
1640 } else if #[cfg(any(feature = "wb", feature = "wl", feature = "l5"))] {
1641 unsafe {
1642 match channel {
1643 TimChannel::C1 => self.regs.ccr1().write(|w| w.ccr1().bits(duty.try_into().unwrap())),
1644 TimChannel::C2 => self.regs.ccr2().write(|w| w.ccr2().bits(duty.try_into().unwrap())),
1645 _ => panic!()
1646 };
1647 }
1648 } else {
1649 unsafe {
1650 match channel {
1651 TimChannel::C1 => self.regs.ccr1().write(|w| w.ccr().bits(duty.try_into().unwrap())),
1652 TimChannel::C2 => self.regs.ccr2().write(|w| w.ccr().bits(duty.try_into().unwrap())),
1653 _ => panic!()
1654 };
1655 }
1656 }
1657 }
1658 }
1659
1660 /// Set output polarity. See docs on the `Polarity` enum.
1661 pub fn set_polarity(&mut self, channel: TimChannel, polarity: Polarity) {
1662 match channel {
1663 TimChannel::C1 => self.regs.ccer().modify(|_, w| w.cc1p().bit(polarity.bit())),
1664 TimChannel::C2 => self.regs.ccer().modify(|_, w| w.cc2p().bit(polarity.bit())),
1665 _ => panic!()
1666 };
1667 }
1668
1669 /// Set complementary output polarity. See docs on the `Polarity` enum.
1670 pub fn set_complementary_polarity(&mut self, channel: TimChannel, polarity: Polarity) {
1671 match channel {
1672 TimChannel::C1 => self.regs.ccer().modify(|_, w| w.cc1np().bit(polarity.bit())),
1673 TimChannel::C2 => self.regs.ccer().modify(|_, w| w.cc2np().bit(polarity.bit())),
1674 _ => panic!()
1675 };
1676 }
1677 /// Disables capture compare on a specific channel.
1678 pub fn disable_capture_compare(&mut self, channel: TimChannel) {
1679 match channel {
1680 TimChannel::C1 => self.regs.ccer().modify(|_, w| w.cc1e().clear_bit()),
1681 #[cfg(not(feature = "c0"))]
1682 TimChannel::C2 => self.regs.ccer().modify(|_, w| w.cc2e().clear_bit()),
1683 _ => panic!()
1684 };
1685 }
1686
1687 /// Enables capture compare on a specific channel.
1688 pub fn enable_capture_compare(&mut self, channel: TimChannel) {
1689 match channel {
1690 TimChannel::C1 => self.regs.ccer().modify(|_, w| w.cc1e().bit(true)),
1691 TimChannel::C2 => self.regs.ccer().modify(|_, w| w.cc2e().bit(true)),
1692 _ => panic!()
1693 };
1694 }
1695
1696 /// Set Capture Compare mode in output mode. See docs on the `CaptureCompare` enum.
1697 ///
1698 /// Note: Also sets MOE bit BDTR register for timers that have it.
1699 pub fn set_capture_compare_output(&mut self, channel: TimChannel, mode: CaptureCompare) {
1700 self.disable_capture_compare(channel);
1701
1702 match channel {
1703 TimChannel::C1 => self
1704 .regs
1705 .ccmr1_output()
1706 .modify(unsafe { |_, w| w.cc1s().bits(mode as u8) }),
1707 #[cfg(not(feature = "c0"))]
1708 TimChannel::C2 => self
1709 .regs
1710 .ccmr1_output()
1711 .modify(unsafe { |_, w| w.cc2s().bits(mode as u8) }),
1712 _ => panic!()
1713 };
1714
1715 $(
1716 self.regs.$bdtr().modify(|_, w| w.moe().set_bit());
1717 )?
1718 }
1719
1720 /// Set Capture Compare mode in input mode. See docs on the `CaptureCompare` enum.
1721 pub fn set_capture_compare_input(&mut self, channel: TimChannel, mode: CaptureCompare) {
1722 self.disable_capture_compare(channel);
1723
1724 match channel {
1725 // Note: CC1S bits are writable only when the channel is OFF (CC1E = 0 in TIMx_CCER)
1726 TimChannel::C1 => self
1727 .regs
1728 .ccmr1_input()
1729 .modify(unsafe { |_, w| w.cc1s().bits(mode as u8) }),
1730
1731 #[cfg(not(feature = "c0"))]
1732 TimChannel::C2 => self
1733 .regs
1734 .ccmr1_input()
1735 .modify(unsafe { |_, w| w.cc2s().bits(mode as u8) }),
1736 _ => panic!()
1737 };
1738 }
1739
1740 /// Set preload mode.
1741 /// OC1PE: Output Compare 1 preload enable
1742 /// 0: Preload register on TIMx_CCR1 disabled. TIMx_CCR1 can be written at anytime, the
1743 /// new value is taken in account immediately.
1744 /// 1: Preload register on TIMx_CCR1 enabled. Read/Write operations access the preload
1745 /// register. TIMx_CCR1 preload value is loaded in the active register at each update event.
1746 /// Note: 1: These bits can not be modified as long as LOCK level 3 has been programmed
1747 /// (LOCK bits in TIMx_BDTR register) and CC1S=’00’ (the channel is configured in
1748 /// output).
1749 /// 2: The PWM mode can be used without validating the preload register only in one
1750 /// pulse mode (OPM bit set in TIMx_CR1 register). Else the behavior is not guaranteed.
1751 ///
1752 /// Setting preload is required to enable PWM.
1753 pub fn set_preload(&mut self, channel: TimChannel, value: bool) {
1754 match channel {
1755 TimChannel::C1 => self.regs.ccmr1_output().modify(|_, w| w.oc1pe().bit(value)),
1756 #[cfg(not(feature = "c0"))]
1757 TimChannel::C2 => self.regs.ccmr1_output().modify(|_, w| w.oc2pe().bit(value)),
1758 _ => panic!()
1759 };
1760
1761 // "As the preload registers are transferred to the shadow registers only when an update event
1762 // occurs, before starting the counter, you have to initialize all the registers by setting the UG
1763 // bit in the TIMx_EGR register."
1764 self.reinitialize();
1765 }
1766
1767 }
1768 }
1769}
1770
1771macro_rules! cc_1_channel {
1772 ($TIMX:ident, $res:ident $(, $bdtr:ident)?) => {
1773 impl Timer<pac::$TIMX> {
1774 /// Function that allows us to set direction only on timers that have this option.
1775 fn set_dir(&mut self) {} // N/A with these 1-channel timers.
1776
1777 // todo: more advanced PWM modes. Asymmetric, combined, center-aligned etc.
1778
1779 /// Set up input capture, eg for PWM input.
1780 /// L4 RM, section 26.3.8. H723 RM, section 43.3.7.
1781 ///
1782 /// Note: Does not handle TISEL (timer input selection register), ICxPS (input capture prescaler),
1783 /// and ICxF (input capture filter) - you must set these manually using the PAC if hardware defaults are not appropriate.
1784 #[cfg(not(any(feature = "f", feature = "l4x5", feature = "l5", feature = "g0")))]
1785 pub fn set_input_capture(
1786 &mut self,
1787 channel: TimChannel,
1788 mode: CaptureCompare,
1789 ccp: Polarity,
1790 ccnp: Polarity,
1791 ) {
1792 self.set_capture_compare_input(channel, mode);
1793
1794 match channel {
1795 TimChannel::C1 => {
1796 self.regs.ccer().modify(|_, w| {
1797 w.cc1p().bit(ccp.bit());
1798 w.cc1np().bit(ccnp.bit())
1799 });
1800 }
1801 _ => panic!(),
1802 };
1803
1804 self.enable_capture_compare(channel);
1805 }
1806
1807 /// Set Output Compare Mode. See docs on the `OutputCompare` enum.
1808 pub fn set_output_compare(&mut self, channel: TimChannel, mode: OutputCompare) {
1809 match channel {
1810 TimChannel::C1 => {
1811 #[cfg(not(feature = "g070"))] // todo: PAC bug?
1812 self.regs.ccmr1_output().modify(|_, w| unsafe {
1813 // todo: L5/WB is probably due to a PAC error. Has oc1m_2.
1814 #[cfg(not(any(
1815 feature = "f",
1816 feature = "l4",
1817 feature = "l5",
1818 feature = "wb",
1819 feature = "g0"
1820 )))]
1821 w.oc1m_3().bit((mode as u8) >> 3 != 0);
1822 w.oc1m().bits((mode as u8) & 0b111)
1823 });
1824 }
1825 _ => panic!(),
1826 };
1827
1828 $(
1829 self.regs.$bdtr().modify(|_, w| w.moe().set_bit());
1830 )?
1831 }
1832
1833 /// Return the set duty period for a given channel. Divide by `get_max_duty()`
1834 /// to find the portion of the duty cycle used.
1835 pub fn get_duty(&self, channel: TimChannel) -> $res {
1836 match channel {
1837 TimChannel::C1 => self.regs.ccr1().read().ccr().bits().try_into().unwrap(),
1838 _ => panic!(),
1839 }
1840 }
1841
1842 /// Set the duty cycle, as a portion of ARR (`get_max_duty()`). Note that this
1843 /// needs to be re-run if you change ARR at any point.
1844 pub fn set_duty(&mut self, channel: TimChannel, duty: $res) {
1845 unsafe {
1846 match channel {
1847 TimChannel::C1 => self
1848 .regs
1849 .ccr1()
1850 .write(|w| w.ccr().bits(duty.try_into().unwrap())),
1851 _ => panic!(),
1852 };
1853 }
1854 }
1855
1856 /// Set output polarity. See docs on the `Polarity` enum.
1857 pub fn set_polarity(&mut self, channel: TimChannel, polarity: Polarity) {
1858 match channel {
1859 TimChannel::C1 => self.regs.ccer().modify(|_, w| w.cc1p().bit(polarity.bit())),
1860 _ => panic!(),
1861 };
1862 }
1863
1864 /// Set complementary output polarity. See docs on the `Polarity` enum.
1865 pub fn set_complementary_polarity(&mut self, channel: TimChannel, polarity: Polarity) {
1866 match channel {
1867 TimChannel::C1 => self
1868 .regs
1869 .ccer()
1870 .modify(|_, w| w.cc1np().bit(polarity.bit())),
1871 _ => panic!(),
1872 };
1873 }
1874 /// Disables capture compare on a specific channel.
1875 pub fn disable_capture_compare(&mut self, channel: TimChannel) {
1876 match channel {
1877 TimChannel::C1 => self.regs.ccer().modify(|_, w| w.cc1e().clear_bit()),
1878 _ => panic!(),
1879 };
1880 }
1881
1882 /// Enables capture compare on a specific channel.
1883 pub fn enable_capture_compare(&mut self, channel: TimChannel) {
1884 match channel {
1885 TimChannel::C1 => self.regs.ccer().modify(|_, w| w.cc1e().bit(true)),
1886 _ => panic!(),
1887 };
1888 }
1889
1890 /// Set Capture Compare mode in output mode. See docs on the `CaptureCompare` enum.
1891 ///
1892 /// Note: Also sets MOE bit BDTR register for timers that have it.
1893 pub fn set_capture_compare_output(
1894 &mut self,
1895 channel: TimChannel,
1896 mode: CaptureCompare,
1897 ) {
1898 self.disable_capture_compare(channel);
1899
1900 match channel {
1901 TimChannel::C1 => self
1902 .regs
1903 .ccmr1_output()
1904 .modify(unsafe { |_, w| w.cc1s().bits(mode as u8) }),
1905 _ => panic!(),
1906 };
1907
1908 $(
1909 self.regs.$bdtr().modify(|_, w| w.moe().set_bit());
1910 )?
1911 }
1912
1913 /// Set Capture Compare mode in input mode. See docs on the `CaptureCompare` enum.
1914 pub fn set_capture_compare_input(&mut self, channel: TimChannel, mode: CaptureCompare) {
1915 self.disable_capture_compare(channel);
1916
1917 match channel {
1918 TimChannel::C1 => self
1919 .regs
1920 .ccmr1_input()
1921 .modify(unsafe { |_, w| w.cc1s().bits(mode as u8) }),
1922 _ => panic!(),
1923 };
1924 }
1925
1926 /// Set preload mode.
1927 /// OC1PE: Output Compare 1 preload enable
1928 /// 0: Preload register on TIMx_CCR1 disabled. TIMx_CCR1 can be written at anytime, the
1929 /// new value is taken in account immediately.
1930 /// 1: Preload register on TIMx_CCR1 enabled. Read/Write operations access the preload
1931 /// register. TIMx_CCR1 preload value is loaded in the active register at each update event.
1932 /// Note: 1: These bits can not be modified as long as LOCK level 3 has been programmed
1933 /// (LOCK bits in TIMx_BDTR register) and CC1S=’00’ (the channel is configured in
1934 /// output).
1935 /// 2: The PWM mode can be used without validating the preload register only in one
1936 /// pulse mode (OPM bit set in TIMx_CR1 register). Else the behavior is not guaranteed.
1937 ///
1938 /// Setting preload is required to enable PWM.
1939 pub fn set_preload(&mut self, channel: TimChannel, value: bool) {
1940 match channel {
1941 TimChannel::C1 => self.regs.ccmr1_output().modify(|_, w| w.oc1pe().bit(value)),
1942 _ => panic!(),
1943 };
1944
1945 // "As the preload registers are transferred to the shadow registers only when an update event
1946 // occurs, before starting the counter, you have to initialize all the registers by setting the UG
1947 // bit in the TIMx_EGR register."
1948 self.reinitialize();
1949 }
1950 }
1951 };
1952}
1953
1954/// Calculate values required to set the timer frequency: `PSC` and `ARR`. This can be
1955/// used for initial timer setup, or changing the value later. If used in performance-sensitive
1956/// code or frequently, set ARR and PSC directly instead of using this.
1957fn calc_freq_vals(freq: f32, clock_speed: u32) -> Result<(u16, u16)> {
1958 // `period` and `clock_speed` are both in Hz.
1959
1960 // PSC and ARR range: 0 to 65535
1961 // (PSC+1)*(ARR+1) = TIMclk/Updatefrequency = TIMclk * period
1962 // APB1 (pclk1) is used by Tim2, 3, 4, 6, 7.
1963 // APB2 (pclk2) is used by Tim8, 15-20 etc.
1964
1965 // We need to factor the right-hand-side of the above equation
1966 // into integers. There are likely clever algorithms available to do this.
1967 // Some examples: https://cp-algorithms.com/algebra/factorization.html
1968 // We've chosen something that attempts to maximize ARR, for precision when
1969 // setting duty cycle. Alternative approaches might involve setting a frequency closest to the
1970 // requested one.
1971
1972 // If you work with pure floats, there are an infinite number of solutions: Ie for any value of PSC,
1973 // you can find an ARR to solve the equation.
1974 // The actual values are integers that must be between 0 and 65_536
1975 // Different combinations will result in different amounts of rounding error.
1976
1977 let max_val = 65_535.;
1978 let rhs = clock_speed as f32 / freq;
1979
1980 let psc = ((rhs - 1.) / (1 << 16) as f32).round();
1981 let arr = rhs / (psc + 1.) - 1.;
1982
1983 if arr > max_val || psc > max_val {
1984 return Err(Error::TimerError(TimerError::ValueError));
1985 }
1986
1987 Ok((psc as u16, arr as u16))
1988}
1989
1990cfg_if! {
1991 if #[cfg(not(any(
1992 feature = "f401",
1993 feature = "f410",
1994 feature = "f411",
1995 feature = "f413",
1996 feature = "g031",
1997 feature = "g041",
1998 feature = "g070",
1999 feature = "g030",
2000 feature = "g051",
2001 feature = "c0",
2002 feature = "wb",
2003 feature = "wl"
2004 )))] {
2005 /// Represents a Basic timer, used primarily to trigger the onboard DAC. Eg Tim6 or Tim7.
2006 pub struct BasicTimer<R> {
2007 pub regs: R,
2008 clock_speed: u32,
2009 }
2010
2011 impl<R> BasicTimer<R>
2012 where
2013 R: Deref<Target = pac::tim6::RegisterBlock> + RccPeriph,
2014 {
2015 /// Initialize a Basic timer, including enabling and resetting
2016 /// its RCC peripheral clock.
2017 pub fn new(
2018 regs: R,
2019 freq: f32,
2020 clock_cfg: &Clocks,
2021 ) -> Self {
2022 let rcc = unsafe { &(*RCC::ptr()) };
2023 R::en_reset(rcc);
2024
2025 // Self { regs, config, clock_speed: clocks.apb1_timer() }
2026 let mut result = Self { regs, clock_speed: clock_cfg.apb1_timer() };
2027
2028 result.set_freq(freq).ok();
2029 result
2030 }
2031
2032 // todo: These fns are DRY from GP timer code!
2033
2034 /// Enable the timer.
2035 pub fn enable(&mut self) {
2036 self.regs.cr1().modify(|_, w| w.cen().bit(true));
2037 }
2038
2039 /// Disable the timer.
2040 pub fn disable(&mut self) {
2041 self.regs.cr1().modify(|_, w| w.cen().clear_bit());
2042 }
2043
2044 /// Check if the timer is enabled.
2045 pub fn is_enabled(&self) -> bool {
2046 self.regs.cr1().read().cen().bit_is_set()
2047 }
2048
2049 /// Set the timer period, in seconds. Overrides the period or frequency set
2050 /// in the constructor. If changing pe riod frequently, don't use this method, as
2051 /// it has computational overhead: use `set_auto_reload` and `set_prescaler` methods instead.
2052 pub fn set_period(&mut self, time: f32) -> Result<() > {
2053 assert!(time > 0.);
2054 self.set_freq(1. / time)
2055 }
2056
2057 /// Set the timer frequency, in Hz. Overrides the period or frequency set
2058 /// in the constructor. If changing frequency frequently, don't use this method, as
2059 /// it has computational overhead: use `set_auto_reload` and `set_prescaler` methods instead.
2060 pub fn set_freq(&mut self, freq: f32) -> Result<() > {
2061 assert!(freq > 0.);
2062
2063 let (psc, arr) = calc_freq_vals(freq, self.clock_speed)?;
2064
2065 self.regs.arr().write(|w| unsafe { w.bits(arr.into()) });
2066 self.regs.psc().write(|w| unsafe { w.bits(psc.into()) });
2067
2068 Ok(())
2069 }
2070
2071 /// Return the integer associated with the maximum duty period.
2072 pub fn get_max_duty(&self) -> u32 {
2073 return self.regs.arr().read().bits()
2074 }
2075
2076 /// Set the auto-reload register value. Used for adjusting frequency.
2077 pub fn set_auto_reload(&mut self, arr: u16) {
2078 self.regs.arr().write(|w| unsafe { w.bits(arr.into()) });
2079 }
2080
2081 /// Set the prescaler value. Used for adjusting frequency.
2082 pub fn set_prescaler(&mut self, psc: u16) {
2083 self.regs.psc().write(|w| unsafe { w.bits(psc.into()) });
2084 }
2085
2086 /// Reset the count; set the counter to 0.
2087 pub fn reset_count(&mut self) {
2088 self.regs.cnt().write(|w| unsafe { w.bits(0) });
2089 }
2090
2091 /// Read the current counter value.
2092 pub fn read_count(&self) -> u16 {
2093 #[cfg(feature = "l5")]
2094 return self.regs.cnt().read().bits() as u16;
2095 #[cfg(not(feature = "l5"))]
2096 self.regs.cnt().read().cnt().bits()
2097 }
2098
2099 /// Allow selected information to be sent in master mode to slave timers for
2100 /// synchronization (TRGO).
2101 pub fn set_mastermode(&self, mode: MasterModeSelection) {
2102 self.regs.cr2().modify(|_, w| unsafe { w.mms().bits(mode as u8) });
2103 }
2104 }
2105 }
2106}
2107
2108/// A freestanding function that does not require access to a `Timer` struct. Clears the Update interrupt.
2109pub fn clear_update_interrupt(tim_num: u8) {
2110 unsafe {
2111 let periphs = pac::Peripherals::steal();
2112
2113 let bits = 0xffff_ffff;
2114
2115 // Note: `.try_into().unwrap()` is for C0.
2116
2117 match tim_num {
2118 #[cfg(not(any(feature = "f373")))]
2119 1 => {
2120 periphs.TIM1.sr().write(|w| w.bits(bits).uif().clear_bit());
2121 }
2122 #[cfg(not(any(
2123 feature = "f410",
2124 feature = "g070",
2125 feature = "g030",
2126 feature = "g031",
2127 feature = "g050",
2128 feature = "g061",
2129 feature = "c011",
2130 feature = "c031",
2131 )))]
2132 2 => {
2133 periphs
2134 .TIM2
2135 .sr()
2136 .write(|w| w.bits(bits.try_into().unwrap()).uif().clear_bit());
2137 }
2138 #[cfg(not(any(
2139 feature = "f301",
2140 feature = "l4x1",
2141 // feature = "l412",
2142 feature = "l4x3",
2143 feature = "l412",
2144 feature = "f410",
2145 feature = "wb",
2146 feature = "wl"
2147 )))]
2148 3 => {
2149 periphs
2150 .TIM3
2151 .sr()
2152 .write(|w| w.bits(bits.try_into().unwrap()).uif().clear_bit());
2153 }
2154 #[cfg(not(any(
2155 feature = "f301",
2156 feature = "f3x4",
2157 feature = "f410",
2158 feature = "l4x1",
2159 feature = "l4x2",
2160 feature = "l412",
2161 feature = "l4x3",
2162 feature = "g0",
2163 feature = "c0",
2164 feature = "wb",
2165 feature = "wl"
2166 )))]
2167 4 => {
2168 periphs.TIM4.sr().write(|w| w.bits(bits).uif().clear_bit());
2169 }
2170 #[cfg(any(
2171 feature = "f373",
2172 feature = "l4x5",
2173 feature = "l4x6",
2174 feature = "l5",
2175 feature = "h5",
2176 feature = "h7",
2177 feature = "g473",
2178 feature = "g474",
2179 feature = "g483",
2180 feature = "g484",
2181 all(feature = "f4", not(feature = "f410")),
2182 ))]
2183 5 => {
2184 periphs.TIM5.sr().write(|w| w.bits(bits).uif().clear_bit());
2185 }
2186 #[cfg(any(
2187 feature = "f303",
2188 feature = "l4x5",
2189 feature = "l4x6",
2190 feature = "l562",
2191 feature = "h5",
2192 feature = "h7",
2193 ))]
2194 8 => {
2195 periphs.TIM8.sr().write(|w| w.bits(bits).uif().clear_bit());
2196 }
2197 #[cfg(any(feature = "h5",))]
2198 12 => {
2199 periphs.TIM12.sr().write(|w| w.bits(bits).uif().clear_bit());
2200 }
2201 #[cfg(any(feature = "h5",))]
2202 13 => {
2203 periphs.TIM13.sr().write(|w| w.bits(bits).uif().clear_bit());
2204 }
2205 #[cfg(any(feature = "h5", feature = "c0",))]
2206 14 => {
2207 periphs
2208 .TIM14
2209 .sr()
2210 .write(|w| w.bits(bits.try_into().unwrap()).uif().clear_bit());
2211 }
2212 #[cfg(not(any(
2213 feature = "f4",
2214 feature = "g031",
2215 feature = "g031",
2216 feature = "g041",
2217 feature = "g030",
2218 feature = "g051",
2219 feature = "g061",
2220 feature = "wb",
2221 feature = "wl",
2222 feature = "c0",
2223 )))]
2224 15 => {
2225 periphs
2226 .TIM15
2227 .sr()
2228 .write(|w| w.bits(bits.try_into().unwrap()).uif().clear_bit());
2229 }
2230 #[cfg(not(any(feature = "f4",)))]
2231 16 => {
2232 periphs
2233 .TIM16
2234 .sr()
2235 .write(|w| w.bits(bits.try_into().unwrap()).uif().clear_bit());
2236 }
2237 #[cfg(not(any(
2238 feature = "l4x1",
2239 feature = "l4x2",
2240 feature = "l412",
2241 feature = "l4x3",
2242 feature = "f4",
2243 )))]
2244 17 => {
2245 periphs
2246 .TIM17
2247 .sr()
2248 .write(|w| w.bits(bits.try_into().unwrap()).uif().clear_bit());
2249 }
2250 _ => unimplemented!(),
2251 }
2252 };
2253}
2254
2255// /// Experimental approach where we set frequency without taking ownership.
2256// pub fn set_freq(timer: TimerNum, mut freq: f32) -> Result<(), ValueError> {
2257//
2258// }
2259
2260// todo: Non-macro refactor base timer reg blocks:
2261
2262// GP 32-bit: Tim2
2263// 2, 3, 4, 5
2264
2265// GP 16-bit:
2266// 15, 16, 17 // (9-14 on F4) 14 on G0
2267
2268// Basic:
2269// 6, 7
2270
2271// Advanced: 1/8/20
2272
2273#[cfg(not(any(feature = "f373")))]
2274make_timer!(TIM1, tim1, 2, u16);
2275
2276#[cfg(not(any(feature = "f373")))]
2277cc_slave_mode!(TIM1);
2278
2279#[cfg(not(any(feature = "f373", feature = "g0", feature = "g4")))]
2280cc_4_channels!(TIM1, u16, bdtr);
2281// todo: PAC error?
2282// TIM1 on G4 is nominally 16-bits, but has ~20 bits on ARR, with PAC showing 32 bits?
2283#[cfg(any(feature = "g0", feature = "g4"))]
2284cc_2_channels!(TIM1, u16, bdtr);
2285
2286cfg_if! {
2287 if #[cfg(not(any(
2288 feature = "f410",
2289 feature = "g070",
2290 feature = "l5", // todo PAC bug?
2291 feature = "g030",
2292 feature = "g031",
2293 feature = "g050",
2294 feature = "g061",
2295 feature = "g031",
2296 feature = "c011",
2297 feature = "c031",
2298 )))] {
2299 make_timer!(TIM2, tim2, 1, u32);
2300 cc_slave_mode!(TIM2);
2301 cc_4_channels!(TIM2, u32);
2302 }
2303}
2304
2305// todo: Note. G4, for example, has TIM2 and 5 as 32-bit, and TIM3 and 4 as 16-bit per RM,
2306// todo: But PAC shows different.
2307cfg_if! {
2308 if #[cfg(not(any(
2309 feature = "f301",
2310 feature = "l4x1",
2311 // feature = "l412",
2312 feature = "l5", // todo PAC bug?
2313 feature = "l4x3",
2314 feature = "l412",
2315 feature = "f410",
2316 feature = "wb",
2317 feature = "wl",
2318 )))] {
2319 make_timer!(TIM3, tim3, 1, u32);
2320 cc_slave_mode!(TIM3);
2321 cc_4_channels!(TIM3, u32);
2322 }
2323}
2324
2325cfg_if! {
2326 if #[cfg(not(any(
2327 feature = "f301",
2328 feature = "f3x4",
2329 feature = "f410",
2330 feature = "l4x1",
2331 feature = "l4x2",
2332 feature = "l412",
2333 feature = "l4x3",
2334 feature = "g0",
2335 feature = "c0",
2336 feature = "wb",
2337 feature = "wl"
2338 )))] {
2339 make_timer!(TIM4, tim4, 1, u32);
2340 cc_slave_mode!(TIM4);
2341 cc_4_channels!(TIM4, u32);
2342 }
2343}
2344
2345cfg_if! {
2346 if #[cfg(any(
2347 feature = "f373",
2348 feature = "l4x5",
2349 feature = "l4x6",
2350 feature = "l562",
2351 feature = "h5",
2352 feature = "h7",
2353 feature = "g473",
2354 feature = "g474",
2355 feature = "g483",
2356 feature = "g484",
2357 all(feature = "f4", not(feature = "f410")),
2358 ))] {
2359 make_timer!(TIM5, tim5, 1, u32);
2360 cc_slave_mode!(TIM5);
2361 cc_4_channels!(TIM5, u32);
2362 }
2363}
2364
2365cfg_if! {
2366 if #[cfg(any(
2367 feature = "f303",
2368 feature = "l4x5",
2369 feature = "l4x6",
2370 feature = "l562",
2371 feature = "h5",
2372 feature = "h7",
2373 ))] {
2374 make_timer!(TIM8, tim8, 2, u16);
2375 cc_slave_mode!(TIM8);
2376 cc_4_channels!(TIM8, u16, bdtr);
2377 }
2378}
2379
2380// todo: G4 should be 16-bits for TIM8. Why does the PAC use 32?
2381cfg_if! {
2382 if #[cfg(feature = "g4")] {
2383 make_timer!(TIM8, tim8, 2, u32);
2384 cc_slave_mode!(TIM8);
2385 cc_4_channels!(TIM8, u32, bdtr);
2386 }
2387}
2388
2389cfg_if! {
2390 if #[cfg(feature = "h5")] {
2391 make_timer!(TIM12, tim12, 1, u32);
2392 cc_slave_mode!(TIM12);
2393 cc_2_channels!(TIM12, u32);
2394
2395 make_timer!(TIM13, tim13, 1, u32);
2396 cc_2_channels!(TIM13, u32);
2397
2398 make_timer!(TIM14, tim14, 1, u32);
2399 cc_2_channels!(TIM14, u32);
2400 }
2401}
2402
2403cfg_if! {
2404 if #[cfg(not(any(
2405 feature = "f4",
2406 feature = "g031",
2407 feature = "g031",
2408 feature = "g041",
2409 feature = "g030",
2410 feature = "g051",
2411 feature = "g061",
2412 feature = "wb",
2413 feature = "wl",
2414 // todo: Tim15 is available on c091/02, but I don't see a PAC for that.
2415 feature = "c0",
2416 )))] {
2417 make_timer!(TIM15, tim15, 2, u16);
2418 cc_slave_mode!(TIM15);
2419 // todo: TIM15 on some variant has 2 channels (Eg H7). On others, like L4x3, it appears to be 1.
2420 cc_1_channel!(TIM15, u16, bdtr);
2421 }
2422}
2423
2424#[cfg(not(any(feature = "f4", feature = "c0")))]
2425make_timer!(TIM16, tim16, 2, u16);
2426#[cfg(not(any(feature = "f4", feature = "c0")))]
2427cc_1_channel!(TIM16, u16, bdtr);
2428
2429#[cfg(feature = "c0")]
2430make_timer!(TIM16, tim16, 2, u32);
2431#[cfg(feature = "c0")]
2432cc_1_channel!(TIM16, u32, bdtr);
2433
2434cfg_if! {
2435 if #[cfg(not(any(
2436 feature = "l4x1",
2437 feature = "l4x2",
2438 feature = "l412",
2439 feature = "l4x3",
2440 feature = "f4",
2441 )))] {
2442 make_timer!(TIM17, tim17, 2, u16);
2443 cc_1_channel!(TIM17, u16, bdtr);
2444 }
2445}
2446
2447cfg_if! {
2448 if #[cfg(any(feature = "f373"))] {
2449 make_timer!(TIM12, tim12, 1, u16);
2450 make_timer!(TIM13, tim13, 1, u16);
2451 make_timer!(TIM14, tim14, 1, u16);
2452 make_timer!(TIM19, tim19, 2, u16);
2453
2454 cc_slave_mode!(TIM12);
2455 cc_slave_mode!(TIM19);
2456
2457 cc_1_channel!(TIM12, u16);
2458 cc_1_channel!(TIM13, u16);
2459 cc_1_channel!(TIM14, u16);
2460 cc_1_channel!(TIM19, u16);
2461 }
2462}
2463
2464// todo: G4 (maybe not all variants?) have TIM20.
2465#[cfg(any(feature = "f303"))]
2466make_timer!(TIM20, tim20, 2, u16);
2467#[cfg(any(feature = "f303"))]
2468cc_slave_mode!(TIM20);
2469#[cfg(any(feature = "f303"))]
2470cc_4_channels!(TIM20, u16);