stm32f3xx_hal/
delay.rs

1//! # Delays
2//!
3//! Implementations for the [`DelayMs`] and [`DelayUs`] traits
4//!
5//! [DelayMs]: embedded_hal::blocking::delay::DelayMs
6//! [DelayUs]: embedded_hal::blocking::delay::DelayUs
7
8use core::convert::From;
9use core::fmt;
10
11use cortex_m::peripheral::syst::SystClkSource;
12use cortex_m::peripheral::SYST;
13
14use crate::hal::blocking::delay::{DelayMs, DelayUs};
15use crate::rcc::Clocks;
16use crate::time::duration::{Microseconds, Milliseconds};
17use crate::time::fixed_point::FixedPoint;
18
19/// System timer (`SysTick`) as a delay provider
20pub struct Delay {
21    clocks: Clocks,
22    syst: SYST,
23}
24
25#[cfg(feature = "defmt")]
26impl defmt::Format for Delay {
27    fn format(&self, f: defmt::Formatter) {
28        defmt::write!(f, "Delay {{ clocks: {} , syst: SYST }}", self.clocks);
29    }
30}
31
32impl fmt::Debug for Delay {
33    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34        f.debug_struct("Delay")
35            .field("clocks", &self.clocks)
36            .field("syst", &"SYST")
37            .finish()
38    }
39}
40
41impl Delay {
42    /// Configures the system timer (`SysTick`) as a delay provider
43    ///
44    /// # Limitations
45    ///
46    /// Depending on the core clock, this delay provider
47    /// can delay between 1 minute (for 72 Mhz) up to almost 9 minutes (for 8 Mhz).
48    /// Higher input values will be capped to these limits.
49    ///
50    /// For accuracy purposes and because this is a blocking, busy-waiting function,
51    /// if delays in the second to minute range are needed, use timers instead.
52    #[must_use]
53    pub fn new(mut syst: SYST, clocks: Clocks) -> Self {
54        syst.set_clock_source(SystClkSource::Core);
55
56        Delay { clocks, syst }
57    }
58
59    /// Get access to the underlying register block.
60    ///
61    /// # Safety
62    ///
63    /// This function is not _memory_ unsafe per se, but does not guarantee
64    /// anything about assumptions of invariants made in this implementation.
65    ///
66    /// Changing specific options can lead to un-expected behavior and nothing
67    /// is guaranteed.
68    pub unsafe fn peripheral(&mut self) -> &mut SYST {
69        &mut self.syst
70    }
71
72    /// Releases the system timer (`SysTick`) resource
73    #[must_use]
74    pub fn free(self) -> SYST {
75        self.syst
76    }
77}
78
79impl DelayMs<u32> for Delay {
80    fn delay_ms(&mut self, ms: u32) {
81        self.delay_us(ms.saturating_mul(1_000));
82    }
83}
84
85impl DelayMs<u16> for Delay {
86    fn delay_ms(&mut self, ms: u16) {
87        self.delay_ms(u32::from(ms));
88    }
89}
90
91impl DelayMs<u8> for Delay {
92    fn delay_ms(&mut self, ms: u8) {
93        self.delay_ms(u32::from(ms));
94    }
95}
96
97impl DelayUs<u32> for Delay {
98    fn delay_us(&mut self, us: u32) {
99        // The SysTick Reload Value register supports values between 1 and 0x00FFFFFF.
100        const MAX_RVR: u32 = 0x00FF_FFFF;
101
102        // Depending on hclk (core clock), this 32 bit value allows
103        // delays between 1 min to 9 min.
104        //
105        // (((32^2) - 1) / 72) µs ~ 59.6 seconds
106        // (((32^2) - 1) / 8) µs  ~ 536.8 seconds
107        let mut total_rvr = us.saturating_mul(self.clocks.hclk().0 / 1_000_000);
108
109        // Use the full 32 bit range to allow longer delays
110        //
111        // Like dividing total_rvr / MAX_RVR
112        // and delaying by MAX_RVR * (fraction).
113        while total_rvr != 0 {
114            let current_rvr = if total_rvr <= MAX_RVR {
115                total_rvr
116            } else {
117                MAX_RVR
118            };
119
120            self.syst.set_reload(current_rvr);
121            self.syst.clear_current();
122            self.syst.enable_counter();
123
124            // Update the tracking variable while we are waiting...
125            total_rvr -= current_rvr;
126
127            while !self.syst.has_wrapped() {}
128
129            self.syst.disable_counter();
130        }
131    }
132}
133
134impl DelayUs<u16> for Delay {
135    fn delay_us(&mut self, us: u16) {
136        self.delay_us(u32::from(us));
137    }
138}
139
140impl DelayUs<u8> for Delay {
141    fn delay_us(&mut self, us: u8) {
142        self.delay_us(u32::from(us));
143    }
144}
145
146impl DelayUs<Microseconds> for Delay {
147    fn delay_us(&mut self, us: Microseconds) {
148        self.delay_us(us.integer());
149    }
150}
151
152impl DelayMs<Milliseconds> for Delay {
153    fn delay_ms(&mut self, ms: Milliseconds) {
154        self.delay_ms(ms.integer());
155    }
156}