1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
//! Timers
use crate::hal::timer::{CountDown, Periodic};
use crate::pac::{tim2, tim21, tim22, tim6, TIM2, TIM21, TIM22, TIM3, TIM6};
use crate::rcc::{Clocks, Enable, Rcc, Reset};
use cast::{u16, u32};
use cortex_m::peripheral::syst::SystClkSource;
use cortex_m::peripheral::SYST;
use embedded_time::rate::Hertz;
use void::Void;
pub trait TimerExt<TIM> {
fn timer<T>(self, timeout: T, rcc: &mut Rcc) -> Timer<TIM>
where
T: Into<Hertz>;
}
/// Hardware timers
pub struct Timer<TIM> {
clocks: Clocks,
tim: TIM,
}
impl Timer<SYST> {
/// Configures the SYST clock as a periodic count down timer
pub fn syst<T>(mut syst: SYST, timeout: T, rcc: &mut Rcc) -> Self
where
T: Into<Hertz>,
{
syst.set_clock_source(SystClkSource::Core);
let mut timer = Timer {
tim: syst,
clocks: rcc.clocks,
};
timer.start(timeout);
timer
}
/// Starts listening
pub fn listen(&mut self) {
self.tim.enable_interrupt()
}
/// Stops listening
pub fn unlisten(&mut self) {
self.tim.disable_interrupt()
}
}
impl CountDown for Timer<SYST> {
type Time = Hertz;
fn start<T>(&mut self, timeout: T)
where
T: Into<Hertz>,
{
let rvr = self.clocks.sys_clk().0 / timeout.into().0 - 1;
assert!(rvr < (1 << 24));
self.tim.set_reload(rvr);
self.tim.clear_current();
self.tim.enable_counter();
}
fn wait(&mut self) -> nb::Result<(), Void> {
if self.tim.has_wrapped() {
Ok(())
} else {
Err(nb::Error::WouldBlock)
}
}
}
impl TimerExt<SYST> for SYST {
fn timer<T>(self, timeout: T, rcc: &mut Rcc) -> Timer<SYST>
where
T: Into<Hertz>,
{
Timer::syst(self, timeout, rcc)
}
}
impl Periodic for Timer<SYST> {}
/// Trait for general purpose timer peripherals
pub trait GeneralPurposeTimer: Enable + Reset {
type MasterMode;
/// Selects the master mode for this timer
fn select_master_mode(&mut self, variant: Self::MasterMode);
}
impl<T: GeneralPurposeTimer> Timer<T> {
pub fn new(tim: T, rcc: &mut Rcc) -> Self {
T::enable(rcc);
T::reset(rcc);
Timer {
tim,
clocks: rcc.clocks,
}
}
}
macro_rules! timers {
($($TIM:ident: ($tim:ident, $timclk:ident, $mms:ty),)+) => {
$(
impl TimerExt<$TIM> for $TIM {
fn timer<T>(self, timeout: T, rcc: &mut Rcc) -> Timer<$TIM>
where
T: Into<Hertz>,
{
Timer::$tim(self, timeout, rcc)
}
}
impl Timer<$TIM> where $TIM: GeneralPurposeTimer {
/// Configures a TIM peripheral as a periodic count down timer
pub fn $tim<T>(tim: $TIM, timeout: T, rcc: &mut Rcc) -> Self
where
T: Into<Hertz>,
{
let mut timer = Timer::new(tim, rcc);
timer.start(timeout);
timer
}
/// Starts listening
pub fn listen(&mut self) {
self.tim.dier.write(|w| w.uie().set_bit());
}
/// Stops listening
pub fn unlisten(&mut self) {
self.tim.dier.write(|w| w.uie().clear_bit());
}
/// Clears interrupt flag
pub fn clear_irq(&mut self) {
self.tim.sr.write(|w| w.uif().clear_bit());
}
/// Releases the TIM peripheral
pub fn release(self) -> $TIM {
self.tim.cr1.modify(|_, w| w.cen().clear_bit());
self.tim
}
/// Reset counter
pub fn reset(&mut self) {
// pause
self.tim.cr1.modify(|_, w| w.cen().clear_bit());
// reset counter
self.tim.cnt.reset();
// continue
self.tim.cr1.modify(|_, w| w.cen().set_bit());
}
/// Select master mode
pub fn select_master_mode(&mut self,
variant: <$TIM as GeneralPurposeTimer>::MasterMode,
) {
self.tim.select_master_mode(variant);
}
}
impl CountDown for Timer<$TIM> {
type Time = Hertz;
fn start<T>(&mut self, timeout: T)
where
T: Into<Hertz>,
{
// pause
self.tim.cr1.modify(|_, w| w.cen().clear_bit());
// reset counter
self.tim.cnt.reset();
let freq = timeout.into().0;
let ticks = self.clocks.$timclk().0 / freq;
let psc = u16((ticks - 1) / (1 << 16)).unwrap();
self.tim.psc.write(|w| w.psc().bits(psc));
// This is only unsafe for some timers, so we need this to
// suppress the warnings.
#[allow(unused_unsafe)]
self.tim.arr.write(|w|
unsafe {
w.arr().bits(u16(ticks / u32(psc + 1)).unwrap())
}
);
// Load prescaler value and reset its counter.
// Setting URS makes sure no interrupt is generated.
self.tim.cr1.modify(|_, w| w.urs().set_bit());
self.tim.egr.write(|w| w.ug().set_bit());
self.tim.cr1.modify(|_, w| w.cen().set_bit());
}
fn wait(&mut self) -> nb::Result<(), Void> {
if self.tim.sr.read().uif().bit_is_clear() {
Err(nb::Error::WouldBlock)
} else {
self.tim.sr.modify(|_, w| w.uif().clear_bit());
Ok(())
}
}
}
impl Periodic for Timer<$TIM> {}
impl GeneralPurposeTimer for $TIM {
type MasterMode = $mms;
fn select_master_mode(&mut self, variant: Self::MasterMode) {
self.cr2.modify(|_, w| w.mms().variant(variant));
}
}
)+
}
}
/// Two linked 16 bit timers that form a 32 bit timer.
pub trait LinkedTimer {
/// Return the current 16 bit counter value of the MSB timer.
fn get_counter_msb(&self) -> u16;
/// Return the current 16 bit counter value of the LSB timer.
fn get_counter_lsb(&self) -> u16;
/// Return the current 32 bit counter value.
fn get_counter(&self) -> u32;
/// Reset the counter to 0.
fn reset(&mut self);
}
/// A pair of timers that can be linked.
///
/// The two timers are configured so that an overflow of the primary timer
/// triggers an update on the secondary timer. This way, two 16 bit timers can
/// be combined to a single 32 bit timer.
pub struct LinkedTimerPair<PRIMARY, SECONDARY> {
/// Timer in primary mode
tim_primary: PRIMARY,
/// Timer in secondary mode
tim_secondary: SECONDARY,
}
macro_rules! linked_timers {
($(
($PRIMARY:ident, $SECONDARY:ident): (
$new:ident,
$mms:ty, $sms:ty, $ts:expr
),
)+) => {
$(
impl LinkedTimerPair<$PRIMARY, $SECONDARY> {
/// Create and configure a new `LinkedTimerPair` with the
/// specified timers.
pub fn $new(tim_primary: $PRIMARY, tim_secondary: $SECONDARY, rcc: &mut Rcc) -> Self {
// Enable timers
<$PRIMARY>::enable(rcc);
<$SECONDARY>::enable(rcc);
// Reset timers
<$PRIMARY>::reset(rcc);
<$SECONDARY>::reset(rcc);
// Enable counter
tim_primary.cr1.modify(|_, w| w.cen().set_bit());
tim_secondary.cr1.modify(|_, w| w.cen().set_bit());
// In the MMS (Master Mode Selection) register, set the master mode so
// that a rising edge is output on the trigger output TRGO every time
// an update event is generated.
tim_primary.cr2.modify(|_, w| w.mms().variant(<$mms>::Update));
// In the SMCR (Slave Mode Control Register), select the
// appropriate internal trigger source (TS).
tim_secondary.smcr.modify(|_, w| w.ts().variant($ts));
// Set the SMS (Slave Mode Selection) register to "external clock mode 1",
// where the rising edges of the selected trigger (TRGI) clock the counter.
tim_secondary.smcr.modify(|_, w| w.sms().variant(<$sms>::ExtClockMode));
Self { tim_primary, tim_secondary }
}
}
impl LinkedTimer for LinkedTimerPair<$PRIMARY, $SECONDARY> {
/// Return the current 16 bit counter value of the primary timer (LSB).
fn get_counter_lsb(&self) -> u16 {
self.tim_primary.cnt.read().cnt().bits()
}
/// Return the current 16 bit counter value of the secondary timer (MSB).
fn get_counter_msb(&self) -> u16 {
self.tim_secondary.cnt.read().cnt().bits()
}
/// Return the current 32 bit counter value.
///
/// Note: Due to the potential for a race condition between
/// reading MSB and LSB, it's possible that the registers must
/// be re-read once. Therefore reading the counter value is not
/// constant time.
fn get_counter(&self) -> u32 {
loop {
let msb = self.tim_secondary.cnt.read().cnt().bits() as u32;
let lsb = self.tim_primary.cnt.read().cnt().bits() as u32;
// Because the timer is still running at high frequency
// between reading MSB and LSB, it's possible that LSB
// has already overflowed. Therefore we read MSB again
// to check that it hasn't changed.
let msb_again = self.tim_secondary.cnt.read().cnt().bits() as u32;
if msb == msb_again {
return (msb << 16) | lsb;
}
}
}
fn reset(&mut self) {
// Pause
self.tim_primary.cr1.modify(|_, w| w.cen().clear_bit());
self.tim_secondary.cr1.modify(|_, w| w.cen().clear_bit());
// Reset counter
self.tim_primary.cnt.reset();
self.tim_secondary.cnt.reset();
// Continue
self.tim_secondary.cr1.modify(|_, w| w.cen().set_bit());
self.tim_primary.cr1.modify(|_, w| w.cen().set_bit());
}
}
)+
}
}
timers! {
TIM2: (tim2, apb1_tim_clk, tim2::cr2::MMS_A),
TIM3: (tim3, apb1_tim_clk, tim2::cr2::MMS_A),
TIM6: (tim6, apb1_tim_clk, tim6::cr2::MMS_A),
TIM21: (tim21, apb2_tim_clk, tim21::cr2::MMS_A),
TIM22: (tim22, apb2_tim_clk, tim22::cr2::MMS_A),
}
linked_timers! {
// Internal trigger connection: RM0377 table 76
(TIM2, TIM3): (tim2_tim3, tim2::cr2::MMS_A, tim2::smcr::SMS_A, tim2::smcr::TS_A::Itr0),
// Internal trigger connection: RM0377 table 80
(TIM21, TIM22): (tim21_tim22, tim21::cr2::MMS_A, tim22::smcr::SMS_A, tim22::smcr::TS_A::Itr0),
// Note: Other combinations would be possible as well, e.g. (TIM21, TIM2) or (TIM2, TIM22).
// They can be implemented if needed.
}