stm32g0xx_hal/timer/
delay.rs

1//! Delays
2use core::cmp;
3use cortex_m::peripheral::{syst::SystClkSource, SYST};
4use fugit::ExtU32;
5use hal::blocking::delay::{DelayMs, DelayUs};
6
7use crate::rcc::*;
8use crate::stm32::*;
9use crate::time::{Hertz, MicroSecond};
10
11/// Delay provider
12pub struct Delay<TIM> {
13    clk: Hertz,
14    tim: TIM,
15}
16
17pub trait DelayExt<TIM> {
18    fn delay(self, rcc: &mut Rcc) -> Delay<TIM>;
19}
20
21impl Delay<SYST> {
22    /// Configures the system timer (SysTick) as a delay provider
23    pub fn syst(mut syst: SYST, rcc: &Rcc) -> Self {
24        let clk = match syst.get_clock_source() {
25            SystClkSource::Core => rcc.clocks.ahb_clk,
26            SystClkSource::External => rcc.clocks.core_clk,
27        };
28        Delay { tim: syst, clk }
29    }
30
31    pub fn delay(&mut self, delay: MicroSecond) {
32        let mut cycles = crate::time::cycles(delay, self.clk);
33        while cycles > 0 {
34            let reload = cmp::min(cycles, 0x00ff_ffff);
35            cycles -= reload;
36            self.tim.set_reload(reload);
37            self.tim.clear_current();
38            self.tim.enable_counter();
39            while !self.tim.has_wrapped() {}
40            self.tim.disable_counter();
41        }
42    }
43
44    /// Releases the system timer (SysTick) resource
45    pub fn release(self) -> SYST {
46        self.tim
47    }
48}
49
50impl DelayUs<u32> for Delay<SYST> {
51    fn delay_us(&mut self, us: u32) {
52        self.delay(us.micros())
53    }
54}
55
56impl DelayUs<u16> for Delay<SYST> {
57    fn delay_us(&mut self, us: u16) {
58        self.delay_us(us as u32)
59    }
60}
61
62impl DelayUs<u8> for Delay<SYST> {
63    fn delay_us(&mut self, us: u8) {
64        self.delay_us(us as u32)
65    }
66}
67
68impl DelayMs<u32> for Delay<SYST> {
69    fn delay_ms(&mut self, ms: u32) {
70        self.delay_us(ms.saturating_mul(1_000));
71    }
72}
73
74impl DelayMs<u16> for Delay<SYST> {
75    fn delay_ms(&mut self, ms: u16) {
76        self.delay_ms(ms as u32);
77    }
78}
79
80impl DelayMs<u8> for Delay<SYST> {
81    fn delay_ms(&mut self, ms: u8) {
82        self.delay_ms(ms as u32);
83    }
84}
85
86impl DelayExt<SYST> for SYST {
87    fn delay(self, rcc: &mut Rcc) -> Delay<SYST> {
88        Delay::syst(self, rcc)
89    }
90}
91
92macro_rules! delays {
93    ($($TIM:ident: $tim:ident,)+) => {
94        $(
95            impl Delay<$TIM> {
96                /// Configures $TIM timer as a delay provider
97                pub fn $tim(tim: $TIM, rcc: &mut Rcc) -> Self {
98                    $TIM::enable(rcc);
99                    $TIM::reset(rcc);
100
101                    Delay {
102                        tim,
103                        clk: rcc.clocks.apb_tim_clk,
104                    }
105                }
106
107                pub fn delay(&mut self, delay: MicroSecond) {
108                    let mut cycles = crate::time::cycles(delay, self.clk);
109                    while cycles > 0 {
110                        let reload = cmp::min(cycles, 0xffff);
111                        cycles -= reload;
112                        self.tim.arr.write(|w| unsafe { w.bits(reload) });
113                        self.tim.cnt.reset();
114                        self.tim.cr1.modify(|_, w| w.cen().set_bit().urs().set_bit());
115                        while self.tim.sr.read().uif().bit_is_clear() {}
116                        self.tim.sr.modify(|_, w| w.uif().clear_bit());
117                        self.tim.cr1.modify(|_, w| w.cen().clear_bit());
118                    }
119                }
120
121                pub fn release(self) -> $TIM {
122                    self.tim
123                }
124            }
125
126            impl DelayUs<u32> for Delay<$TIM> {
127                fn delay_us(&mut self, us: u32) {
128                    self.delay(us.micros())
129                }
130            }
131
132            impl DelayUs<u16> for Delay<$TIM> {
133                fn delay_us(&mut self, us: u16) {
134                    self.delay_us(us as u32)
135                }
136            }
137
138            impl DelayUs<u8> for Delay<$TIM> {
139                fn delay_us(&mut self, us: u8) {
140                    self.delay_us(us as u32)
141                }
142            }
143
144            impl DelayMs<u32> for Delay<$TIM> {
145                fn delay_ms(&mut self, ms: u32) {
146                    self.delay_us(ms.saturating_mul(1_000));
147                }
148            }
149
150            impl DelayMs<u16> for Delay<$TIM> {
151                fn delay_ms(&mut self, ms: u16) {
152                    self.delay_ms(ms as u32);
153                }
154            }
155
156            impl DelayMs<u8> for Delay<$TIM> {
157                fn delay_ms(&mut self, ms: u8) {
158                    self.delay_ms(ms as u32);
159                }
160            }
161
162            impl DelayExt<$TIM> for $TIM {
163                fn delay(self, rcc: &mut Rcc) -> Delay<$TIM> {
164                    Delay::$tim(self, rcc)
165                }
166            }
167        )+
168    }
169}
170
171delays! {
172    TIM1: tim1,
173    TIM3: tim3,
174    TIM14: tim14,
175    TIM16: tim16,
176    TIM17: tim17,
177}
178
179#[cfg(feature = "stm32g0x1")]
180delays! {
181    TIM2: tim2,
182}
183
184#[cfg(any(feature = "stm32g070", feature = "stm32g071", feature = "stm32g081"))]
185delays! {
186    TIM6: tim6,
187    TIM7: tim7,
188    TIM15: tim15,
189}