stm32f1_hal/timer/
syst.rs

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