aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThales Fragoso <[email protected]>2021-02-16 18:25:06 -0300
committerThales Fragoso <[email protected]>2021-02-17 19:41:00 -0300
commitfc7977bd9ac0a2c58942bbd3987230a3c7066a9b (patch)
tree1990221ca6d8dddc8f674b70f62bf15c6d99658a
parent9d895a63832336590ce6780ea38825d2e0183573 (diff)
Add remaining stm32f4 timers
-rw-r--r--embassy-stm32f4/src/rtc.rs327
1 files changed, 234 insertions, 93 deletions
diff --git a/embassy-stm32f4/src/rtc.rs b/embassy-stm32f4/src/rtc.rs
index 7dc3a563f..283442712 100644
--- a/embassy-stm32f4/src/rtc.rs
+++ b/embassy-stm32f4/src/rtc.rs
@@ -26,7 +26,6 @@ use crate::interrupt::{CriticalSection, Mutex, OwnedInterrupt};
26// corresponds to the next period. 26// corresponds to the next period.
27// 27//
28// `period` is a 32bit integer, so It overflows on 2^32 * 2^15 / 32768 seconds of uptime, which is 136 years. 28// `period` is a 32bit integer, so It overflows on 2^32 * 2^15 / 32768 seconds of uptime, which is 136 years.
29
30fn calc_now(period: u32, counter: u16) -> u64 { 29fn calc_now(period: u32, counter: u16) -> u64 {
31 ((period as u64) << 15) + ((counter as u32 ^ ((period & 1) << 15)) as u64) 30 ((period as u64) << 15) + ((counter as u32 ^ ((period & 1) << 15)) as u64)
32} 31}
@@ -48,6 +47,13 @@ impl AlarmState {
48// TODO: This is sometimes wasteful, try to find a better way 47// TODO: This is sometimes wasteful, try to find a better way
49const ALARM_COUNT: usize = 3; 48const ALARM_COUNT: usize = 3;
50 49
50/// RTC timer that can be used by the executor and to set alarms.
51///
52/// It can work with Timers 2, 3, 4, 5, 9 and 12. Timers 9 and 12 only have one alarm available,
53/// while the others have three each.
54/// This timer works internally with a unit of 2^15 ticks, which means that if a call to
55/// [`embassy::time::Clock::now`] is blocked for that amount of ticks the returned value will be
56/// wrong (an old value). The current default tick rate is 32768 ticks per second.
51pub struct RTC<T: Instance> { 57pub struct RTC<T: Instance> {
52 rtc: T, 58 rtc: T,
53 irq: T::Interrupt, 59 irq: T::Interrupt,
@@ -240,6 +246,7 @@ pub trait Instance: sealed::Sealed + Sized + 'static {
240 fn compare_clear_flag(&self, n: usize); 246 fn compare_clear_flag(&self, n: usize);
241 fn overflow_interrupt_status(&self) -> bool; 247 fn overflow_interrupt_status(&self) -> bool;
242 fn overflow_clear_flag(&self); 248 fn overflow_clear_flag(&self);
249 // This method should ensure that the values are really updated before returning
243 fn set_psc_arr(&self, psc: u16, arr: u16); 250 fn set_psc_arr(&self, psc: u16, arr: u16);
244 fn stop_and_reset(&self); 251 fn stop_and_reset(&self);
245 fn start(&self); 252 fn start(&self);
@@ -248,117 +255,251 @@ pub trait Instance: sealed::Sealed + Sized + 'static {
248 fn pclk(clocks: &Clocks) -> u32; 255 fn pclk(clocks: &Clocks) -> u32;
249} 256}
250 257
251mod tim2 { 258#[allow(unused_macros)]
252 use super::*; 259macro_rules! impl_timer {
253 use stm32f4xx_hal::pac::{RCC, TIM2}; 260 ($module:ident: ($TYPE:ident, $INT:ident, $apbenr:ident, $enrbit:expr, $apbrstr:ident, $rstrbit:expr, $ppre:ident, $pclk: ident), 3) => {
261 mod $module {
262 use super::*;
263 use stm32f4xx_hal::pac::{$TYPE, RCC};
254 264
255 impl sealed::Sealed for TIM2 {} 265 impl sealed::Sealed for $TYPE {}
256 266
257 impl Instance for TIM2 { 267 impl Instance for $TYPE {
258 type Interrupt = interrupt::TIM2Interrupt; 268 type Interrupt = interrupt::$INT;
259 const REAL_ALARM_COUNT: usize = 3; 269 const REAL_ALARM_COUNT: usize = 3;
260 270
261 fn enable_clock(&self) { 271 fn enable_clock(&self) {
262 // NOTE(unsafe) It will only be used for atomic operations 272 // NOTE(unsafe) It will only be used for atomic operations
263 unsafe { 273 unsafe {
264 let rcc = &*RCC::ptr(); 274 let rcc = &*RCC::ptr();
265 275
266 bb::set(&rcc.apb1enr, 0); 276 bb::set(&rcc.$apbenr, $enrbit);
267 bb::set(&rcc.apb1rstr, 0); 277 bb::set(&rcc.$apbrstr, $rstrbit);
268 bb::clear(&rcc.apb1rstr, 0); 278 bb::clear(&rcc.$apbrstr, $rstrbit);
269 } 279 }
270 } 280 }
271 281
272 fn set_compare(&self, n: usize, value: u16) { 282 fn set_compare(&self, n: usize, value: u16) {
273 // NOTE(unsafe) these registers accept all the range of u16 values 283 // NOTE(unsafe) these registers accept all the range of u16 values
274 match n { 284 match n {
275 0 => self.ccr1.write(|w| unsafe { w.bits(value.into()) }), 285 0 => self.ccr1.write(|w| unsafe { w.bits(value.into()) }),
276 1 => self.ccr2.write(|w| unsafe { w.bits(value.into()) }), 286 1 => self.ccr2.write(|w| unsafe { w.bits(value.into()) }),
277 2 => self.ccr3.write(|w| unsafe { w.bits(value.into()) }), 287 2 => self.ccr3.write(|w| unsafe { w.bits(value.into()) }),
278 3 => self.ccr4.write(|w| unsafe { w.bits(value.into()) }), 288 3 => self.ccr4.write(|w| unsafe { w.bits(value.into()) }),
279 _ => {} 289 _ => {}
280 } 290 }
281 } 291 }
282 292
283 fn set_compare_interrupt(&self, n: usize, enable: bool) { 293 fn set_compare_interrupt(&self, n: usize, enable: bool) {
284 if n > 3 { 294 if n > 3 {
285 return; 295 return;
286 } 296 }
287 let bit = n as u8 + 1; 297 let bit = n as u8 + 1;
288 unsafe { 298 unsafe {
289 if enable { 299 if enable {
290 bb::set(&self.dier, bit); 300 bb::set(&self.dier, bit);
291 } else { 301 } else {
292 bb::clear(&self.dier, bit); 302 bb::clear(&self.dier, bit);
303 }
304 }
293 } 305 }
294 }
295 }
296 306
297 fn compare_interrupt_status(&self, n: usize) -> bool { 307 fn compare_interrupt_status(&self, n: usize) -> bool {
298 let status = self.sr.read(); 308 let status = self.sr.read();
299 match n { 309 match n {
300 0 => status.cc1if().bit_is_set(), 310 0 => status.cc1if().bit_is_set(),
301 1 => status.cc2if().bit_is_set(), 311 1 => status.cc2if().bit_is_set(),
302 2 => status.cc3if().bit_is_set(), 312 2 => status.cc3if().bit_is_set(),
303 3 => status.cc4if().bit_is_set(), 313 3 => status.cc4if().bit_is_set(),
304 _ => false, 314 _ => false,
305 } 315 }
306 } 316 }
307 317
308 fn compare_clear_flag(&self, n: usize) { 318 fn compare_clear_flag(&self, n: usize) {
309 if n > 3 { 319 if n > 3 {
310 return; 320 return;
311 } 321 }
312 let bit = n as u8 + 1; 322 let bit = n as u8 + 1;
313 unsafe { 323 unsafe {
314 bb::clear(&self.sr, bit); 324 bb::clear(&self.sr, bit);
315 } 325 }
316 } 326 }
317 327
318 fn overflow_interrupt_status(&self) -> bool { 328 fn overflow_interrupt_status(&self) -> bool {
319 self.sr.read().uif().bit_is_set() 329 self.sr.read().uif().bit_is_set()
320 } 330 }
321 331
322 fn overflow_clear_flag(&self) { 332 fn overflow_clear_flag(&self) {
323 unsafe { 333 unsafe {
324 bb::clear(&self.sr, 0); 334 bb::clear(&self.sr, 0);
325 } 335 }
326 } 336 }
327 337
328 fn set_psc_arr(&self, psc: u16, arr: u16) { 338 fn set_psc_arr(&self, psc: u16, arr: u16) {
329 // NOTE(unsafe) All u16 values are valid 339 // NOTE(unsafe) All u16 values are valid
330 self.psc.write(|w| unsafe { w.bits(psc.into()) }); 340 self.psc.write(|w| unsafe { w.bits(psc.into()) });
331 self.arr.write(|w| unsafe { w.bits(arr.into()) }); 341 self.arr.write(|w| unsafe { w.bits(arr.into()) });
342
343 unsafe {
344 // Set URS, generate update, clear URS
345 bb::set(&self.cr1, 2);
346 self.egr.write(|w| w.ug().set_bit());
347 bb::clear(&self.cr1, 2);
348 }
349 }
332 350
333 unsafe { 351 fn stop_and_reset(&self) {
334 // Set URS, generate update, clear URS 352 unsafe {
335 bb::set(&self.cr1, 2); 353 bb::clear(&self.cr1, 0);
336 self.egr.write(|w| w.ug().set_bit()); 354 }
337 bb::clear(&self.cr1, 2); 355 self.cnt.reset();
338 } 356 }
339 } 357
358 fn start(&self) {
359 unsafe { bb::set(&self.cr1, 0) }
360 }
361
362 fn counter(&self) -> u16 {
363 self.cnt.read().bits() as u16
364 }
340 365
341 fn stop_and_reset(&self) { 366 fn ppre(clocks: &Clocks) -> u8 {
342 unsafe { 367 clocks.$ppre()
343 bb::clear(&self.cr1, 0); 368 }
369
370 fn pclk(clocks: &Clocks) -> u32 {
371 clocks.$pclk().0
372 }
344 } 373 }
345 self.cnt.reset();
346 } 374 }
375 };
347 376
348 fn start(&self) { 377 ($module:ident: ($TYPE:ident, $INT:ident, $apbenr:ident, $enrbit:expr, $apbrstr:ident, $rstrbit:expr, $ppre:ident, $pclk: ident), 1) => {
349 unsafe { bb::set(&self.cr1, 0) } 378 mod $module {
350 } 379 use super::*;
380 use stm32f4xx_hal::pac::{$TYPE, RCC};
351 381
352 fn counter(&self) -> u16 { 382 impl sealed::Sealed for $TYPE {}
353 self.cnt.read().bits() as u16
354 }
355 383
356 fn ppre(clocks: &Clocks) -> u8 { 384 impl Instance for $TYPE {
357 clocks.ppre1() 385 type Interrupt = interrupt::$INT;
358 } 386 const REAL_ALARM_COUNT: usize = 1;
387
388 fn enable_clock(&self) {
389 // NOTE(unsafe) It will only be used for atomic operations
390 unsafe {
391 let rcc = &*RCC::ptr();
392
393 bb::set(&rcc.$apbenr, $enrbit);
394 bb::set(&rcc.$apbrstr, $rstrbit);
395 bb::clear(&rcc.$apbrstr, $rstrbit);
396 }
397 }
398
399 fn set_compare(&self, n: usize, value: u16) {
400 // NOTE(unsafe) these registers accept all the range of u16 values
401 match n {
402 0 => self.ccr1.write(|w| unsafe { w.bits(value.into()) }),
403 1 => self.ccr2.write(|w| unsafe { w.bits(value.into()) }),
404 _ => {}
405 }
406 }
407
408 fn set_compare_interrupt(&self, n: usize, enable: bool) {
409 if n > 1 {
410 return;
411 }
412 let bit = n as u8 + 1;
413 unsafe {
414 if enable {
415 bb::set(&self.dier, bit);
416 } else {
417 bb::clear(&self.dier, bit);
418 }
419 }
420 }
421
422 fn compare_interrupt_status(&self, n: usize) -> bool {
423 let status = self.sr.read();
424 match n {
425 0 => status.cc1if().bit_is_set(),
426 1 => status.cc2if().bit_is_set(),
427 _ => false,
428 }
429 }
430
431 fn compare_clear_flag(&self, n: usize) {
432 if n > 1 {
433 return;
434 }
435 let bit = n as u8 + 1;
436 unsafe {
437 bb::clear(&self.sr, bit);
438 }
439 }
440
441 fn overflow_interrupt_status(&self) -> bool {
442 self.sr.read().uif().bit_is_set()
443 }
444
445 fn overflow_clear_flag(&self) {
446 unsafe {
447 bb::clear(&self.sr, 0);
448 }
449 }
450
451 fn set_psc_arr(&self, psc: u16, arr: u16) {
452 // NOTE(unsafe) All u16 values are valid
453 self.psc.write(|w| unsafe { w.bits(psc.into()) });
454 self.arr.write(|w| unsafe { w.bits(arr.into()) });
455
456 unsafe {
457 // Set URS, generate update, clear URS
458 bb::set(&self.cr1, 2);
459 self.egr.write(|w| w.ug().set_bit());
460 bb::clear(&self.cr1, 2);
461 }
462 }
463
464 fn stop_and_reset(&self) {
465 unsafe {
466 bb::clear(&self.cr1, 0);
467 }
468 self.cnt.reset();
469 }
470
471 fn start(&self) {
472 unsafe { bb::set(&self.cr1, 0) }
473 }
474
475 fn counter(&self) -> u16 {
476 self.cnt.read().bits() as u16
477 }
478
479 fn ppre(clocks: &Clocks) -> u8 {
480 clocks.$ppre()
481 }
359 482
360 fn pclk(clocks: &Clocks) -> u32 { 483 fn pclk(clocks: &Clocks) -> u32 {
361 clocks.pclk1().0 484 clocks.$pclk().0
485 }
486 }
362 } 487 }
363 } 488 };
364} 489}
490
491#[cfg(not(feature = "stm32f410"))]
492impl_timer!(tim2: (TIM2, TIM2Interrupt, apb1enr, 0, apb1rstr, 0, ppre1, pclk1), 3);
493
494#[cfg(not(feature = "stm32f410"))]
495impl_timer!(tim3: (TIM3, TIM3Interrupt, apb1enr, 1, apb1rstr, 1, ppre1, pclk1), 3);
496
497#[cfg(not(feature = "stm32f410"))]
498impl_timer!(tim4: (TIM4, TIM4Interrupt, apb1enr, 2, apb1rstr, 2, ppre1, pclk1), 3);
499
500impl_timer!(tim5: (TIM5, TIM5Interrupt, apb1enr, 3, apb1rstr, 3, ppre1, pclk1), 3);
501
502impl_timer!(tim9: (TIM9, TIM1_BRK_TIM9Interrupt, apb2enr, 16, apb2rstr, 16, ppre2, pclk2), 1);
503
504#[cfg(not(any(feature = "stm32f401", feature = "stm32f410", feature = "stm32f411")))]
505impl_timer!(tim12: (TIM12, TIM8_BRK_TIM12Interrupt, apb1enr, 6, apb1rstr, 6, ppre1, pclk1), 1);