stm32f4xx_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 implements [embedded_hal_02::blocking::delay] traits.
62///
63/// ### Example: Millisecond precision
64///
65/// To instantiate this with the TIM2 timer and millisecond precision:
66///
67/// ```rust
68/// let mut delay = dp.TIM2.delay_ms(&clocks);
69/// delay.delay_ms(320_u32);
70/// ```
71///
72/// With millisecond precision, you can wait from 2 ms to 49 days.
73///
74/// ### Example: Microsecond precision
75///
76/// To instantiate this with the TIM5 timer and microsecond precision:
77///
78/// ```rust
79/// let delay = dp.TIM5.delay_us(&clocks);
80/// delay.delay_us(30_u32);
81/// delay.delay_ms(5_u32);
82/// delay.delay(5.millis());
83/// delay.delay(3.secs());
84/// ```
85///
86/// With microsecond precision, you can wait from 2 µs to 71 min.
87pub struct Delay<TIM, const FREQ: u32>(pub(super) FTimer<TIM, FREQ>);
88
89impl<T, const FREQ: u32> Deref for Delay<T, FREQ> {
90    type Target = FTimer<T, FREQ>;
91    fn deref(&self) -> &Self::Target {
92        &self.0
93    }
94}
95
96impl<T, const FREQ: u32> DerefMut for Delay<T, FREQ> {
97    fn deref_mut(&mut self) -> &mut Self::Target {
98        &mut self.0
99    }
100}
101
102/// `Delay` with precision of 1 μs (1 MHz sampling)
103pub type DelayUs<TIM> = Delay<TIM, 1_000_000>;
104
105/// `Delay` with precision of 1 ms (1 kHz sampling)
106///
107/// NOTE: don't use this if your system frequency more than 65 MHz
108pub type DelayMs<TIM> = Delay<TIM, 1_000>;
109
110impl<TIM: Instance, const FREQ: u32> Delay<TIM, FREQ> {
111    /// Sleep for given time
112    pub fn delay(&mut self, time: TimerDurationU32<FREQ>) {
113        let mut ticks = time.ticks();
114        if ticks > 1 {
115            ticks -= 1;
116        }
117        while ticks != 0 {
118            let reload = ticks.min(TIM::max_auto_reload());
119
120            // Write Auto-Reload Register (ARR)
121            unsafe {
122                self.tim.set_auto_reload_unchecked(reload);
123            }
124
125            // Trigger update event (UEV) in the event generation register (EGR)
126            // in order to immediately apply the config
127            self.tim.trigger_update();
128
129            // Configure the counter in one-pulse mode (counter stops counting at
130            // the next updateevent, clearing the CEN bit) and enable the counter.
131            self.tim.start_one_pulse();
132
133            // Update the tracking variable while we are waiting...
134            ticks -= reload;
135            // Wait for CEN bit to clear
136            while self.tim.is_counter_enabled() { /* wait */ }
137        }
138    }
139
140    pub fn max_delay(&self) -> TimerDurationU32<FREQ> {
141        TimerDurationU32::from_ticks(TIM::max_auto_reload())
142    }
143
144    /// Releases the TIM peripheral
145    pub fn release(mut self) -> FTimer<TIM, FREQ> {
146        // stop counter
147        self.tim.cr1_reset();
148        self.0
149    }
150}
151
152impl<TIM: Instance, const FREQ: u32> fugit_timer::Delay<FREQ> for Delay<TIM, FREQ> {
153    type Error = core::convert::Infallible;
154
155    fn delay(&mut self, duration: TimerDurationU32<FREQ>) -> Result<(), Self::Error> {
156        self.delay(duration);
157        Ok(())
158    }
159}
160
161impl fugit_timer::Delay<1_000_000> for SysDelay {
162    type Error = core::convert::Infallible;
163
164    fn delay(&mut self, duration: MicrosDurationU32) -> Result<(), Self::Error> {
165        self.delay(duration);
166        Ok(())
167    }
168}