stm32f3xx_hal_v2/
timer.rs

1//! Timers
2
3use core::convert::{From, TryFrom};
4use num_traits::float::Float;
5
6use crate::hal::timer::{CountDown, Periodic};
7#[cfg(any(
8    feature = "stm32f301",
9    feature = "stm32f302",
10    feature = "stm32f303",
11    feature = "stm32f334",
12    feature = "stm32f318",
13    feature = "stm32f328",
14    feature = "stm32f358",
15    feature = "stm32f398",
16))]
17use crate::pac::TIM1;
18#[cfg(any(
19    feature = "stm32f303",
20    feature = "stm32f328",
21    feature = "stm32f358",
22    feature = "stm32f398"
23))]
24use crate::pac::TIM20;
25#[cfg(any(
26    feature = "stm32f303",
27    feature = "stm32f328",
28    feature = "stm32f358",
29    feature = "stm32f373",
30    feature = "stm32f378",
31    feature = "stm32f398"
32))]
33use crate::pac::TIM4;
34#[cfg(any(
35    feature = "stm32f303",
36    feature = "stm32f328",
37    feature = "stm32f358",
38    feature = "stm32f398",
39))]
40use crate::pac::TIM8;
41#[cfg(any(feature = "stm32f373", feature = "stm32f378"))]
42use crate::pac::{TIM12, TIM13, TIM14, TIM18, TIM19, TIM5};
43use crate::pac::{TIM15, TIM16, TIM17, TIM2, TIM6};
44#[cfg(any(
45    feature = "stm32f303",
46    feature = "stm32f328",
47    feature = "stm32f334",
48    feature = "stm32f358",
49    feature = "stm32f373",
50    feature = "stm32f378",
51    feature = "stm32f398"
52))]
53use crate::pac::{TIM3, TIM7};
54
55use void::Void;
56
57use crate::{
58    clocks,
59    rcc::{Clocks, APB1, APB2},
60    time::Hertz,
61};
62
63#[derive(Clone, Copy)]
64/// Used for when attempting to set a timer period that is out of range.
65pub struct ValueError {}
66
67/// Associated clocks with timers
68pub trait PclkSrc {
69    /// Get the current frequency of the associated clock
70    fn get_clk(clocks: &Clocks) -> Hertz;
71}
72
73/// Hardware timers
74pub struct Timer<TIM> {
75    clocks: Clocks,
76    tim: TIM,
77}
78
79/// Interrupt events
80pub enum Event {
81    /// Timer timed out / count down ended
82    Update,
83}
84
85/// Output alignment
86#[derive(Clone, Copy, Debug)]
87pub enum Alignment {
88    Edge,
89    Center1,
90    Center2,
91    Center3,
92}
93
94#[derive(Clone, Copy, Debug)]
95pub enum Channel {
96    One,
97    Two,
98    Three,
99    Four,
100}
101
102/// Capture/Compare selection.
103/// This bit-field defines the direction of the channel (input/output) as well as the used input.
104#[repr(u8)]
105#[derive(Clone, Copy, Debug)]
106pub enum CaptureCompare {
107    Output = 0b00,
108    InputTi1 = 0b01,
109    InputTi2 = 0b10,
110    InputTrc = 0b11,
111}
112
113/// Capture/Compare output polarity. Defaults to `ActiveHigh` in hardware.
114#[derive(Clone, Copy, Debug)]
115pub enum Polarity {
116    ActiveHigh,
117    ActiveLow,
118}
119
120#[cfg(feature = "stm32f303")]
121impl Polarity {
122    /// For use with `set_bit()`.
123    fn bit(&self) -> bool {
124        match self {
125            Self::ActiveHigh => false,
126            Self::ActiveLow => true,
127        }
128    }
129}
130
131#[derive(Clone, Copy, Debug)]
132#[repr(u8)]
133/// See F303 ref man, section 21.4.7.
134/// These bits define the behavior of the output reference signal OC1REF from which OC1 and
135/// OC1N are derived. OC1REF is active high whereas OC1 and OC1N active level depends
136/// on CC1P and CC1NP bits.
137/// 0000: Frozen - The comparison between the output compare register TIMx_CCR1 and the
138/// counter TIMx_CNT has no effect on the outputs.(this mode is used to generate a timing
139/// base).
140/// 0001: Set channel 1 to active level on match. OC1REF signal is forced high when the
141/// counter TIMx_CNT matches the capture/compare register 1 (TIMx_CCR1).
142/// 0010: Set channel 1 to inactive level on match. OC1REF signal is forced low when the
143/// counter TIMx_CNT matches the capture/compare register 1 (TIMx_CCR1).
144/// 0011: Toggle - OC1REF toggles when TIMx_CNT=TIMx_CCR1.
145/// 0100: Force inactive level - OC1REF is forced low.
146/// 0101: Force active level - OC1REF is forced high.
147/// 0110: PWM mode 1 - In upcounting, channel 1 is active as long as TIMx_CNT<TIMx_CCR1
148/// else inactive. In downcounting, channel 1 is inactive (OC1REF=‘0) as long as
149/// TIMx_CNT>TIMx_CCR1 else active (OC1REF=1).
150/// 0111: PWM mode 2 - In upcounting, channel 1 is inactive as long as
151/// TIMx_CNT<TIMx_CCR1 else active. In downcounting, channel 1 is active as long as
152/// TIMx_CNT>TIMx_CCR1 else inactive.
153/// 1000: Retriggerable OPM mode 1 - In up-counting mode, the channel is active until a trigger
154/// event is detected (on TRGI signal). Then, a comparison is performed as in PWM mode 1
155/// and the channels becomes inactive again at the next update. In down-counting mode, the
156/// channel is inactive until a trigger event is detected (on TRGI signal). Then, a comparison is
157/// performed as in PWM mode 1 and the channels becomes inactive again at the next update.
158/// 1001: Retriggerable OPM mode 2 - In up-counting mode, the channel is inactive until a
159/// trigger event is detected (on TRGI signal). Then, a comparison is performed as in PWM
160/// mode 2 and the channels becomes inactive again at the next update. In down-counting
161/// mode, the channel is active until a trigger event is detected (on TRGI signal). Then, a
162/// comparison is performed as in PWM mode 1 and the channels becomes active again at the
163/// next update.
164/// 1010: Reserved,
165/// 1011: Reserved,
166/// 1100: Combined PWM mode 1 - OC1REF has the same behavior as in PWM mode 1.
167/// OC1REFC is the logical OR between OC1REF and OC2REF.
168/// 1101: Combined PWM mode 2 - OC1REF has the same behavior as in PWM mode 2.
169/// OC1REFC is the logical AND between OC1REF and OC2REF.
170/// 1110: Asymmetric PWM mode 1 - OC1REF has the same behavior as in PWM mode 1.
171/// OC1REFC outputs OC1REF when the counter is counting up, OC2REF when it is counting
172/// down.
173/// 1111: Asymmetric PWM mode 2 - OC1REF has the same behavior as in PWM mode 2.
174/// OC1REFC outputs OC1REF when the counter is counting up, OC2REF when it is counting
175/// down
176pub enum OutputCompare {
177    // In our current implementation, the left bit here is ignored due to how
178    // the `ocxm` fields are split between left most, and right three bits.
179    // see `left_fit()` method below.
180    Frozen = 0b0000,
181    Active = 0b0001,
182    Inactive = 0b0010,
183    ForceInactive = 0b0100,
184    ForceActive = 0b0101,
185    Pwm1 = 0b0110,
186    Pwm2 = 0b0111,
187    RetriggerableOpmMode1 = 0b1000,
188    RetriggerableOpmMode2 = 0b1001,
189    CombinedPwm1 = 0b1100,
190    CombinedPwm2 = 0b1101,
191    AsymmetricPwm1 = 0b1110,
192    AsymmetricPwm2 = 0b1111,
193}
194
195impl OutputCompare {
196    /// A workaround due to the `ccmrx_output.ocym` fields being split into
197    /// the left most, and first 3.
198    /// Get the left bit, as a boolean. For the right three, we just
199    /// parse the variant as a u8, and the left bit is ignored when setting
200    /// in the 3-bit field.
201    pub fn left_bit(&self) -> bool {
202        matches!(
203            self,
204            Self::RetriggerableOpmMode1
205                | Self::RetriggerableOpmMode2
206                | Self::CombinedPwm1
207                | Self::CombinedPwm2
208                | Self::AsymmetricPwm1
209                | Self::AsymmetricPwm2
210        )
211    }
212}
213
214macro_rules! hal {
215    ($({
216        $TIMX:ident: ($tim:ident, $timXen:ident, $timXrst:ident),
217        $APB:ident: ($apb:ident, $pclkX:ident),
218    },)+) => {
219        $(
220            impl PclkSrc for $TIMX {
221                fn get_clk(clocks: &Clocks) -> Hertz {
222                    clocks.$pclkX()
223                }
224            }
225
226            impl Periodic for Timer<$TIMX> {}
227
228            impl CountDown for Timer<$TIMX> {
229                type Time = Hertz;
230
231                fn start<T>(&mut self, timeout: T)
232                where
233                    T: Into<Hertz>,
234                {
235                    self.stop();
236
237                    let frequency = timeout.into().0;
238                    let timer_clock = $TIMX::get_clk(&self.clocks);
239                    let ticks = timer_clock.0 * if self.clocks.ppre1() == 1 { 1 } else { 2 }
240                        / frequency;
241                    let psc = crate::unwrap!(u16::try_from((ticks - 1) / (1 << 16)).ok());
242
243                    // NOTE(write): uses all bits in this register.
244                    self.tim.psc.write(|w| w.psc().bits(psc));
245
246                    let arr = crate::unwrap!(u16::try_from(ticks / u32::from(psc + 1)).ok());
247
248                    // TODO (sh3rm4n)
249                    // self.tim.arr.write(|w| { w.arr().bits(arr) });
250                    self.tim.arr.write(|w| unsafe { w.bits(u32::from(arr)) });
251
252                    // Trigger an update event to load the prescaler value to the clock
253                    // NOTE(write): uses all bits in this register.
254                    self.tim.egr.write(|w| w.ug().update());
255                    // The above line raises an update event which will indicate
256                    // that the timer is already finished. Since this is not the case,
257                    // it should be cleared
258                    self.clear_update_interrupt_flag();
259
260                    // start counter
261                    self.tim.cr1.modify(|_, w| w.cen().enabled());
262                }
263
264                fn wait(&mut self) -> nb::Result<(), Void> {
265                    if self.tim.sr.read().uif().is_clear() {
266                        Err(nb::Error::WouldBlock)
267                    } else {
268                        self.clear_update_interrupt_flag();
269                        Ok(())
270                    }
271                }
272            }
273
274            impl Timer<$TIMX> {
275                /// Configures a TIM peripheral as a periodic count down timer
276                pub fn $tim<T>(tim: $TIMX, timeout: T, clocks: Clocks, $apb: &mut $APB) -> Self
277                where
278                    T: Into<Hertz>,
279                {
280                    // enable and reset peripheral to a clean slate state
281                    $apb.enr().modify(|_, w| w.$timXen().enabled());
282                    $apb.rstr().modify(|_, w| w.$timXrst().reset());
283                    $apb.rstr().modify(|_, w| w.$timXrst().clear_bit());
284
285                    let mut timer = Timer { clocks, tim };
286                    timer.start(timeout);
287
288                    timer
289                }
290
291                /// Starts listening for an `event`
292                pub fn listen(&mut self, event: Event) {
293                    match event {
294                        Event::Update => self.tim.dier.write(|w| w.uie().enabled()),
295                    }
296                }
297
298                /// Stops listening for an `event`
299                pub fn unlisten(&mut self, event: Event) {
300                    match event {
301                        Event::Update => self.tim.dier.write(|w| w.uie().disabled()),
302                    }
303                }
304
305                /// Stops the timer
306                pub fn stop(&mut self) {
307                    self.tim.cr1.modify(|_, w| w.cen().disabled());
308                }
309
310                /// Clears Update Interrupt Flag
311                pub fn clear_update_interrupt_flag(&mut self) {
312                    self.tim.sr.modify(|_, w| w.uif().clear());
313                }
314
315                /// Releases the TIM peripheral
316                pub fn release(mut self) -> $TIMX {
317                    self.stop();
318                    self.tim
319                }
320
321                /// Set the timer period, in seconds. Overrides the period or frequency set
322                /// in the constructor.
323                /// This allows you to set periods greater than 1hz.
324                pub fn set_period(&mut self, period: f32, clocks: &clocks::Clocks) -> Result<(), ValueError> {
325                    // PSC and ARR range: 0 to 65535
326                    // (PSC+1)*(ARR+1) = TIMclk/Updatefrequency = TIMclk * period
327                    // APB1 (pclk1) is used by Tim2, 3, 4, 6, 7.
328                    // APB2 (pclk2) is used by Tim8, 15-20 etc.
329                    // todo: It appears there's a (fixed?) 2x multiplier on APB1
330                    // timers; it's twice `pclk1`. See clocks diagram in RM, or `Clock Configuration`
331                    // tool in STM32CubeIDE.
332                    let tim_clk = clocks.calc_speeds().pclk1 * 1_000_000. * 2.;
333
334                    // We need to factor the right-hand-side of the above equation (`rhs` variable)
335                    // into integers. There are likely clever algorithms available to do this.
336                    // Some examples: https://cp-algorithms.com/algebra/factorization.html
337                    // We've chosen something quick to write, and with sloppy precision;
338                    // should be good enough for most cases.
339
340                    // - If you work with pure floats, there are an infinite number of solutions: Ie for any value of PSC, you can find an ARR to solve the equation.
341                    // - The actual values are integers that must be between 0 and 65_536
342                    // - Different combinations will result in different amounts of rounding errors. Ideally, we pick the one with the lowest rounding error.
343                    // - The aboveapproach sets PSC and ARR always equal to each other.
344                    // This results in concise code, is computationally easy, and doesn't limit
345                    // the maximum period. There will usually be solutions that have a smaller rounding error.
346
347                    let max_val = 65_535;
348                    let rhs = tim_clk * period;
349
350                    // todo: Round instead of cast?
351                    let arr = (rhs.sqrt() - 1.) as u16;
352                    let psc = arr;
353
354                    if arr > max_val || psc > max_val {
355                        return Err(ValueError {})
356                    }
357
358
359                    self.tim.arr.write(|w| unsafe { w.bits(u32::from(arr)) });
360                    self.tim.psc.write(|w| unsafe { w.bits(u32::from(psc)) });
361
362                    Ok(())
363                }
364
365                /// Reset the countdown; set the counter to 0.
366                pub fn reset_countdown(&mut self) {
367                    self.tim.cnt.write(|w| unsafe { w.bits(0) });
368                }
369            }
370        )+
371    }
372}
373
374// These features are separate from the rest, since many of the variants
375// don't support them.
376#[cfg(feature = "stm32f303")]
377macro_rules! pwm_features {
378    ($({
379        $TIMX:ident: ($tim:ident, $timXen:ident, $timXrst:ident),
380        $APB:ident: ($apb:ident, $pclkX:ident),
381        $res:ident,
382    },)+) => {
383        $(
384            impl Timer<$TIMX> {
385
386                /// Set the value of the auto-reload resolution. Use a lower value to increase
387                /// precision. If you wish for a precise tick speed, multiply the system clock
388                /// speed by the desired frequency, then round to the nearest integer.
389                pub fn set_resolution(&mut self, word: $res) {
390                    self.tim.arr.write(|w| w.arr().bits(word) );
391                }
392
393                /// Set Output Compare Mode. See docs on the `OutputCompare` enum.
394                pub fn set_output_compare(&mut self, channel: Channel, mode: OutputCompare) {
395                    match channel {
396                        Channel::One => {
397                            self.tim.ccmr1_output().modify(|_, w| w.oc1m().bits(mode as u8));
398                            self.tim.ccmr1_output().modify(|_, w| w.oc1m_3().bit(mode.left_bit()));
399                        }
400                        Channel::Two => {
401                            self.tim.ccmr1_output().modify(|_, w| w.oc2m().bits(mode as u8));
402                            self.tim.ccmr1_output().modify(|_, w| w.oc2m_3().bit(mode.left_bit()));
403                        }
404                        Channel::Three => {
405                            self.tim.ccmr2_output().modify(|_, w| w.oc3m().bits(mode as u8));
406                            self.tim.ccmr2_output().modify(|_, w| w.oc3m_3().bit(mode.left_bit()));
407                        }
408                        Channel::Four => {
409                            self.tim.ccmr2_output().modify(|_, w| w.oc4m().bits(mode as u8));
410                            self.tim.ccmr2_output().modify(|_, w| w.oc4m_3().bit(mode.left_bit()));
411                        }
412                    }
413                }
414
415                /// Return the set duty period for a given channel. Divide by `get_max_duty()`
416                /// to find the portion of the duty cycle used.
417                pub fn get_duty(&self, channel: Channel) -> $res {
418                    match channel {
419                        Channel::One => self.tim.ccr1.read().ccr().bits(),
420                        Channel::Two => self.tim.ccr2.read().ccr().bits(),
421                        Channel::Three => self.tim.ccr3.read().ccr().bits(),
422                        Channel::Four => self.tim.ccr4.read().ccr().bits(),
423                    }
424                }
425
426                /// Set the duty cycle, as a portion of `get_max_duty()`.
427                pub fn set_duty(&mut self, channel: Channel, duty: $res) {
428                    match channel {
429                        Channel::One => self.tim.ccr1.write(|w| w.ccr().bits(duty)),
430                        Channel::Two => self.tim.ccr2.write(|w| w.ccr().bits(duty)),
431                        Channel::Three => self.tim.ccr3.write(|w| w.ccr().bits(duty)),
432                        Channel::Four => self.tim.ccr4.write(|w| w.ccr().bits(duty)),
433                    }
434                }
435
436                /// Return the integer associated with the maximum duty period.
437                /// todo: Duty could be u16 for low-precision timers.
438                pub fn get_max_duty(&self) -> $res {
439                    self.tim.arr.read().arr().bits()
440                }
441
442                /// Set timer alignment to Edge, or one of 3 center modes.
443                /// STM32F303 ref man, section 21.4.1:
444                /// Bits 6:5 CMS: Center-aligned mode selection
445                /// 00: Edge-aligned mode. The counter counts up or down depending on the direction bit
446                /// (DIR).
447                /// 01: Center-aligned mode 1. The counter counts up and down alternatively. Output compare
448                /// interrupt flags of channels configured in output (CCxS=00 in TIMx_CCMRx register) are set
449                /// only when the counter is counting down.
450                /// 10: Center-aligned mode 2. The counter counts up and down alternatively. Output compare
451                /// interrupt flags of channels configured in output (CCxS=00 in TIMx_CCMRx register) are set
452                /// only when the counter is counting up.
453                /// 11: Center-aligned mode 3. The counter counts up and down alternatively. Output compare
454                /// interrupt flags of channels configured in output (CCxS=00 in TIMx_CCMRx register) are set
455                /// both when the counter is counting up or down.
456                pub fn set_alignment(&mut self, alignment: Alignment) {
457                    let word = match alignment {
458                        Alignment::Edge => 0b00,
459                        Alignment::Center1 => 0b01,
460                        Alignment::Center2 => 0b10,
461                        Alignment::Center3 => 0b11,
462                    };
463                    self.tim.cr1.modify(|_, w| w.cms().bits(word));
464                }
465
466                /// Set output polarity. See docs on the `Polarity` enum.
467                pub fn set_polarity(&mut self, channel: Channel, polarity: Polarity) {
468                    match channel {
469                        Channel::One => self.tim.ccer.modify(|_, w| w.cc1p().bit(polarity.bit())),
470                        Channel::Two => self.tim.ccer.modify(|_, w| w.cc2p().bit(polarity.bit())),
471                        Channel::Three => self.tim.ccer.modify(|_, w| w.cc3p().bit(polarity.bit())),
472                        Channel::Four => self.tim.ccer.modify(|_, w| w.cc4p().bit(polarity.bit())),
473                    }
474                }
475
476                /// Set complementary output polarity. See docs on the `Polarity` enum.
477                pub fn set_complementary_polarity(&mut self, channel: Channel, polarity: Polarity) {
478                    match channel {
479                        Channel::One => self.tim.ccer.modify(|_, w| w.cc1np().bit(polarity.bit())),
480                        Channel::Two => self.tim.ccer.modify(|_, w| w.cc2np().bit(polarity.bit())),
481                        Channel::Three => self.tim.ccer.modify(|_, w| w.cc3np().bit(polarity.bit())),
482                        Channel::Four => self.tim.ccer.modify(|_, w| w.cc4np().bit(polarity.bit())),
483                    }
484                }
485
486                /// Disables the timer.
487                pub fn disable(&mut self, channel: Channel) {
488                    match channel {
489                        Channel::One => self.tim.ccer.modify(|_, w| w.cc1e().clear_bit()),
490                        Channel::Two => self.tim.ccer.modify(|_, w| w.cc2e().clear_bit()),
491                        Channel::Three => self.tim.ccer.modify(|_, w| w.cc3e().clear_bit()),
492                        Channel::Four => self.tim.ccer.modify(|_, w| w.cc4e().clear_bit()),
493                    }
494                }
495
496                /// Enables the timer.
497                pub fn enable(&mut self, channel: Channel) {
498                    match channel {
499                        Channel::One => self.tim.ccer.modify(|_, w| w.cc1e().set_bit()),
500                        Channel::Two => self.tim.ccer.modify(|_, w| w.cc2e().set_bit()),
501                        Channel::Three => self.tim.ccer.modify(|_, w| w.cc3e().set_bit()),
502                        Channel::Four => self.tim.ccer.modify(|_, w| w.cc4e().set_bit()),
503                    }
504                }
505
506                /// Set Capture Compare Mode. See docs on the `CaptureCompare` enum.
507                pub fn set_capture_compare(&mut self, channel: Channel, mode: CaptureCompare) {
508                    match channel {
509                        // Note: CC1S bits are writable only when the channel is OFF (CC1E = 0 in TIMx_CCER)
510                        Channel::One => self.tim.ccmr1_output().modify( unsafe { |_, w| w.cc1s().bits(mode as u8)} ),
511                        Channel::Two => self.tim.ccmr1_output().modify(unsafe {|_, w| w.cc2s().bits(mode as u8)}),
512                        Channel::Three => self.tim.ccmr2_output().modify(unsafe {|_, w| w.cc3s().bits(mode as u8)}),
513                        Channel::Four => self.tim.ccmr2_output().modify(unsafe {|_, w| w.cc4s().bits(mode as u8)}),
514                    }
515                }
516
517                /// Set preload mode.
518                /// OC1PE: Output Compare 1 preload enable
519                /// 0: Preload register on TIMx_CCR1 disabled. TIMx_CCR1 can be written at anytime, the
520                /// new value is taken in account immediately.
521                /// 1: Preload register on TIMx_CCR1 enabled. Read/Write operations access the preload
522                /// register. TIMx_CCR1 preload value is loaded in the active register at each update event.
523                /// Note: 1: These bits can not be modified as long as LOCK level 3 has been programmed
524                /// (LOCK bits in TIMx_BDTR register) and CC1S=’00’ (the channel is configured in
525                /// output).
526                /// 2: The PWM mode can be used without validating the preload register only in one
527                /// pulse mode (OPM bit set in TIMx_CR1 register). Else the behavior is not guaranteed.
528                ///
529                /// Setting preload is required to enable PWM.
530                pub fn set_preload(&mut self, channel: Channel, value: bool) {
531                    match channel {
532                        Channel::One => self.tim.ccmr1_output().modify(|_, w| w.oc1pe().bit(value)),
533                        Channel::Two => self.tim.ccmr1_output().modify(|_, w| w.oc2pe().bit(value)),
534                        Channel::Three => self.tim.ccmr2_output().modify(|_, w| w.oc3pe().bit(value)),
535                        Channel::Four => self.tim.ccmr2_output().modify(|_, w| w.oc4pe().bit(value)),
536                    }
537
538                    // "As the preload registers are transferred to the shadow registers only when an update event
539                    // occurs, before starting the counter, you have to initialize all the registers by setting the UG
540                    // bit in the TIMx_EGR register."
541                    self.tim.egr.write(|w| w.ug().update());
542                }
543            }
544        )+
545    }
546}
547
548#[cfg(any(feature = "stm32f301", feature = "stm32f318"))]
549hal! {
550    {
551        TIM1: (tim1, tim1en, tim1rst),
552        APB2: (apb2, pclk2),
553    },
554    {
555        TIM2: (tim2, tim2en, tim2rst),
556        APB1: (apb1, pclk1),
557    },
558    {
559        TIM6: (tim6, tim6en, tim6rst),
560        APB1: (apb1, pclk1),
561    },
562    {
563        TIM15: (tim15, tim15en, tim15rst),
564        APB2: (apb2, pclk2),
565    },
566    {
567        TIM16: (tim16, tim16en, tim16rst),
568        APB2: (apb2, pclk2),
569    },
570    {
571        TIM17: (tim17, tim17en, tim17rst),
572        APB2: (apb2, pclk2),
573    },
574}
575
576#[cfg(feature = "stm32f302")]
577hal! {
578    {
579        TIM1: (tim1, tim1en, tim1rst),
580        APB2: (apb2, pclk2),
581    },
582    {
583        TIM2: (tim2, tim2en, tim2rst),
584        APB1: (apb1, pclk1),
585    },
586    {
587        TIM6: (tim6, tim6en, tim6rst),
588        APB1: (apb1,pclk1),
589    },
590    {
591        TIM15: (tim15, tim15en, tim15rst),
592        APB2: (apb2, pclk2),
593    },
594    {
595        TIM16: (tim16, tim16en, tim16rst),
596        APB2: (apb2, pclk2),
597    },
598    {
599        TIM17: (tim17, tim17en, tim17rst),
600        APB2: (apb2, pclk2),
601    },
602}
603
604#[cfg(feature = "stm32f303")]
605hal! {
606    {
607        TIM1: (tim1, tim1en, tim1rst),
608        APB2: (apb2, pclk2),
609    },
610    {
611        TIM2: (tim2, tim2en, tim2rst),
612        APB1: (apb1, pclk1),
613    },
614    {
615        TIM3: (tim3, tim3en, tim3rst),
616        APB1: (apb1, pclk1),
617    },
618    {
619        TIM4: (tim4, tim4en, tim4rst),
620        APB1: (apb1, pclk1),
621    },
622    {
623        TIM6: (tim6, tim6en, tim6rst),
624        APB1: (apb1, pclk1),
625    },
626    {
627        TIM7: (tim7, tim7en, tim7rst),
628        APB1: (apb1, pclk1),
629    },
630    {
631        TIM8: (tim8, tim8en, tim8rst),
632        APB2: (apb2, pclk2),
633    },
634    {
635        TIM15: (tim15, tim15en, tim15rst),
636        APB2: (apb2, pclk2),
637    },
638    {
639        TIM16: (tim16, tim16en, tim16rst),
640        APB2: (apb2, pclk2),
641    },
642    {
643        TIM17: (tim17, tim17en, tim17rst),
644        APB2: (apb2, pclk2),
645    },
646    {
647        TIM20: (tim20, tim20en, tim20rst),
648        APB2: (apb2, pclk2),
649    },
650}
651
652#[cfg(feature = "stm32f334")]
653hal! {
654    {
655        TIM1: (tim1, tim1en, tim1rst),
656        APB2: (apb2, pclk2),
657    },
658    {
659        TIM2: (tim2, tim2en, tim2rst),
660        APB1: (apb1, pclk1),
661    },
662    {
663        TIM3: (tim3, tim3en, tim3rst),
664        APB1: (apb1, pclk1),
665    },
666    {
667        TIM6: (tim6, tim6en, tim6rst),
668        APB1: (apb1, pclk1),
669    },
670    {
671        TIM7: (tim7, tim7en, tim7rst),
672        APB1: (apb1, pclk1),
673    },
674    {
675        TIM15: (tim15, tim15en, tim15rst),
676        APB2: (apb2, pclk2),
677    },
678    {
679        TIM16: (tim16, tim16en, tim16rst),
680        APB2: (apb2, pclk2),
681    },
682    {
683        TIM17: (tim17, tim17en, tim17rst),
684        APB2: (apb2, pclk2),
685    },
686}
687
688#[cfg(any(feature = "stm32f373", feature = "stm32f378"))]
689hal! {
690    {
691        TIM2: (tim2, tim2en, tim2rst),
692        APB1: (apb1, pclk1),
693    },
694    {
695        TIM3: (tim3, tim3en, tim3rst),
696        APB1: (apb1, pclk1),
697    },
698    {
699        TIM4: (tim4, tim4en, tim4rst),
700        APB1: (apb1, pclk1),
701    },
702    {
703        TIM5: (tim5, tim5en, tim5rst),
704        APB1: (apb1, pclk1),
705    },
706    {
707        TIM6: (tim6, tim6en, tim6rst),
708        APB1: (apb1, pclk1),
709    },
710    {
711        TIM7: (tim7, tim7en, tim7rst),
712        APB1: (apb1, pclk1),
713    },
714    {
715        TIM12: (tim12, tim12en, tim12rst),
716        APB1: (apb1, pclk1),
717    },
718    {
719        TIM13: (tim13, tim13en, tim13rst),
720        APB1: (apb1, pclk1),
721    },
722    {
723        TIM14: (tim14, tim14en, tim14rst),
724        APB1: (apb1, pclk1),
725    },
726    {
727        TIM15: (tim15, tim15en, tim15rst),
728        APB2: (apb2, pclk2),
729    },
730    {
731        TIM16: (tim16, tim16en, tim16rst),
732        APB2: (apb2, pclk2),
733    },
734    {
735        TIM17: (tim17, tim17en, tim17rst),
736        APB2: (apb2, pclk2),
737    },
738    {
739        TIM18: (tim18, tim18en, tim18rst),
740        APB1: (apb1, pclk1),
741    },
742    {
743        TIM19: (tim19, tim19en, tim19rst),
744        APB2: (apb2, pclk2),
745    },
746}
747
748#[cfg(any(feature = "stm32f328", feature = "stm32f358", feature = "stm32f398"))]
749hal! {
750    {
751        TIM1: (tim1, tim1en, tim1rst),
752        APB2: (apb2, pclk2),
753    },
754    {
755        TIM2: (tim2, tim2en, tim2rst),
756        APB1: (apb1, pclk1),
757    },
758    {
759        TIM3: (tim3, tim3en, tim3rst),
760        APB1: (apb1, pclk1),
761    },
762    {
763        TIM4: (tim4, tim4en, tim4rst),
764        APB1: (apb1, pclk1),
765    },
766    {
767        TIM6: (tim6, tim6en, tim6rst),
768        APB1: (apb1, pclk1),
769    },
770    {
771        TIM7: (tim7, tim7en, tim7rst),
772        APB1: (apb1, pclk1),
773    },
774    {
775        TIM8: (tim8, tim8en, tim8rst),
776        APB2: (apb2, pclk2),
777    },
778    {
779        TIM15: (tim15, tim15en, tim15rst),
780        APB2: (apb2, pclk2),
781    },
782    {
783        TIM16: (tim16, tim16en, tim16rst),
784        APB2: (apb2, pclk2),
785    },
786    {
787        TIM17: (tim17, tim17en, tim17rst),
788        APB2: (apb2, pclk2),
789    },
790    {
791        TIM20: (tim20, tim20en, tim20rst),
792        APB2: (apb2, pclk2),
793    },
794}
795
796// todo: Run `pwm_features` for more timer types. Currently only set up for first
797// set of gp timers.
798#[cfg(feature = "stm32f303")]
799pwm_features! {
800    {
801        TIM2: (tim2, tim2en, tim2rst),
802        APB1: (apb1, pclk1),
803        u32,
804    },
805    {
806        TIM3: (tim3, tim3en, tim3rst),
807        APB1: (apb1, pclk1),
808        u16,
809    },
810    {
811        TIM4: (tim4, tim4en, tim4rst),
812        APB1: (apb1, pclk1),
813        u16,
814    },
815}