stm32l4xx_hal/
delay.rs

1//! Delays
2
3use cast::u32;
4use cortex_m::asm;
5use cortex_m::peripheral::syst::SystClkSource;
6use cortex_m::peripheral::SYST;
7
8use crate::hal::blocking::delay::{DelayMs, DelayUs};
9use crate::rcc::Clocks;
10use crate::time::Hertz;
11
12/// System timer (SysTick) as a delay provider
13pub struct Delay {
14    clocks: Clocks,
15    syst: SYST,
16}
17
18impl Delay {
19    /// Configures the system timer (SysTick) as a delay provider
20    pub fn new(mut syst: SYST, clocks: Clocks) -> Self {
21        syst.set_clock_source(SystClkSource::Core);
22
23        Delay { syst, clocks }
24    }
25
26    /// Releases the system timer (SysTick) resource
27    pub fn free(self) -> SYST {
28        self.syst
29    }
30}
31
32/// System timer (SysTick) as a delay provider.
33impl DelayMs<u32> for Delay {
34    fn delay_ms(&mut self, ms: u32) {
35        self.delay_us(ms * 1_000);
36    }
37}
38
39impl DelayMs<u16> for Delay {
40    fn delay_ms(&mut self, ms: u16) {
41        self.delay_ms(u32(ms));
42    }
43}
44
45impl DelayMs<u8> for Delay {
46    fn delay_ms(&mut self, ms: u8) {
47        self.delay_ms(u32(ms));
48    }
49}
50
51impl DelayUs<u32> for Delay {
52    fn delay_us(&mut self, us: u32) {
53        // The SysTick Reload Value register supports values between 1 and 0x00FFFFFF.
54        const MAX_RVR: u32 = 0x00FF_FFFF;
55
56        let mut total_rvr = us * (self.clocks.hclk().raw() / 1_000_000);
57
58        while total_rvr != 0 {
59            let current_rvr = if total_rvr <= MAX_RVR {
60                total_rvr
61            } else {
62                MAX_RVR
63            };
64
65            self.syst.set_reload(current_rvr);
66            self.syst.clear_current();
67            self.syst.enable_counter();
68
69            // Update the tracking variable while we are waiting...
70            total_rvr -= current_rvr;
71
72            while !self.syst.has_wrapped() {}
73
74            self.syst.disable_counter();
75        }
76    }
77}
78
79impl DelayUs<u16> for Delay {
80    fn delay_us(&mut self, us: u16) {
81        self.delay_us(u32(us))
82    }
83}
84
85impl DelayUs<u8> for Delay {
86    fn delay_us(&mut self, us: u8) {
87        self.delay_us(u32(us))
88    }
89}
90
91/// Cortex-M `asm::delay` as provider
92#[derive(Clone, Copy)]
93pub struct DelayCM {
94    sysclk: Hertz,
95}
96
97impl DelayCM {
98    /// Create a new delay
99    pub fn new(clocks: Clocks) -> Self {
100        DelayCM {
101            sysclk: clocks.sysclk(),
102        }
103    }
104
105    /// Create a new delay that is unchecked. The user needs to know the `sysclk`.
106    ///
107    /// # Safety
108    /// Sysclk must be the same as the actual clock frequency of the chip
109    pub unsafe fn new_unchecked(sysclk: Hertz) -> Self {
110        DelayCM { sysclk }
111    }
112}
113
114impl DelayMs<u32> for DelayCM {
115    fn delay_ms(&mut self, ms: u32) {
116        self.delay_us(ms * 1_000);
117    }
118}
119
120impl DelayMs<u16> for DelayCM {
121    fn delay_ms(&mut self, ms: u16) {
122        self.delay_ms(u32(ms));
123    }
124}
125
126impl DelayMs<u8> for DelayCM {
127    fn delay_ms(&mut self, ms: u8) {
128        self.delay_ms(u32(ms));
129    }
130}
131
132impl DelayUs<u32> for DelayCM {
133    fn delay_us(&mut self, us: u32) {
134        // Max delay is 53_687_091 us at 80 MHz
135        let ticks = self.sysclk.raw() / 1_000_000;
136
137        asm::delay(ticks * us);
138    }
139}
140
141impl DelayUs<u16> for DelayCM {
142    fn delay_us(&mut self, us: u16) {
143        self.delay_us(u32(us))
144    }
145}
146
147impl DelayUs<u8> for DelayCM {
148    fn delay_us(&mut self, us: u8) {
149        self.delay_us(u32(us))
150    }
151}