stm32f1_hal/timer/
syst.rs

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