From 05417e91093dfd7e150083738988259d66ee4e37 Mon Sep 17 00:00:00 2001 From: Eicke Hecht Date: Mon, 24 Nov 2025 21:54:25 +0100 Subject: fix: Warnings and formatting all fixed --- embassy-stm32/src/timer/low_level.rs | 4 +--- embassy-stm32/src/timer/ringbuffered.rs | 25 +++++++++++++++++++++---- embassy-stm32/src/timer/simple_pwm.rs | 31 +++++++++++++++++++++++-------- 3 files changed, 45 insertions(+), 15 deletions(-) (limited to 'embassy-stm32/src') diff --git a/embassy-stm32/src/timer/low_level.rs b/embassy-stm32/src/timer/low_level.rs index 2cee5f1f5..d1cf11386 100644 --- a/embassy-stm32/src/timer/low_level.rs +++ b/embassy-stm32/src/timer/low_level.rs @@ -812,8 +812,6 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { /// 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]) { - - use crate::pac::timer::vals::Ccds; #[allow(clippy::let_unit_value)] // eg. stm32f334 @@ -855,7 +853,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { req: dma::Request, channel: Channel, duty: &[u16], - circular: bool, + #[allow(unused_variables)] circular: bool, ) { let original_duty_state = self.get_compare_value(channel); let original_enable_state = self.get_channel_enable_state(channel); diff --git a/embassy-stm32/src/timer/ringbuffered.rs b/embassy-stm32/src/timer/ringbuffered.rs index bb602f8a7..e8f97bf59 100644 --- a/embassy-stm32/src/timer/ringbuffered.rs +++ b/embassy-stm32/src/timer/ringbuffered.rs @@ -5,9 +5,24 @@ use core::task::Waker; use super::low_level::Timer; use super::{Channel, GeneralInstance4Channel}; -use crate::dma::ringbuffer::Error; use crate::dma::WritableRingBuffer; +use crate::dma::ringbuffer::Error; +/// A PWM channel that uses a DMA ring buffer for continuous waveform generation. +/// +/// This allows you to continuously update PWM duty cycles via DMA without blocking the CPU. +/// The ring buffer enables smooth, uninterrupted waveform generation by automatically cycling +/// through duty cycle values stored in memory. +/// +/// You can write new duty cycle values to the ring buffer while it's running, enabling +/// dynamic waveform generation for applications like motor control, LED dimming, or audio output. +/// +/// # Example +/// ```ignore +/// let mut channel = pwm.ch1().into_ring_buffered_channel(dma_ch, &mut buffer); +/// channel.start(); // Start DMA transfer +/// channel.write(&[100, 200, 300]).ok(); // Update duty cycles +/// ``` pub struct RingBufferedPwmChannel<'d, T: GeneralInstance4Channel> { timer: ManuallyDrop>, ring_buf: WritableRingBuffer<'d, u16>, @@ -15,7 +30,11 @@ pub struct RingBufferedPwmChannel<'d, T: GeneralInstance4Channel> { } impl<'d, T: GeneralInstance4Channel> RingBufferedPwmChannel<'d, T> { - pub(crate) fn new(timer: ManuallyDrop>, channel: Channel, ring_buf: WritableRingBuffer<'d, u16>) -> Self { + pub(crate) fn new( + timer: ManuallyDrop>, + channel: Channel, + ring_buf: WritableRingBuffer<'d, u16>, + ) -> Self { Self { timer, ring_buf, @@ -148,5 +167,3 @@ pub struct RingBufferedPwmChannels<'d, T: GeneralInstance4Channel> { /// Channel 4 pub ch4: RingBufferedPwmChannel<'d, T>, } - - diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs index 53e0345ea..f4656b7bd 100644 --- a/embassy-stm32/src/timer/simple_pwm.rs +++ b/embassy-stm32/src/timer/simple_pwm.rs @@ -6,11 +6,11 @@ use core::mem::ManuallyDrop; use super::low_level::{CountingMode, OutputCompareMode, OutputPolarity, Timer}; use super::ringbuffered::RingBufferedPwmChannel; use super::{Ch1, Ch2, Ch3, Ch4, Channel, GeneralInstance4Channel, TimerChannel, TimerPin}; -use crate::dma::WritableRingBuffer; use crate::Peri; +use crate::dma::TransferOptions; +use crate::dma::WritableRingBuffer; #[cfg(not(any(bdma, gpdma)))] use crate::dma::{Burst, FifoThreshold}; -use crate::dma::TransferOptions; #[cfg(gpio_v2)] use crate::gpio::Pull; use crate::gpio::{AfType, AnyPin, OutputType, Speed}; @@ -379,9 +379,27 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { pub async fn waveform_continuous(&mut self, dma: Peri<'_, impl super::Dma>, duty: &[u16]) { self.inner.waveform_continuous(dma, duty).await; } - pub fn into_ring_buffered_channel(self, tx_dma: Peri<'d, impl super::Dma>, dma_buf: &'d mut [u16]) -> RingBufferedPwmChannel<'d, T> { + + /// Convert this PWM channel into a ring-buffered PWM channel. + /// + /// This allows continuous PWM waveform generation using a DMA ring buffer. + /// The ring buffer enables dynamic updates to the PWM duty cycle without blocking. + /// + /// # Arguments + /// * `tx_dma` - The DMA channel to use for transferring duty cycle values + /// * `dma_buf` - The buffer to use as a ring buffer (must be non-empty and <= 65535 elements) + /// + /// # Panics + /// Panics if `dma_buf` is empty or longer than 65535 elements. + pub fn into_ring_buffered_channel( + self, + tx_dma: Peri<'d, impl super::Dma>, + dma_buf: &'d mut [u16], + ) -> RingBufferedPwmChannel<'d, T> { assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); + use crate::pac::timer::vals::Ccds; + let channel = C::CHANNEL; let request = tx_dma.request(); @@ -393,6 +411,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { ..Default::default() }; + self.inner.set_cc_dma_selection(Ccds::ON_UPDATE); let ring_buf = unsafe { WritableRingBuffer::new( tx_dma, @@ -403,11 +422,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { ) }; - RingBufferedPwmChannel::new( - unsafe { self.inner.clone_unchecked() }, - channel, - ring_buf - ) + RingBufferedPwmChannel::new(unsafe { self.inner.clone_unchecked() }, channel, ring_buf) } } -- cgit