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}