diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs index 7a5475c31..77d902e35 100644 --- a/embassy-stm32/src/timer/simple_pwm.rs +++ b/embassy-stm32/src/timer/simple_pwm.rs @@ -55,19 +55,12 @@ channel_impl!(new_ch3, Ch3, Channel3Pin); channel_impl!(new_ch4, Ch4, Channel4Pin); /// Simple PWM driver. -pub struct SimplePwm<'d, T, Dma> { +pub struct SimplePwm<'d, T> { inner: PeripheralRef<'d, T>, - dma: PeripheralRef<'d, Dma>, } -impl<'d, T: CaptureCompare16bitInstance, Dma> SimplePwm<'d, T, Dma> { +impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { /// Create a new simple PWM driver. - /// - /// Note: - /// If you want to use [`Self::gen_waveform()`], you need to provide corresponding TIMx_UP DMA channel. - /// Otherwise you can just put a [`dma::NoDma`](crate::dma::NoDma) - /// Currently, you can only use one channel at a time to generate waveform with [`Self::gen_waveform()`]. - /// But you can always use multiple TIM to generate multiple waveform simultaneously. pub fn new( tim: impl Peripheral
+ 'd,
_ch1: Option + 'd,
) -> Self {
- Self::new_inner(tim, freq, counting_mode, dma)
+ Self::new_inner(tim, freq, counting_mode)
}
- fn new_inner(
- tim: impl Peripheral + 'd,
- freq: Hertz,
- counting_mode: CountingMode,
- dma: impl Peripheral + 'd,
- ) -> Self {
- into_ref!(tim, dma);
+ fn new_inner(tim: impl Peripheral + 'd, freq: Hertz, counting_mode: CountingMode) -> Self {
+ into_ref!(tim);
T::enable_and_reset();
- let mut this = Self { inner: tim, dma };
+ let mut this = Self { inner: tim };
this.inner.set_counting_mode(counting_mode);
this.set_frequency(freq);
@@ -165,32 +152,23 @@ impl<'d, T: CaptureCompare16bitInstance, Dma> SimplePwm<'d, T, Dma> {
}
}
-impl<'d, T: CaptureCompare16bitInstance + Basic16bitInstance, Dma> SimplePwm<'d, T, Dma>
-where
- Dma: super::UpDma >,
+ channel: Channel,
+ duty: &[u16],
+ ) {
assert!(duty.iter().all(|v| *v <= self.get_max_duty()));
- #[cfg_attr(any(stm32f334, stm32f378), allow(clippy::let_unit_value))]
- let req = self.dma.request();
+ into_ref!(dma);
- #[cfg(not(any(bdma, gpdma)))]
- let (isr_bit, isr_reg, ifcr_reg) = {
- let dma_regs = self.dma.regs();
- let isr_num = self.dma.num() / 4;
- let isr_bit = self.dma.num() % 4;
- let isr_reg = dma_regs.isr(isr_num);
- let ifcr_reg = dma_regs.ifcr(isr_num);
- (isr_bit, isr_reg, ifcr_reg)
- };
-
- #[cfg(not(any(bdma, gpdma)))]
- // clean DMA FIFO error before a transfer
- if isr_reg.read().feif(isr_bit) {
- ifcr_reg.write(|v| v.set_feif(isr_bit, true));
- }
+ #[allow(clippy::let_unit_value)] // eg. stm32f334
+ let req = dma.request();
let original_duty_state = self.get_duty(channel);
let original_enable_state = self.is_enabled(channel);
@@ -218,7 +196,7 @@ where
};
Transfer::new_write(
- &mut self.dma,
+ &mut dma,
req,
duty,
T::regs_gp16().ccr(channel.index()).as_ptr() as *mut _,
@@ -231,21 +209,21 @@ where
if !original_enable_state {
self.disable(channel);
}
+
self.set_duty(channel, original_duty_state);
+
+ // Since DMA is closed before timer update event trigger DMA is turn off,
+ // this can almost always trigger a DMA FIFO error.
+ //
+ // optional TODO:
+ // clean FEIF after disable UDE
if !original_update_dma_state {
self.inner.enable_update_dma(false);
-
- #[cfg(not(any(bdma, gpdma)))]
- // Since DMA could be closed before timer update event trigger DMA is turn off, this can almost always trigger a DMA FIFO error.
- // Thus, we will try clean DMA FEIF after each transfer
- if isr_reg.read().feif(isr_bit) {
- ifcr_reg.write(|v| v.set_feif(isr_bit, true));
- }
}
}
}
-impl<'d, T: CaptureCompare16bitInstance, Dma> embedded_hal_02::Pwm for SimplePwm<'d, T, Dma> {
+impl<'d, T: CaptureCompare16bitInstance> embedded_hal_02::Pwm for SimplePwm<'d, T> {
type Channel = Channel;
type Time = Hertz;
type Duty = u16;
diff --git a/examples/stm32f4/src/bin/pwm.rs b/examples/stm32f4/src/bin/pwm.rs
index 92bc42ec8..8844a9f0e 100644
--- a/examples/stm32f4/src/bin/pwm.rs
+++ b/examples/stm32f4/src/bin/pwm.rs
@@ -3,7 +3,6 @@
use defmt::*;
use embassy_executor::Spawner;
-use embassy_stm32::dma;
use embassy_stm32::gpio::OutputType;
use embassy_stm32::time::khz;
use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
@@ -17,16 +16,7 @@ async fn main(_spawner: Spawner) {
info!("Hello World!");
let ch1 = PwmPin::new_ch1(p.PE9, OutputType::PushPull);
- let mut pwm = SimplePwm::new(
- p.TIM1,
- Some(ch1),
- None,
- None,
- None,
- khz(10),
- Default::default(),
- dma::NoDma,
- );
+ let mut pwm = SimplePwm::new(p.TIM1, Some(ch1), None, None, None, khz(10), Default::default());
let max = pwm.get_max_duty();
pwm.enable(Channel::Ch1);
diff --git a/examples/stm32f4/src/bin/ws2812_pwm.rs b/examples/stm32f4/src/bin/ws2812_pwm.rs
index 93a89f16a..239709253 100644
--- a/examples/stm32f4/src/bin/ws2812_pwm.rs
+++ b/examples/stm32f4/src/bin/ws2812_pwm.rs
@@ -45,7 +45,7 @@ async fn main(_spawner: Spawner) {
device_config.rcc.sys = Sysclk::PLL1_P;
}
- let dp = embassy_stm32::init(device_config);
+ let mut dp = embassy_stm32::init(device_config);
let mut ws2812_pwm = SimplePwm::new(
dp.TIM3,
@@ -55,7 +55,6 @@ async fn main(_spawner: Spawner) {
None,
khz(800), // data rate of ws2812
CountingMode::EdgeAlignedUp,
- dp.DMA1_CH2,
);
// construct ws2812 non-return-to-zero (NRZ) code bit by bit
@@ -91,7 +90,8 @@ async fn main(_spawner: Spawner) {
loop {
for &color in color_list {
- ws2812_pwm.gen_waveform(pwm_channel, color).await;
+ // with &mut, we can easily reuse same DMA channel multiple times
+ ws2812_pwm.gen_waveform(&mut dp.DMA1_CH2, pwm_channel, color).await;
// ws2812 need at least 50 us low level input to confirm the input data and change it's state
Timer::after_micros(50).await;
// wait until ticker tick
diff --git a/examples/stm32g4/src/bin/pwm.rs b/examples/stm32g4/src/bin/pwm.rs
index 9fa004c3e..d4809a481 100644
--- a/examples/stm32g4/src/bin/pwm.rs
+++ b/examples/stm32g4/src/bin/pwm.rs
@@ -3,7 +3,6 @@
use defmt::*;
use embassy_executor::Spawner;
-use embassy_stm32::dma;
use embassy_stm32::gpio::OutputType;
use embassy_stm32::time::khz;
use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
@@ -17,16 +16,7 @@ async fn main(_spawner: Spawner) {
info!("Hello World!");
let ch1 = PwmPin::new_ch1(p.PC0, OutputType::PushPull);
- let mut pwm = SimplePwm::new(
- p.TIM1,
- Some(ch1),
- None,
- None,
- None,
- khz(10),
- Default::default(),
- dma::NoDma,
- );
+ let mut pwm = SimplePwm::new(p.TIM1, Some(ch1), None, None, None, khz(10), Default::default());
let max = pwm.get_max_duty();
pwm.enable(Channel::Ch1);
diff --git a/examples/stm32h7/src/bin/pwm.rs b/examples/stm32h7/src/bin/pwm.rs
index de155fc94..1e48ba67b 100644
--- a/examples/stm32h7/src/bin/pwm.rs
+++ b/examples/stm32h7/src/bin/pwm.rs
@@ -7,7 +7,7 @@ use embassy_stm32::gpio::OutputType;
use embassy_stm32::time::khz;
use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
use embassy_stm32::timer::Channel;
-use embassy_stm32::{dma, Config};
+use embassy_stm32::Config;
use embassy_time::Timer;
use {defmt_rtt as _, panic_probe as _};
@@ -38,16 +38,7 @@ async fn main(_spawner: Spawner) {
info!("Hello World!");
let ch1 = PwmPin::new_ch1(p.PA6, OutputType::PushPull);
- let mut pwm = SimplePwm::new(
- p.TIM3,
- Some(ch1),
- None,
- None,
- None,
- khz(10),
- Default::default(),
- dma::NoDma,
- );
+ let mut pwm = SimplePwm::new(p.TIM3, Some(ch1), None, None, None, khz(10), Default::default());
let max = pwm.get_max_duty();
pwm.enable(Channel::Ch1);