stm32f4xx_hal/timer/
monotonic.rs

1// RTICv1 Monotonic impl for the 32-bit timers
2use super::{Channel, Event, FTimer, Flag, General, Instance, WithPwm};
3use crate::rcc::Clocks;
4use crate::ReadFlags;
5use core::ops::{Deref, DerefMut};
6pub use fugit::{self, ExtU32};
7use systick_monotonic::Systick;
8
9pub struct MonoTimer<TIM, const FREQ: u32>(FTimer<TIM, FREQ>);
10
11impl<TIM, const FREQ: u32> Deref for MonoTimer<TIM, FREQ> {
12    type Target = FTimer<TIM, FREQ>;
13    fn deref(&self) -> &Self::Target {
14        &self.0
15    }
16}
17
18impl<TIM, const FREQ: u32> DerefMut for MonoTimer<TIM, FREQ> {
19    fn deref_mut(&mut self) -> &mut Self::Target {
20        &mut self.0
21    }
22}
23
24/// `MonoTimer` with precision of 1 μs (1 MHz sampling)
25pub type MonoTimerUs<TIM> = MonoTimer<TIM, 1_000_000>;
26pub type MonoTimer64Us<TIM> = MonoTimer64<TIM, 1_000_000>;
27
28impl<TIM: Instance, const FREQ: u32> MonoTimer<TIM, FREQ> {
29    /// Releases the TIM peripheral
30    pub fn release(mut self) -> FTimer<TIM, FREQ> {
31        // stop counter
32        self.tim.cr1_reset();
33        self.0
34    }
35}
36
37pub trait MonoTimerExt: Sized {
38    fn monotonic<const FREQ: u32>(self, clocks: &Clocks) -> MonoTimer<Self, FREQ>;
39    fn monotonic_us(self, clocks: &Clocks) -> MonoTimer<Self, 1_000_000> {
40        self.monotonic::<1_000_000>(clocks)
41    }
42}
43
44impl<TIM> MonoTimerExt for TIM
45where
46    Self: Instance + General<Width = u32> + WithPwm,
47{
48    fn monotonic<const FREQ: u32>(self, clocks: &Clocks) -> MonoTimer<Self, FREQ> {
49        FTimer::new(self, clocks).monotonic()
50    }
51}
52
53pub trait MonoTimer64Ext: Sized {
54    fn monotonic64<const FREQ: u32>(self, clocks: &Clocks) -> MonoTimer64<Self, FREQ>;
55    fn monotonic64_us(self, clocks: &Clocks) -> MonoTimer64<Self, 1_000_000> {
56        self.monotonic64::<1_000_000>(clocks)
57    }
58}
59
60impl<TIM> MonoTimer64Ext for TIM
61where
62    Self: Instance + General + WithPwm,
63{
64    fn monotonic64<const FREQ: u32>(self, clocks: &Clocks) -> MonoTimer64<Self, FREQ> {
65        FTimer::new(self, clocks).monotonic64()
66    }
67}
68
69pub trait SysMonoTimerExt: Sized {
70    fn monotonic<const FREQ: u32>(self, clocks: &Clocks) -> Systick<FREQ>;
71    fn monotonic_us(self, clocks: &Clocks) -> Systick<1_000_000> {
72        self.monotonic::<1_000_000>(clocks)
73    }
74}
75
76impl SysMonoTimerExt for cortex_m::peripheral::SYST {
77    fn monotonic<const FREQ: u32>(self, clocks: &Clocks) -> Systick<FREQ> {
78        Systick::new(self, clocks.hclk().raw())
79    }
80}
81
82impl<TIM, const FREQ: u32> FTimer<TIM, FREQ>
83where
84    TIM: Instance + General<Width = u32> + WithPwm,
85{
86    pub fn monotonic(mut self) -> MonoTimer<TIM, FREQ> {
87        unsafe {
88            self.tim.set_auto_reload_unchecked(TIM::max_auto_reload());
89        }
90        self.tim.trigger_update();
91        self.tim.start_free(false);
92        MonoTimer(self)
93    }
94}
95
96impl<TIM, const FREQ: u32> FTimer<TIM, FREQ>
97where
98    TIM: Instance + General + WithPwm,
99{
100    pub fn monotonic64(mut self) -> MonoTimer64<TIM, FREQ> {
101        unsafe {
102            self.tim.set_auto_reload_unchecked(TIM::max_auto_reload());
103        }
104        self.tim.trigger_update();
105        self.tim.start_free(true);
106        MonoTimer64 {
107            ftimer: self,
108            ovf: 0,
109        }
110    }
111}
112
113impl<TIM, const FREQ: u32> rtic_monotonic::Monotonic for MonoTimer<TIM, FREQ>
114where
115    TIM: Instance + General<Width = u32> + WithPwm,
116{
117    type Instant = fugit::TimerInstantU32<FREQ>;
118    type Duration = fugit::TimerDurationU32<FREQ>;
119
120    unsafe fn reset(&mut self) {
121        self.tim.listen_event(None, Some(Event::C1.into()));
122        self.tim.reset_counter();
123    }
124
125    #[inline(always)]
126    fn now(&mut self) -> Self::Instant {
127        Self::Instant::from_ticks(self.tim.read_count())
128    }
129
130    fn set_compare(&mut self, instant: Self::Instant) {
131        TIM::set_cc_value(Channel::C1 as u8, instant.duration_since_epoch().ticks());
132    }
133
134    fn clear_compare_flag(&mut self) {
135        self.tim.clear_interrupt_flag(Flag::C1.into());
136    }
137
138    #[inline(always)]
139    fn zero() -> Self::Instant {
140        Self::Instant::from_ticks(0)
141    }
142}
143
144/// Extended TIM15/16 (16-bits) to 64 bits
145pub struct MonoTimer64<TIM, const FREQ: u32> {
146    ftimer: FTimer<TIM, FREQ>,
147    ovf: u64,
148}
149
150impl<TIM, const FREQ: u32> Deref for MonoTimer64<TIM, FREQ> {
151    type Target = FTimer<TIM, FREQ>;
152    fn deref(&self) -> &Self::Target {
153        &self.ftimer
154    }
155}
156
157impl<TIM, const FREQ: u32> DerefMut for MonoTimer64<TIM, FREQ> {
158    fn deref_mut(&mut self) -> &mut Self::Target {
159        &mut self.ftimer
160    }
161}
162
163impl<TIM: Instance, const FREQ: u32> MonoTimer64<TIM, FREQ> {
164    fn is_overflow(&self) -> bool {
165        self.flags().contains(Flag::Update)
166    }
167}
168
169/// Use Compare channel 1 for Monotonic
170impl<TIM, const FREQ: u32> rtic_monotonic::Monotonic for MonoTimer64<TIM, FREQ>
171where
172    TIM: Instance + General + WithPwm,
173    TIM::Width: ArrWidth,
174    u64: From<TIM::Width>,
175    u32: From<TIM::Width>,
176{
177    // Since we are counting overflows we can't let RTIC disable the interrupt.
178    const DISABLE_INTERRUPT_ON_EMPTY_QUEUE: bool = false;
179
180    type Instant = fugit::TimerInstantU64<FREQ>;
181    type Duration = fugit::TimerDurationU64<FREQ>;
182
183    fn now(&mut self) -> Self::Instant {
184        let cnt = self.tim.read_count();
185
186        // If the overflow bit is set, we add this to the timer value. It means the `on_interrupt`
187        // has not yet happened, and we need to compensate here.
188        let ovf = if self.is_overflow() {
189            TIM::Width::OVF_VALUE
190        } else {
191            0
192        };
193        Self::Instant::from_ticks(u64::from(cnt) + ovf + self.ovf)
194    }
195
196    fn zero() -> Self::Instant {
197        Self::Instant::from_ticks(0)
198    }
199
200    unsafe fn reset(&mut self) {
201        // Since reset is only called once, we use it to enable the interrupt generation bit.
202        self.tim.listen_event(None, Some(Event::C1.into()));
203        self.tim.reset_counter();
204    }
205
206    fn set_compare(&mut self, instant: Self::Instant) {
207        let now = self.now();
208
209        // Since the timer may or may not overflow based on the requested compare val, we check
210        // how many ticks are left.
211        let val: TIM::Width = match instant.checked_duration_since(now) {
212            None => TIM::Width::ONE, // In the past, RTIC will handle this
213            Some(x) if x.ticks() < TIM::Width::OVF_VALUE => {
214                TIM::Width::cast_u64(instant.duration_since_epoch().ticks())
215            } // Will not overflow
216            Some(_x) => self.tim.read_count().wrapping_add(TIM::Width::FOR_WRAP), // Will overflow
217        };
218
219        TIM::set_cc_value(Channel::C1 as u8, u32::from(val));
220    }
221
222    fn clear_compare_flag(&mut self) {
223        self.tim.clear_interrupt_flag(Flag::C1.into());
224    }
225
226    fn on_interrupt(&mut self) {
227        // If there was an overflow, increment the overflow counter.
228        if self.is_overflow() {
229            self.tim.clear_interrupt_flag(Flag::Update.into());
230
231            self.ovf += TIM::Width::OVF_VALUE;
232        }
233    }
234}
235
236trait ArrWidth {
237    const OVF_VALUE: u64;
238    const FOR_WRAP: Self;
239    const ONE: Self;
240    fn cast_u64(from: u64) -> Self;
241    fn wrapping_add(self, other: Self) -> Self;
242}
243
244impl ArrWidth for u16 {
245    const OVF_VALUE: u64 = 0x1_0000;
246    const FOR_WRAP: Self = 0xfffe;
247    const ONE: Self = 1;
248    fn cast_u64(from: u64) -> Self {
249        from as _
250    }
251    fn wrapping_add(self, other: Self) -> Self {
252        self.wrapping_add(other)
253    }
254}
255
256impl ArrWidth for u32 {
257    const OVF_VALUE: u64 = 0x1_0000_0000;
258    const FOR_WRAP: Self = 0xffff_fffe;
259    const ONE: Self = 1;
260    fn cast_u64(from: u64) -> Self {
261        from as _
262    }
263    fn wrapping_add(self, other: Self) -> Self {
264        self.wrapping_add(other)
265    }
266}