aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2025-11-25 15:20:54 +0000
committerGitHub <[email protected]>2025-11-25 15:20:54 +0000
commit1f9c436afe6b0bcb306803d916e28df9e910479c (patch)
treee2227fbac5f2c404130c444cd1b31a4c53b3b31e
parent9e82cdc023cf001bd628ad68a712a41f8045455d (diff)
parent2612f07f549fa0b9d8565ef760814d5f7ebea785 (diff)
Merge pull request #4944 from xoviat/timer
stm32: remove waveform method
-rw-r--r--embassy-stm32/CHANGELOG.md1
-rw-r--r--embassy-stm32/src/timer/complementary_pwm.rs17
-rw-r--r--embassy-stm32/src/timer/low_level.rs174
-rw-r--r--embassy-stm32/src/timer/simple_pwm.rs17
4 files changed, 60 insertions, 149 deletions
diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md
index 6140b3238..949ea03b5 100644
--- a/embassy-stm32/CHANGELOG.md
+++ b/embassy-stm32/CHANGELOG.md
@@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7 7
8## Unreleased - ReleaseDate 8## Unreleased - ReleaseDate
9 9
10- change: remove waveform timer method
10- change: low power: store stop mode for dma channels 11- change: low power: store stop mode for dma channels
11- fix: Fixed ADC4 enable() for WBA 12- fix: Fixed ADC4 enable() for WBA
12- feat: allow use of anyadcchannel for adc4 13- feat: allow use of anyadcchannel for adc4
diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs
index 6d4c70dff..77f19a37b 100644
--- a/embassy-stm32/src/timer/complementary_pwm.rs
+++ b/embassy-stm32/src/timer/complementary_pwm.rs
@@ -220,9 +220,11 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
220 /// 220 ///
221 /// Note: 221 /// Note:
222 /// you will need to provide corresponding TIMx_UP DMA channel to use this method. 222 /// you will need to provide corresponding TIMx_UP DMA channel to use this method.
223 #[inline(always)]
224 pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma<T>>, channel: Channel, duty: &[u16]) { 223 pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma<T>>, channel: Channel, duty: &[u16]) {
225 self.inner.waveform_up(dma, channel, duty).await 224 self.inner.enable_channel(channel, true);
225 self.inner.enable_update_dma(true);
226 self.inner.setup_update_dma(dma, channel, duty).await;
227 self.inner.enable_update_dma(false);
226 } 228 }
227 229
228 /// Generate a multichannel sequence of PWM waveforms using DMA triggered by timer update events. 230 /// Generate a multichannel sequence of PWM waveforms using DMA triggered by timer update events.
@@ -254,7 +256,6 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
254 /// Also be aware that embassy timers use one of timers internally. It is possible to 256 /// Also be aware that embassy timers use one of timers internally. It is possible to
255 /// switch this timer by using `time-driver-timX` feature. 257 /// switch this timer by using `time-driver-timX` feature.
256 /// 258 ///
257 #[inline(always)]
258 pub async fn waveform_up_multi_channel( 259 pub async fn waveform_up_multi_channel(
259 &mut self, 260 &mut self,
260 dma: Peri<'_, impl super::UpDma<T>>, 261 dma: Peri<'_, impl super::UpDma<T>>,
@@ -262,15 +263,11 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
262 ending_channel: Channel, 263 ending_channel: Channel,
263 duty: &[u16], 264 duty: &[u16],
264 ) { 265 ) {
266 self.inner.enable_update_dma(true);
265 self.inner 267 self.inner
266 .waveform_up_multi_channel(dma, starting_channel, ending_channel, duty) 268 .setup_update_dma_burst(dma, starting_channel, ending_channel, duty)
267 .await; 269 .await;
268 } 270 self.inner.enable_update_dma(false);
269
270 /// Generate a sequence of PWM waveform
271 #[inline(always)]
272 pub async fn waveform<C: TimerChannel>(&mut self, dma: Peri<'_, impl super::Dma<T, C>>, duty: &[u16]) {
273 self.inner.waveform(dma, duty).await;
274 } 271 }
275} 272}
276 273
diff --git a/embassy-stm32/src/timer/low_level.rs b/embassy-stm32/src/timer/low_level.rs
index f0105ece8..f986c8dab 100644
--- a/embassy-stm32/src/timer/low_level.rs
+++ b/embassy-stm32/src/timer/low_level.rs
@@ -13,9 +13,10 @@ use embassy_hal_internal::Peri;
13pub use stm32_metapac::timer::vals::{FilterValue, Mms as MasterMode, Sms as SlaveMode, Ts as TriggerSource}; 13pub use stm32_metapac::timer::vals::{FilterValue, Mms as MasterMode, Sms as SlaveMode, Ts as TriggerSource};
14 14
15use super::*; 15use super::*;
16use crate::dma::Transfer;
16use crate::pac::timer::vals; 17use crate::pac::timer::vals;
18use crate::rcc;
17use crate::time::Hertz; 19use crate::time::Hertz;
18use crate::{dma, rcc};
19 20
20/// Input capture mode. 21/// Input capture mode.
21#[derive(Clone, Copy)] 22#[derive(Clone, Copy)]
@@ -663,25 +664,51 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
663 /// 664 ///
664 /// Note: 665 /// Note:
665 /// you will need to provide corresponding TIMx_UP DMA channel to use this method. 666 /// you will need to provide corresponding TIMx_UP DMA channel to use this method.
666 pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma<T>>, channel: Channel, duty: &[u16]) { 667 pub fn setup_update_dma<'a>(
668 &mut self,
669 dma: Peri<'a, impl super::UpDma<T>>,
670 channel: Channel,
671 duty: &'a [u16],
672 ) -> Transfer<'a> {
667 #[allow(clippy::let_unit_value)] // eg. stm32f334 673 #[allow(clippy::let_unit_value)] // eg. stm32f334
668 let req = dma.request(); 674 let req = dma.request();
669 675
670 let original_update_dma_state = self.get_update_dma_state(); 676 unsafe {
677 #[cfg(not(any(bdma, gpdma)))]
678 use crate::dma::{Burst, FifoThreshold};
679 use crate::dma::{Transfer, TransferOptions};
671 680
672 if !original_update_dma_state { 681 let dma_transfer_option = TransferOptions {
673 self.enable_update_dma(true); 682 #[cfg(not(any(bdma, gpdma)))]
674 } 683 fifo_threshold: Some(FifoThreshold::Full),
684 #[cfg(not(any(bdma, gpdma)))]
685 mburst: Burst::Incr8,
686 ..Default::default()
687 };
675 688
676 self.waveform_helper(dma, req, channel, duty).await; 689 match self.bits() {
690 TimerBits::Bits16 => Transfer::new_write(
691 dma,
692 req,
693 duty,
694 self.regs_1ch().ccr(channel.index()).as_ptr() as *mut u16,
695 dma_transfer_option,
696 ),
697 #[cfg(not(any(stm32l0)))]
698 TimerBits::Bits32 => {
699 #[cfg(not(any(bdma, gpdma)))]
700 panic!("unsupported timer bits");
677 701
678 // Since DMA is closed before timer update event trigger DMA is turn off, 702 #[cfg(any(bdma, gpdma))]
679 // this can almost always trigger a DMA FIFO error. 703 Transfer::new_write(
680 // 704 dma,
681 // optional TODO: 705 req,
682 // clean FEIF after disable UDE 706 duty,
683 if !original_update_dma_state { 707 self.regs_1ch().ccr(channel.index()).as_ptr() as *mut u32,
684 self.enable_update_dma(false); 708 dma_transfer_option,
709 )
710 }
711 }
685 } 712 }
686 } 713 }
687 714
@@ -714,13 +741,13 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
714 /// Also be aware that embassy timers use one of timers internally. It is possible to 741 /// Also be aware that embassy timers use one of timers internally. It is possible to
715 /// switch this timer by using `time-driver-timX` feature. 742 /// switch this timer by using `time-driver-timX` feature.
716 /// 743 ///
717 pub async fn waveform_up_multi_channel( 744 pub fn setup_update_dma_burst<'a>(
718 &mut self, 745 &mut self,
719 dma: Peri<'_, impl super::UpDma<T>>, 746 dma: Peri<'a, impl super::UpDma<T>>,
720 starting_channel: Channel, 747 starting_channel: Channel,
721 ending_channel: Channel, 748 ending_channel: Channel,
722 duty: &[u16], 749 duty: &'a [u16],
723 ) { 750 ) -> Transfer<'a> {
724 let cr1_addr = self.regs_gp16().cr1().as_ptr() as u32; 751 let cr1_addr = self.regs_gp16().cr1().as_ptr() as u32;
725 let start_ch_index = starting_channel.index(); 752 let start_ch_index = starting_channel.index();
726 let end_ch_index = ending_channel.index(); 753 let end_ch_index = ending_channel.index();
@@ -738,11 +765,6 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
738 #[allow(clippy::let_unit_value)] // eg. stm32f334 765 #[allow(clippy::let_unit_value)] // eg. stm32f334
739 let req = dma.request(); 766 let req = dma.request();
740 767
741 let original_update_dma_state = self.get_update_dma_state();
742 if !original_update_dma_state {
743 self.enable_update_dma(true);
744 }
745
746 unsafe { 768 unsafe {
747 #[cfg(not(any(bdma, gpdma)))] 769 #[cfg(not(any(bdma, gpdma)))]
748 use crate::dma::{Burst, FifoThreshold}; 770 use crate::dma::{Burst, FifoThreshold};
@@ -763,113 +785,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> {
763 self.regs_gp16().dmar().as_ptr() as *mut u16, 785 self.regs_gp16().dmar().as_ptr() as *mut u16,
764 dma_transfer_option, 786 dma_transfer_option,
765 ) 787 )
766 .await
767 };
768
769 if !original_update_dma_state {
770 self.enable_update_dma(false);
771 }
772 }
773
774 /// Generate a sequence of PWM waveform
775 pub async fn waveform<C: TimerChannel>(&mut self, dma: Peri<'_, impl super::Dma<T, C>>, duty: &[u16]) {
776 use crate::pac::timer::vals::Ccds;
777
778 #[allow(clippy::let_unit_value)] // eg. stm32f334
779 let req = dma.request();
780
781 let cc_channel = C::CHANNEL;
782
783 let original_cc_dma_on_update = self.get_cc_dma_selection() == Ccds::ON_UPDATE;
784 let original_cc_dma_enabled = self.get_cc_dma_enable_state(cc_channel);
785
786 // redirect CC DMA request onto Update Event
787 if !original_cc_dma_on_update {
788 self.set_cc_dma_selection(Ccds::ON_UPDATE)
789 } 788 }
790
791 if !original_cc_dma_enabled {
792 self.set_cc_dma_enable_state(cc_channel, true);
793 }
794
795 self.waveform_helper(dma, req, cc_channel, duty).await;
796
797 // Since DMA is closed before timer Capture Compare Event trigger DMA is turn off,
798 // this can almost always trigger a DMA FIFO error.
799 //
800 // optional TODO:
801 // clean FEIF after disable UDE
802 if !original_cc_dma_enabled {
803 self.set_cc_dma_enable_state(cc_channel, false);
804 }
805
806 if !original_cc_dma_on_update {
807 self.set_cc_dma_selection(Ccds::ON_COMPARE)
808 }
809 }
810
811 async fn waveform_helper(
812 &mut self,
813 dma: Peri<'_, impl dma::Channel>,
814 req: dma::Request,
815 channel: Channel,
816 duty: &[u16],
817 ) {
818 let original_duty_state = self.get_compare_value(channel);
819 let original_enable_state = self.get_channel_enable_state(channel);
820
821 if !original_enable_state {
822 self.enable_channel(channel, true);
823 }
824
825 unsafe {
826 #[cfg(not(any(bdma, gpdma)))]
827 use crate::dma::{Burst, FifoThreshold};
828 use crate::dma::{Transfer, TransferOptions};
829
830 let dma_transfer_option = TransferOptions {
831 #[cfg(not(any(bdma, gpdma)))]
832 fifo_threshold: Some(FifoThreshold::Full),
833 #[cfg(not(any(bdma, gpdma)))]
834 mburst: Burst::Incr8,
835 ..Default::default()
836 };
837
838 match self.bits() {
839 TimerBits::Bits16 => {
840 Transfer::new_write(
841 dma,
842 req,
843 duty,
844 self.regs_1ch().ccr(channel.index()).as_ptr() as *mut u16,
845 dma_transfer_option,
846 )
847 .await
848 }
849 #[cfg(not(any(stm32l0)))]
850 TimerBits::Bits32 => {
851 #[cfg(not(any(bdma, gpdma)))]
852 panic!("unsupported timer bits");
853
854 #[cfg(any(bdma, gpdma))]
855 Transfer::new_write(
856 dma,
857 req,
858 duty,
859 self.regs_1ch().ccr(channel.index()).as_ptr() as *mut u32,
860 dma_transfer_option,
861 )
862 .await
863 }
864 };
865 };
866
867 // restore output compare state
868 if !original_enable_state {
869 self.enable_channel(channel, false);
870 }
871
872 self.set_compare_value(channel, original_duty_state);
873 } 789 }
874 790
875 /// Get capture value for a channel. 791 /// Get capture value for a channel.
diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs
index 6c9ef17e0..eb1b66358 100644
--- a/embassy-stm32/src/timer/simple_pwm.rs
+++ b/embassy-stm32/src/timer/simple_pwm.rs
@@ -316,9 +316,11 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
316 /// You will need to provide corresponding `TIMx_UP` DMA channel to use this method. 316 /// You will need to provide corresponding `TIMx_UP` DMA channel to use this method.
317 /// Also be aware that embassy timers use one of timers internally. It is possible to 317 /// Also be aware that embassy timers use one of timers internally. It is possible to
318 /// switch this timer by using `time-driver-timX` feature. 318 /// switch this timer by using `time-driver-timX` feature.
319 #[inline(always)]
320 pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma<T>>, channel: Channel, duty: &[u16]) { 319 pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma<T>>, channel: Channel, duty: &[u16]) {
321 self.inner.waveform_up(dma, channel, duty).await; 320 self.inner.enable_channel(channel, true);
321 self.inner.enable_update_dma(true);
322 self.inner.setup_update_dma(dma, channel, duty).await;
323 self.inner.enable_update_dma(false);
322 } 324 }
323 325
324 /// Generate a multichannel sequence of PWM waveforms using DMA triggered by timer update events. 326 /// Generate a multichannel sequence of PWM waveforms using DMA triggered by timer update events.
@@ -350,7 +352,6 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
350 /// Also be aware that embassy timers use one of timers internally. It is possible to 352 /// Also be aware that embassy timers use one of timers internally. It is possible to
351 /// switch this timer by using `time-driver-timX` feature. 353 /// switch this timer by using `time-driver-timX` feature.
352 /// 354 ///
353 #[inline(always)]
354 pub async fn waveform_up_multi_channel( 355 pub async fn waveform_up_multi_channel(
355 &mut self, 356 &mut self,
356 dma: Peri<'_, impl super::UpDma<T>>, 357 dma: Peri<'_, impl super::UpDma<T>>,
@@ -358,15 +359,11 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> {
358 ending_channel: Channel, 359 ending_channel: Channel,
359 duty: &[u16], 360 duty: &[u16],
360 ) { 361 ) {
362 self.inner.enable_update_dma(true);
361 self.inner 363 self.inner
362 .waveform_up_multi_channel(dma, starting_channel, ending_channel, duty) 364 .setup_update_dma_burst(dma, starting_channel, ending_channel, duty)
363 .await; 365 .await;
364 } 366 self.inner.enable_update_dma(false);
365
366 /// Generate a sequence of PWM waveform
367 #[inline(always)]
368 pub async fn waveform<C: TimerChannel>(&mut self, dma: Peri<'_, impl super::Dma<T, C>>, duty: &[u16]) {
369 self.inner.waveform(dma, duty).await;
370 } 367 }
371} 368}
372 369