stm32f1xx_hal/timer/
delay.rs

1//! Delays
2
3use super::{FTimer, Instance, Timer};
4use core::ops::{Deref, DerefMut};
5use cortex_m::peripheral::SYST;
6use fugit::{MicrosDurationU32, TimerDurationU32};
7
8/// Timer as a delay provider (SysTick by default)
9pub struct SysDelay(Timer<SYST>);
10
11impl Deref for SysDelay {
12    type Target = Timer<SYST>;
13    fn deref(&self) -> &Self::Target {
14        &self.0
15    }
16}
17
18impl DerefMut for SysDelay {
19    fn deref_mut(&mut self) -> &mut Self::Target {
20        &mut self.0
21    }
22}
23
24impl SysDelay {
25    /// Releases the timer resource
26    pub fn release(self) -> Timer<SYST> {
27        self.0
28    }
29}
30
31impl Timer<SYST> {
32    pub fn delay(self) -> SysDelay {
33        SysDelay(self)
34    }
35}
36
37impl SysDelay {
38    pub fn delay(&mut self, us: MicrosDurationU32) {
39        // The SysTick Reload Value register supports values between 1 and 0x00FFFFFF.
40        const MAX_RVR: u32 = 0x00FF_FFFF;
41
42        let mut total_rvr = us.ticks() * (self.clk.raw() / 1_000_000);
43
44        while total_rvr != 0 {
45            let current_rvr = total_rvr.min(MAX_RVR);
46
47            self.tim.set_reload(current_rvr);
48            self.tim.clear_current();
49            self.tim.enable_counter();
50
51            // Update the tracking variable while we are waiting...
52            total_rvr -= current_rvr;
53
54            while !self.tim.has_wrapped() {}
55
56            self.tim.disable_counter();
57        }
58    }
59}
60
61/// Periodic non-blocking timer that imlements [embedded_hal_02::blocking::delay] traits
62pub struct Delay<TIM, const FREQ: u32>(pub(super) FTimer<TIM, FREQ>);
63
64impl<T, const FREQ: u32> Deref for Delay<T, FREQ> {
65    type Target = FTimer<T, FREQ>;
66    fn deref(&self) -> &Self::Target {
67        &self.0
68    }
69}
70
71impl<T, const FREQ: u32> DerefMut for Delay<T, FREQ> {
72    fn deref_mut(&mut self) -> &mut Self::Target {
73        &mut self.0
74    }
75}
76
77/// `Delay` with precision of 1 μs (1 MHz sampling)
78pub type DelayUs<TIM> = Delay<TIM, 1_000_000>;
79
80/// `Delay` with precision of 1 ms (1 kHz sampling)
81///
82/// NOTE: don't use this if your system frequency more than 65 MHz
83pub type DelayMs<TIM> = Delay<TIM, 1_000>;
84
85impl<TIM: Instance, const FREQ: u32> Delay<TIM, FREQ> {
86    /// Sleep for given time
87    pub fn delay(&mut self, time: TimerDurationU32<FREQ>) {
88        let mut ticks = time.ticks().max(1) - 1;
89        while ticks != 0 {
90            let reload = ticks.min(TIM::max_auto_reload());
91
92            // Write Auto-Reload Register (ARR)
93            unsafe {
94                self.tim.set_auto_reload_unchecked(reload);
95            }
96
97            // Trigger update event (UEV) in the event generation register (EGR)
98            // in order to immediately apply the config
99            self.tim.trigger_update();
100
101            // Configure the counter in one-pulse mode (counter stops counting at
102            // the next updateevent, clearing the CEN bit) and enable the counter.
103            self.tim.start_one_pulse();
104
105            // Update the tracking variable while we are waiting...
106            ticks -= reload;
107            // Wait for CEN bit to clear
108            while self.tim.is_counter_enabled() { /* wait */ }
109        }
110    }
111
112    pub fn max_delay(&self) -> TimerDurationU32<FREQ> {
113        TimerDurationU32::from_ticks(TIM::max_auto_reload())
114    }
115
116    /// Releases the TIM peripheral
117    pub fn release(mut self) -> FTimer<TIM, FREQ> {
118        // stop counter
119        self.tim.cr1_reset();
120        self.0
121    }
122}
123
124impl<TIM: Instance, const FREQ: u32> fugit_timer::Delay<FREQ> for Delay<TIM, FREQ> {
125    type Error = core::convert::Infallible;
126
127    fn delay(&mut self, duration: TimerDurationU32<FREQ>) -> Result<(), Self::Error> {
128        self.delay(duration);
129        Ok(())
130    }
131}
132
133impl fugit_timer::Delay<1_000_000> for SysDelay {
134    type Error = core::convert::Infallible;
135
136    fn delay(&mut self, duration: MicrosDurationU32) -> Result<(), Self::Error> {
137        self.delay(duration);
138        Ok(())
139    }
140}