1use cast::{u16, u32};
4use cortex_m::peripheral::syst::SystClkSource;
5use cortex_m::peripheral::SYST;
6use embedded_hal::timer::{CountDown, Periodic};
7use nb;
8use void::Void;
9
10use crate::stm32::RCC;
11
12use crate::stm32::{
13 TIM1, TIM10, TIM11, TIM12, TIM13, TIM14, TIM2, TIM3, TIM4, TIM5, TIM6, TIM7, TIM8, TIM9,
14};
15
16use crate::rcc::Clocks;
17use crate::time::Hertz;
18
19pub struct Timer<TIM> {
21 clocks: Clocks,
22 tim: TIM,
23}
24
25pub enum Event {
27 TimeOut,
29}
30
31impl Timer<SYST> {
32 pub fn syst<T>(mut syst: SYST, timeout: T, clocks: Clocks) -> Self
34 where
35 T: Into<Hertz>,
36 {
37 syst.set_clock_source(SystClkSource::Core);
38 let mut timer = Timer { tim: syst, clocks };
39 timer.start(timeout);
40 timer
41 }
42
43 pub fn listen(&mut self, event: Event) {
45 match event {
46 Event::TimeOut => self.tim.enable_interrupt(),
47 }
48 }
49
50 pub fn unlisten(&mut self, event: Event) {
52 match event {
53 Event::TimeOut => self.tim.disable_interrupt(),
54 }
55 }
56}
57
58impl CountDown for Timer<SYST> {
59 type Time = Hertz;
60
61 fn start<T>(&mut self, timeout: T)
62 where
63 T: Into<Hertz>,
64 {
65 let rvr = self.clocks.sysclk().0 / timeout.into().0 - 1;
66
67 assert!(rvr < (1 << 24));
68
69 self.tim.set_reload(rvr);
70 self.tim.clear_current();
71 self.tim.enable_counter();
72 }
73
74 fn wait(&mut self) -> nb::Result<(), Void> {
75 if self.tim.has_wrapped() {
76 Ok(())
77 } else {
78 Err(nb::Error::WouldBlock)
79 }
80 }
81}
82
83impl Periodic for Timer<SYST> {}
84
85macro_rules! hal {
86 ($($TIM:ident: ($tim:ident, $timXen:ident, $timXrst:ident, $apbenr:ident, $apbrstr:ident, $pclk:ident, $ppre:ident),)+) => {
87 $(
88 impl Timer<$TIM> {
89 pub fn $tim<T>(tim: $TIM, timeout: T, clocks: Clocks) -> Self
91 where
92 T: Into<Hertz>,
93 {
94 let rcc = unsafe { &(*RCC::ptr()) };
96 rcc.$apbenr.modify(|_, w| w.$timXen().set_bit());
97 rcc.$apbrstr.modify(|_, w| w.$timXrst().set_bit());
98 rcc.$apbrstr.modify(|_, w| w.$timXrst().clear_bit());
99
100 let mut timer = Timer {
101 clocks,
102 tim,
103 };
104 timer.start(timeout);
105
106 timer
107 }
108
109 pub fn listen(&mut self, event: Event) {
111 match event {
112 Event::TimeOut => {
113 self.tim.dier.write(|w| w.uie().set_bit());
115 }
116 }
117 }
118
119 pub fn unlisten(&mut self, event: Event) {
121 match event {
122 Event::TimeOut => {
123 self.tim.dier.write(|w| w.uie().clear_bit());
125 }
126 }
127 }
128
129 pub fn release(self) -> $TIM {
131 self.tim.cr1.modify(|_, w| w.cen().clear_bit());
133 self.tim
134 }
135 }
136
137 impl CountDown for Timer<$TIM> {
138 type Time = Hertz;
139
140 fn start<T>(&mut self, timeout: T)
141 where
142 T: Into<Hertz>,
143 {
144 self.tim.cr1.modify(|_, w| w.cen().clear_bit());
146 self.tim.cnt.reset();
148
149 let frequency = timeout.into().0;
150 let pclk_mul = if self.clocks.$ppre() == 1 { 1 } else { 2 };
151 let ticks = self.clocks.$pclk().0 * pclk_mul / frequency;
152
153 let psc = u16((ticks - 1) / (1 << 16)).unwrap();
154 self.tim.psc.write(|w| unsafe { w.psc().bits(psc) });
155
156 let arr = u16(ticks / u32(psc + 1)).unwrap();
157 self.tim.arr.write(|w| unsafe { w.bits(u32(arr)) });
158
159 self.tim.cr1.modify(|_, w| w.cen().set_bit());
161 }
162
163 fn wait(&mut self) -> nb::Result<(), Void> {
164 if self.tim.sr.read().uif().bit_is_clear() {
165 Err(nb::Error::WouldBlock)
166 } else {
167 self.tim.sr.modify(|_, w| w.uif().clear_bit());
168 Ok(())
169 }
170 }
171 }
172
173 impl Periodic for Timer<$TIM> {}
174 )+
175 }
176}
177
178hal! {
179 TIM1: (tim1, tim1en, tim1rst, apb2enr, apb2rstr, pclk2, ppre2),
180 TIM5: (tim5, tim5en, tim5rst, apb1enr, apb1rstr, pclk1, ppre1),
181 TIM9: (tim9, tim9en, tim9rst, apb2enr, apb2rstr, pclk1, ppre1),
182 TIM11: (tim11, tim11en, tim11rst, apb2enr, apb2rstr, pclk2, ppre2),
183 TIM2: (tim2, tim2en, tim2rst, apb1enr, apb1rstr, pclk1, ppre1),
184 TIM3: (tim3, tim3en, tim3rst, apb1enr, apb1rstr, pclk1, ppre1),
185 TIM4: (tim4, tim4en, tim4rst, apb1enr, apb1rstr, pclk1, ppre1),
186 TIM10: (tim10, tim10en, tim10rst, apb2enr, apb2rstr, pclk2, ppre2),
187 TIM6: (tim6, tim6en, tim6rst, apb1enr, apb1rstr, pclk1, ppre1),
188 TIM7: (tim7, tim7en, tim7rst, apb1enr, apb1rstr, pclk1, ppre1),
189 TIM8: (tim8, tim8en, tim8rst, apb2enr, apb2rstr, pclk2, ppre2),
190 TIM12: (tim12, tim12en, tim12rst, apb1enr, apb1rstr, pclk1, ppre1),
191 TIM13: (tim13, tim13en, tim13rst, apb1enr, apb1rstr, pclk1, ppre1),
192 TIM14: (tim14, tim14en, tim14rst, apb1enr, apb1rstr, pclk1, ppre1),
193}