stm32f030_hal/
timers.rs

1use stm32::{RCC, TIM1, TIM14, TIM15, TIM16, TIM17, TIM3, TIM6, TIM7};
2
3use cast::{u16, u32};
4use hal::timer::{CountDown, Periodic};
5use nb;
6use rcc::Clocks;
7use void::Void;
8
9use time::Hertz;
10
11/// Hardware timers
12pub struct Timer<TIM> {
13    clocks: Clocks,
14    tim: TIM,
15    timeout: Hertz,
16}
17
18/// Interrupt events
19pub enum Event {
20    /// Timer timed out / count down ended
21    TimeOut,
22}
23
24macro_rules! timers {
25    ($($TIM:ident: ($tim:ident, $timXen:ident, $timXrst:ident, $apbenr:ident, $apbrstr:ident),)+) => {
26        $(
27            impl Periodic for Timer<$TIM> {}
28
29            impl CountDown for Timer<$TIM> {
30                type Time = Hertz;
31
32                // NOTE(allow) `w.psc().bits()` is safe for TIM{6,7} but not for TIM{2,3,4} due to
33                // some SVD omission
34                #[allow(unused_unsafe)]
35                fn start<T>(&mut self, timeout: T)
36                where
37                    T: Into<Hertz>,
38                {
39                    // pause
40                    self.tim.cr1.modify(|_, w| w.cen().clear_bit());
41                    // restart counter
42                    self.tim.cnt.reset();
43
44                    self.timeout = timeout.into();
45
46                    let frequency = self.timeout.0;
47                    let ticks = self.clocks.pclk().0 / frequency;
48
49                    let psc = u16((ticks - 1) / (1 << 16)).unwrap();
50                    self.tim.psc.write(|w| unsafe { w.psc().bits(psc) });
51
52                    let arr = u16(ticks / u32(psc + 1)).unwrap();
53                    self.tim.arr.write(|w| unsafe { w.bits(u32(arr)) });
54
55                    // start counter
56                    self.tim.cr1.modify(|_, w| w.cen().set_bit());
57                }
58
59                fn wait(&mut self) -> nb::Result<(), Void> {
60                    if self.tim.sr.read().uif().bit_is_clear() {
61                        Err(nb::Error::WouldBlock)
62                    } else {
63                        self.tim.sr.modify(|_, w| w.uif().clear_bit());
64                        Ok(())
65                    }
66                }
67            }
68
69            impl Timer<$TIM> {
70                // XXX(why not name this `new`?) bummer: constructors need to have different names
71                // even if the `$TIM` are non overlapping (compare to the `free` function below
72                // which just works)
73                /// Configures a TIM peripheral as a periodic count down timer
74                pub fn $tim<T>(tim: $TIM, timeout: T, clocks: Clocks) -> Self
75                where
76                    T: Into<Hertz>,
77                {
78                    // NOTE(unsafe) This executes only during initialisation
79                    let rcc = unsafe { &(*RCC::ptr()) };
80                    // enable and reset peripheral to a clean slate state
81                    rcc.$apbenr.modify(|_, w| w.$timXen().set_bit());
82                    rcc.$apbrstr.modify(|_, w| w.$timXrst().set_bit());
83                    rcc.$apbrstr.modify(|_, w| w.$timXrst().clear_bit());
84
85                    let mut timer = Timer {
86                        clocks,
87                        tim,
88                        timeout: Hertz(0),
89                    };
90                    timer.start(timeout);
91
92                    timer
93                }
94
95                /// Starts listening for an `event`
96                pub fn listen(&mut self, event: Event) {
97                    match event {
98                        Event::TimeOut => {
99                            // Enable update event interrupt
100                            self.tim.dier.write(|w| w.uie().set_bit());
101                        }
102                    }
103                }
104
105                /// Stops listening for an `event`
106                pub fn unlisten(&mut self, event: Event) {
107                    match event {
108                        Event::TimeOut => {
109                            // Enable update event interrupt
110                            self.tim.dier.write(|w| w.uie().clear_bit());
111                        }
112                    }
113                }
114
115                /// Releases the TIM peripheral
116                pub fn free(self) -> $TIM {
117                    // pause counter
118                    self.tim.cr1.modify(|_, w| w.cen().clear_bit());
119                    self.tim
120                }
121            }
122        )+
123    }
124}
125
126#[cfg(any(
127    feature = "stm32f030f4",
128    feature = "stm32f030k6",
129    feature = "stm32f030c6",
130    feature = "stm32f030c8",
131    feature = "stm32f030r8",
132    feature = "stm32f030cc",
133    feature = "stm32f030rc"
134))]
135timers! {
136    TIM1: (tim1, tim1en, tim1rst, apb2enr, apb2rstr),
137    TIM3: (tim3, tim3en, tim3rst, apb1enr, apb1rstr),
138    TIM14: (tim14, tim14en, tim14rst, apb1enr, apb1rstr),
139    TIM16: (tim16, tim16en, tim16rst, apb2enr, apb2rstr),
140    TIM17: (tim17, tim17en, tim17rst, apb2enr, apb2rstr),
141}
142
143#[cfg(any(
144    feature = "stm32f030c8",
145    feature = "stm32f030r8",
146    feature = "stm32f030cc",
147    feature = "stm32f030rc"
148))]
149timers! {
150    TIM6: (tim6, tim6en, tim6rst, apb1enr, apb1rstr),
151    TIM15: (tim15, tim15en, tim15rst, apb2enr, apb2rstr),
152}
153
154#[cfg(any(feature = "stm32f030cc", feature = "stm32f030rc"))]
155timers! {
156    TIM7: (tim7, tim7en, tim7rst, apb1enr, apb1rstr),
157}