From 6f88c2c73caa63a6e534130f4a064cb95d3e9d7d Mon Sep 17 00:00:00 2001 From: melvdl Date: Fri, 27 Jun 2025 01:08:28 +0200 Subject: stm32: rename timer channel trait; replace impls via macro with impls generic over timer channels --- embassy-stm32/src/timer/complementary_pwm.rs | 33 ++-- embassy-stm32/src/timer/input_capture.rs | 41 ++-- embassy-stm32/src/timer/low_level.rs | 38 ++-- embassy-stm32/src/timer/mod.rs | 48 ++--- embassy-stm32/src/timer/one_pulse.rs | 44 ++--- embassy-stm32/src/timer/pwm_input.rs | 28 +-- embassy-stm32/src/timer/qei.rs | 4 +- embassy-stm32/src/timer/simple_pwm.rs | 279 ++++++++++++--------------- 8 files changed, 241 insertions(+), 274 deletions(-) diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs index 4600dd1a3..a450705a2 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs @@ -6,11 +6,11 @@ use stm32_metapac::timer::vals::Ckd; use super::low_level::{CountingMode, OutputPolarity, Timer}; use super::simple_pwm::PwmPin; -use super::{AdvancedInstance4Channel, Ch1, Ch2, Ch3, Ch4, TimerChannel, TimerComplementaryPin}; +use super::{AdvancedInstance4Channel, Ch1, Ch2, Ch3, Ch4, Channel, TimerComplementaryPin}; use crate::gpio::{AnyPin, OutputType}; use crate::time::Hertz; use crate::timer::low_level::OutputCompareMode; -use crate::timer::Channel; +use crate::timer::TimerChannel; use crate::Peri; /// Complementary PWM pin wrapper. @@ -21,7 +21,7 @@ pub struct ComplementaryPwmPin<'d, T, C> { phantom: PhantomData<(T, C)>, } -impl<'d, T: AdvancedInstance4Channel, C: Channel> ComplementaryPwmPin<'d, T, C> { +impl<'d, T: AdvancedInstance4Channel, C: TimerChannel> ComplementaryPwmPin<'d, T, C> { /// Create a new complementary PWM pin instance. pub fn new(pin: Peri<'d, impl TimerComplementaryPin>, output_type: OutputType) -> Self { critical_section::with(|_| { @@ -71,29 +71,24 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { this.inner.enable_outputs(); - [ - TimerChannel::Ch1, - TimerChannel::Ch2, - TimerChannel::Ch3, - TimerChannel::Ch4, - ] - .iter() - .for_each(|&channel| { - this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1); - this.inner.set_output_compare_preload(channel, true); - }); + [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4] + .iter() + .for_each(|&channel| { + this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1); + this.inner.set_output_compare_preload(channel, true); + }); this } /// Enable the given channel. - pub fn enable(&mut self, channel: TimerChannel) { + pub fn enable(&mut self, channel: Channel) { self.inner.enable_channel(channel, true); self.inner.enable_complementary_channel(channel, true); } /// Disable the given channel. - pub fn disable(&mut self, channel: TimerChannel) { + pub fn disable(&mut self, channel: Channel) { self.inner.enable_complementary_channel(channel, false); self.inner.enable_channel(channel, false); } @@ -121,13 +116,13 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { /// Set the duty for a given channel. /// /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included. - pub fn set_duty(&mut self, channel: TimerChannel, duty: u16) { + pub fn set_duty(&mut self, channel: Channel, duty: u16) { assert!(duty <= self.get_max_duty()); self.inner.set_compare_value(channel, duty as _) } /// Set the output polarity for a given channel. - pub fn set_polarity(&mut self, channel: TimerChannel, polarity: OutputPolarity) { + pub fn set_polarity(&mut self, channel: Channel, polarity: OutputPolarity) { self.inner.set_output_polarity(channel, polarity); self.inner.set_complementary_output_polarity(channel, polarity); } @@ -142,7 +137,7 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { } impl<'d, T: AdvancedInstance4Channel> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> { - type Channel = TimerChannel; + type Channel = Channel; type Time = Hertz; type Duty = u16; diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs index da567d504..49e22b10f 100644 --- a/embassy-stm32/src/timer/input_capture.rs +++ b/embassy-stm32/src/timer/input_capture.rs @@ -6,12 +6,12 @@ use core::pin::Pin; use core::task::{Context, Poll}; use super::low_level::{CountingMode, FilterValue, InputCaptureMode, InputTISelection, Timer}; -use super::{CaptureCompareInterruptHandler, GeneralInstance4Channel, TimerChannel, TimerPin}; +use super::{CaptureCompareInterruptHandler, GeneralInstance4Channel, Channel, TimerPin}; pub use super::{Ch1, Ch2, Ch3, Ch4}; use crate::gpio::{AfType, AnyPin, Pull}; use crate::interrupt::typelevel::{Binding, Interrupt}; use crate::time::Hertz; -use crate::timer::Channel; +use crate::timer::TimerChannel; use crate::Peri; /// Capture pin wrapper. @@ -21,7 +21,7 @@ pub struct CapturePin<'d, T, C> { _pin: Peri<'d, AnyPin>, phantom: PhantomData<(T, C)>, } -impl<'d, T: GeneralInstance4Channel, C: Channel> CapturePin<'d, T, C> { +impl<'d, T: GeneralInstance4Channel, C: TimerChannel> CapturePin<'d, T, C> { /// Create a new capture pin instance. pub fn new(pin: Peri<'d, impl TimerPin>, pull: Pull) -> Self { pin.set_as_af(pin.af_num(), AfType::input(pull)); @@ -68,46 +68,41 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { } /// Enable the given channel. - pub fn enable(&mut self, channel: TimerChannel) { + pub fn enable(&mut self, channel: Channel) { self.inner.enable_channel(channel, true); } /// Disable the given channel. - pub fn disable(&mut self, channel: TimerChannel) { + pub fn disable(&mut self, channel: Channel) { self.inner.enable_channel(channel, false); } /// Check whether given channel is enabled - pub fn is_enabled(&self, channel: TimerChannel) -> bool { + pub fn is_enabled(&self, channel: Channel) -> bool { self.inner.get_channel_enable_state(channel) } /// Set the input capture mode for a given channel. - pub fn set_input_capture_mode(&mut self, channel: TimerChannel, mode: InputCaptureMode) { + pub fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) { self.inner.set_input_capture_mode(channel, mode); } /// Set input TI selection. - pub fn set_input_ti_selection(&mut self, channel: TimerChannel, tisel: InputTISelection) { + pub fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) { self.inner.set_input_ti_selection(channel, tisel) } /// Get capture value for a channel. - pub fn get_capture_value(&self, channel: TimerChannel) -> u32 { + pub fn get_capture_value(&self, channel: Channel) -> u32 { self.inner.get_capture_value(channel) } /// Get input interrupt. - pub fn get_input_interrupt(&self, channel: TimerChannel) -> bool { + pub fn get_input_interrupt(&self, channel: Channel) -> bool { self.inner.get_input_interrupt(channel) } - fn new_future( - &self, - channel: TimerChannel, - mode: InputCaptureMode, - tisel: InputTISelection, - ) -> InputCaptureFuture { + fn new_future(&self, channel: Channel, mode: InputCaptureMode, tisel: InputTISelection) -> InputCaptureFuture { // Configuration steps from ST RM0390 (STM32F446) chapter 17.3.5 // or ST RM0008 (STM32F103) chapter 15.3.5 Input capture mode self.inner.set_input_ti_selection(channel, tisel); @@ -124,37 +119,37 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { } /// Asynchronously wait until the pin sees a rising edge. - pub async fn wait_for_rising_edge(&mut self, channel: TimerChannel) -> u32 { + pub async fn wait_for_rising_edge(&mut self, channel: Channel) -> u32 { self.new_future(channel, InputCaptureMode::Rising, InputTISelection::Normal) .await } /// Asynchronously wait until the pin sees a falling edge. - pub async fn wait_for_falling_edge(&mut self, channel: TimerChannel) -> u32 { + pub async fn wait_for_falling_edge(&mut self, channel: Channel) -> u32 { self.new_future(channel, InputCaptureMode::Falling, InputTISelection::Normal) .await } /// Asynchronously wait until the pin sees any edge. - pub async fn wait_for_any_edge(&mut self, channel: TimerChannel) -> u32 { + pub async fn wait_for_any_edge(&mut self, channel: Channel) -> u32 { self.new_future(channel, InputCaptureMode::BothEdges, InputTISelection::Normal) .await } /// Asynchronously wait until the (alternate) pin sees a rising edge. - pub async fn wait_for_rising_edge_alternate(&mut self, channel: TimerChannel) -> u32 { + pub async fn wait_for_rising_edge_alternate(&mut self, channel: Channel) -> u32 { self.new_future(channel, InputCaptureMode::Rising, InputTISelection::Alternate) .await } /// Asynchronously wait until the (alternate) pin sees a falling edge. - pub async fn wait_for_falling_edge_alternate(&mut self, channel: TimerChannel) -> u32 { + pub async fn wait_for_falling_edge_alternate(&mut self, channel: Channel) -> u32 { self.new_future(channel, InputCaptureMode::Falling, InputTISelection::Alternate) .await } /// Asynchronously wait until the (alternate) pin sees any edge. - pub async fn wait_for_any_edge_alternate(&mut self, channel: TimerChannel) -> u32 { + pub async fn wait_for_any_edge_alternate(&mut self, channel: Channel) -> u32 { self.new_future(channel, InputCaptureMode::BothEdges, InputTISelection::Alternate) .await } @@ -162,7 +157,7 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { #[must_use = "futures do nothing unless you `.await` or poll them"] struct InputCaptureFuture { - channel: TimerChannel, + channel: Channel, phantom: PhantomData, } diff --git a/embassy-stm32/src/timer/low_level.rs b/embassy-stm32/src/timer/low_level.rs index bfdbcf968..dc8ceb725 100644 --- a/embassy-stm32/src/timer/low_level.rs +++ b/embassy-stm32/src/timer/low_level.rs @@ -503,7 +503,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { } /// Set input capture filter. - pub fn set_input_capture_filter(&self, channel: TimerChannel, icf: vals::FilterValue) { + pub fn set_input_capture_filter(&self, channel: Channel, icf: vals::FilterValue) { let raw_channel = channel.index(); self.regs_gp16() .ccmr_input(raw_channel / 2) @@ -511,22 +511,22 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { } /// Clear input interrupt. - pub fn clear_input_interrupt(&self, channel: TimerChannel) { + pub fn clear_input_interrupt(&self, channel: Channel) { self.regs_gp16().sr().modify(|r| r.set_ccif(channel.index(), false)); } /// Get input interrupt. - pub fn get_input_interrupt(&self, channel: TimerChannel) -> bool { + pub fn get_input_interrupt(&self, channel: Channel) -> bool { self.regs_gp16().sr().read().ccif(channel.index()) } /// Enable input interrupt. - pub fn enable_input_interrupt(&self, channel: TimerChannel, enable: bool) { + pub fn enable_input_interrupt(&self, channel: Channel, enable: bool) { self.regs_gp16().dier().modify(|r| r.set_ccie(channel.index(), enable)); } /// Set input capture prescaler. - pub fn set_input_capture_prescaler(&self, channel: TimerChannel, factor: u8) { + pub fn set_input_capture_prescaler(&self, channel: Channel, factor: u8) { let raw_channel = channel.index(); self.regs_gp16() .ccmr_input(raw_channel / 2) @@ -534,7 +534,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { } /// Set input TI selection. - pub fn set_input_ti_selection(&self, channel: TimerChannel, tisel: InputTISelection) { + pub fn set_input_ti_selection(&self, channel: Channel, tisel: InputTISelection) { let raw_channel = channel.index(); self.regs_gp16() .ccmr_input(raw_channel / 2) @@ -542,7 +542,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { } /// Set input capture mode. - pub fn set_input_capture_mode(&self, channel: TimerChannel, mode: InputCaptureMode) { + pub fn set_input_capture_mode(&self, channel: Channel, mode: InputCaptureMode) { self.regs_gp16().ccer().modify(|r| match mode { InputCaptureMode::Rising => { r.set_ccnp(channel.index(), false); @@ -560,7 +560,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { } /// Set output compare mode. - pub fn set_output_compare_mode(&self, channel: TimerChannel, mode: OutputCompareMode) { + pub fn set_output_compare_mode(&self, channel: Channel, mode: OutputCompareMode) { let raw_channel: usize = channel.index(); self.regs_gp16() .ccmr_output(raw_channel / 2) @@ -568,24 +568,24 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { } /// Set output polarity. - pub fn set_output_polarity(&self, channel: TimerChannel, polarity: OutputPolarity) { + pub fn set_output_polarity(&self, channel: Channel, polarity: OutputPolarity) { self.regs_gp16() .ccer() .modify(|w| w.set_ccp(channel.index(), polarity.into())); } /// Enable/disable a channel. - pub fn enable_channel(&self, channel: TimerChannel, enable: bool) { + pub fn enable_channel(&self, channel: Channel, enable: bool) { self.regs_gp16().ccer().modify(|w| w.set_cce(channel.index(), enable)); } /// Get enable/disable state of a channel - pub fn get_channel_enable_state(&self, channel: TimerChannel) -> bool { + pub fn get_channel_enable_state(&self, channel: Channel) -> bool { self.regs_gp16().ccer().read().cce(channel.index()) } /// Set compare value for a channel. - pub fn set_compare_value(&self, channel: TimerChannel, value: u32) { + pub fn set_compare_value(&self, channel: Channel, value: u32) { match T::BITS { TimerBits::Bits16 => { let value = unwrap!(u16::try_from(value)); @@ -599,7 +599,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { } /// Get compare value for a channel. - pub fn get_compare_value(&self, channel: TimerChannel) -> u32 { + pub fn get_compare_value(&self, channel: Channel) -> u32 { match T::BITS { TimerBits::Bits16 => self.regs_gp16().ccr(channel.index()).read().ccr() as u32, #[cfg(not(stm32l0))] @@ -608,12 +608,12 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { } /// Get capture value for a channel. - pub fn get_capture_value(&self, channel: TimerChannel) -> u32 { + pub fn get_capture_value(&self, channel: Channel) -> u32 { self.get_compare_value(channel) } /// Set output compare preload. - pub fn set_output_compare_preload(&self, channel: TimerChannel, preload: bool) { + pub fn set_output_compare_preload(&self, channel: Channel, preload: bool) { let channel_index = channel.index(); self.regs_gp16() .ccmr_output(channel_index / 2) @@ -631,12 +631,12 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { } /// Get capture compare DMA enable state - pub fn get_cc_dma_enable_state(&self, channel: TimerChannel) -> bool { + pub fn get_cc_dma_enable_state(&self, channel: Channel) -> bool { self.regs_gp16().dier().read().ccde(channel.index()) } /// Set capture compare DMA enable state - pub fn set_cc_dma_enable_state(&self, channel: TimerChannel, ccde: bool) { + pub fn set_cc_dma_enable_state(&self, channel: Channel, ccde: bool) { self.regs_gp16().dier().modify(|w| w.set_ccde(channel.index(), ccde)) } @@ -713,14 +713,14 @@ impl<'d, T: AdvancedInstance4Channel> Timer<'d, T> { } /// Set complementary output polarity. - pub fn set_complementary_output_polarity(&self, channel: TimerChannel, polarity: OutputPolarity) { + pub fn set_complementary_output_polarity(&self, channel: Channel, polarity: OutputPolarity) { self.regs_advanced() .ccer() .modify(|w| w.set_ccnp(channel.index(), polarity.into())); } /// Enable/disable a complementary channel. - pub fn enable_complementary_channel(&self, channel: TimerChannel, enable: bool) { + pub fn enable_complementary_channel(&self, channel: Channel, enable: bool) { self.regs_advanced() .ccer() .modify(|w| w.set_ccne(channel.index(), enable)); diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 362d95e25..7062f5f4c 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -19,7 +19,7 @@ use crate::rcc::RccPeripheral; /// Timer channel. #[derive(Clone, Copy)] -pub enum TimerChannel { +pub enum Channel { /// Channel 1. Ch1, /// Channel 2. @@ -30,14 +30,14 @@ pub enum TimerChannel { Ch4, } -impl TimerChannel { +impl Channel { /// Get the channel index (0..3) pub fn index(&self) -> usize { match self { - TimerChannel::Ch1 => 0, - TimerChannel::Ch2 => 1, - TimerChannel::Ch3 => 2, - TimerChannel::Ch4 => 3, + Channel::Ch1 => 0, + Channel::Ch2 => 1, + Channel::Ch3 => 2, + Channel::Ch4 => 3, } } } @@ -53,33 +53,33 @@ pub enum Ch4 {} /// Timer channel trait. #[allow(private_bounds)] -pub trait Channel: SealedChannel { +pub trait TimerChannel: SealedTimerChannel { /// The runtime channel. - const CHANNEL: TimerChannel; + const CHANNEL: Channel; } -trait SealedChannel {} +trait SealedTimerChannel {} -impl Channel for Ch1 { - const CHANNEL: TimerChannel = TimerChannel::Ch1; +impl TimerChannel for Ch1 { + const CHANNEL: Channel = Channel::Ch1; } -impl Channel for Ch2 { - const CHANNEL: TimerChannel = TimerChannel::Ch2; +impl TimerChannel for Ch2 { + const CHANNEL: Channel = Channel::Ch2; } -impl Channel for Ch3 { - const CHANNEL: TimerChannel = TimerChannel::Ch3; +impl TimerChannel for Ch3 { + const CHANNEL: Channel = Channel::Ch3; } -impl Channel for Ch4 { - const CHANNEL: TimerChannel = TimerChannel::Ch4; +impl TimerChannel for Ch4 { + const CHANNEL: Channel = Channel::Ch4; } -impl SealedChannel for Ch1 {} -impl SealedChannel for Ch2 {} -impl SealedChannel for Ch3 {} -impl SealedChannel for Ch4 {} +impl SealedTimerChannel for Ch1 {} +impl SealedTimerChannel for Ch2 {} +impl SealedTimerChannel for Ch3 {} +impl SealedTimerChannel for Ch4 {} /// Timer break input. #[derive(Clone, Copy)] @@ -223,10 +223,10 @@ pub trait AdvancedInstance2Channel: BasicInstance + GeneralInstance2Channel + Ad /// Advanced 16-bit timer with 4 channels instance. pub trait AdvancedInstance4Channel: AdvancedInstance2Channel + GeneralInstance4Channel {} -pin_trait!(TimerPin, GeneralInstance4Channel, Channel); +pin_trait!(TimerPin, GeneralInstance4Channel, TimerChannel); pin_trait!(ExternalTriggerPin, GeneralInstance4Channel); -pin_trait!(TimerComplementaryPin, AdvancedInstance4Channel, Channel); +pin_trait!(TimerComplementaryPin, AdvancedInstance4Channel, TimerChannel); pin_trait!(BreakInputPin, AdvancedInstance4Channel, BreakInput); @@ -236,7 +236,7 @@ pin_trait!(BreakInputComparator2Pin, AdvancedInstance4Channel, BreakInput); // Update Event trigger DMA for every timer dma_trait!(UpDma, BasicInstance); -dma_trait!(Dma, GeneralInstance4Channel, Channel); +dma_trait!(Dma, GeneralInstance4Channel, TimerChannel); #[allow(unused)] macro_rules! impl_core_timer { diff --git a/embassy-stm32/src/timer/one_pulse.rs b/embassy-stm32/src/timer/one_pulse.rs index e89ad8390..c8f0cafe7 100644 --- a/embassy-stm32/src/timer/one_pulse.rs +++ b/embassy-stm32/src/timer/one_pulse.rs @@ -9,7 +9,7 @@ use core::task::{Context, Poll}; use super::low_level::{ CountingMode, FilterValue, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource as Ts, }; -use super::{CaptureCompareInterruptHandler, ExternalTriggerPin, GeneralInstance4Channel, TimerChannel, TimerPin}; +use super::{CaptureCompareInterruptHandler, Channel, ExternalTriggerPin, GeneralInstance4Channel, TimerPin}; pub use super::{Ch1, Ch2}; use crate::gpio::{AfType, AnyPin, Pull}; use crate::interrupt::typelevel::{Binding, Interrupt}; @@ -76,7 +76,7 @@ impl TimerTriggerPin for P where T: GeneralInstance4Channel, P: TimerPin, - C: super::Channel + TriggerSource, + C: super::TimerChannel + TriggerSource, { fn af_num(&self) -> u8 { TimerPin::af_num(self) @@ -97,7 +97,7 @@ impl SealedTimerTriggerPin for P where T: GeneralInstance4Channel, P: TimerPin, - C: super::Channel + TriggerSource, + C: super::TimerChannel + TriggerSource, { } @@ -143,9 +143,9 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { this.inner.set_trigger_source(Ts::TI1F_ED); this.inner - .set_input_ti_selection(TimerChannel::Ch1, InputTISelection::Normal); + .set_input_ti_selection(Channel::Ch1, InputTISelection::Normal); this.inner - .set_input_capture_filter(TimerChannel::Ch1, FilterValue::NO_FILTER); + .set_input_capture_filter(Channel::Ch1, FilterValue::NO_FILTER); this.new_inner(freq, pulse_end, counting_mode); this @@ -168,10 +168,10 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { this.inner.set_trigger_source(Ts::TI1FP1); this.inner - .set_input_ti_selection(TimerChannel::Ch1, InputTISelection::Normal); + .set_input_ti_selection(Channel::Ch1, InputTISelection::Normal); this.inner - .set_input_capture_filter(TimerChannel::Ch1, FilterValue::NO_FILTER); - this.inner.set_input_capture_mode(TimerChannel::Ch1, capture_mode); + .set_input_capture_filter(Channel::Ch1, FilterValue::NO_FILTER); + this.inner.set_input_capture_mode(Channel::Ch1, capture_mode); this.new_inner(freq, pulse_end, counting_mode); this @@ -194,10 +194,10 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { this.inner.set_trigger_source(Ts::TI2FP2); this.inner - .set_input_ti_selection(TimerChannel::Ch2, InputTISelection::Normal); + .set_input_ti_selection(Channel::Ch2, InputTISelection::Normal); this.inner - .set_input_capture_filter(TimerChannel::Ch2, FilterValue::NO_FILTER); - this.inner.set_input_capture_mode(TimerChannel::Ch2, capture_mode); + .set_input_capture_filter(Channel::Ch2, FilterValue::NO_FILTER); + this.inner.set_input_capture_mode(Channel::Ch2, capture_mode); this.new_inner(freq, pulse_end, counting_mode); this @@ -269,7 +269,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { /// Get a single channel /// /// If you need to use multiple channels, use [`Self::split`]. - pub fn channel(&mut self, channel: TimerChannel) -> OnePulseChannel<'_, T> { + pub fn channel(&mut self, channel: Channel) -> OnePulseChannel<'_, T> { OnePulseChannel { inner: unsafe { self.inner.clone_unchecked() }, channel, @@ -282,7 +282,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { /// /// If you need to use multiple channels, use [`Self::split`]. pub fn ch1(&mut self) -> OnePulseChannel<'_, T> { - self.channel(TimerChannel::Ch1) + self.channel(Channel::Ch1) } /// Channel 2 @@ -291,7 +291,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { /// /// If you need to use multiple channels, use [`Self::split`]. pub fn ch2(&mut self) -> OnePulseChannel<'_, T> { - self.channel(TimerChannel::Ch2) + self.channel(Channel::Ch2) } /// Channel 3 @@ -300,7 +300,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { /// /// If you need to use multiple channels, use [`Self::split`]. pub fn ch3(&mut self) -> OnePulseChannel<'_, T> { - self.channel(TimerChannel::Ch3) + self.channel(Channel::Ch3) } /// Channel 4 @@ -309,7 +309,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { /// /// If you need to use multiple channels, use [`Self::split`]. pub fn ch4(&mut self) -> OnePulseChannel<'_, T> { - self.channel(TimerChannel::Ch4) + self.channel(Channel::Ch4) } /// Splits a [`OnePulse`] into four output channels. @@ -328,10 +328,10 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { }; OnePulseChannels { - ch1: ch(TimerChannel::Ch1), - ch2: ch(TimerChannel::Ch2), - ch3: ch(TimerChannel::Ch3), - ch4: ch(TimerChannel::Ch4), + ch1: ch(Channel::Ch1), + ch2: ch(Channel::Ch2), + ch3: ch(Channel::Ch3), + ch4: ch(Channel::Ch4), } } } @@ -355,7 +355,7 @@ pub struct OnePulseChannels<'d, T: GeneralInstance4Channel> { /// configuration is shared with all four channels. pub struct OnePulseChannel<'d, T: GeneralInstance4Channel> { inner: ManuallyDrop>, - channel: TimerChannel, + channel: Channel, } impl<'d, T: GeneralInstance4Channel> OnePulseChannel<'d, T> { @@ -402,7 +402,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulseChannel<'d, T> { #[must_use = "futures do nothing unless you `.await` or poll them"] struct OnePulseFuture { - channel: TimerChannel, + channel: Channel, phantom: PhantomData, } diff --git a/embassy-stm32/src/timer/pwm_input.rs b/embassy-stm32/src/timer/pwm_input.rs index 3f9e5f651..2e05a0593 100644 --- a/embassy-stm32/src/timer/pwm_input.rs +++ b/embassy-stm32/src/timer/pwm_input.rs @@ -1,14 +1,14 @@ //! PWM Input driver. use super::low_level::{CountingMode, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource}; -use super::{Ch1, Ch2, GeneralInstance4Channel, TimerChannel, TimerPin}; +use super::{Ch1, Ch2, GeneralInstance4Channel, Channel, TimerPin}; use crate::gpio::{AfType, Pull}; use crate::time::Hertz; use crate::Peri; /// PWM Input driver. pub struct PwmInput<'d, T: GeneralInstance4Channel> { - channel: TimerChannel, + channel: Channel, inner: Timer<'d, T>, } @@ -17,17 +17,17 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { pub fn new(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin>, pull: Pull, freq: Hertz) -> Self { pin.set_as_af(pin.af_num(), AfType::input(pull)); - Self::new_inner(tim, freq, TimerChannel::Ch1, TimerChannel::Ch2) + Self::new_inner(tim, freq, Channel::Ch1, Channel::Ch2) } /// Create a new PWM input driver. pub fn new_alt(tim: Peri<'d, T>, pin: Peri<'d, impl TimerPin>, pull: Pull, freq: Hertz) -> Self { pin.set_as_af(pin.af_num(), AfType::input(pull)); - Self::new_inner(tim, freq, TimerChannel::Ch2, TimerChannel::Ch1) + Self::new_inner(tim, freq, Channel::Ch2, Channel::Ch1) } - fn new_inner(tim: Peri<'d, T>, freq: Hertz, ch1: TimerChannel, ch2: TimerChannel) -> Self { + fn new_inner(tim: Peri<'d, T>, freq: Hertz, ch1: Channel, ch2: Channel) -> Self { let mut inner = Timer::new(tim); inner.set_counting_mode(CountingMode::EdgeAlignedUp); @@ -44,8 +44,8 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { inner.set_input_capture_mode(ch2, InputCaptureMode::Falling); inner.set_trigger_source(match ch1 { - TimerChannel::Ch1 => TriggerSource::TI1FP1, - TimerChannel::Ch2 => TriggerSource::TI2FP2, + Channel::Ch1 => TriggerSource::TI1FP1, + Channel::Ch2 => TriggerSource::TI2FP2, _ => panic!("Invalid channel for PWM input"), }); @@ -58,19 +58,19 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { /// Enable the given channel. pub fn enable(&mut self) { - self.inner.enable_channel(TimerChannel::Ch1, true); - self.inner.enable_channel(TimerChannel::Ch2, true); + self.inner.enable_channel(Channel::Ch1, true); + self.inner.enable_channel(Channel::Ch2, true); } /// Disable the given channel. pub fn disable(&mut self) { - self.inner.enable_channel(TimerChannel::Ch1, false); - self.inner.enable_channel(TimerChannel::Ch2, false); + self.inner.enable_channel(Channel::Ch1, false); + self.inner.enable_channel(Channel::Ch2, false); } /// Check whether given channel is enabled pub fn is_enabled(&self) -> bool { - self.inner.get_channel_enable_state(TimerChannel::Ch1) + self.inner.get_channel_enable_state(Channel::Ch1) } /// Get the period tick count @@ -81,8 +81,8 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { /// Get the pulse width tick count pub fn get_width_ticks(&self) -> u32 { self.inner.get_capture_value(match self.channel { - TimerChannel::Ch1 => TimerChannel::Ch2, - TimerChannel::Ch2 => TimerChannel::Ch1, + Channel::Ch1 => Channel::Ch2, + Channel::Ch2 => Channel::Ch1, _ => panic!("Invalid channel for PWM input"), }) } diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs index 657052cfa..eabe1b22a 100644 --- a/embassy-stm32/src/timer/qei.rs +++ b/embassy-stm32/src/timer/qei.rs @@ -8,7 +8,7 @@ use super::low_level::Timer; pub use super::{Ch1, Ch2}; use super::{GeneralInstance4Channel, TimerPin}; use crate::gpio::{AfType, AnyPin, Pull}; -use crate::timer::Channel; +use crate::timer::TimerChannel; use crate::Peri; /// Counting direction @@ -39,7 +39,7 @@ impl<'d, T: GeneralInstance4Channel, C: QeiChannel> QeiPin<'d, T, C> { } } -trait SealedQeiChannel: Channel {} +trait SealedQeiChannel: TimerChannel {} /// Marker trait for a timer channel eligible for use with QEI. #[expect(private_bounds)] diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs index 02835c379..c04b1ab97 100644 --- a/embassy-stm32/src/timer/simple_pwm.rs +++ b/embassy-stm32/src/timer/simple_pwm.rs @@ -4,7 +4,7 @@ use core::marker::PhantomData; use core::mem::ManuallyDrop; use super::low_level::{CountingMode, OutputCompareMode, OutputPolarity, Timer}; -use super::{Ch1, Ch2, Ch3, Ch4, GeneralInstance4Channel, TimerBits, TimerChannel, TimerPin}; +use super::{Ch1, Ch2, Ch3, Ch4, Channel, GeneralInstance4Channel, TimerBits, TimerChannel, TimerPin}; #[cfg(gpio_v2)] use crate::gpio::Pull; use crate::gpio::{AfType, AnyPin, OutputType, Speed}; @@ -34,46 +34,37 @@ pub struct PwmPinConfig { pub pull: Pull, } -macro_rules! channel_impl { - ($new_chx:ident, $new_chx_with_config:ident, $channel:ident, $pin_trait:ident) => { - impl<'d, T: GeneralInstance4Channel> PwmPin<'d, T, $channel> { - #[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance.")] - pub fn $new_chx(pin: Peri<'d, impl $pin_trait>, output_type: OutputType) -> Self { - critical_section::with(|_| { - pin.set_low(); - pin.set_as_af(pin.af_num(), AfType::output(output_type, Speed::VeryHigh)); - }); - PwmPin { - _pin: pin.into(), - phantom: PhantomData, - } - } - - #[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance with config.")] - pub fn $new_chx_with_config(pin: Peri<'d, impl $pin_trait>, pin_config: PwmPinConfig) -> Self { - critical_section::with(|_| { - pin.set_low(); - pin.set_as_af( - pin.af_num(), - #[cfg(gpio_v1)] - AfType::output(pin_config.output_type, pin_config.speed), - #[cfg(gpio_v2)] - AfType::output_pull(pin_config.output_type, pin_config.speed, pin_config.pull), - ); - }); - PwmPin { - _pin: pin.into(), - phantom: PhantomData, - } - } +impl<'d, T: GeneralInstance4Channel, C: TimerChannel> PwmPin<'d, T, C> { + /// Create a new PWM pin instance. + pub fn new(pin: Peri<'d, impl TimerPin>, output_type: OutputType) -> Self { + critical_section::with(|_| { + pin.set_low(); + pin.set_as_af(pin.af_num(), AfType::output(output_type, Speed::VeryHigh)); + }); + PwmPin { + _pin: pin.into(), + phantom: PhantomData, } - }; -} + } -channel_impl!(new_ch1, new_ch1_with_config, Ch1, TimerPin); -channel_impl!(new_ch2, new_ch2_with_config, Ch2, TimerPin); -channel_impl!(new_ch3, new_ch3_with_config, Ch3, TimerPin); -channel_impl!(new_ch4, new_ch4_with_config, Ch4, TimerPin); + /// Create a new PWM pin instance with config. + pub fn new_with_config(pin: Peri<'d, impl TimerPin>, pin_config: PwmPinConfig) -> Self { + critical_section::with(|_| { + pin.set_low(); + pin.set_as_af( + pin.af_num(), + #[cfg(gpio_v1)] + AfType::output(pin_config.output_type, pin_config.speed), + #[cfg(gpio_v2)] + AfType::output_pull(pin_config.output_type, pin_config.speed, pin_config.pull), + ); + }); + PwmPin { + _pin: pin.into(), + phantom: PhantomData, + } + } +} /// A single channel of a pwm, obtained from [`SimplePwm::split`], /// [`SimplePwm::channel`], [`SimplePwm::ch1`], etc. @@ -82,7 +73,7 @@ channel_impl!(new_ch4, new_ch4_with_config, Ch4, TimerPin); /// the frequency configuration is shared with all four channels. pub struct SimplePwmChannel<'d, T: GeneralInstance4Channel> { timer: ManuallyDrop>, - channel: TimerChannel, + channel: Channel, } // TODO: check for RMW races @@ -207,18 +198,13 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { this.inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details this.inner.start(); - [ - TimerChannel::Ch1, - TimerChannel::Ch2, - TimerChannel::Ch3, - TimerChannel::Ch4, - ] - .iter() - .for_each(|&channel| { - this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1); - - this.inner.set_output_compare_preload(channel, true); - }); + [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4] + .iter() + .for_each(|&channel| { + this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1); + + this.inner.set_output_compare_preload(channel, true); + }); this } @@ -226,7 +212,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// Get a single channel /// /// If you need to use multiple channels, use [`Self::split`]. - pub fn channel(&mut self, channel: TimerChannel) -> SimplePwmChannel<'_, T> { + pub fn channel(&mut self, channel: Channel) -> SimplePwmChannel<'_, T> { SimplePwmChannel { timer: unsafe { self.inner.clone_unchecked() }, channel, @@ -239,7 +225,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// /// If you need to use multiple channels, use [`Self::split`]. pub fn ch1(&mut self) -> SimplePwmChannel<'_, T> { - self.channel(TimerChannel::Ch1) + self.channel(Channel::Ch1) } /// Channel 2 @@ -248,7 +234,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// /// If you need to use multiple channels, use [`Self::split`]. pub fn ch2(&mut self) -> SimplePwmChannel<'_, T> { - self.channel(TimerChannel::Ch2) + self.channel(Channel::Ch2) } /// Channel 3 @@ -257,7 +243,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// /// If you need to use multiple channels, use [`Self::split`]. pub fn ch3(&mut self) -> SimplePwmChannel<'_, T> { - self.channel(TimerChannel::Ch3) + self.channel(Channel::Ch3) } /// Channel 4 @@ -266,7 +252,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// /// If you need to use multiple channels, use [`Self::split`]. pub fn ch4(&mut self) -> SimplePwmChannel<'_, T> { - self.channel(TimerChannel::Ch4) + self.channel(Channel::Ch4) } /// Splits a [`SimplePwm`] into four pwm channels. @@ -288,10 +274,10 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { }; SimplePwmChannels { - ch1: ch(TimerChannel::Ch1), - ch2: ch(TimerChannel::Ch2), - ch3: ch(TimerChannel::Ch3), - ch4: ch(TimerChannel::Ch4), + ch1: ch(Channel::Ch1), + ch2: ch(Channel::Ch2), + ch3: ch(Channel::Ch3), + ch4: ch(Channel::Ch4), } } @@ -322,7 +308,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// /// Note: /// you will need to provide corresponding TIMx_UP DMA channel to use this method. - pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma>, channel: TimerChannel, duty: &[u16]) { + pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma>, channel: Channel, duty: &[u16]) { #[allow(clippy::let_unit_value)] // eg. stm32f334 let req = dma.request(); @@ -405,8 +391,8 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { pub async fn waveform_up_multi_channel( &mut self, dma: Peri<'_, impl super::UpDma>, - starting_channel: TimerChannel, - ending_channel: TimerChannel, + starting_channel: Channel, + ending_channel: Channel, duty: &[u16], ) { let cr1_addr = self.inner.regs_gp16().cr1().as_ptr() as u32; @@ -462,106 +448,97 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { } } -macro_rules! impl_waveform_chx { - ($fn_name:ident, $dma_ch:ident, $cc_ch:ident) => { - impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { - /// Generate a sequence of PWM waveform - pub async fn $fn_name(&mut self, dma: Peri<'_, impl super::$dma_ch>, duty: &[u16]) { - use crate::pac::timer::vals::Ccds; +impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { + /// Generate a sequence of PWM waveform + pub async fn waveform(&mut self, dma: Peri<'_, impl super::Dma>, duty: &[u16]) { + use crate::pac::timer::vals::Ccds; - #[allow(clippy::let_unit_value)] // eg. stm32f334 - let req = dma.request(); + #[allow(clippy::let_unit_value)] // eg. stm32f334 + let req = dma.request(); - let cc_channel = TimerChannel::$cc_ch; + let cc_channel = C::CHANNEL; - let original_duty_state = self.channel(cc_channel).current_duty_cycle(); - let original_enable_state = self.channel(cc_channel).is_enabled(); - let original_cc_dma_on_update = self.inner.get_cc_dma_selection() == Ccds::ON_UPDATE; - let original_cc_dma_enabled = self.inner.get_cc_dma_enable_state(cc_channel); + let original_duty_state = self.channel(cc_channel).current_duty_cycle(); + let original_enable_state = self.channel(cc_channel).is_enabled(); + let original_cc_dma_on_update = self.inner.get_cc_dma_selection() == Ccds::ON_UPDATE; + let original_cc_dma_enabled = self.inner.get_cc_dma_enable_state(cc_channel); - // redirect CC DMA request onto Update Event - if !original_cc_dma_on_update { - self.inner.set_cc_dma_selection(Ccds::ON_UPDATE) - } + // redirect CC DMA request onto Update Event + if !original_cc_dma_on_update { + self.inner.set_cc_dma_selection(Ccds::ON_UPDATE) + } - if !original_cc_dma_enabled { - self.inner.set_cc_dma_enable_state(cc_channel, true); - } + if !original_cc_dma_enabled { + self.inner.set_cc_dma_enable_state(cc_channel, true); + } - if !original_enable_state { - self.channel(cc_channel).enable(); - } + if !original_enable_state { + self.channel(cc_channel).enable(); + } - unsafe { + unsafe { + #[cfg(not(any(bdma, gpdma)))] + use crate::dma::{Burst, FifoThreshold}; + use crate::dma::{Transfer, TransferOptions}; + + let dma_transfer_option = TransferOptions { + #[cfg(not(any(bdma, gpdma)))] + fifo_threshold: Some(FifoThreshold::Full), + #[cfg(not(any(bdma, gpdma)))] + mburst: Burst::Incr8, + ..Default::default() + }; + + match self.inner.bits() { + TimerBits::Bits16 => { + Transfer::new_write( + dma, + req, + duty, + self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u16, + dma_transfer_option, + ) + .await + } + #[cfg(not(any(stm32l0)))] + TimerBits::Bits32 => { #[cfg(not(any(bdma, gpdma)))] - use crate::dma::{Burst, FifoThreshold}; - use crate::dma::{Transfer, TransferOptions}; - - let dma_transfer_option = TransferOptions { - #[cfg(not(any(bdma, gpdma)))] - fifo_threshold: Some(FifoThreshold::Full), - #[cfg(not(any(bdma, gpdma)))] - mburst: Burst::Incr8, - ..Default::default() - }; - - match self.inner.bits() { - TimerBits::Bits16 => { - Transfer::new_write( - dma, - req, - duty, - self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u16, - dma_transfer_option, - ) - .await - } - #[cfg(not(any(stm32l0)))] - TimerBits::Bits32 => { - #[cfg(not(any(bdma, gpdma)))] - panic!("unsupported timer bits"); - - #[cfg(any(bdma, gpdma))] - Transfer::new_write( - dma, - req, - duty, - self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u32, - dma_transfer_option, - ) - .await - } - }; - }; - - // restore output compare state - if !original_enable_state { - self.channel(cc_channel).disable(); + panic!("unsupported timer bits"); + + #[cfg(any(bdma, gpdma))] + Transfer::new_write( + dma, + req, + duty, + self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut u32, + dma_transfer_option, + ) + .await } + }; + }; - self.channel(cc_channel).set_duty_cycle(original_duty_state); + // restore output compare state + if !original_enable_state { + self.channel(cc_channel).disable(); + } - // Since DMA is closed before timer Capture Compare Event trigger DMA is turn off, - // this can almost always trigger a DMA FIFO error. - // - // optional TODO: - // clean FEIF after disable UDE - if !original_cc_dma_enabled { - self.inner.set_cc_dma_enable_state(cc_channel, false); - } + self.channel(cc_channel).set_duty_cycle(original_duty_state); - if !original_cc_dma_on_update { - self.inner.set_cc_dma_selection(Ccds::ON_COMPARE) - } - } + // Since DMA is closed before timer Capture Compare Event trigger DMA is turn off, + // this can almost always trigger a DMA FIFO error. + // + // optional TODO: + // clean FEIF after disable UDE + if !original_cc_dma_enabled { + self.inner.set_cc_dma_enable_state(cc_channel, false); } - }; -} -impl_waveform_chx!(waveform_ch1, Dma, Ch1); -impl_waveform_chx!(waveform_ch2, Dma, Ch2); -impl_waveform_chx!(waveform_ch3, Dma, Ch3); -impl_waveform_chx!(waveform_ch4, Dma, Ch4); + if !original_cc_dma_on_update { + self.inner.set_cc_dma_selection(Ccds::ON_COMPARE) + } + } +} impl<'d, T: GeneralInstance4Channel> embedded_hal_1::pwm::ErrorType for SimplePwmChannel<'d, T> { type Error = core::convert::Infallible; @@ -599,7 +576,7 @@ impl<'d, T: GeneralInstance4Channel> embedded_hal_1::pwm::SetDutyCycle for Simpl } impl<'d, T: GeneralInstance4Channel> embedded_hal_02::Pwm for SimplePwm<'d, T> { - type Channel = TimerChannel; + type Channel = Channel; type Time = Hertz; type Duty = u32; -- cgit