From cbc7a9fe5b9bfda8a53316cd231d6a4b7a3bbfd9 Mon Sep 17 00:00:00 2001 From: Liu Hancheng Date: Wed, 1 Jan 2025 17:05:48 +0800 Subject: [PATCH] feat: Add 32-bit timer support for waveform function --- embassy-stm32/src/timer/low_level.rs | 4 +++ embassy-stm32/src/timer/simple_pwm.rs | 39 ++++++++++++++++++++------- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/embassy-stm32/src/timer/low_level.rs b/embassy-stm32/src/timer/low_level.rs index 7360d6aef..448069ab3 100644 --- a/embassy-stm32/src/timer/low_level.rs +++ b/embassy-stm32/src/timer/low_level.rs @@ -235,6 +235,10 @@ impl<'d, T: CoreInstance> Timer<'d, T> { self.regs_core().cnt().write(|r| r.set_cnt(0)); } + pub fn get_bits(&self) -> TimerBits { + T::BITS + } + /// Set the frequency of how many times per second the timer counts up to the max value or down to 0. /// /// This means that in the default edge-aligned mode, diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs index 56fb1871e..c6808593a 100644 --- a/embassy-stm32/src/timer/simple_pwm.rs +++ b/embassy-stm32/src/timer/simple_pwm.rs @@ -6,6 +6,7 @@ use core::mem::ManuallyDrop; use embassy_hal_internal::{into_ref, PeripheralRef}; use super::low_level::{CountingMode, OutputCompareMode, OutputPolarity, Timer}; +use super::TimerBits; use super::{Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin, GeneralInstance4Channel}; use crate::gpio::{AfType, AnyPin, OutputType, Speed}; use crate::time::Hertz; @@ -365,7 +366,7 @@ macro_rules! impl_waveform_chx { /// /// Note: /// you will need to provide corresponding TIMx_CHy DMA channel to use this method. - pub async fn $fn_name(&mut self, dma: impl Peripheral

>, duty: &[u16]) { + pub async fn $fn_name(&mut self, dma: impl Peripheral

>, duty: &[u8]) { use crate::pac::timer::vals::Ccds; into_ref!(dma); @@ -406,14 +407,34 @@ macro_rules! impl_waveform_chx { ..Default::default() }; - Transfer::new_write( - &mut dma, - req, - duty, - self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut _, - dma_transfer_option, - ) - .await + match self.inner.get_bits() { + TimerBits::Bits16 => { + // the data must be aligned to double words + assert!(duty.len() % 2 == 0); + let duty = core::slice::from_raw_parts(duty.as_ptr() as *const u16, duty.len() / 2); + Transfer::new_write( + &mut dma, + req, + duty, + self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut _, + dma_transfer_option, + ) + .await + } + TimerBits::Bits32 => { + // the data must be aligned to quad words + assert!(duty.len() % 4 == 0); + let duty = core::slice::from_raw_parts(duty.as_ptr() as *const u32, duty.len() / 4); + Transfer::new_write( + &mut dma, + req, + duty, + self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut _, + dma_transfer_option, + ) + .await + } + }; }; // restore output compare state