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) => {
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 pub fn set_capture_compare_output(
1434 &mut self,
1435 channel: TimChannel,
1436 mode: CaptureCompare,
1437 ) {
1438 // Note: CC1S bits are writable only when the channel is OFF (CC1E = 0 in TIMx_CCER)
1439 self.disable_capture_compare(channel);
1440
1441 match channel {
1442 TimChannel::C1 => self
1443 .regs
1444 .ccmr1_output()
1445 .modify(unsafe { |_, w| w.cc1s().bits(mode as u8) }),
1446 TimChannel::C2 => self
1447 .regs
1448 .ccmr1_output()
1449 .modify(unsafe { |_, w| w.cc2s().bits(mode as u8) }),
1450 TimChannel::C3 => self
1451 .regs
1452 .ccmr2_output()
1453 .modify(unsafe { |_, w| w.cc3s().bits(mode as u8) }),
1454 #[cfg(not(feature = "wl"))]
1455 TimChannel::C4 => self
1456 .regs
1457 .ccmr2_output()
1458 .modify(unsafe { |_, w| w.cc4s().bits(mode as u8) }),
1459 };
1460 }
1461
1462 /// Set Capture Compare mode in input mode. See docs on the `CaptureCompare` enum.
1463 pub fn set_capture_compare_input(&mut self, channel: TimChannel, mode: CaptureCompare) {
1464 // Note: CC1S bits are writable only when the channel is OFF (CC1E = 0 in TIMx_CCER)
1465 self.disable_capture_compare(channel);
1466
1467 match channel {
1468 TimChannel::C1 => self
1469 .regs
1470 .ccmr1_input()
1471 .modify(unsafe { |_, w| w.cc1s().bits(mode as u8) }),
1472 TimChannel::C2 => self
1473 .regs
1474 .ccmr1_input()
1475 .modify(unsafe { |_, w| w.cc2s().bits(mode as u8) }),
1476 TimChannel::C3 => self
1477 .regs
1478 .ccmr2_input()
1479 .modify(unsafe { |_, w| w.cc3s().bits(mode as u8) }),
1480 #[cfg(not(feature = "wl"))]
1481 TimChannel::C4 => self
1482 .regs
1483 .ccmr2_input()
1484 .modify(unsafe { |_, w| w.cc4s().bits(mode as u8) }),
1485 };
1486 }
1487
1488 /// Set preload mode.
1489 /// OC1PE: Output Compare 1 preload enable
1490 /// 0: Preload register on TIMx_CCR1 disabled. TIMx_CCR1 can be written at anytime, the
1491 /// new value is taken in account immediately.
1492 /// 1: Preload register on TIMx_CCR1 enabled. Read/Write operations access the preload
1493 /// register. TIMx_CCR1 preload value is loaded in the active register at each update event.
1494 /// Note: 1: These bits can not be modified as long as LOCK level 3 has been programmed
1495 /// (LOCK bits in TIMx_BDTR register) and CC1S=’00’ (the channel is configured in
1496 /// output).
1497 /// 2: The PWM mode can be used without validating the preload register only in one
1498 /// pulse mode (OPM bit set in TIMx_CR1 register). Else the behavior is not guaranteed.
1499 ///
1500 /// Setting preload is required to enable PWM.
1501 pub fn set_preload(&mut self, channel: TimChannel, value: bool) {
1502 match channel {
1503 TimChannel::C1 => self.regs.ccmr1_output().modify(|_, w| w.oc1pe().bit(value)),
1504 TimChannel::C2 => self.regs.ccmr1_output().modify(|_, w| w.oc2pe().bit(value)),
1505 TimChannel::C3 => self.regs.ccmr2_output().modify(|_, w| w.oc3pe().bit(value)),
1506 #[cfg(not(feature = "wl"))]
1507 TimChannel::C4 => self.regs.ccmr2_output().modify(|_, w| w.oc4pe().bit(value)),
1508 };
1509
1510 // "As the preload registers are transferred to the shadow registers only when an update event
1511 // occurs, before starting the counter, you have to initialize all the registers by setting the UG
1512 // bit in the TIMx_EGR register."
1513 self.reinitialize();
1514 }
1515 }
1516 };
1517}
1518
1519#[cfg(any(feature = "g0", feature = "g4", feature = "c0"))]
1520macro_rules! cc_2_channels {
1521 ($TIMX:ident, $res:ident) => {
1522 impl Timer<pac::$TIMX> {
1523 /// Function that allows us to set direction only on timers that have this option.
1524 fn set_dir(&mut self) {
1525 // self.regs.cr1().modify(|_, w| w.dir().bit(self.cfg.direction as u8 != 0));
1526 }
1527
1528 // todo: more advanced PWM modes. Asymmetric, combined, center-aligned etc.
1529
1530 /// Set up input capture, eg for PWM input.
1531 /// L4 RM, section 26.3.8. H723 RM, section 43.3.7.
1532 ///
1533 /// Note: Does not handle TISEL (timer input selection register), ICxPS (input capture prescaler),
1534 /// and ICxF (input capture filter) - you must set these manually using the PAC if hardware defaults are not appropriate.
1535 #[cfg(not(any(feature = "f", feature = "l4x5", feature = "l5", feature = "g0")))]
1536 pub fn set_input_capture(
1537 &mut self,
1538 channel: TimChannel,
1539 mode: CaptureCompare,
1540 ccp: Polarity,
1541 ccnp: Polarity,
1542 ) {
1543 self.set_capture_compare_input(channel, mode);
1544
1545 match channel {
1546 TimChannel::C1 => {
1547 self.regs.ccer().modify(|_, w| {
1548 w.cc1p().bit(ccp.bit());
1549 w.cc1np().bit(ccnp.bit())
1550 });
1551 }
1552 TimChannel::C2 => {
1553 #[cfg(not(feature = "c0"))]
1554 self.regs.ccer().modify(|_, w| {
1555 w.cc2p().bit(ccp.bit());
1556 w.cc2np().bit(ccnp.bit())
1557 });
1558 }
1559 _ => panic!()
1560 }
1561
1562 // self.regs.smcr().modify(|_, w| unsafe {
1563 // w.ts().bits(trigger as u8);
1564 // w.sms().bits(slave_mode as u8)
1565 // });
1566
1567 self.enable_capture_compare(channel);
1568 }
1569
1570 /// Set Output Compare Mode. See docs on the `OutputCompare` enum.
1571 pub fn set_output_compare(&mut self, channel: TimChannel, mode: OutputCompare) {
1572 match channel {
1573 TimChannel::C1 => {
1574 self.regs.ccmr1_output().modify(|_, w| unsafe {
1575 #[cfg(not(any(feature = "f4", feature = "l5", feature = "wb")))]
1576 w.oc1m_3().bit((mode as u8) >> 3 != 0);
1577 w.oc1m().bits((mode as u8) & 0b111)
1578
1579 });
1580 }
1581 TimChannel::C2 => {
1582 self.regs.ccmr1_output().modify(|_, w| unsafe {
1583 #[cfg(not(any(feature = "f4", feature = "l5", feature = "wb")))]
1584 w.oc2m_3().bit((mode as u8) >> 3 != 0);
1585 w.oc2m().bits((mode as u8) & 0b111)
1586
1587 });
1588 }
1589 _ => panic!()
1590 }
1591 }
1592
1593 /// Return the set duty period for a given channel. Divide by `get_max_duty()`
1594 /// to find the portion of the duty cycle used.
1595 pub fn get_duty(&self, channel: TimChannel) -> $res {
1596 cfg_if! {
1597 if #[cfg(feature = "g0")] {
1598 match channel {
1599 TimChannel::C1 => self.regs.ccr1().read().bits().try_into().unwrap(),
1600 TimChannel::C2 => self.regs.ccr2().read().bits().try_into().unwrap(),
1601 _ => panic!()
1602 }
1603 } else if #[cfg(any(feature = "wb", feature = "wl", feature = "l5"))] {
1604 match channel {
1605 TimChannel::C1 => self.regs.ccr1().read().ccr1().bits(),
1606 TimChannel::C2 => self.regs.ccr2().read().ccr2().bits(),
1607 _ => panic!()
1608 }
1609 } else {
1610 match channel {
1611 TimChannel::C1 => self.regs.ccr1().read().ccr().bits().try_into().unwrap(),
1612 TimChannel::C2 => self.regs.ccr2().read().ccr().bits().try_into().unwrap(),
1613 _ => panic!()
1614 }
1615 }
1616 }
1617 }
1618
1619 /// Set the duty cycle, as a portion of ARR (`get_max_duty()`). Note that this
1620 /// needs to be re-run if you change ARR at any point.
1621 pub fn set_duty(&mut self, channel: TimChannel, duty: $res) {
1622 cfg_if! {
1623 if #[cfg(feature = "g0")] {
1624 match channel {
1625 // TimChannel::C1 => self.regs.ccr1().write(|w| w.ccr1().bits(duty.try_into().unwrap())),
1626 // TimChannel::C2 => self.regs.ccr2().write(|w| w.ccr2().bits(duty.try_into().unwrap())),
1627 _ => panic!()
1628 };
1629 } else if #[cfg(any(feature = "wb", feature = "wl", feature = "l5"))] {
1630 unsafe {
1631 match channel {
1632 TimChannel::C1 => self.regs.ccr1().write(|w| w.ccr1().bits(duty.try_into().unwrap())),
1633 TimChannel::C2 => self.regs.ccr2().write(|w| w.ccr2().bits(duty.try_into().unwrap())),
1634 _ => panic!()
1635 };
1636 }
1637 } else {
1638 unsafe {
1639 match channel {
1640 TimChannel::C1 => self.regs.ccr1().write(|w| w.ccr().bits(duty.try_into().unwrap())),
1641 TimChannel::C2 => self.regs.ccr2().write(|w| w.ccr().bits(duty.try_into().unwrap())),
1642 _ => panic!()
1643 };
1644 }
1645 }
1646 }
1647 }
1648
1649 /// Set output polarity. See docs on the `Polarity` enum.
1650 pub fn set_polarity(&mut self, channel: TimChannel, polarity: Polarity) {
1651 match channel {
1652 TimChannel::C1 => self.regs.ccer().modify(|_, w| w.cc1p().bit(polarity.bit())),
1653 TimChannel::C2 => self.regs.ccer().modify(|_, w| w.cc2p().bit(polarity.bit())),
1654 _ => panic!()
1655 };
1656 }
1657
1658 /// Set complementary output polarity. See docs on the `Polarity` enum.
1659 pub fn set_complementary_polarity(&mut self, channel: TimChannel, polarity: Polarity) {
1660 match channel {
1661 TimChannel::C1 => self.regs.ccer().modify(|_, w| w.cc1np().bit(polarity.bit())),
1662 TimChannel::C2 => self.regs.ccer().modify(|_, w| w.cc2np().bit(polarity.bit())),
1663 _ => panic!()
1664 };
1665 }
1666 /// Disables capture compare on a specific channel.
1667 pub fn disable_capture_compare(&mut self, channel: TimChannel) {
1668 match channel {
1669 TimChannel::C1 => self.regs.ccer().modify(|_, w| w.cc1e().clear_bit()),
1670 #[cfg(not(feature = "c0"))]
1671 TimChannel::C2 => self.regs.ccer().modify(|_, w| w.cc2e().clear_bit()),
1672 _ => panic!()
1673 };
1674 }
1675
1676 /// Enables capture compare on a specific channel.
1677 pub fn enable_capture_compare(&mut self, channel: TimChannel) {
1678 match channel {
1679 TimChannel::C1 => self.regs.ccer().modify(|_, w| w.cc1e().bit(true)),
1680 TimChannel::C2 => self.regs.ccer().modify(|_, w| w.cc2e().bit(true)),
1681 _ => panic!()
1682 };
1683 }
1684
1685 /// Set Capture Compare mode in output mode. See docs on the `CaptureCompare` enum.
1686 pub fn set_capture_compare_output(&mut self, channel: TimChannel, mode: CaptureCompare) {
1687 self.disable_capture_compare(channel);
1688
1689 match channel {
1690 TimChannel::C1 => self
1691 .regs
1692 .ccmr1_output()
1693 .modify(unsafe { |_, w| w.cc1s().bits(mode as u8) }),
1694 #[cfg(not(feature = "c0"))]
1695 TimChannel::C2 => self
1696 .regs
1697 .ccmr1_output()
1698 .modify(unsafe { |_, w| w.cc2s().bits(mode as u8) }),
1699 _ => panic!()
1700 };
1701 }
1702
1703 /// Set Capture Compare mode in input mode. See docs on the `CaptureCompare` enum.
1704 pub fn set_capture_compare_input(&mut self, channel: TimChannel, mode: CaptureCompare) {
1705 self.disable_capture_compare(channel);
1706
1707 match channel {
1708 // Note: CC1S bits are writable only when the channel is OFF (CC1E = 0 in TIMx_CCER)
1709 TimChannel::C1 => self
1710 .regs
1711 .ccmr1_input()
1712 .modify(unsafe { |_, w| w.cc1s().bits(mode as u8) }),
1713
1714 #[cfg(not(feature = "c0"))]
1715 TimChannel::C2 => self
1716 .regs
1717 .ccmr1_input()
1718 .modify(unsafe { |_, w| w.cc2s().bits(mode as u8) }),
1719 _ => panic!()
1720 };
1721 }
1722
1723 /// Set preload mode.
1724 /// OC1PE: Output Compare 1 preload enable
1725 /// 0: Preload register on TIMx_CCR1 disabled. TIMx_CCR1 can be written at anytime, the
1726 /// new value is taken in account immediately.
1727 /// 1: Preload register on TIMx_CCR1 enabled. Read/Write operations access the preload
1728 /// register. TIMx_CCR1 preload value is loaded in the active register at each update event.
1729 /// Note: 1: These bits can not be modified as long as LOCK level 3 has been programmed
1730 /// (LOCK bits in TIMx_BDTR register) and CC1S=’00’ (the channel is configured in
1731 /// output).
1732 /// 2: The PWM mode can be used without validating the preload register only in one
1733 /// pulse mode (OPM bit set in TIMx_CR1 register). Else the behavior is not guaranteed.
1734 ///
1735 /// Setting preload is required to enable PWM.
1736 pub fn set_preload(&mut self, channel: TimChannel, value: bool) {
1737 match channel {
1738 TimChannel::C1 => self.regs.ccmr1_output().modify(|_, w| w.oc1pe().bit(value)),
1739 #[cfg(not(feature = "c0"))]
1740 TimChannel::C2 => self.regs.ccmr1_output().modify(|_, w| w.oc2pe().bit(value)),
1741 _ => panic!()
1742 };
1743
1744 // "As the preload registers are transferred to the shadow registers only when an update event
1745 // occurs, before starting the counter, you have to initialize all the registers by setting the UG
1746 // bit in the TIMx_EGR register."
1747 self.reinitialize();
1748 }
1749
1750 }
1751 }
1752}
1753
1754macro_rules! cc_1_channel {
1755 ($TIMX:ident, $res:ident) => {
1756 impl Timer<pac::$TIMX> {
1757 /// Function that allows us to set direction only on timers that have this option.
1758 fn set_dir(&mut self) {} // N/A with these 1-channel timers.
1759
1760 // todo: more advanced PWM modes. Asymmetric, combined, center-aligned etc.
1761
1762 /// Set up input capture, eg for PWM input.
1763 /// L4 RM, section 26.3.8. H723 RM, section 43.3.7.
1764 ///
1765 /// Note: Does not handle TISEL (timer input selection register), ICxPS (input capture prescaler),
1766 /// and ICxF (input capture filter) - you must set these manually using the PAC if hardware defaults are not appropriate.
1767 #[cfg(not(any(feature = "f", feature = "l4x5", feature = "l5", feature = "g0")))]
1768 pub fn set_input_capture(
1769 &mut self,
1770 channel: TimChannel,
1771 mode: CaptureCompare,
1772 ccp: Polarity,
1773 ccnp: Polarity,
1774 ) {
1775 self.set_capture_compare_input(channel, mode);
1776
1777 match channel {
1778 TimChannel::C1 => {
1779 self.regs.ccer().modify(|_, w| {
1780 w.cc1p().bit(ccp.bit());
1781 w.cc1np().bit(ccnp.bit())
1782 });
1783 }
1784 _ => panic!(),
1785 };
1786
1787 self.enable_capture_compare(channel);
1788 }
1789
1790 /// Set Output Compare Mode. See docs on the `OutputCompare` enum.
1791 pub fn set_output_compare(&mut self, channel: TimChannel, mode: OutputCompare) {
1792 match channel {
1793 TimChannel::C1 => {
1794 #[cfg(not(feature = "g070"))] // todo: PAC bug?
1795 self.regs.ccmr1_output().modify(|_, w| unsafe {
1796 // todo: L5/WB is probably due to a PAC error. Has oc1m_2.
1797 #[cfg(not(any(
1798 feature = "f",
1799 feature = "l4",
1800 feature = "l5",
1801 feature = "wb",
1802 feature = "g0"
1803 )))]
1804 w.oc1m_3().bit((mode as u8) >> 3 != 0);
1805 w.oc1m().bits((mode as u8) & 0b111)
1806 });
1807 }
1808 _ => panic!(),
1809 };
1810 }
1811
1812 /// Return the set duty period for a given channel. Divide by `get_max_duty()`
1813 /// to find the portion of the duty cycle used.
1814 pub fn get_duty(&self, channel: TimChannel) -> $res {
1815 match channel {
1816 TimChannel::C1 => self.regs.ccr1().read().ccr().bits().try_into().unwrap(),
1817 _ => panic!(),
1818 }
1819 }
1820
1821 /// Set the duty cycle, as a portion of ARR (`get_max_duty()`). Note that this
1822 /// needs to be re-run if you change ARR at any point.
1823 pub fn set_duty(&mut self, channel: TimChannel, duty: $res) {
1824 unsafe {
1825 match channel {
1826 TimChannel::C1 => self
1827 .regs
1828 .ccr1()
1829 .write(|w| w.ccr().bits(duty.try_into().unwrap())),
1830 _ => panic!(),
1831 };
1832 }
1833 }
1834
1835 /// Set output polarity. See docs on the `Polarity` enum.
1836 pub fn set_polarity(&mut self, channel: TimChannel, polarity: Polarity) {
1837 match channel {
1838 TimChannel::C1 => self.regs.ccer().modify(|_, w| w.cc1p().bit(polarity.bit())),
1839 _ => panic!(),
1840 };
1841 }
1842
1843 /// Set complementary output polarity. See docs on the `Polarity` enum.
1844 pub fn set_complementary_polarity(&mut self, channel: TimChannel, polarity: Polarity) {
1845 match channel {
1846 TimChannel::C1 => self
1847 .regs
1848 .ccer()
1849 .modify(|_, w| w.cc1np().bit(polarity.bit())),
1850 _ => panic!(),
1851 };
1852 }
1853 /// Disables capture compare on a specific channel.
1854 pub fn disable_capture_compare(&mut self, channel: TimChannel) {
1855 match channel {
1856 TimChannel::C1 => self.regs.ccer().modify(|_, w| w.cc1e().clear_bit()),
1857 _ => panic!(),
1858 };
1859 }
1860
1861 /// Enables capture compare on a specific channel.
1862 pub fn enable_capture_compare(&mut self, channel: TimChannel) {
1863 match channel {
1864 TimChannel::C1 => self.regs.ccer().modify(|_, w| w.cc1e().bit(true)),
1865 _ => panic!(),
1866 };
1867 }
1868
1869 /// Set Capture Compare mode in output mode. See docs on the `CaptureCompare` enum.
1870 pub fn set_capture_compare_output(
1871 &mut self,
1872 channel: TimChannel,
1873 mode: CaptureCompare,
1874 ) {
1875 self.disable_capture_compare(channel);
1876
1877 match channel {
1878 TimChannel::C1 => self
1879 .regs
1880 .ccmr1_output()
1881 .modify(unsafe { |_, w| w.cc1s().bits(mode as u8) }),
1882 _ => panic!(),
1883 };
1884 }
1885
1886 /// Set Capture Compare mode in input mode. See docs on the `CaptureCompare` enum.
1887 pub fn set_capture_compare_input(&mut self, channel: TimChannel, mode: CaptureCompare) {
1888 self.disable_capture_compare(channel);
1889
1890 match channel {
1891 TimChannel::C1 => self
1892 .regs
1893 .ccmr1_input()
1894 .modify(unsafe { |_, w| w.cc1s().bits(mode as u8) }),
1895 _ => panic!(),
1896 };
1897 }
1898
1899 /// Set preload mode.
1900 /// OC1PE: Output Compare 1 preload enable
1901 /// 0: Preload register on TIMx_CCR1 disabled. TIMx_CCR1 can be written at anytime, the
1902 /// new value is taken in account immediately.
1903 /// 1: Preload register on TIMx_CCR1 enabled. Read/Write operations access the preload
1904 /// register. TIMx_CCR1 preload value is loaded in the active register at each update event.
1905 /// Note: 1: These bits can not be modified as long as LOCK level 3 has been programmed
1906 /// (LOCK bits in TIMx_BDTR register) and CC1S=’00’ (the channel is configured in
1907 /// output).
1908 /// 2: The PWM mode can be used without validating the preload register only in one
1909 /// pulse mode (OPM bit set in TIMx_CR1 register). Else the behavior is not guaranteed.
1910 ///
1911 /// Setting preload is required to enable PWM.
1912 pub fn set_preload(&mut self, channel: TimChannel, value: bool) {
1913 match channel {
1914 TimChannel::C1 => self.regs.ccmr1_output().modify(|_, w| w.oc1pe().bit(value)),
1915 _ => panic!(),
1916 };
1917
1918 // "As the preload registers are transferred to the shadow registers only when an update event
1919 // occurs, before starting the counter, you have to initialize all the registers by setting the UG
1920 // bit in the TIMx_EGR register."
1921 self.reinitialize();
1922 }
1923 }
1924 };
1925}
1926
1927/// Calculate values required to set the timer frequency: `PSC` and `ARR`. This can be
1928/// used for initial timer setup, or changing the value later. If used in performance-sensitive
1929/// code or frequently, set ARR and PSC directly instead of using this.
1930fn calc_freq_vals(freq: f32, clock_speed: u32) -> Result<(u16, u16)> {
1931 // `period` and `clock_speed` are both in Hz.
1932
1933 // PSC and ARR range: 0 to 65535
1934 // (PSC+1)*(ARR+1) = TIMclk/Updatefrequency = TIMclk * period
1935 // APB1 (pclk1) is used by Tim2, 3, 4, 6, 7.
1936 // APB2 (pclk2) is used by Tim8, 15-20 etc.
1937
1938 // We need to factor the right-hand-side of the above equation
1939 // into integers. There are likely clever algorithms available to do this.
1940 // Some examples: https://cp-algorithms.com/algebra/factorization.html
1941 // We've chosen something that attempts to maximize ARR, for precision when
1942 // setting duty cycle. Alternative approaches might involve setting a frequency closest to the
1943 // requested one.
1944
1945 // If you work with pure floats, there are an infinite number of solutions: Ie for any value of PSC,
1946 // you can find an ARR to solve the equation.
1947 // The actual values are integers that must be between 0 and 65_536
1948 // Different combinations will result in different amounts of rounding error.
1949
1950 let max_val = 65_535.;
1951 let rhs = clock_speed as f32 / freq;
1952
1953 let psc = ((rhs - 1.) / (1 << 16) as f32).round();
1954 let arr = rhs / (psc + 1.) - 1.;
1955
1956 if arr > max_val || psc > max_val {
1957 return Err(Error::TimerError(TimerError::ValueError));
1958 }
1959
1960 Ok((psc as u16, arr as u16))
1961}
1962
1963cfg_if! {
1964 if #[cfg(not(any(
1965 feature = "f401",
1966 feature = "f410",
1967 feature = "f411",
1968 feature = "f413",
1969 feature = "g031",
1970 feature = "g041",
1971 feature = "g070",
1972 feature = "g030",
1973 feature = "g051",
1974 feature = "c0",
1975 feature = "wb",
1976 feature = "wl"
1977 )))] {
1978 /// Represents a Basic timer, used primarily to trigger the onboard DAC. Eg Tim6 or Tim7.
1979 pub struct BasicTimer<R> {
1980 pub regs: R,
1981 clock_speed: u32,
1982 }
1983
1984 impl<R> BasicTimer<R>
1985 where
1986 R: Deref<Target = pac::tim6::RegisterBlock> + RccPeriph,
1987 {
1988 /// Initialize a Basic timer, including enabling and resetting
1989 /// its RCC peripheral clock.
1990 pub fn new(
1991 regs: R,
1992 freq: f32,
1993 clock_cfg: &Clocks,
1994 ) -> Self {
1995 let rcc = unsafe { &(*RCC::ptr()) };
1996 R::en_reset(rcc);
1997
1998 // Self { regs, config, clock_speed: clocks.apb1_timer() }
1999 let mut result = Self { regs, clock_speed: clock_cfg.apb1_timer() };
2000
2001 result.set_freq(freq).ok();
2002 result
2003 }
2004
2005 // todo: These fns are DRY from GP timer code!
2006
2007 /// Enable the timer.
2008 pub fn enable(&mut self) {
2009 self.regs.cr1().modify(|_, w| w.cen().bit(true));
2010 }
2011
2012 /// Disable the timer.
2013 pub fn disable(&mut self) {
2014 self.regs.cr1().modify(|_, w| w.cen().clear_bit());
2015 }
2016
2017 /// Check if the timer is enabled.
2018 pub fn is_enabled(&self) -> bool {
2019 self.regs.cr1().read().cen().bit_is_set()
2020 }
2021
2022 /// Set the timer period, in seconds. Overrides the period or frequency set
2023 /// in the constructor. If changing pe riod frequently, don't use this method, as
2024 /// it has computational overhead: use `set_auto_reload` and `set_prescaler` methods instead.
2025 pub fn set_period(&mut self, time: f32) -> Result<() > {
2026 assert!(time > 0.);
2027 self.set_freq(1. / time)
2028 }
2029
2030 /// Set the timer frequency, in Hz. Overrides the period or frequency set
2031 /// in the constructor. If changing frequency frequently, don't use this method, as
2032 /// it has computational overhead: use `set_auto_reload` and `set_prescaler` methods instead.
2033 pub fn set_freq(&mut self, freq: f32) -> Result<() > {
2034 assert!(freq > 0.);
2035
2036 let (psc, arr) = calc_freq_vals(freq, self.clock_speed)?;
2037
2038 self.regs.arr().write(|w| unsafe { w.bits(arr.into()) });
2039 self.regs.psc().write(|w| unsafe { w.bits(psc.into()) });
2040
2041 Ok(())
2042 }
2043
2044 /// Return the integer associated with the maximum duty period.
2045 pub fn get_max_duty(&self) -> u32 {
2046 return self.regs.arr().read().bits()
2047 }
2048
2049 /// Set the auto-reload register value. Used for adjusting frequency.
2050 pub fn set_auto_reload(&mut self, arr: u16) {
2051 self.regs.arr().write(|w| unsafe { w.bits(arr.into()) });
2052 }
2053
2054 /// Set the prescaler value. Used for adjusting frequency.
2055 pub fn set_prescaler(&mut self, psc: u16) {
2056 self.regs.psc().write(|w| unsafe { w.bits(psc.into()) });
2057 }
2058
2059 /// Reset the count; set the counter to 0.
2060 pub fn reset_count(&mut self) {
2061 self.regs.cnt().write(|w| unsafe { w.bits(0) });
2062 }
2063
2064 /// Read the current counter value.
2065 pub fn read_count(&self) -> u16 {
2066 #[cfg(feature = "l5")]
2067 return self.regs.cnt().read().bits() as u16;
2068 #[cfg(not(feature = "l5"))]
2069 self.regs.cnt().read().cnt().bits()
2070 }
2071
2072 /// Allow selected information to be sent in master mode to slave timers for
2073 /// synchronization (TRGO).
2074 pub fn set_mastermode(&self, mode: MasterModeSelection) {
2075 self.regs.cr2().modify(|_, w| unsafe { w.mms().bits(mode as u8) });
2076 }
2077 }
2078 }
2079}
2080
2081/// A freestanding function that does not require access to a `Timer` struct. Clears the Update interrupt.
2082pub fn clear_update_interrupt(tim_num: u8) {
2083 unsafe {
2084 let periphs = pac::Peripherals::steal();
2085
2086 let bits = 0xffff_ffff;
2087
2088 // Note: `.try_into().unwrap()` is for C0.
2089
2090 match tim_num {
2091 #[cfg(not(any(feature = "f373")))]
2092 1 => {
2093 periphs.TIM1.sr().write(|w| w.bits(bits).uif().clear_bit());
2094 }
2095 #[cfg(not(any(
2096 feature = "f410",
2097 feature = "g070",
2098 feature = "g030",
2099 feature = "g031",
2100 feature = "g050",
2101 feature = "g061",
2102 feature = "c011",
2103 feature = "c031",
2104 )))]
2105 2 => {
2106 periphs
2107 .TIM2
2108 .sr()
2109 .write(|w| w.bits(bits.try_into().unwrap()).uif().clear_bit());
2110 }
2111 #[cfg(not(any(
2112 feature = "f301",
2113 feature = "l4x1",
2114 // feature = "l412",
2115 feature = "l4x3",
2116 feature = "l412",
2117 feature = "f410",
2118 feature = "wb",
2119 feature = "wl"
2120 )))]
2121 3 => {
2122 periphs
2123 .TIM3
2124 .sr()
2125 .write(|w| w.bits(bits.try_into().unwrap()).uif().clear_bit());
2126 }
2127 #[cfg(not(any(
2128 feature = "f301",
2129 feature = "f3x4",
2130 feature = "f410",
2131 feature = "l4x1",
2132 feature = "l4x2",
2133 feature = "l412",
2134 feature = "l4x3",
2135 feature = "g0",
2136 feature = "c0",
2137 feature = "wb",
2138 feature = "wl"
2139 )))]
2140 4 => {
2141 periphs.TIM4.sr().write(|w| w.bits(bits).uif().clear_bit());
2142 }
2143 #[cfg(any(
2144 feature = "f373",
2145 feature = "l4x5",
2146 feature = "l4x6",
2147 feature = "l5",
2148 feature = "h5",
2149 feature = "h7",
2150 feature = "g473",
2151 feature = "g474",
2152 feature = "g483",
2153 feature = "g484",
2154 all(feature = "f4", not(feature = "f410")),
2155 ))]
2156 5 => {
2157 periphs.TIM5.sr().write(|w| w.bits(bits).uif().clear_bit());
2158 }
2159 #[cfg(any(
2160 feature = "f303",
2161 feature = "l4x5",
2162 feature = "l4x6",
2163 feature = "l562",
2164 feature = "h5",
2165 feature = "h7",
2166 ))]
2167 8 => {
2168 periphs.TIM8.sr().write(|w| w.bits(bits).uif().clear_bit());
2169 }
2170 #[cfg(any(feature = "h5",))]
2171 12 => {
2172 periphs.TIM12.sr().write(|w| w.bits(bits).uif().clear_bit());
2173 }
2174 #[cfg(any(feature = "h5",))]
2175 13 => {
2176 periphs.TIM13.sr().write(|w| w.bits(bits).uif().clear_bit());
2177 }
2178 #[cfg(any(feature = "h5", feature = "c0",))]
2179 14 => {
2180 periphs
2181 .TIM14
2182 .sr()
2183 .write(|w| w.bits(bits.try_into().unwrap()).uif().clear_bit());
2184 }
2185 #[cfg(not(any(
2186 feature = "f4",
2187 feature = "g031",
2188 feature = "g031",
2189 feature = "g041",
2190 feature = "g030",
2191 feature = "g051",
2192 feature = "g061",
2193 feature = "wb",
2194 feature = "wl",
2195 feature = "c0",
2196 )))]
2197 15 => {
2198 periphs
2199 .TIM15
2200 .sr()
2201 .write(|w| w.bits(bits.try_into().unwrap()).uif().clear_bit());
2202 }
2203 #[cfg(not(any(feature = "f4",)))]
2204 16 => {
2205 periphs
2206 .TIM16
2207 .sr()
2208 .write(|w| w.bits(bits.try_into().unwrap()).uif().clear_bit());
2209 }
2210 #[cfg(not(any(
2211 feature = "l4x1",
2212 feature = "l4x2",
2213 feature = "l412",
2214 feature = "l4x3",
2215 feature = "f4",
2216 )))]
2217 17 => {
2218 periphs
2219 .TIM17
2220 .sr()
2221 .write(|w| w.bits(bits.try_into().unwrap()).uif().clear_bit());
2222 }
2223 _ => unimplemented!(),
2224 }
2225 };
2226}
2227
2228// /// Experimental approach where we set frequency without taking ownership.
2229// pub fn set_freq(timer: TimerNum, mut freq: f32) -> Result<(), ValueError> {
2230//
2231// }
2232
2233// todo: Non-macro refactor base timer reg blocks:
2234
2235// GP 32-bit: Tim2
2236// 2, 3, 4, 5
2237
2238// GP 16-bit:
2239// 15, 16, 17 // (9-14 on F4) 14 on G0
2240
2241// Basic:
2242// 6, 7
2243
2244// Advanced: 1/8/20
2245
2246#[cfg(not(any(feature = "f373")))]
2247make_timer!(TIM1, tim1, 2, u16);
2248
2249#[cfg(not(any(feature = "f373")))]
2250cc_slave_mode!(TIM1);
2251
2252#[cfg(not(any(feature = "f373", feature = "g0", feature = "g4")))]
2253cc_4_channels!(TIM1, u16);
2254// todo: PAC error?
2255// TIM1 on G4 is nominally 16-bits, but has ~20 bits on ARR, with PAC showing 32 bits?
2256#[cfg(any(feature = "g0", feature = "g4"))]
2257cc_2_channels!(TIM1, u16);
2258
2259cfg_if! {
2260 if #[cfg(not(any(
2261 feature = "f410",
2262 feature = "g070",
2263 feature = "l5", // todo PAC bug?
2264 feature = "wb55", // todo PAC bug?
2265 feature = "g030",
2266 feature = "g031",
2267 feature = "g050",
2268 feature = "g061",
2269 feature = "g031",
2270 feature = "c011",
2271 feature = "c031",
2272 )))] {
2273 make_timer!(TIM2, tim2, 1, u32);
2274 cc_slave_mode!(TIM2);
2275 cc_4_channels!(TIM2, u32);
2276 }
2277}
2278
2279// todo: Note. G4, for example, has TIM2 and 5 as 32-bit, and TIM3 and 4 as 16-bit per RM,
2280// todo: But PAC shows different.
2281cfg_if! {
2282 if #[cfg(not(any(
2283 feature = "f301",
2284 feature = "l4x1",
2285 // feature = "l412",
2286 feature = "l5", // todo PAC bug?
2287 feature = "l4x3",
2288 feature = "l412",
2289 feature = "f410",
2290 feature = "wb",
2291 feature = "wl",
2292 // feature = "c0",
2293 )))] {
2294 make_timer!(TIM3, tim3, 1, u32);
2295 cc_slave_mode!(TIM3);
2296 cc_4_channels!(TIM3, u32);
2297 }
2298}
2299
2300// #[cfg(feature = "c0")]
2301// make_timer!(TIM3, tim3, 1, u16);
2302// #[cfg(feature = "c0")]
2303// cc_4_channels!(TIM3, u16);
2304
2305cfg_if! {
2306 if #[cfg(not(any(
2307 feature = "f301",
2308 feature = "f3x4",
2309 feature = "f410",
2310 feature = "l4x1",
2311 feature = "l4x2",
2312 feature = "l412",
2313 feature = "l4x3",
2314 feature = "g0",
2315 feature = "c0",
2316 feature = "wb",
2317 feature = "wl"
2318 )))] {
2319 make_timer!(TIM4, tim4, 1, u32);
2320 cc_slave_mode!(TIM4);
2321 cc_4_channels!(TIM4, u32);
2322 }
2323}
2324
2325cfg_if! {
2326 if #[cfg(any(
2327 feature = "f373",
2328 feature = "l4x5",
2329 feature = "l4x6",
2330 feature = "l562",
2331 feature = "h5",
2332 feature = "h7",
2333 feature = "g473",
2334 feature = "g474",
2335 feature = "g483",
2336 feature = "g484",
2337 all(feature = "f4", not(feature = "f410")),
2338 ))] {
2339 make_timer!(TIM5, tim5, 1, u32);
2340 cc_slave_mode!(TIM5);
2341 cc_4_channels!(TIM5, u32);
2342 }
2343}
2344
2345cfg_if! {
2346 if #[cfg(any(
2347 feature = "f303",
2348 feature = "l4x5",
2349 feature = "l4x6",
2350 feature = "l562",
2351 feature = "h5",
2352 feature = "h7",
2353 ))] {
2354 make_timer!(TIM8, tim8, 2, u16);
2355 cc_slave_mode!(TIM8);
2356 // todo: Some issues with field names or something on l562 here.
2357 #[cfg(not(feature = "l5"))] // PAC bug.
2358 cc_4_channels!(TIM8, u16);
2359 #[cfg(feature = "l5")] // PAC bug.
2360 cc_1_channel!(TIM8, u16);
2361 }
2362}
2363
2364// todo: G4 should be 16-bits for TIM8. Why does the PAC use 32?
2365cfg_if! {
2366 if #[cfg(feature = "g4")] {
2367 make_timer!(TIM8, tim8, 2, u32);
2368 cc_slave_mode!(TIM8);
2369 cc_4_channels!(TIM8, u32);
2370 }
2371}
2372
2373cfg_if! {
2374 if #[cfg(feature = "h5")] {
2375 make_timer!(TIM12, tim12, 1, u32);
2376 cc_slave_mode!(TIM12);
2377 cc_2_channels!(TIM12, u32);
2378
2379 make_timer!(TIM13, tim13, 1, u32);
2380 cc_2_channels!(TIM13, u32);
2381
2382 make_timer!(TIM14, tim14, 1, u32);
2383 cc_2_channels!(TIM14, u32);
2384 }
2385}
2386
2387// #[cfg(feature = "c0")]
2388// make_timer!(TIM14, tim14, 1, u32);
2389// #[cfg(feature = "c0")]
2390// cc_2_channels!(TIM14, u16);
2391
2392cfg_if! {
2393 if #[cfg(not(any(
2394 feature = "f4",
2395 feature = "g031",
2396 feature = "g031",
2397 feature = "g041",
2398 feature = "g030",
2399 feature = "g051",
2400 feature = "g061",
2401 feature = "wb",
2402 feature = "wl",
2403 // todo: Tim15 is available on c091/02, but I don't see a PAC for that.
2404 feature = "c0",
2405 )))] {
2406 make_timer!(TIM15, tim15, 2, u16);
2407 cc_slave_mode!(TIM15);
2408 // todo: TIM15 on some variant has 2 channels (Eg H7). On others, like L4x3, it appears to be 1.
2409 cc_1_channel!(TIM15, u16);
2410 }
2411}
2412
2413#[cfg(not(any(feature = "f4", feature = "c0")))]
2414make_timer!(TIM16, tim16, 2, u16);
2415#[cfg(not(any(feature = "f4", feature = "c0")))]
2416cc_1_channel!(TIM16, u16);
2417
2418#[cfg(feature = "c0")]
2419make_timer!(TIM16, tim16, 2, u32);
2420#[cfg(feature = "c0")]
2421cc_1_channel!(TIM16, u32);
2422
2423cfg_if! {
2424 if #[cfg(not(any(
2425 feature = "l4x1",
2426 feature = "l4x2",
2427 feature = "l412",
2428 feature = "l4x3",
2429 feature = "f4",
2430 // feature = "c0"
2431 )))] {
2432 make_timer!(TIM17, tim17, 2, u16);
2433 cc_1_channel!(TIM17, u16);
2434 }
2435}
2436
2437// cfg_if! {
2438// if #[cfg(any(
2439// feature = "c0"
2440// ))] {
2441// make_timer!(TIM17, tim17, 2, u32);
2442// cc_1_channel!(TIM17, u32);
2443// }
2444// }
2445
2446// { todo: tim18
2447// TIM18: (tim18, apb2, enr, rstr),
2448// },
2449
2450cfg_if! {
2451 if #[cfg(any(feature = "f373"))] {
2452 make_timer!(TIM12, tim12, 1, u16);
2453 make_timer!(TIM13, tim13, 1, u16);
2454 make_timer!(TIM14, tim14, 1, u16);
2455 make_timer!(TIM19, tim19, 2, u16);
2456
2457 cc_slave_mode!(TIM12);
2458 cc_slave_mode!(TIM19);
2459
2460 cc_1_channel!(TIM12, u16);
2461 cc_1_channel!(TIM13, u16);
2462 cc_1_channel!(TIM14, u16);
2463 cc_1_channel!(TIM19, u16);
2464 }
2465}
2466
2467// todo: G4 (maybe not all variants?) have TIM20.
2468#[cfg(any(feature = "f303"))]
2469make_timer!(TIM20, tim20, 2, u16);
2470#[cfg(any(feature = "f303"))]
2471cc_slave_mode!(TIM20);
2472#[cfg(any(feature = "f303"))]
2473cc_4_channels!(TIM20, u16);
2474
2475// todo: Remove the final "true/false" for adv ctrl. You need a sep macro like you do for ccx_channel!.