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