diff options
| author | Thales Fragoso <[email protected]> | 2021-02-16 18:25:06 -0300 |
|---|---|---|
| committer | Thales Fragoso <[email protected]> | 2021-02-17 19:41:00 -0300 |
| commit | fc7977bd9ac0a2c58942bbd3987230a3c7066a9b (patch) | |
| tree | 1990221ca6d8dddc8f674b70f62bf15c6d99658a | |
| parent | 9d895a63832336590ce6780ea38825d2e0183573 (diff) | |
Add remaining stm32f4 timers
| -rw-r--r-- | embassy-stm32f4/src/rtc.rs | 327 |
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 | |||
| 30 | fn calc_now(period: u32, counter: u16) -> u64 { | 29 | fn 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 |
| 49 | const ALARM_COUNT: usize = 3; | 48 | const 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. | ||
| 51 | pub struct RTC<T: Instance> { | 57 | pub 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 | ||
| 251 | mod tim2 { | 258 | #[allow(unused_macros)] |
| 252 | use super::*; | 259 | macro_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"))] | ||
| 492 | impl_timer!(tim2: (TIM2, TIM2Interrupt, apb1enr, 0, apb1rstr, 0, ppre1, pclk1), 3); | ||
| 493 | |||
| 494 | #[cfg(not(feature = "stm32f410"))] | ||
| 495 | impl_timer!(tim3: (TIM3, TIM3Interrupt, apb1enr, 1, apb1rstr, 1, ppre1, pclk1), 3); | ||
| 496 | |||
| 497 | #[cfg(not(feature = "stm32f410"))] | ||
| 498 | impl_timer!(tim4: (TIM4, TIM4Interrupt, apb1enr, 2, apb1rstr, 2, ppre1, pclk1), 3); | ||
| 499 | |||
| 500 | impl_timer!(tim5: (TIM5, TIM5Interrupt, apb1enr, 3, apb1rstr, 3, ppre1, pclk1), 3); | ||
| 501 | |||
| 502 | impl_timer!(tim9: (TIM9, TIM1_BRK_TIM9Interrupt, apb2enr, 16, apb2rstr, 16, ppre2, pclk2), 1); | ||
| 503 | |||
| 504 | #[cfg(not(any(feature = "stm32f401", feature = "stm32f410", feature = "stm32f411")))] | ||
| 505 | impl_timer!(tim12: (TIM12, TIM8_BRK_TIM12Interrupt, apb1enr, 6, apb1rstr, 6, ppre1, pclk1), 1); | ||
