From 36f4075b9054576ccf6dba2dedb08c62484a0599 Mon Sep 17 00:00:00 2001 From: Eicke Hecht Date: Sun, 23 Nov 2025 12:29:56 +0100 Subject: fix: Fix waveform for channels > 1 and disallow for unsupported dmas --- embassy-stm32/src/timer/low_level.rs | 12 +++++-- examples/stm32f7/src/bin/pwm.rs | 65 ++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 examples/stm32f7/src/bin/pwm.rs diff --git a/embassy-stm32/src/timer/low_level.rs b/embassy-stm32/src/timer/low_level.rs index 670298d23..307d614bf 100644 --- a/embassy-stm32/src/timer/low_level.rs +++ b/embassy-stm32/src/timer/low_level.rs @@ -781,7 +781,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { let cc_channel = C::CHANNEL; let original_cc_dma_on_update = self.get_cc_dma_selection() == Ccds::ON_UPDATE; - let original_cc_dma_enabled = self.get_c fsc_dma_enable_state(cc_channel); + let original_cc_dma_enabled = self.get_cc_dma_enable_state(cc_channel); // redirect CC DMA request onto Update Event if !original_cc_dma_on_update { @@ -810,7 +810,12 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { /// Generate a sequence of PWM waveform that will run continously /// You may want to start this in a new thread as this will block forever + pub async fn waveform_continuous(&mut self, dma: Peri<'_, impl super::Dma>, duty: &[u16]) { + + #[cfg(any(bdma, gpdma))] + panic!("unsupported DMA"); + use crate::pac::timer::vals::Ccds; #[allow(clippy::let_unit_value)] // eg. stm32f334 @@ -871,6 +876,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { fifo_threshold: Some(FifoThreshold::Full), #[cfg(not(any(bdma, gpdma)))] mburst: Burst::Incr8, + #[cfg(not(any(bdma, gpdma)))] circular: circular, ..Default::default() }; @@ -881,7 +887,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { dma, req, duty, - self.regs_1ch().ccr(channel.index()).as_ptr() as *mut u16, + self.regs_gp16().ccr(channel.index()).as_ptr() as *mut u16, dma_transfer_option, ) .await @@ -896,7 +902,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { dma, req, duty, - self.regs_1ch().ccr(channel.index()).as_ptr() as *mut u32, + self.regs_gp16().ccr(channel.index()).as_ptr() as *mut u32, dma_transfer_option, ) .await diff --git a/examples/stm32f7/src/bin/pwm.rs b/examples/stm32f7/src/bin/pwm.rs new file mode 100644 index 000000000..872d99859 --- /dev/null +++ b/examples/stm32f7/src/bin/pwm.rs @@ -0,0 +1,65 @@ +#![no_std] +#![no_main] + +use defmt::{panic, *}; +use embassy_executor::Spawner; +use embassy_futures::join::join; +use embassy_stm32::time::Hertz; +use embassy_stm32::{Config, peripherals}; +use embassy_stm32::gpio::OutputType; +use embassy_stm32::time::mhz; +use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; +use embassy_time::Timer; +use {defmt_rtt as _, panic_probe as _}; + +// If you are trying this and your USB device doesn't connect, the most +// common issues are the RCC config and vbus_detection +// +// See https://embassy.dev/book/#_the_usb_examples_are_not_working_on_my_board_is_there_anything_else_i_need_to_configure +// for more information. +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + info!("Hello World!"); + + let mut config = Config::default(); + { + use embassy_stm32::rcc::*; + config.rcc.hse = Some(Hse { + freq: Hertz(8_000_000), + mode: HseMode::Bypass, + }); + config.rcc.pll_src = PllSource::HSE; + config.rcc.pll = Some(Pll { + prediv: PllPreDiv::DIV4, + mul: PllMul::MUL200, + divp: Some(PllPDiv::DIV2), // 8mhz / 4 * 200 / 2 = 200Mhz + divq: Some(PllQDiv::DIV4), // 8mhz / 4 * 200 / 4 = 100Mhz + divr: None, + }); + config.rcc.ahb_pre = AHBPrescaler::DIV1; + config.rcc.apb1_pre = APBPrescaler::DIV4; + config.rcc.apb2_pre = APBPrescaler::DIV2; + config.rcc.sys = Sysclk::PLL1_P; + } + let p = embassy_stm32::init(config); + let ch1_pin = PwmPin::new(p.PE9, OutputType::PushPull); + let ch2_pin = PwmPin::new(p.PE11, OutputType::PushPull); + let mut pwm = SimplePwm::new(p.TIM1, Some(ch1_pin), Some(ch2_pin), None, None, mhz(1), Default::default()); + let mut ch1 = pwm.ch1(); + ch1.enable(); + info!("PWM initialized"); + info!("PWM max duty {}", ch1.max_duty_cycle()); + + info!("PWM duty on channel 1 (D6) 50%"); + ch1.set_duty_cycle_fraction(1, 2); + info!("PWM waveform on channel 2 (D5)"); + const max_duty: usize = 200; + let mut duty = [0u16;max_duty]; + for i in 0..max_duty { + duty[i] = i as u16; + } + pwm.waveform_continuous::(p.DMA2_CH6, &duty).await; + + +} + -- cgit