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