stm32f1xx_hal/timer/
monotonic.rs

1//! RTIC Monotonic implementation
2
3use super::{FTimer, Instance};
4use crate::rcc::Rcc;
5use core::ops::{Deref, DerefMut};
6pub use fugit::{self, ExtU32};
7use rtic_monotonic::Monotonic;
8
9pub struct MonoTimer<TIM, const FREQ: u32> {
10    timer: FTimer<TIM, FREQ>,
11    ovf: u32,
12}
13
14impl<TIM, const FREQ: u32> Deref for MonoTimer<TIM, FREQ> {
15    type Target = FTimer<TIM, FREQ>;
16    fn deref(&self) -> &Self::Target {
17        &self.timer
18    }
19}
20
21impl<TIM, const FREQ: u32> DerefMut for MonoTimer<TIM, FREQ> {
22    fn deref_mut(&mut self) -> &mut Self::Target {
23        &mut self.timer
24    }
25}
26
27/// `MonoTimer` with precision of 1 μs (1 MHz sampling)
28pub type MonoTimerUs<TIM> = MonoTimer<TIM, 1_000_000>;
29
30impl<TIM: Instance, const FREQ: u32> MonoTimer<TIM, FREQ> {
31    /// Releases the TIM peripheral
32    pub fn release(mut self) -> FTimer<TIM, FREQ> {
33        // stop counter
34        self.tim.cr1_reset();
35        self.timer
36    }
37}
38
39pub trait MonoTimerExt: Sized {
40    fn monotonic<const FREQ: u32>(self, rcc: &mut Rcc) -> MonoTimer<Self, FREQ>;
41    fn monotonic_us(self, rcc: &mut Rcc) -> MonoTimer<Self, 1_000_000> {
42        self.monotonic::<1_000_000>(rcc)
43    }
44}
45
46macro_rules! mono {
47    ($TIM:ty) => {
48        impl MonoTimerExt for $TIM {
49            fn monotonic<const FREQ: u32>(self, rcc: &mut Rcc) -> MonoTimer<Self, FREQ> {
50                FTimer::new(self, rcc).monotonic()
51            }
52        }
53
54        impl<const FREQ: u32> FTimer<$TIM, FREQ> {
55            pub fn monotonic(self) -> MonoTimer<$TIM, FREQ> {
56                MonoTimer::<$TIM, FREQ>::_new(self)
57            }
58        }
59
60        impl<const FREQ: u32> MonoTimer<$TIM, FREQ> {
61            fn _new(timer: FTimer<$TIM, FREQ>) -> Self {
62                // Set auto-reload value.
63                timer.tim.arr().write(|w| w.arr().set(u16::MAX));
64                // Generate interrupt on overflow.
65                timer.tim.egr().write(|w| w.ug().set_bit());
66
67                // Start timer.
68                // Clear interrupt flag.
69                timer.tim.sr().modify(|_, w| w.uif().clear_bit());
70                timer.tim.cr1().modify(|_, w| {
71                    // Enable counter.
72                    w.cen().set_bit();
73                    // Overflow should trigger update event.
74                    w.udis().clear_bit();
75                    // Only overflow triggers interrupt.
76                    w.urs().set_bit()
77                });
78
79                Self { timer, ovf: 0 }
80            }
81        }
82
83        impl<const FREQ: u32> Monotonic for MonoTimer<$TIM, FREQ> {
84            type Instant = fugit::TimerInstantU32<FREQ>;
85            type Duration = fugit::TimerDurationU32<FREQ>;
86
87            unsafe fn reset(&mut self) {
88                self.tim.dier().modify(|_, w| w.cc1ie().set_bit());
89            }
90
91            #[inline(always)]
92            fn now(&mut self) -> Self::Instant {
93                let cnt = self.tim.cnt().read().cnt().bits() as u32;
94
95                // If the overflow bit is set, we add this to the timer value. It means the `on_interrupt`
96                // has not yet happened, and we need to compensate here.
97                let ovf = if self.tim.sr().read().uif().bit_is_set() {
98                    0x10000
99                } else {
100                    0
101                };
102
103                Self::Instant::from_ticks(cnt.wrapping_add(ovf).wrapping_add(self.ovf))
104            }
105
106            fn set_compare(&mut self, instant: Self::Instant) {
107                let now = self.now();
108                let cnt = self.tim.cnt().read().cnt().bits();
109
110                // Since the timer may or may not overflow based on the requested compare val, we check
111                // how many ticks are left.
112                let val = match instant.checked_duration_since(now) {
113                    None => cnt.wrapping_add(0xffff), // In the past, RTIC will handle this
114                    Some(x) if x.ticks() <= 0xffff => instant.duration_since_epoch().ticks() as u16, // Will not overflow
115                    Some(_) => cnt.wrapping_add(0xffff), // Will overflow, run for as long as possible
116                };
117
118                self.tim.ccr1().write(|w| w.ccr().set(val));
119            }
120
121            fn clear_compare_flag(&mut self) {
122                self.tim.sr().modify(|_, w| w.cc1if().clear_bit());
123            }
124
125            fn on_interrupt(&mut self) {
126                // If there was an overflow, increment the overflow counter.
127                if self.tim.sr().read().uif().bit_is_set() {
128                    self.tim.sr().modify(|_, w| w.uif().clear_bit());
129
130                    self.ovf += 0x10000;
131                }
132            }
133
134            #[inline(always)]
135            fn zero() -> Self::Instant {
136                Self::Instant::from_ticks(0)
137            }
138        }
139    };
140}
141
142mono!(crate::pac::TIM2);
143mono!(crate::pac::TIM3);
144
145#[cfg(any(feature = "stm32f100", feature = "stm32f103", feature = "connectivity"))]
146mono!(crate::pac::TIM1);
147
148#[cfg(feature = "medium")]
149mono!(crate::pac::TIM4);
150
151#[cfg(any(feature = "high", feature = "connectivity"))]
152mono!(crate::pac::TIM5);
153
154#[cfg(all(feature = "stm32f103", feature = "high"))]
155mono!(crate::pac::TIM8);