stm32g0xx_hal/timer/
mod.rs

1//! Timers
2use crate::rcc::*;
3use crate::stm32::*;
4use crate::time::{Hertz, MicroSecond};
5use core::marker::PhantomData;
6use cortex_m::peripheral::syst::SystClkSource;
7use cortex_m::peripheral::SYST;
8use hal::timer::{CountDown, Periodic};
9use void::Void;
10
11pub mod delay;
12pub mod opm;
13pub mod pins;
14pub mod pwm;
15pub mod qei;
16pub mod stopwatch;
17
18/// Hardware timers
19pub struct Timer<TIM> {
20    clk: Hertz,
21    tim: TIM,
22}
23
24pub struct Channel1;
25pub struct Channel2;
26pub struct Channel3;
27pub struct Channel4;
28
29/// System timer
30impl Timer<SYST> {
31    /// Configures the SYST clock as a periodic count down timer
32    pub fn syst(mut syst: SYST, rcc: &mut Rcc) -> Self {
33        syst.set_clock_source(SystClkSource::Core);
34        Timer {
35            tim: syst,
36            clk: rcc.clocks.apb_tim_clk,
37        }
38    }
39
40    /// Starts listening
41    pub fn listen(&mut self) {
42        self.tim.enable_interrupt()
43    }
44
45    /// Stops listening
46    pub fn unlisten(&mut self) {
47        self.tim.disable_interrupt()
48    }
49
50    pub fn get_current(&self) -> u32 {
51        SYST::get_current()
52    }
53}
54
55impl Timer<SYST> {
56    pub fn start(&mut self, timeout: MicroSecond) {
57        let cycles = crate::time::cycles(timeout, self.clk);
58        assert!(cycles < 0x00ff_ffff);
59        self.tim.set_reload(cycles);
60        self.tim.clear_current();
61        self.tim.enable_counter();
62    }
63
64    pub fn wait(&mut self) -> nb::Result<(), Void> {
65        if self.tim.has_wrapped() {
66            Ok(())
67        } else {
68            Err(nb::Error::WouldBlock)
69        }
70    }
71}
72
73impl CountDown for Timer<SYST> {
74    type Time = MicroSecond;
75
76    fn start<T>(&mut self, timeout: T)
77    where
78        T: Into<MicroSecond>,
79    {
80        self.start(timeout.into())
81    }
82
83    fn wait(&mut self) -> nb::Result<(), Void> {
84        self.wait()
85    }
86}
87
88pub trait TimerExt<TIM> {
89    fn timer(self, rcc: &mut Rcc) -> Timer<TIM>;
90}
91
92impl TimerExt<SYST> for SYST {
93    fn timer(self, rcc: &mut Rcc) -> Timer<SYST> {
94        Timer::syst(self, rcc)
95    }
96}
97
98impl Periodic for Timer<SYST> {}
99
100macro_rules! timers {
101    ($($TIM:ident: ($tim:ident, $cnt:ident $(,$cnt_h:ident)*),)+) => {
102        $(
103            impl Timer<$TIM> {
104                /// Configures a TIM peripheral as a periodic count down timer
105                pub fn $tim(tim: $TIM, rcc: &mut Rcc) -> Self {
106                    $TIM::enable(rcc);
107                    $TIM::reset(rcc);
108
109                    Timer {
110                        tim,
111                        clk: rcc.clocks.apb_tim_clk,
112                    }
113                }
114
115                /// Pauses timer
116                pub fn pause(&mut self) {
117                    self.tim.cr1.modify(|_, w| w.cen().clear_bit());
118                }
119
120                /// Resumes timer
121                pub fn resume(&mut self) {
122                    self.tim.cr1.modify(|_, w| w.cen().set_bit());
123                }
124
125                /// Starts listening
126                pub fn listen(&mut self) {
127                    self.tim.dier.write(|w| w.uie().set_bit());
128                }
129
130                /// Stops listening
131                pub fn unlisten(&mut self) {
132                    self.tim.dier.write(|w| w.uie().clear_bit());
133                }
134
135                /// Clears interrupt flag
136                pub fn clear_irq(&mut self) {
137                    self.tim.sr.modify(|_, w| w.uif().clear_bit());
138                }
139
140                /// Resets counter value
141                pub fn reset(&mut self) {
142                    self.tim.cnt.reset();
143                }
144
145                /// Gets timer counter current value
146                pub fn get_current(&self) -> u32 {
147                    let _high = 0;
148                    $(
149                        let _high = self.tim.cnt.read().$cnt_h().bits() as u32;
150                    )*
151                    let low = self.tim.cnt.read().$cnt().bits() as u32;
152                    low | (_high << 16)
153                }
154
155                pub fn start(&mut self, timeout: MicroSecond) {
156                    // Pause the counter. Also set URS so that when we set UG below, it will
157                    // generate an update event *without* triggering an interrupt.
158                    self.tim.cr1.modify(|_, w| w.cen().clear_bit().urs().set_bit());
159                    // reset counter
160                    self.tim.cnt.reset();
161                    // clear interrupt flag
162                    self.tim.sr.modify(|_, w| w.uif().clear_bit());
163
164                    // Calculate counter configuration
165                    let cycles = crate::time::cycles(timeout, self.clk);
166                    let psc = cycles / 0xffff;
167                    let arr = cycles / (psc + 1);
168
169                    self.tim.psc.write(|w| unsafe { w.psc().bits(psc as u16) });
170                    self.tim.arr.write(|w| unsafe { w.bits(arr) });
171
172                    // Generate an update event so that PSC and ARR values are copied into their
173                    // shadow registers.
174                    self.tim.egr.write(|w| w.ug().set_bit());
175
176                    self.tim.cr1.modify(|_, w| w.cen().set_bit());
177                }
178
179                pub fn wait(&mut self) -> nb::Result<(), Void> {
180                    if self.tim.sr.read().uif().bit_is_clear() {
181                        Err(nb::Error::WouldBlock)
182                    } else {
183                        self.tim.sr.modify(|_, w| w.uif().clear_bit());
184                        Ok(())
185                    }
186                }
187
188                /// Releases the TIM peripheral
189                pub fn release(self) -> $TIM {
190                    self.tim
191                }
192            }
193
194            impl TimerExt<$TIM> for $TIM {
195                fn timer(self, rcc: &mut Rcc) -> Timer<$TIM> {
196                    Timer::$tim(self, rcc)
197                }
198            }
199
200            impl CountDown for Timer<$TIM> {
201                type Time = MicroSecond;
202
203                fn start<T>(&mut self, timeout: T)
204                where
205                    T: Into<MicroSecond>,
206                {
207                    self.start(timeout.into())
208                }
209
210                fn wait(&mut self) -> nb::Result<(), Void> {
211                    self.wait()
212                }
213            }
214
215            impl Periodic for Timer<$TIM> {}
216        )+
217    }
218}
219
220pub enum ExternalClockMode {
221    Mode1,
222    Mode2,
223}
224
225pub trait ExternalClock {
226    fn mode(&self) -> ExternalClockMode;
227}
228
229macro_rules! timers_external_clocks {
230    ($($TIM:ident: ($tim:ident, $sms:ident $(,$ece:ident)*),)+) => {
231        $(
232            impl Timer<$TIM> {
233                pub fn use_external_clock<C: ExternalClock>(&mut self, clk: C, freq: Hertz) {
234                    self.clk = freq;
235                    match clk.mode() {
236                        ExternalClockMode::Mode1 => {
237                            self.tim.smcr.modify(|_, w| unsafe { w.$sms().bits(0b111) });
238                            $(
239                                self.tim.smcr.modify(|_, w| w.$ece().clear_bit());
240                            )*
241                        },
242                        ExternalClockMode::Mode2 => {
243                            self.tim.smcr.modify(|_, w| unsafe { w.$sms().bits(0b0) });
244                            $(
245                                self.tim.smcr.modify(|_, w| w.$ece().set_bit());
246                            )*
247                        },
248                    }
249                }
250            }
251        )+
252    }
253}
254
255timers_external_clocks! {
256    TIM1: (tim1, sms, ece),
257    TIM3: (tim3, sms, ece),
258}
259
260#[cfg(feature = "stm32g0x1")]
261timers_external_clocks! {
262    TIM2: (tim2, sms, ece),
263}
264
265#[cfg(any(feature = "stm32g070", feature = "stm32g071"))]
266timers_external_clocks! {
267    TIM15: (tim15, sms1),
268}
269
270timers! {
271    TIM1: (tim1, cnt),
272    TIM3: (tim3, cnt_l, cnt_h),
273    TIM14: (tim14, cnt),
274    TIM16: (tim16, cnt),
275    TIM17: (tim17, cnt),
276}
277
278#[cfg(feature = "stm32g0x1")]
279timers! {
280    TIM2: (tim2, cnt_l, cnt_h),
281}
282
283#[cfg(any(feature = "stm32g070", feature = "stm32g071", feature = "stm32g081"))]
284timers! {
285    TIM6: (tim6, cnt),
286    TIM7: (tim7, cnt),
287    TIM15: (tim15, cnt),
288}