diff options
Diffstat (limited to 'embassy-stm32/src/timer/low_level.rs')
| -rw-r--r-- | embassy-stm32/src/timer/low_level.rs | 191 |
1 files changed, 71 insertions, 120 deletions
diff --git a/embassy-stm32/src/timer/low_level.rs b/embassy-stm32/src/timer/low_level.rs index aba08081f..73a81bff1 100644 --- a/embassy-stm32/src/timer/low_level.rs +++ b/embassy-stm32/src/timer/low_level.rs | |||
| @@ -268,6 +268,11 @@ impl<'d, T: CoreInstance> Timer<'d, T> { | |||
| 268 | unsafe { crate::pac::timer::TimGp32::from_ptr(T::regs()) } | 268 | unsafe { crate::pac::timer::TimGp32::from_ptr(T::regs()) } |
| 269 | } | 269 | } |
| 270 | 270 | ||
| 271 | #[cfg(stm32l0)] | ||
| 272 | fn regs_gp32_unchecked(&self) -> crate::pac::timer::TimGp16 { | ||
| 273 | unsafe { crate::pac::timer::TimGp16::from_ptr(T::regs()) } | ||
| 274 | } | ||
| 275 | |||
| 271 | /// Start the timer. | 276 | /// Start the timer. |
| 272 | pub fn start(&self) { | 277 | pub fn start(&self) { |
| 273 | self.regs_core().cr1().modify(|r| r.set_cen(true)); | 278 | self.regs_core().cr1().modify(|r| r.set_cen(true)); |
| @@ -296,7 +301,12 @@ impl<'d, T: CoreInstance> Timer<'d, T> { | |||
| 296 | 301 | ||
| 297 | /// get the capability of the timer | 302 | /// get the capability of the timer |
| 298 | pub fn bits(&self) -> TimerBits { | 303 | pub fn bits(&self) -> TimerBits { |
| 299 | T::BITS | 304 | match T::Word::bits() { |
| 305 | 16 => TimerBits::Bits16, | ||
| 306 | #[cfg(not(stm32l0))] | ||
| 307 | 32 => TimerBits::Bits32, | ||
| 308 | _ => unreachable!(), | ||
| 309 | } | ||
| 300 | } | 310 | } |
| 301 | 311 | ||
| 302 | /// Set the frequency of how many times per second the timer counts up to the max value or down to 0. | 312 | /// Set the frequency of how many times per second the timer counts up to the max value or down to 0. |
| @@ -306,18 +316,10 @@ impl<'d, T: CoreInstance> Timer<'d, T> { | |||
| 306 | /// In center-aligned mode (which not all timers support), the wrap-around frequency is effectively halved | 316 | /// In center-aligned mode (which not all timers support), the wrap-around frequency is effectively halved |
| 307 | /// because it needs to count up and down. | 317 | /// because it needs to count up and down. |
| 308 | pub fn set_frequency(&self, frequency: Hertz) { | 318 | pub fn set_frequency(&self, frequency: Hertz) { |
| 309 | match T::BITS { | 319 | self.set_frequency_internal(frequency, T::Word::bits()); |
| 310 | TimerBits::Bits16 => { | ||
| 311 | self.set_frequency_internal(frequency, 16); | ||
| 312 | } | ||
| 313 | #[cfg(not(stm32l0))] | ||
| 314 | TimerBits::Bits32 => { | ||
| 315 | self.set_frequency_internal(frequency, 32); | ||
| 316 | } | ||
| 317 | } | ||
| 318 | } | 320 | } |
| 319 | 321 | ||
| 320 | pub(crate) fn set_frequency_internal(&self, frequency: Hertz, max_divide_by_bits: u8) { | 322 | pub(crate) fn set_frequency_internal(&self, frequency: Hertz, max_divide_by_bits: usize) { |
| 321 | let f = frequency.0; | 323 | let f = frequency.0; |
| 322 | assert!(f > 0); | 324 | assert!(f > 0); |
| 323 | let timer_f = T::frequency().0; | 325 | let timer_f = T::frequency().0; |
| @@ -326,25 +328,15 @@ impl<'d, T: CoreInstance> Timer<'d, T> { | |||
| 326 | let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << max_divide_by_bits)).try_into()); | 328 | let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << max_divide_by_bits)).try_into()); |
| 327 | let divide_by = pclk_ticks_per_timer_period / (u64::from(psc) + 1); | 329 | let divide_by = pclk_ticks_per_timer_period / (u64::from(psc) + 1); |
| 328 | 330 | ||
| 329 | match T::BITS { | 331 | // the timer counts `0..=arr`, we want it to count `0..divide_by` |
| 330 | TimerBits::Bits16 => { | 332 | let arr: T::Word = unwrap!(T::Word::try_from(divide_by - 1)); |
| 331 | // the timer counts `0..=arr`, we want it to count `0..divide_by` | ||
| 332 | let arr = unwrap!(u16::try_from(divide_by - 1)); | ||
| 333 | |||
| 334 | let regs = self.regs_core(); | ||
| 335 | regs.psc().write_value(psc); | ||
| 336 | regs.arr().write(|r| r.set_arr(arr)); | ||
| 337 | } | ||
| 338 | #[cfg(not(stm32l0))] | ||
| 339 | TimerBits::Bits32 => { | ||
| 340 | // the timer counts `0..=arr`, we want it to count `0..divide_by` | ||
| 341 | let arr: u32 = unwrap!(u32::try_from(divide_by - 1)); | ||
| 342 | 333 | ||
| 343 | let regs = self.regs_gp32_unchecked(); | 334 | let regs = self.regs_gp32_unchecked(); |
| 344 | regs.psc().write_value(psc); | 335 | regs.psc().write_value(psc); |
| 345 | regs.arr().write_value(arr); | 336 | #[cfg(stm32l0)] |
| 346 | } | 337 | regs.arr().write(|r| r.set_arr(unwrap!(arr.try_into()))); |
| 347 | } | 338 | #[cfg(not(stm32l0))] |
| 339 | regs.arr().write_value(arr.into()); | ||
| 348 | } | 340 | } |
| 349 | 341 | ||
| 350 | /// Set tick frequency. | 342 | /// Set tick frequency. |
| @@ -393,23 +385,14 @@ impl<'d, T: CoreInstance> Timer<'d, T> { | |||
| 393 | pub fn get_frequency(&self) -> Hertz { | 385 | pub fn get_frequency(&self) -> Hertz { |
| 394 | let timer_f = T::frequency(); | 386 | let timer_f = T::frequency(); |
| 395 | 387 | ||
| 396 | match T::BITS { | 388 | let regs = self.regs_gp32_unchecked(); |
| 397 | TimerBits::Bits16 => { | 389 | #[cfg(not(stm32l0))] |
| 398 | let regs = self.regs_core(); | 390 | let arr = regs.arr().read(); |
| 399 | let arr = regs.arr().read().arr(); | 391 | #[cfg(stm32l0)] |
| 400 | let psc = regs.psc().read(); | 392 | let arr = regs.arr().read().arr(); |
| 393 | let psc = regs.psc().read(); | ||
| 401 | 394 | ||
| 402 | timer_f / arr / (psc + 1) | 395 | timer_f / arr / (psc + 1) |
| 403 | } | ||
| 404 | #[cfg(not(stm32l0))] | ||
| 405 | TimerBits::Bits32 => { | ||
| 406 | let regs = self.regs_gp32_unchecked(); | ||
| 407 | let arr = regs.arr().read(); | ||
| 408 | let psc = regs.psc().read(); | ||
| 409 | |||
| 410 | timer_f / arr / (psc + 1) | ||
| 411 | } | ||
| 412 | } | ||
| 413 | } | 396 | } |
| 414 | 397 | ||
| 415 | /// Get the clock frequency of the timer (before prescaler is applied). | 398 | /// Get the clock frequency of the timer (before prescaler is applied). |
| @@ -469,42 +452,29 @@ impl<'d, T: GeneralInstance1Channel> Timer<'d, T> { | |||
| 469 | } | 452 | } |
| 470 | 453 | ||
| 471 | /// Get max compare value. This depends on the timer frequency and the clock frequency from RCC. | 454 | /// Get max compare value. This depends on the timer frequency and the clock frequency from RCC. |
| 472 | pub fn get_max_compare_value(&self) -> u32 { | 455 | pub fn get_max_compare_value(&self) -> T::Word { |
| 473 | match T::BITS { | 456 | #[cfg(not(stm32l0))] |
| 474 | TimerBits::Bits16 => self.regs_1ch().arr().read().arr() as u32, | 457 | return unwrap!(self.regs_gp32_unchecked().arr().read().try_into()); |
| 475 | #[cfg(not(stm32l0))] | 458 | #[cfg(stm32l0)] |
| 476 | TimerBits::Bits32 => self.regs_gp32_unchecked().arr().read(), | 459 | return unwrap!(self.regs_gp32_unchecked().arr().read().arr().try_into()); |
| 477 | } | ||
| 478 | } | 460 | } |
| 479 | 461 | ||
| 480 | /// Set the max compare value. | 462 | /// Set the max compare value. |
| 481 | /// | 463 | /// |
| 482 | /// An update event is generated to load the new value. The update event is | 464 | /// An update event is generated to load the new value. The update event is |
| 483 | /// generated such that it will not cause an interrupt or DMA request. | 465 | /// generated such that it will not cause an interrupt or DMA request. |
| 484 | pub fn set_max_compare_value(&self, ticks: u32) { | 466 | pub fn set_max_compare_value(&self, ticks: T::Word) { |
| 485 | match T::BITS { | 467 | let arr = ticks; |
| 486 | TimerBits::Bits16 => { | ||
| 487 | let arr = unwrap!(u16::try_from(ticks)); | ||
| 488 | 468 | ||
| 489 | let regs = self.regs_1ch(); | 469 | let regs = self.regs_gp32_unchecked(); |
| 490 | regs.arr().write(|r| r.set_arr(arr)); | 470 | #[cfg(not(stm32l0))] |
| 471 | regs.arr().write_value(arr.into()); | ||
| 472 | #[cfg(stm32l0)] | ||
| 473 | regs.arr().write(|r| r.set_arr(unwrap!(arr.try_into()))); | ||
| 491 | 474 | ||
| 492 | regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTER_ONLY)); | 475 | regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTER_ONLY)); |
| 493 | regs.egr().write(|r| r.set_ug(true)); | 476 | regs.egr().write(|r| r.set_ug(true)); |
| 494 | regs.cr1().modify(|r| r.set_urs(vals::Urs::ANY_EVENT)); | 477 | regs.cr1().modify(|r| r.set_urs(vals::Urs::ANY_EVENT)); |
| 495 | } | ||
| 496 | #[cfg(not(stm32l0))] | ||
| 497 | TimerBits::Bits32 => { | ||
| 498 | let arr = ticks; | ||
| 499 | |||
| 500 | let regs = self.regs_gp32_unchecked(); | ||
| 501 | regs.arr().write_value(arr); | ||
| 502 | |||
| 503 | regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTER_ONLY)); | ||
| 504 | regs.egr().write(|r| r.set_ug(true)); | ||
| 505 | regs.cr1().modify(|r| r.set_urs(vals::Urs::ANY_EVENT)); | ||
| 506 | } | ||
| 507 | } | ||
| 508 | } | 478 | } |
| 509 | } | 479 | } |
| 510 | 480 | ||
| @@ -638,26 +608,23 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { | |||
| 638 | } | 608 | } |
| 639 | 609 | ||
| 640 | /// Set compare value for a channel. | 610 | /// Set compare value for a channel. |
| 641 | pub fn set_compare_value(&self, channel: Channel, value: u32) { | 611 | pub fn set_compare_value(&self, channel: Channel, value: T::Word) { |
| 642 | match T::BITS { | 612 | #[cfg(not(stm32l0))] |
| 643 | TimerBits::Bits16 => { | 613 | self.regs_gp32_unchecked() |
| 644 | let value = unwrap!(u16::try_from(value)); | 614 | .ccr(channel.index()) |
| 645 | self.regs_gp16().ccr(channel.index()).modify(|w| w.set_ccr(value)); | 615 | .write_value(value.into()); |
| 646 | } | 616 | #[cfg(stm32l0)] |
| 647 | #[cfg(not(stm32l0))] | 617 | self.regs_gp16() |
| 648 | TimerBits::Bits32 => { | 618 | .ccr(channel.index()) |
| 649 | self.regs_gp32_unchecked().ccr(channel.index()).write_value(value); | 619 | .modify(|w| w.set_ccr(unwrap!(value.try_into()))); |
| 650 | } | ||
| 651 | } | ||
| 652 | } | 620 | } |
| 653 | 621 | ||
| 654 | /// Get compare value for a channel. | 622 | /// Get compare value for a channel. |
| 655 | pub fn get_compare_value(&self, channel: Channel) -> u32 { | 623 | pub fn get_compare_value(&self, channel: Channel) -> T::Word { |
| 656 | match T::BITS { | 624 | #[cfg(not(stm32l0))] |
| 657 | TimerBits::Bits16 => self.regs_gp16().ccr(channel.index()).read().ccr() as u32, | 625 | return unwrap!(self.regs_gp32_unchecked().ccr(channel.index()).read().try_into()); |
| 658 | #[cfg(not(stm32l0))] | 626 | #[cfg(stm32l0)] |
| 659 | TimerBits::Bits32 => self.regs_gp32_unchecked().ccr(channel.index()).read(), | 627 | return unwrap!(self.regs_gp32_unchecked().ccr(channel.index()).read().ccr().try_into()); |
| 660 | } | ||
| 661 | } | 628 | } |
| 662 | 629 | ||
| 663 | /// Setup a ring buffer for the channel | 630 | /// Setup a ring buffer for the channel |
| @@ -665,8 +632,8 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { | |||
| 665 | &mut self, | 632 | &mut self, |
| 666 | dma: Peri<'a, impl super::UpDma<T>>, | 633 | dma: Peri<'a, impl super::UpDma<T>>, |
| 667 | channel: Channel, | 634 | channel: Channel, |
| 668 | dma_buf: &'a mut [u16], | 635 | dma_buf: &'a mut [T::Word], |
| 669 | ) -> WritableRingBuffer<'a, u16> { | 636 | ) -> WritableRingBuffer<'a, T::Word> { |
| 670 | #[allow(clippy::let_unit_value)] // eg. stm32f334 | 637 | #[allow(clippy::let_unit_value)] // eg. stm32f334 |
| 671 | let req = dma.request(); | 638 | let req = dma.request(); |
| 672 | 639 | ||
| @@ -686,7 +653,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { | |||
| 686 | WritableRingBuffer::new( | 653 | WritableRingBuffer::new( |
| 687 | dma, | 654 | dma, |
| 688 | req, | 655 | req, |
| 689 | self.regs_1ch().ccr(channel.index()).as_ptr() as *mut u16, | 656 | self.regs_1ch().ccr(channel.index()).as_ptr() as *mut T::Word, |
| 690 | dma_buf, | 657 | dma_buf, |
| 691 | dma_transfer_option, | 658 | dma_transfer_option, |
| 692 | ) | 659 | ) |
| @@ -701,7 +668,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { | |||
| 701 | &mut self, | 668 | &mut self, |
| 702 | dma: Peri<'a, impl super::UpDma<T>>, | 669 | dma: Peri<'a, impl super::UpDma<T>>, |
| 703 | channel: Channel, | 670 | channel: Channel, |
| 704 | duty: &'a [u16], | 671 | duty: &'a [T::Word], |
| 705 | ) -> Transfer<'a> { | 672 | ) -> Transfer<'a> { |
| 706 | #[allow(clippy::let_unit_value)] // eg. stm32f334 | 673 | #[allow(clippy::let_unit_value)] // eg. stm32f334 |
| 707 | let req = dma.request(); | 674 | let req = dma.request(); |
| @@ -719,29 +686,13 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { | |||
| 719 | ..Default::default() | 686 | ..Default::default() |
| 720 | }; | 687 | }; |
| 721 | 688 | ||
| 722 | match self.bits() { | 689 | Transfer::new_write( |
| 723 | TimerBits::Bits16 => Transfer::new_write( | 690 | dma, |
| 724 | dma, | 691 | req, |
| 725 | req, | 692 | duty, |
| 726 | duty, | 693 | self.regs_gp16().ccr(channel.index()).as_ptr() as *mut T::Word, |
| 727 | self.regs_1ch().ccr(channel.index()).as_ptr() as *mut u16, | 694 | dma_transfer_option, |
| 728 | dma_transfer_option, | 695 | ) |
| 729 | ), | ||
| 730 | #[cfg(not(any(stm32l0)))] | ||
| 731 | TimerBits::Bits32 => { | ||
| 732 | #[cfg(not(any(bdma, gpdma)))] | ||
| 733 | panic!("unsupported timer bits"); | ||
| 734 | |||
| 735 | #[cfg(any(bdma, gpdma))] | ||
| 736 | Transfer::new_write( | ||
| 737 | dma, | ||
| 738 | req, | ||
| 739 | duty, | ||
| 740 | self.regs_1ch().ccr(channel.index()).as_ptr() as *mut u32, | ||
| 741 | dma_transfer_option, | ||
| 742 | ) | ||
| 743 | } | ||
| 744 | } | ||
| 745 | } | 696 | } |
| 746 | } | 697 | } |
| 747 | 698 | ||
| @@ -779,7 +730,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { | |||
| 779 | dma: Peri<'a, impl super::UpDma<T>>, | 730 | dma: Peri<'a, impl super::UpDma<T>>, |
| 780 | starting_channel: Channel, | 731 | starting_channel: Channel, |
| 781 | ending_channel: Channel, | 732 | ending_channel: Channel, |
| 782 | duty: &'a [u16], | 733 | duty: &'a [T::Word], |
| 783 | ) -> Transfer<'a> { | 734 | ) -> Transfer<'a> { |
| 784 | let cr1_addr = self.regs_gp16().cr1().as_ptr() as u32; | 735 | let cr1_addr = self.regs_gp16().cr1().as_ptr() as u32; |
| 785 | let start_ch_index = starting_channel.index(); | 736 | let start_ch_index = starting_channel.index(); |
| @@ -815,14 +766,14 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { | |||
| 815 | dma, | 766 | dma, |
| 816 | req, | 767 | req, |
| 817 | duty, | 768 | duty, |
| 818 | self.regs_gp16().dmar().as_ptr() as *mut u16, | 769 | self.regs_gp16().dmar().as_ptr() as *mut T::Word, |
| 819 | dma_transfer_option, | 770 | dma_transfer_option, |
| 820 | ) | 771 | ) |
| 821 | } | 772 | } |
| 822 | } | 773 | } |
| 823 | 774 | ||
| 824 | /// Get capture value for a channel. | 775 | /// Get capture value for a channel. |
| 825 | pub fn get_capture_value(&self, channel: Channel) -> u32 { | 776 | pub fn get_capture_value(&self, channel: Channel) -> T::Word { |
| 826 | self.get_compare_value(channel) | 777 | self.get_compare_value(channel) |
| 827 | } | 778 | } |
| 828 | 779 | ||
