stm32f1_hal/timer/
syst.rs

1//! SysTick: System Timer
2
3use super::*;
4use crate::Mcu;
5use core::ops::{Deref, DerefMut};
6use cortex_m::peripheral::{SYST, syst::SystClkSource};
7use fugit::{
8    HertzU32 as Hertz, MicrosDurationU32, NanosDurationU64, TimerDurationU32, TimerInstantU32,
9};
10use waiter_trait::{Interval, TickInstant, TickWaiter};
11
12pub trait SysTimerInit: Sized {
13    /// Creates timer which takes [Hertz] as Duration
14    fn counter_hz(self, mcu: &Mcu) -> SysCounterHz;
15    /// Creates timer with custom precision (core frequency recommended is known)
16    fn counter<const FREQ: u32>(self, mcu: &Mcu) -> SysCounter<FREQ>;
17    /// Creates timer with precision of 1 μs (1 MHz sampling)
18    fn counter_us(self, mcu: &Mcu) -> SysCounterUs {
19        self.counter::<1_000_000>(mcu)
20    }
21}
22
23impl SysTimerInit for SYST {
24    fn counter_hz(self, mcu: &Mcu) -> SysCounterHz {
25        SystemTimer::syst(self, mcu).counter_hz()
26    }
27    fn counter<const FREQ: u32>(self, mcu: &Mcu) -> SysCounter<FREQ> {
28        SystemTimer::syst(self, mcu).counter()
29    }
30}
31
32pub struct SystemTimer {
33    pub(super) syst: SYST,
34    pub(super) clk: Hertz,
35}
36impl SystemTimer {
37    /// Initialize SysTick timer
38    pub fn syst(mut syst: SYST, mcu: &Mcu) -> Self {
39        syst.set_clock_source(SystClkSource::Core);
40        Self {
41            syst,
42            clk: mcu.rcc.clocks.hclk(),
43        }
44    }
45
46    /// Initialize SysTick timer and set it frequency to `HCLK / 8`
47    pub fn syst_external(mut syst: SYST, mcu: &Mcu) -> Self {
48        syst.set_clock_source(SystClkSource::External);
49        Self {
50            syst,
51            clk: mcu.rcc.clocks.hclk() / 8,
52        }
53    }
54
55    pub fn release(self) -> SYST {
56        self.syst
57    }
58
59    /// Starts listening for an `event`
60    pub fn listen(&mut self, event: SysEvent) {
61        match event {
62            SysEvent::Update => self.syst.enable_interrupt(),
63        }
64    }
65
66    /// Stops listening for an `event`
67    pub fn unlisten(&mut self, event: SysEvent) {
68        match event {
69            SysEvent::Update => self.syst.disable_interrupt(),
70        }
71    }
72
73    /// Resets the counter
74    pub fn reset(&mut self) {
75        // According to the Cortex-M3 Generic User Guide, the interrupt request is only generated
76        // when the counter goes from 1 to 0, so writing zero should not trigger an interrupt
77        self.syst.clear_current();
78    }
79
80    pub fn waiter_us<I: Interval>(
81        &self,
82        timeout: MicrosDurationU32,
83        interval: I,
84    ) -> TickWaiter<SysTickInstant, I, u32> {
85        TickWaiter::us(timeout.ticks(), interval, self.clk.raw())
86    }
87
88    /// It can wait longer with a nanosecond timeout.
89    pub fn waiter_ns<I: Interval>(
90        &self,
91        timeout: NanosDurationU64,
92        interval: I,
93    ) -> TickWaiter<SysTickInstant, I, u64> {
94        TickWaiter::ns(timeout.ticks(), interval, self.clk.raw())
95    }
96}
97
98// Counter --------------------------------------------------------------------
99
100impl SystemTimer {
101    /// Creates [SysCounterHz] which takes [Hertz] as Duration
102    pub fn counter_hz(self) -> SysCounterHz {
103        SysCounterHz(self)
104    }
105
106    /// Creates [SysCounter] with custom precision (core frequency recommended is known)
107    pub fn counter<const FREQ: u32>(self) -> SysCounter<FREQ> {
108        SysCounter(self)
109    }
110
111    /// Creates [SysCounter] 1 microsecond precision
112    pub fn counter_us(self) -> SysCounterUs {
113        SysCounter(self)
114    }
115}
116
117/// Hardware timers
118pub struct SysCounterHz(SystemTimer);
119
120impl Deref for SysCounterHz {
121    type Target = SystemTimer;
122    fn deref(&self) -> &Self::Target {
123        &self.0
124    }
125}
126
127impl DerefMut for SysCounterHz {
128    fn deref_mut(&mut self) -> &mut Self::Target {
129        &mut self.0
130    }
131}
132
133impl SysCounterHz {
134    pub fn start(&mut self, timeout: Hertz) -> Result<(), Error> {
135        let rvr = self.clk.raw() / timeout.raw() - 1;
136
137        if rvr >= (1 << 24) {
138            return Err(Error::WrongAutoReload);
139        }
140
141        self.syst.set_reload(rvr);
142        self.syst.clear_current();
143        self.syst.enable_counter();
144
145        Ok(())
146    }
147
148    pub fn wait(&mut self) -> nb::Result<(), Error> {
149        if self.syst.has_wrapped() {
150            Ok(())
151        } else {
152            Err(nb::Error::WouldBlock)
153        }
154    }
155
156    pub fn cancel(&mut self) -> Result<(), Error> {
157        if !self.syst.is_counter_enabled() {
158            return Err(Error::Disabled);
159        }
160
161        self.syst.disable_counter();
162        Ok(())
163    }
164}
165
166pub type SysCounterUs = SysCounter<1_000_000>;
167
168/// SysTick timer with precision of 1 μs (1 MHz sampling)
169pub struct SysCounter<const FREQ: u32>(SystemTimer);
170
171impl<const FREQ: u32> Deref for SysCounter<FREQ> {
172    type Target = SystemTimer;
173    fn deref(&self) -> &Self::Target {
174        &self.0
175    }
176}
177
178impl<const FREQ: u32> DerefMut for SysCounter<FREQ> {
179    fn deref_mut(&mut self) -> &mut Self::Target {
180        &mut self.0
181    }
182}
183
184impl<const FREQ: u32> SysCounter<FREQ> {
185    /// Starts listening for an `event`
186    pub fn listen(&mut self, event: SysEvent) {
187        match event {
188            SysEvent::Update => self.syst.enable_interrupt(),
189        }
190    }
191
192    /// Stops listening for an `event`
193    pub fn unlisten(&mut self, event: SysEvent) {
194        match event {
195            SysEvent::Update => self.syst.disable_interrupt(),
196        }
197    }
198
199    pub fn now(&self) -> TimerInstantU32<FREQ> {
200        TimerInstantU32::from_ticks(SYST::get_current() / (self.clk.raw() / FREQ))
201    }
202
203    pub fn start(&mut self, timeout: TimerDurationU32<FREQ>) -> Result<(), Error> {
204        let rvr = timeout.ticks() * (self.clk.raw() / FREQ) - 1;
205
206        if rvr >= (1 << 24) {
207            return Err(Error::WrongAutoReload);
208        }
209
210        self.syst.set_reload(rvr);
211        self.syst.clear_current();
212        self.syst.enable_counter();
213
214        Ok(())
215    }
216
217    pub fn wait(&mut self) -> nb::Result<(), Error> {
218        if self.syst.has_wrapped() {
219            Ok(())
220        } else {
221            Err(nb::Error::WouldBlock)
222        }
223    }
224
225    pub fn cancel(&mut self) -> Result<(), Error> {
226        if !self.syst.is_counter_enabled() {
227            return Err(Error::Disabled);
228        }
229
230        self.syst.disable_counter();
231        Ok(())
232    }
233}
234
235// ----------------------------------------------------------------------------
236
237/// A `TickInstant` implementation
238#[derive(Copy, Clone)]
239pub struct SysTickInstant {
240    tick: u32,
241}
242impl TickInstant for SysTickInstant {
243    #[inline(always)]
244    fn now() -> Self {
245        Self {
246            tick: SYST::get_current(),
247        }
248    }
249
250    #[inline(always)]
251    fn tick_since(self, earlier: Self) -> u32 {
252        if self.tick <= earlier.tick {
253            earlier.tick - self.tick
254        } else {
255            earlier.tick + (SYST::get_reload() - self.tick + 1)
256        }
257    }
258}