stm32f3xx_hal/
timer.rs

1//! # Timers
2//!
3//! Abstractions of the internal timer peripherals
4//! The timer modules implements the [`CountDown`] and [`Periodic`] traits.
5//!
6//! ## Examples
7//!
8//! Check out [examples/adc.rs], where a [`Periodic`] timer is used to wake
9//! up the main-loop regularly.
10//!
11//! [examples/adc.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.10.0/examples/adc.rs
12
13use crate::pac::{DCB, DWT};
14#[cfg(feature = "enumset")]
15use enumset::{EnumSet, EnumSetType};
16use void::Void;
17
18use crate::hal::timer::{Cancel, CountDown, Periodic};
19#[allow(unused)]
20use crate::pac::{self, RCC};
21use crate::rcc::{self, Clocks};
22use crate::time::{duration, fixed_point::FixedPoint, rate::Hertz};
23
24mod interrupts;
25
26/// A monotonic nondecreasing timer.
27#[allow(clippy::module_name_repetitions)]
28#[derive(Debug, Clone, Copy)]
29pub struct MonoTimer {
30    frequency: Hertz,
31}
32
33#[cfg(feature = "defmt")]
34impl defmt::Format for MonoTimer {
35    fn format(&self, f: defmt::Formatter) {
36        defmt::write!(
37            f,
38            "MonoTimer {{ frequency: {} Hz }}",
39            self.frequency.integer(),
40        );
41    }
42}
43
44impl MonoTimer {
45    /// Creates a new `Monotonic` timer
46    pub fn new(mut dwt: DWT, clocks: Clocks, dcb: &mut DCB) -> Self {
47        // Takes ownership of `DWT` so that the CYCCNT counter can't be stopped or resetted.
48
49        // This is needed, so that the DWT timer starts to count.
50        dcb.enable_trace();
51        dwt.enable_cycle_counter();
52
53        MonoTimer {
54            frequency: clocks.hclk(),
55        }
56    }
57
58    /// Returns the frequency at which the monotonic timer is operating at
59    #[must_use]
60    pub fn frequency(&self) -> Hertz {
61        self.frequency
62    }
63
64    /// Returns an `Instant` corresponding to "now"
65    #[must_use]
66    pub fn now(&self) -> Instant {
67        Instant {
68            now: DWT::cycle_count(),
69        }
70    }
71}
72
73/// A measurement of a monotonically nondecreasing clock
74#[derive(Debug, Clone, Copy)]
75#[cfg_attr(feature = "defmt", derive(defmt::Format))]
76pub struct Instant {
77    now: u32,
78}
79
80impl Instant {
81    /// Ticks elapsed since the `Instant` was created
82    #[must_use]
83    pub fn elapsed(self) -> u32 {
84        DWT::cycle_count().wrapping_sub(self.now)
85    }
86}
87
88/// Hardware timers
89#[derive(Debug)]
90#[cfg_attr(feature = "defmt", derive(defmt::Format))]
91pub struct Timer<TIM> {
92    tim: TIM,
93    clocks: Clocks,
94}
95
96/// Interrupt events
97#[derive(Debug)]
98#[cfg_attr(feature = "defmt", derive(defmt::Format))]
99#[cfg_attr(feature = "enumset", derive(EnumSetType))]
100#[cfg_attr(not(feature = "enumset"), derive(Copy, Clone, PartialEq, Eq))]
101#[non_exhaustive]
102// TODO(Sh3Rm4n): What to do about events, which not all timers support?
103pub enum Event {
104    /// Timer timed out / count down ended
105    Update,
106}
107
108impl<TIM> Timer<TIM>
109where
110    TIM: Instance,
111{
112    /// Configures a TIM peripheral as a periodic count down timer
113    pub fn new(tim: TIM, clocks: Clocks, apb: &mut <TIM as rcc::RccBus>::Bus) -> Self {
114        TIM::enable(apb);
115        TIM::reset(apb);
116
117        Timer { tim, clocks }
118    }
119
120    /// Stops the timer
121    #[inline]
122    pub fn stop(&mut self) {
123        self.tim.set_cr1_cen(false);
124    }
125
126    /// Enable or disable the interrupt for the specified [`Event`].
127    #[inline]
128    pub fn enable_interrupt(&mut self, event: Event) {
129        self.configure_interrupt(event, true);
130    }
131
132    /// Enable or disable the interrupt for the specified [`Event`].
133    #[inline]
134    pub fn disable_interrupt(&mut self, event: Event) {
135        self.configure_interrupt(event, false);
136    }
137
138    /// Obtain the associated interupt number for the serial peripheral.
139    ///
140    /// Used to unmask / enable the interrupt with [`cortex_m::peripheral::NVIC::unmask()`].
141    /// This is useful for all `cortex_m::peripheral::INTERRUPT` functions.
142    ///
143    /// # Note
144    ///
145    /// This is the easier alternative to obatain the interrupt for:
146    ///
147    /// ```
148    /// use cortex_m::peripheral::INTERRUPT;
149    /// use stm32f3xx_hal::pac::TIM1;
150    /// use stm32f3xx_hal::interrupts::InterruptNumber;
151    ///
152    /// const INTERRUPT: Interrupt = <TIM2 as InterruptNumber>::INTERRUPT;
153    /// ```
154    ///
155    /// though this function can not be used in a const context.
156    #[doc(alias = "unmask")]
157    pub fn interrupt(&self) -> <TIM as crate::interrupts::InterruptNumber>::Interrupt {
158        <TIM as crate::interrupts::InterruptNumber>::INTERRUPT
159    }
160
161    /// Enable or disable the interrupt for the specified [`Event`].
162    #[inline]
163    pub fn configure_interrupt(&mut self, event: Event, enable: bool) {
164        match event {
165            Event::Update => self.tim.set_dier_uie(enable),
166        }
167    }
168
169    /// Enable or disable interrupt for the specified [`Event`]s.
170    ///
171    /// Like [`Timer::configure_interrupt`], but instead using an enumset. The corresponding
172    /// interrupt for every [`Event`] in the set will be enabled, every other interrupt will be
173    /// **disabled**.
174    #[cfg(feature = "enumset")]
175    #[cfg_attr(docsrs, doc(cfg(feature = "enumset")))]
176    pub fn configure_interrupts(&mut self, events: EnumSet<Event>) {
177        for event in events.complement().iter() {
178            self.configure_interrupt(event, false);
179        }
180        for event in events.iter() {
181            self.configure_interrupt(event, true);
182        }
183    }
184
185    /// Check if an interrupt is configured for the [`Event`]
186    #[inline]
187    pub fn is_interrupt_configured(&self, event: Event) -> bool {
188        match event {
189            Event::Update => self.tim.is_dier_uie_set(),
190        }
191    }
192
193    // TODO: Add to other implementations as well (Serial, ...)
194    /// Check which interrupts are enabled for all [`Event`]s
195    #[cfg(feature = "enumset")]
196    #[cfg_attr(docsrs, doc(cfg(feature = "enumset")))]
197    #[inline]
198    pub fn configured_interrupts(&mut self) -> EnumSet<Event> {
199        let mut events = EnumSet::new();
200
201        for event in EnumSet::<Event>::all().iter() {
202            if self.is_interrupt_configured(event) {
203                events |= event;
204            }
205        }
206
207        events
208    }
209
210    /// Check if an interrupt event happened.
211    pub fn is_event_triggered(&self, event: Event) -> bool {
212        match event {
213            Event::Update => self.tim.is_sr_uief_set(),
214        }
215    }
216
217    /// Get an [`EnumSet`] of all fired interrupt events.
218    #[cfg(feature = "enumset")]
219    #[cfg_attr(docsrs, doc(cfg(feature = "enumset")))]
220    pub fn triggered_events(&self) -> EnumSet<Event> {
221        let mut events = EnumSet::new();
222
223        for event in EnumSet::<Event>::all().iter() {
224            if self.is_event_triggered(event) {
225                events |= event;
226            }
227        }
228
229        events
230    }
231
232    /// Clear the given interrupt event flag.
233    #[inline]
234    pub fn clear_event(&mut self, event: Event) {
235        match event {
236            Event::Update => self.tim.clear_sr_uief(),
237        }
238    }
239
240    /// Clear **all** interrupt events.
241    #[inline]
242    pub fn clear_events(&mut self) {
243        self.tim.clear_sr();
244    }
245
246    /// Get access to the underlying register block.
247    ///
248    /// # Safety
249    ///
250    /// This function is not _memory_ unsafe per se, but does not guarantee
251    /// anything about assumptions of invariants made in this implementation.
252    ///
253    /// Changing specific options can lead to un-expected behavior and nothing
254    /// is guaranteed.
255    pub unsafe fn peripheral(&mut self) -> &mut TIM {
256        &mut self.tim
257    }
258
259    /// Releases the TIM peripheral
260    #[inline]
261    pub fn free(mut self) -> TIM {
262        self.stop();
263        self.tim
264    }
265}
266
267impl<TIM> Periodic for Timer<TIM> where TIM: Instance {}
268
269impl<TIM> CountDown for Timer<TIM>
270where
271    TIM: Instance,
272{
273    type Time = duration::Generic<u32>;
274
275    fn start<T>(&mut self, timeout: T)
276    where
277        T: Into<Self::Time>,
278    {
279        self.stop();
280
281        let timeout: Self::Time = timeout.into();
282        let clock = TIM::clock(&self.clocks);
283
284        let ticks = u64::from(clock.integer()).saturating_mul(u64::from(timeout.integer()))
285            * *timeout.scaling_factor();
286
287        let psc = ticks.saturating_sub(1) / (1 << 16);
288        self.tim.set_psc(crate::unwrap!(u16::try_from(psc).ok()));
289
290        let mut arr = ticks / psc.saturating_add(1);
291        // If the set frequency is to high to get a meaningful timer resolution,
292        // set arr to one, so the timer can at least do something and code waiting
293        // on it is not stuck.
294        if psc == 0 && arr == 0 {
295            arr = 1;
296        }
297        self.tim.set_arr(crate::unwrap!(u16::try_from(arr).ok()));
298
299        // Ensure that the below procedure does not create an unexpected interrupt.
300        let is_update_interrupt_active = self.is_interrupt_configured(Event::Update);
301        if is_update_interrupt_active {
302            self.configure_interrupt(Event::Update, false);
303        }
304
305        // Trigger an update event to load the prescaler value to the clock The above line raises
306        // an update event which will indicate that the timer is already finished.
307        self.tim.set_egr_ug();
308        // Since this is not the case, it should be cleared.
309        self.clear_event(Event::Update);
310
311        if is_update_interrupt_active {
312            self.configure_interrupt(Event::Update, true);
313        }
314
315        // start counter
316        self.tim.set_cr1_cen(true);
317    }
318
319    /// Wait until [`Event::Update`] / the timer has elapsed
320    /// and than clear the event.
321    fn wait(&mut self) -> nb::Result<(), Void> {
322        if self.tim.is_sr_uief_set() {
323            self.clear_event(Event::Update);
324            Ok(())
325        } else {
326            Err(nb::Error::WouldBlock)
327        }
328    }
329}
330
331/// Error if a [`Cancel`]-ble [`Timer`] was cancled already or never been started.
332#[derive(Debug, Copy, Clone, PartialEq, Eq)]
333#[cfg_attr(feature = "defmt", derive(defmt::Format))]
334pub struct AlreadyCancled;
335
336impl<TIM> Cancel for Timer<TIM>
337where
338    TIM: Instance,
339{
340    type Error = AlreadyCancled;
341    fn cancel(&mut self) -> Result<(), Self::Error> {
342        // If timer is already stopped.
343        if !self.tim.is_cr1_cen_set() {
344            return Err(AlreadyCancled);
345        }
346        self.stop();
347        Ok(())
348    }
349}
350
351/// Common functionalities of all timer `RegisterBlock` types
352/// based on [`crate::pac::tim6::RegisterBlock`].
353///
354/// This is not meant to be used outside of this crate.
355pub trait CommonRegisterBlock: crate::private::Sealed {
356    #[doc(hidden)]
357    fn set_cr1_cen(&mut self, enable: bool);
358    #[doc(hidden)]
359    fn is_cr1_cen_set(&mut self) -> bool;
360    #[doc(hidden)]
361    fn set_dier_uie(&mut self, enable: bool);
362    #[doc(hidden)]
363    fn is_dier_uie_set(&self) -> bool;
364    #[doc(hidden)]
365    fn clear_sr_uief(&mut self);
366    #[doc(hidden)]
367    fn clear_sr(&mut self);
368    #[doc(hidden)]
369    fn is_sr_uief_set(&self) -> bool;
370    #[doc(hidden)]
371    fn set_egr_ug(&mut self);
372    #[doc(hidden)]
373    fn set_psc(&mut self, psc: u16);
374    #[doc(hidden)]
375    fn set_arr(&mut self, arr: u16);
376}
377
378/// Associated clocks with timers
379pub trait Instance:
380    CommonRegisterBlock
381    + crate::interrupts::InterruptNumber
382    + crate::private::Sealed
383    + rcc::Enable
384    + rcc::Reset
385{
386    #[doc(hidden)]
387    fn clock(clocks: &Clocks) -> Hertz;
388}
389
390macro_rules! timer {
391    ($TIMX:ident) => {
392        impl CommonRegisterBlock for crate::pac::$TIMX {
393            #[inline]
394            fn set_cr1_cen(&mut self, enable: bool) {
395                self.cr1.modify(|_, w| w.cen().bit(enable));
396            }
397
398            #[inline]
399            fn is_cr1_cen_set(&mut self) -> bool {
400                self.cr1.read().cen().bit()
401            }
402
403            #[inline]
404            fn set_dier_uie(&mut self, enable: bool) {
405                self.dier.modify(|_, w| w.uie().bit(enable));
406            }
407
408            #[inline]
409            fn is_dier_uie_set(&self) -> bool {
410                self.dier.read().uie().bit()
411            }
412
413            #[inline]
414            fn clear_sr_uief(&mut self) {
415                self.sr.modify(|_, w| w.uif().clear())
416            }
417
418            #[inline]
419            fn clear_sr(&mut self) {
420                // SAFETY: This atomic write clears all flags and ignores the reserverd bit fields.
421                self.sr.write(|w| unsafe { w.bits(0) });
422            }
423
424            #[inline]
425            fn is_sr_uief_set(&self) -> bool {
426                self.sr.read().uif().is_update_pending()
427            }
428
429            #[inline]
430            fn set_egr_ug(&mut self) {
431                // NOTE(write): uses all bits in this register.
432                self.egr.write(|w| w.ug().update());
433            }
434
435            #[inline]
436            fn set_psc(&mut self, psc: u16) {
437                // NOTE(write): uses all bits in this register.
438                self.psc.write(|w| w.psc().bits(psc));
439            }
440
441            #[inline]
442            fn set_arr(&mut self, arr: u16) {
443                #[allow(unused_unsafe)]
444                // SAFETY: For easier compatibility between timers write to whole register
445                self.arr.write(|w| unsafe { w.arr().bits(arr.into()) });
446            }
447        }
448    };
449}
450
451#[allow(unused)]
452macro_rules! timer_var_clock {
453    ($($TIMX:ident, $timXsw:ident),+) => {
454        $(
455            impl Instance for crate::pac::$TIMX {
456                #[inline]
457                fn clock(clocks: &Clocks) -> Hertz {
458                    // SAFETY: Atomic read with no side-effects.
459                    match unsafe {(*RCC::ptr()).cfgr3.read().$timXsw().variant()} {
460                        // PCLK2 is really the wrong name, as depending on the type of chip, it is
461                        // pclk1 or pclk2. This distinction is however not made in stm32f3.
462                        crate::pac::rcc::cfgr3::TIM1SW_A::Pclk2 =>  {
463                            // Conditional mutliplier after APB prescaler is used.
464                            // See RM0316 Fig 13.
465                            <pac::$TIMX as rcc::BusTimerClock>::timer_clock(clocks)
466                        }
467                        crate::pac::rcc::cfgr3::TIM1SW_A::Pll => {
468                            if let Some(pllclk) = clocks.pllclk() {
469                                pllclk * 2
470                            } else {
471                                // This state should currently not be possible,
472                                // because the software source can not be configured right now.
473                                crate::panic!("Invalid timer clock source.");
474                            }
475                        }
476                    }
477                }
478            }
479
480            timer!($TIMX);
481        )+
482    };
483    ($(($X:literal: $Y:literal)),+) => {
484        paste::paste! {
485            timer_var_clock!(
486                $([<TIM $X>], [<tim $Y sw>]),+
487            );
488
489        }
490    };
491    ($($X:literal),+) => {
492        timer_var_clock!($(($X: $X)),+);
493    };
494}
495
496macro_rules! timer_static_clock {
497    ($($TIMX:ident),+) => {
498        $(
499            impl Instance for crate::pac::$TIMX {
500                #[inline]
501                fn clock(clocks: &Clocks) -> Hertz {
502                    <pac::$TIMX as rcc::BusTimerClock>::timer_clock(clocks)
503                }
504            }
505
506            timer!($TIMX);
507        )+
508    };
509    ($($X:literal),+) => {
510        paste::paste! {
511            timer_static_clock!(
512                $([<TIM $X>]),+
513            );
514        }
515    };
516}
517
518// NOTE: Most informations are read out of the clock tree (example RM0316 Fig. 13)
519// This gives us the following information:
520// - To which APB is the timer connected
521// - Which timers are really supported by the chip family
522// - Which timers have a static clock and which can also be connected to the PLL clock line
523cfg_if::cfg_if! {
524    // RM0366 Fig. 11
525    //
526    // NOTE: Even though timer 7 appears in the clock tree and an interrupt exists for 7
527    // (Interrupt::TIM7_IRQ), TIM7 has no chapter is nowwhere to be mentioned. Also tim7sw() does
528    // not exsist.
529    if #[cfg(feature = "svd-f301")] {
530        timer_static_clock!(2, 6);
531        timer_var_clock!(1, 15, 16, 17);
532    }
533}
534
535cfg_if::cfg_if! {
536    // RM0365 Fig. 12
537    if #[cfg(all(feature = "svd-f302", feature = "gpio-f303"))] {
538        timer_static_clock!(2, 3, 4, 6, 15, 16, 17);
539        timer_var_clock!(1);
540    }
541
542    // RM0365 Fig. 13
543    else if #[cfg(all(feature = "svd-f302", feature = "gpio-f303e"))] {
544        timer_static_clock!(6);
545        timer_var_clock!(1, 2, 15, 16, 17);
546        timer_var_clock!((3: 34), (4: 34));
547    }
548
549    // RM0365 Fig. 14
550    //
551    // NOTE: Even though timer 7 appears in the clock tree and an interrupt exists for 7
552    // (Interrupt::TIM7_IRQ), TIM7 has no chapter is nowhere to be mentioned. Also tim7sw() does
553    // not exsist.
554    else if #[cfg(all(feature = "svd-f302", feature = "gpio-f302"))] {
555        timer_static_clock!(2, 6);
556        timer_var_clock!(1, 15, 16, 17);
557    }
558
559    // RM0316 Fig. 13
560    else if #[cfg(all(feature = "svd-f303", feature = "gpio-f303"))] {
561        timer_static_clock!(2, 3, 4, 6, 7, 15, 16, 17);
562        timer_var_clock!(1, 8);
563    }
564
565    // RM0316 Fig. 14
566    else if #[cfg(all(feature = "svd-f303", feature = "gpio-f303e"))] {
567        timer_static_clock!(6, 7);
568        timer_var_clock!(1, 2, 8, 15, 16, 17, 20);
569        timer_var_clock!((3: 34), (4: 34));
570    }
571
572    // RM0316 Fig. 15
573    else if #[cfg(all(feature = "svd-f303", feature = "gpio-f333"))] {
574        timer_static_clock!(2, 3, 6, 7, 15, 16, 17);
575        timer_var_clock!(1);
576    }
577
578    // RM0313 Fig. 12 - this clock does not deliver the information about the timers.
579    //
580    // This information is from chapter 16, 17 and 18 of RM0313.
581    // The information, which APB is connected to the timer, is only avaliable while looking
582    // at the apb[1,2]rst registers.
583    else if #[cfg(feature = "gpio-f373")] {
584        timer_static_clock!(2, 3, 4, 5, 6, 7, 12, 13, 14, 15, 16, 17, 18, 19);
585    }
586
587    // RM0364 Fig. 10
588    else if #[cfg(all(feature = "svd-f3x4", feature = "gpio-f333"))] {
589        timer_static_clock!(2, 3, 6, 7, 15, 16, 17);
590        timer_var_clock!(1);
591    }
592}