stm32f1_hal/timer/
syst.rs

1//! SysTick: System Timer
2
3use super::*;
4use crate::{Mcu, time::Hertz};
5use core::ops::{Deref, DerefMut};
6use cortex_m::peripheral::{SYST, syst::SystClkSource};
7use embedded_hal::delay::DelayNs;
8use fugit::{ExtU32Ceil, MicrosDurationU32, TimerDurationU32, TimerInstantU32};
9
10pub struct SystemTimer {
11    pub(super) syst: SYST,
12    pub(super) clk: Hertz,
13}
14impl SystemTimer {
15    /// Initialize SysTick timer
16    pub fn syst(mut syst: SYST, mcu: &Mcu) -> Self {
17        syst.set_clock_source(SystClkSource::Core);
18        Self {
19            syst,
20            clk: mcu.rcc.clocks.hclk(),
21        }
22    }
23
24    /// Initialize SysTick timer and set it frequency to `HCLK / 8`
25    pub fn syst_external(mut syst: SYST, mcu: &Mcu) -> Self {
26        syst.set_clock_source(SystClkSource::External);
27        Self {
28            syst,
29            clk: mcu.rcc.clocks.hclk() / 8,
30        }
31    }
32
33    pub fn release(self) -> SYST {
34        self.syst
35    }
36
37    /// Starts listening for an `event`
38    pub fn listen(&mut self, event: SysEvent) {
39        match event {
40            SysEvent::Update => self.syst.enable_interrupt(),
41        }
42    }
43
44    /// Stops listening for an `event`
45    pub fn unlisten(&mut self, event: SysEvent) {
46        match event {
47            SysEvent::Update => self.syst.disable_interrupt(),
48        }
49    }
50
51    /// Resets the counter
52    pub fn reset(&mut self) {
53        // According to the Cortex-M3 Generic User Guide, the interrupt request is only generated
54        // when the counter goes from 1 to 0, so writing zero should not trigger an interrupt
55        self.syst.clear_current();
56    }
57}
58
59pub trait SysTimerInit: Sized {
60    /// Creates timer which takes [Hertz] as Duration
61    fn counter_hz(self, mcu: &Mcu) -> SysCounterHz;
62
63    /// Creates timer with custom precision (core frequency recommended is known)
64    fn counter<const FREQ: u32>(self, mcu: &Mcu) -> SysCounter<FREQ>;
65    /// Creates timer with precision of 1 μs (1 MHz sampling)
66    fn counter_us(self, mcu: &Mcu) -> SysCounterUs {
67        self.counter::<1_000_000>(mcu)
68    }
69    /// Blocking [Delay] with custom precision
70    fn delay(self, mcu: &Mcu) -> SysDelay;
71}
72
73impl SysTimerInit for SYST {
74    fn counter_hz(self, mcu: &Mcu) -> SysCounterHz {
75        SystemTimer::syst(self, mcu).counter_hz()
76    }
77    fn counter<const FREQ: u32>(self, mcu: &Mcu) -> SysCounter<FREQ> {
78        SystemTimer::syst(self, mcu).counter()
79    }
80    fn delay(self, mcu: &Mcu) -> SysDelay {
81        SystemTimer::syst_external(self, mcu).delay()
82    }
83}
84
85// Counter --------------------------------------------------------------------
86
87impl SystemTimer {
88    /// Creates [SysCounterHz] which takes [Hertz] as Duration
89    pub fn counter_hz(self) -> SysCounterHz {
90        SysCounterHz(self)
91    }
92
93    /// Creates [SysCounter] with custom precision (core frequency recommended is known)
94    pub fn counter<const FREQ: u32>(self) -> SysCounter<FREQ> {
95        SysCounter(self)
96    }
97
98    /// Creates [SysCounter] 1 microsecond precision
99    pub fn counter_us(self) -> SysCounterUs {
100        SysCounter(self)
101    }
102}
103
104/// Hardware timers
105pub struct SysCounterHz(SystemTimer);
106
107impl Deref for SysCounterHz {
108    type Target = SystemTimer;
109    fn deref(&self) -> &Self::Target {
110        &self.0
111    }
112}
113
114impl DerefMut for SysCounterHz {
115    fn deref_mut(&mut self) -> &mut Self::Target {
116        &mut self.0
117    }
118}
119
120impl SysCounterHz {
121    pub fn start(&mut self, timeout: Hertz) -> Result<(), Error> {
122        let rvr = self.clk.raw() / timeout.raw() - 1;
123
124        if rvr >= (1 << 24) {
125            return Err(Error::WrongAutoReload);
126        }
127
128        self.syst.set_reload(rvr);
129        self.syst.clear_current();
130        self.syst.enable_counter();
131
132        Ok(())
133    }
134
135    pub fn wait(&mut self) -> nb::Result<(), Error> {
136        if self.syst.has_wrapped() {
137            Ok(())
138        } else {
139            Err(nb::Error::WouldBlock)
140        }
141    }
142
143    pub fn cancel(&mut self) -> Result<(), Error> {
144        if !self.syst.is_counter_enabled() {
145            return Err(Error::Disabled);
146        }
147
148        self.syst.disable_counter();
149        Ok(())
150    }
151}
152
153pub type SysCounterUs = SysCounter<1_000_000>;
154
155/// SysTick timer with precision of 1 μs (1 MHz sampling)
156pub struct SysCounter<const FREQ: u32>(SystemTimer);
157
158impl<const FREQ: u32> Deref for SysCounter<FREQ> {
159    type Target = SystemTimer;
160    fn deref(&self) -> &Self::Target {
161        &self.0
162    }
163}
164
165impl<const FREQ: u32> DerefMut for SysCounter<FREQ> {
166    fn deref_mut(&mut self) -> &mut Self::Target {
167        &mut self.0
168    }
169}
170
171impl<const FREQ: u32> SysCounter<FREQ> {
172    /// Starts listening for an `event`
173    pub fn listen(&mut self, event: SysEvent) {
174        match event {
175            SysEvent::Update => self.syst.enable_interrupt(),
176        }
177    }
178
179    /// Stops listening for an `event`
180    pub fn unlisten(&mut self, event: SysEvent) {
181        match event {
182            SysEvent::Update => self.syst.disable_interrupt(),
183        }
184    }
185
186    pub fn now(&self) -> TimerInstantU32<FREQ> {
187        TimerInstantU32::from_ticks(SYST::get_current() / (self.clk.raw() / FREQ))
188    }
189
190    pub fn start(&mut self, timeout: TimerDurationU32<FREQ>) -> Result<(), Error> {
191        let rvr = timeout.ticks() * (self.clk.raw() / FREQ) - 1;
192
193        if rvr >= (1 << 24) {
194            return Err(Error::WrongAutoReload);
195        }
196
197        self.syst.set_reload(rvr);
198        self.syst.clear_current();
199        self.syst.enable_counter();
200
201        Ok(())
202    }
203
204    pub fn wait(&mut self) -> nb::Result<(), Error> {
205        if self.syst.has_wrapped() {
206            Ok(())
207        } else {
208            Err(nb::Error::WouldBlock)
209        }
210    }
211
212    pub fn cancel(&mut self) -> Result<(), Error> {
213        if !self.syst.is_counter_enabled() {
214            return Err(Error::Disabled);
215        }
216
217        self.syst.disable_counter();
218        Ok(())
219    }
220}
221
222impl<const FREQ: u32> fugit_timer::Timer<FREQ> for SysCounter<FREQ> {
223    type Error = Error;
224
225    fn now(&mut self) -> TimerInstantU32<FREQ> {
226        Self::now(self)
227    }
228
229    fn start(&mut self, duration: TimerDurationU32<FREQ>) -> Result<(), Self::Error> {
230        self.start(duration)
231    }
232
233    fn wait(&mut self) -> nb::Result<(), Self::Error> {
234        self.wait()
235    }
236
237    fn cancel(&mut self) -> Result<(), Self::Error> {
238        self.cancel()
239    }
240}
241
242// Delay ----------------------------------------------------------------------
243
244/// Timer as a delay provider (SysTick by default)
245pub struct SysDelay(SystemTimer);
246
247impl Deref for SysDelay {
248    type Target = SystemTimer;
249    fn deref(&self) -> &Self::Target {
250        &self.0
251    }
252}
253
254impl DerefMut for SysDelay {
255    fn deref_mut(&mut self) -> &mut Self::Target {
256        &mut self.0
257    }
258}
259
260impl SysDelay {
261    /// Releases the timer resource
262    pub fn release(self) -> SystemTimer {
263        self.0
264    }
265}
266
267impl SystemTimer {
268    pub fn delay(self) -> SysDelay {
269        SysDelay(self)
270    }
271}
272
273impl SysDelay {
274    pub fn delay(&mut self, us: MicrosDurationU32) {
275        // The SysTick Reload Value register supports values between 1 and 0x00FFFFFF.
276        const MAX_RVR: u32 = 0x00FF_FFFF;
277
278        let mut total_rvr = us.ticks() * (self.clk.raw() / 1_000_000);
279
280        while total_rvr != 0 {
281            let current_rvr = total_rvr.min(MAX_RVR);
282
283            self.syst.set_reload(current_rvr);
284            self.syst.clear_current();
285            self.syst.enable_counter();
286
287            // Update the tracking variable while we are waiting...
288            total_rvr -= current_rvr;
289
290            while !self.syst.has_wrapped() {}
291
292            self.syst.disable_counter();
293        }
294    }
295}
296
297impl fugit_timer::Delay<1_000_000> for SysDelay {
298    type Error = core::convert::Infallible;
299
300    fn delay(&mut self, duration: MicrosDurationU32) -> Result<(), Self::Error> {
301        self.delay(duration);
302        Ok(())
303    }
304}
305
306impl DelayNs for SysDelay {
307    fn delay_ns(&mut self, ns: u32) {
308        self.delay(ns.nanos_at_least());
309    }
310
311    fn delay_ms(&mut self, ms: u32) {
312        self.delay(ms.millis_at_least());
313    }
314}