From 790940a18c093fb7c7f94585be81d7d02892b4fb Mon Sep 17 00:00:00 2001 From: xoviat Date: Thu, 27 Nov 2025 11:29:24 -0600 Subject: stm32: use typelevel timer type --- embassy-stm32/CHANGELOG.md | 1 + embassy-stm32/src/fmt.rs | 10 ++ embassy-stm32/src/timer/complementary_pwm.rs | 18 +-- embassy-stm32/src/timer/input_capture.rs | 2 +- embassy-stm32/src/timer/low_level.rs | 191 ++++++++++----------------- embassy-stm32/src/timer/mod.rs | 30 +++-- embassy-stm32/src/timer/one_pulse.rs | 12 +- embassy-stm32/src/timer/pwm_input.rs | 14 +- embassy-stm32/src/timer/ringbuffered.rs | 12 +- embassy-stm32/src/timer/simple_pwm.rs | 16 +-- 10 files changed, 138 insertions(+), 168 deletions(-) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index 4c38b0add..13c95b60a 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased - ReleaseDate +- change: stm32: use typelevel timer type to allow dma for 32 bit timers - fix: fix incorrect handling of split interrupts in timer driver - feat: allow granular stop for regular usart - feat: Add continuous waveform method to SimplePWM diff --git a/embassy-stm32/src/fmt.rs b/embassy-stm32/src/fmt.rs index b6ae24ee8..b731796f0 100644 --- a/embassy-stm32/src/fmt.rs +++ b/embassy-stm32/src/fmt.rs @@ -206,6 +206,16 @@ macro_rules! error { }; } +#[cfg(feature = "defmt")] +trait_set::trait_set! { + pub trait Debuggable = Debug + defmt::Format; +} + +#[cfg(not(feature = "defmt"))] +trait_set::trait_set! { + pub trait Debuggable = Debug; +} + #[cfg(feature = "defmt")] #[collapse_debuginfo(yes)] macro_rules! unwrap { diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs index 77f19a37b..d194899c6 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs @@ -178,9 +178,9 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { /// This value depends on the configured frequency and the timer's clock rate from RCC. pub fn get_max_duty(&self) -> u16 { if self.inner.get_counting_mode().is_center_aligned() { - self.inner.get_max_compare_value() as u16 + unwrap!(self.inner.get_max_compare_value().try_into()) } else { - self.inner.get_max_compare_value() as u16 + 1 + unwrap!(self.inner.get_max_compare_value().try_into()) + 1 } } @@ -189,7 +189,7 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { /// 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: Channel, duty: u16) { assert!(duty <= self.get_max_duty()); - self.inner.set_compare_value(channel, duty as _) + self.inner.set_compare_value(channel, duty.into()) } /// Set the output polarity for a given channel. @@ -220,7 +220,7 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'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: Channel, duty: &[u16]) { + pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma>, channel: Channel, duty: &[T::Word]) { self.inner.enable_channel(channel, true); self.inner.enable_update_dma(true); self.inner.setup_update_dma(dma, channel, duty).await; @@ -261,7 +261,7 @@ impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { dma: Peri<'_, impl super::UpDma>, starting_channel: Channel, ending_channel: Channel, - duty: &[u16], + duty: &[T::Word], ) { self.inner.enable_update_dma(true); self.inner @@ -291,20 +291,20 @@ impl<'d, T: AdvancedInstance4Channel> embedded_hal_02::Pwm for ComplementaryPwm< } fn get_duty(&self, channel: Self::Channel) -> Self::Duty { - self.inner.get_compare_value(channel) as u16 + unwrap!(self.inner.get_compare_value(channel).try_into()) } fn get_max_duty(&self) -> Self::Duty { if self.inner.get_counting_mode().is_center_aligned() { - self.inner.get_max_compare_value() as u16 + unwrap!(self.inner.get_max_compare_value().try_into()) } else { - self.inner.get_max_compare_value() as u16 + 1 + unwrap!(self.inner.get_max_compare_value().try_into()) + 1 } } fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) { assert!(duty <= self.get_max_duty()); - self.inner.set_compare_value(channel, duty as u32) + self.inner.set_compare_value(channel, unwrap!(duty.try_into())) } fn set_period

(&mut self, period: P) diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs index 9cf0f8c34..3e1482b67 100644 --- a/embassy-stm32/src/timer/input_capture.rs +++ b/embassy-stm32/src/timer/input_capture.rs @@ -97,7 +97,7 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { /// Get capture value for a channel. pub fn get_capture_value(&self, channel: Channel) -> u32 { - self.inner.get_capture_value(channel) + self.inner.get_capture_value(channel).into() } /// Get input interrupt. diff --git a/embassy-stm32/src/timer/low_level.rs b/embassy-stm32/src/timer/low_level.rs index aba08081f..73a81bff1 100644 --- a/embassy-stm32/src/timer/low_level.rs +++ b/embassy-stm32/src/timer/low_level.rs @@ -268,6 +268,11 @@ impl<'d, T: CoreInstance> Timer<'d, T> { unsafe { crate::pac::timer::TimGp32::from_ptr(T::regs()) } } + #[cfg(stm32l0)] + fn regs_gp32_unchecked(&self) -> crate::pac::timer::TimGp16 { + unsafe { crate::pac::timer::TimGp16::from_ptr(T::regs()) } + } + /// Start the timer. pub fn start(&self) { self.regs_core().cr1().modify(|r| r.set_cen(true)); @@ -296,7 +301,12 @@ impl<'d, T: CoreInstance> Timer<'d, T> { /// get the capability of the timer pub fn bits(&self) -> TimerBits { - T::BITS + match T::Word::bits() { + 16 => TimerBits::Bits16, + #[cfg(not(stm32l0))] + 32 => TimerBits::Bits32, + _ => unreachable!(), + } } /// Set the frequency of how many times per second the timer counts up to the max value or down to 0. @@ -306,18 +316,10 @@ impl<'d, T: CoreInstance> Timer<'d, T> { /// In center-aligned mode (which not all timers support), the wrap-around frequency is effectively halved /// because it needs to count up and down. pub fn set_frequency(&self, frequency: Hertz) { - match T::BITS { - TimerBits::Bits16 => { - self.set_frequency_internal(frequency, 16); - } - #[cfg(not(stm32l0))] - TimerBits::Bits32 => { - self.set_frequency_internal(frequency, 32); - } - } + self.set_frequency_internal(frequency, T::Word::bits()); } - pub(crate) fn set_frequency_internal(&self, frequency: Hertz, max_divide_by_bits: u8) { + pub(crate) fn set_frequency_internal(&self, frequency: Hertz, max_divide_by_bits: usize) { let f = frequency.0; assert!(f > 0); let timer_f = T::frequency().0; @@ -326,25 +328,15 @@ impl<'d, T: CoreInstance> Timer<'d, T> { let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << max_divide_by_bits)).try_into()); let divide_by = pclk_ticks_per_timer_period / (u64::from(psc) + 1); - match T::BITS { - TimerBits::Bits16 => { - // the timer counts `0..=arr`, we want it to count `0..divide_by` - let arr = unwrap!(u16::try_from(divide_by - 1)); - - let regs = self.regs_core(); - regs.psc().write_value(psc); - regs.arr().write(|r| r.set_arr(arr)); - } - #[cfg(not(stm32l0))] - TimerBits::Bits32 => { - // the timer counts `0..=arr`, we want it to count `0..divide_by` - let arr: u32 = unwrap!(u32::try_from(divide_by - 1)); + // the timer counts `0..=arr`, we want it to count `0..divide_by` + let arr: T::Word = unwrap!(T::Word::try_from(divide_by - 1)); - let regs = self.regs_gp32_unchecked(); - regs.psc().write_value(psc); - regs.arr().write_value(arr); - } - } + let regs = self.regs_gp32_unchecked(); + regs.psc().write_value(psc); + #[cfg(stm32l0)] + regs.arr().write(|r| r.set_arr(unwrap!(arr.try_into()))); + #[cfg(not(stm32l0))] + regs.arr().write_value(arr.into()); } /// Set tick frequency. @@ -393,23 +385,14 @@ impl<'d, T: CoreInstance> Timer<'d, T> { pub fn get_frequency(&self) -> Hertz { let timer_f = T::frequency(); - match T::BITS { - TimerBits::Bits16 => { - let regs = self.regs_core(); - let arr = regs.arr().read().arr(); - let psc = regs.psc().read(); + let regs = self.regs_gp32_unchecked(); + #[cfg(not(stm32l0))] + let arr = regs.arr().read(); + #[cfg(stm32l0)] + let arr = regs.arr().read().arr(); + let psc = regs.psc().read(); - timer_f / arr / (psc + 1) - } - #[cfg(not(stm32l0))] - TimerBits::Bits32 => { - let regs = self.regs_gp32_unchecked(); - let arr = regs.arr().read(); - let psc = regs.psc().read(); - - timer_f / arr / (psc + 1) - } - } + timer_f / arr / (psc + 1) } /// Get the clock frequency of the timer (before prescaler is applied). @@ -469,42 +452,29 @@ impl<'d, T: GeneralInstance1Channel> Timer<'d, T> { } /// Get max compare value. This depends on the timer frequency and the clock frequency from RCC. - pub fn get_max_compare_value(&self) -> u32 { - match T::BITS { - TimerBits::Bits16 => self.regs_1ch().arr().read().arr() as u32, - #[cfg(not(stm32l0))] - TimerBits::Bits32 => self.regs_gp32_unchecked().arr().read(), - } + pub fn get_max_compare_value(&self) -> T::Word { + #[cfg(not(stm32l0))] + return unwrap!(self.regs_gp32_unchecked().arr().read().try_into()); + #[cfg(stm32l0)] + return unwrap!(self.regs_gp32_unchecked().arr().read().arr().try_into()); } /// Set the max compare value. /// /// An update event is generated to load the new value. The update event is /// generated such that it will not cause an interrupt or DMA request. - pub fn set_max_compare_value(&self, ticks: u32) { - match T::BITS { - TimerBits::Bits16 => { - let arr = unwrap!(u16::try_from(ticks)); + pub fn set_max_compare_value(&self, ticks: T::Word) { + let arr = ticks; - let regs = self.regs_1ch(); - regs.arr().write(|r| r.set_arr(arr)); + let regs = self.regs_gp32_unchecked(); + #[cfg(not(stm32l0))] + regs.arr().write_value(arr.into()); + #[cfg(stm32l0)] + regs.arr().write(|r| r.set_arr(unwrap!(arr.try_into()))); - regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTER_ONLY)); - regs.egr().write(|r| r.set_ug(true)); - regs.cr1().modify(|r| r.set_urs(vals::Urs::ANY_EVENT)); - } - #[cfg(not(stm32l0))] - TimerBits::Bits32 => { - let arr = ticks; - - let regs = self.regs_gp32_unchecked(); - regs.arr().write_value(arr); - - regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTER_ONLY)); - regs.egr().write(|r| r.set_ug(true)); - regs.cr1().modify(|r| r.set_urs(vals::Urs::ANY_EVENT)); - } - } + regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTER_ONLY)); + regs.egr().write(|r| r.set_ug(true)); + regs.cr1().modify(|r| r.set_urs(vals::Urs::ANY_EVENT)); } } @@ -638,26 +608,23 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { } /// Set compare value for a channel. - pub fn set_compare_value(&self, channel: Channel, value: u32) { - match T::BITS { - TimerBits::Bits16 => { - let value = unwrap!(u16::try_from(value)); - self.regs_gp16().ccr(channel.index()).modify(|w| w.set_ccr(value)); - } - #[cfg(not(stm32l0))] - TimerBits::Bits32 => { - self.regs_gp32_unchecked().ccr(channel.index()).write_value(value); - } - } + pub fn set_compare_value(&self, channel: Channel, value: T::Word) { + #[cfg(not(stm32l0))] + self.regs_gp32_unchecked() + .ccr(channel.index()) + .write_value(value.into()); + #[cfg(stm32l0)] + self.regs_gp16() + .ccr(channel.index()) + .modify(|w| w.set_ccr(unwrap!(value.try_into()))); } /// Get compare value for a channel. - 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))] - TimerBits::Bits32 => self.regs_gp32_unchecked().ccr(channel.index()).read(), - } + pub fn get_compare_value(&self, channel: Channel) -> T::Word { + #[cfg(not(stm32l0))] + return unwrap!(self.regs_gp32_unchecked().ccr(channel.index()).read().try_into()); + #[cfg(stm32l0)] + return unwrap!(self.regs_gp32_unchecked().ccr(channel.index()).read().ccr().try_into()); } /// Setup a ring buffer for the channel @@ -665,8 +632,8 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { &mut self, dma: Peri<'a, impl super::UpDma>, channel: Channel, - dma_buf: &'a mut [u16], - ) -> WritableRingBuffer<'a, u16> { + dma_buf: &'a mut [T::Word], + ) -> WritableRingBuffer<'a, T::Word> { #[allow(clippy::let_unit_value)] // eg. stm32f334 let req = dma.request(); @@ -686,7 +653,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { WritableRingBuffer::new( dma, req, - self.regs_1ch().ccr(channel.index()).as_ptr() as *mut u16, + self.regs_1ch().ccr(channel.index()).as_ptr() as *mut T::Word, dma_buf, dma_transfer_option, ) @@ -701,7 +668,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { &mut self, dma: Peri<'a, impl super::UpDma>, channel: Channel, - duty: &'a [u16], + duty: &'a [T::Word], ) -> Transfer<'a> { #[allow(clippy::let_unit_value)] // eg. stm32f334 let req = dma.request(); @@ -719,29 +686,13 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { ..Default::default() }; - match self.bits() { - TimerBits::Bits16 => Transfer::new_write( - dma, - req, - duty, - self.regs_1ch().ccr(channel.index()).as_ptr() as *mut u16, - dma_transfer_option, - ), - #[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.regs_1ch().ccr(channel.index()).as_ptr() as *mut u32, - dma_transfer_option, - ) - } - } + Transfer::new_write( + dma, + req, + duty, + self.regs_gp16().ccr(channel.index()).as_ptr() as *mut T::Word, + dma_transfer_option, + ) } } @@ -779,7 +730,7 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { dma: Peri<'a, impl super::UpDma>, starting_channel: Channel, ending_channel: Channel, - duty: &'a [u16], + duty: &'a [T::Word], ) -> Transfer<'a> { let cr1_addr = self.regs_gp16().cr1().as_ptr() as u32; let start_ch_index = starting_channel.index(); @@ -815,14 +766,14 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { dma, req, duty, - self.regs_gp16().dmar().as_ptr() as *mut u16, + self.regs_gp16().dmar().as_ptr() as *mut T::Word, dma_transfer_option, ) } } /// Get capture value for a channel. - pub fn get_capture_value(&self, channel: Channel) -> u32 { + pub fn get_capture_value(&self, channel: Channel) -> T::Word { self.get_compare_value(channel) } diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 3fa363881..74d1c9e77 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -15,6 +15,8 @@ pub mod qei; pub mod ringbuffered; pub mod simple_pwm; +use crate::dma::word::Word; +use crate::fmt::Debuggable; use crate::interrupt; use crate::rcc::RccPeripheral; @@ -163,7 +165,12 @@ pub trait CoreInstance: SealedInstance + 'static { type UpdateInterrupt: interrupt::typelevel::Interrupt; /// Amount of bits this timer has. - const BITS: TimerBits; + type Word: Word + + TryInto + + From + + TryFrom + + Into + + TryFrom; /// Registers for this timer. /// @@ -241,7 +248,7 @@ dma_trait!(Dma, GeneralInstance4Channel, TimerChannel); #[allow(unused)] macro_rules! impl_core_timer { - ($inst:ident, $bits:expr) => { + ($inst:ident, $bits:ident) => { impl SealedInstance for crate::peripherals::$inst { fn state() -> &'static State { static STATE: State = State::new(); @@ -251,8 +258,7 @@ macro_rules! impl_core_timer { impl CoreInstance for crate::peripherals::$inst { type UpdateInterrupt = crate::_generated::peripheral_interrupts::$inst::UP; - - const BITS: TimerBits = $bits; + type Word = $bits; fn regs() -> *mut () { crate::pac::$inst.as_ptr() @@ -306,13 +312,13 @@ macro_rules! impl_general_4ch_blank_sealed { foreach_interrupt! { ($inst:ident, timer, TIM_BASIC, UP, $irq:ident) => { - impl_core_timer!($inst, TimerBits::Bits16); + impl_core_timer!($inst, u16); impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {} }; ($inst:ident, timer, TIM_1CH, UP, $irq:ident) => { - impl_core_timer!($inst, TimerBits::Bits16); + impl_core_timer!($inst, u16); impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {} impl_general_1ch!($inst); @@ -322,7 +328,7 @@ foreach_interrupt! { }; ($inst:ident, timer, TIM_2CH, UP, $irq:ident) => { - impl_core_timer!($inst, TimerBits::Bits16); + impl_core_timer!($inst, u16); impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {} impl_general_1ch!($inst); @@ -332,7 +338,7 @@ foreach_interrupt! { }; ($inst:ident, timer, TIM_GP16, UP, $irq:ident) => { - impl_core_timer!($inst, TimerBits::Bits16); + impl_core_timer!($inst, u16); impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {} impl_general_1ch!($inst); @@ -342,7 +348,7 @@ foreach_interrupt! { }; ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => { - impl_core_timer!($inst, TimerBits::Bits32); + impl_core_timer!($inst, u32); impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {} impl_general_1ch!($inst); @@ -353,7 +359,7 @@ foreach_interrupt! { }; ($inst:ident, timer, TIM_1CH_CMP, UP, $irq:ident) => { - impl_core_timer!($inst, TimerBits::Bits16); + impl_core_timer!($inst, u16); impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {} impl_general_1ch!($inst); @@ -366,7 +372,7 @@ foreach_interrupt! { }; ($inst:ident, timer, TIM_2CH_CMP, UP, $irq:ident) => { - impl_core_timer!($inst, TimerBits::Bits16); + impl_core_timer!($inst, u16); impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {} impl_general_1ch!($inst); @@ -379,7 +385,7 @@ foreach_interrupt! { }; ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => { - impl_core_timer!($inst, TimerBits::Bits16); + impl_core_timer!($inst, u16); impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {} impl_general_1ch!($inst); diff --git a/embassy-stm32/src/timer/one_pulse.rs b/embassy-stm32/src/timer/one_pulse.rs index fe8681356..989e1d630 100644 --- a/embassy-stm32/src/timer/one_pulse.rs +++ b/embassy-stm32/src/timer/one_pulse.rs @@ -199,7 +199,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { fn new_inner(&mut self, freq: Hertz, pulse_end: u32, counting_mode: CountingMode) { self.inner.set_counting_mode(counting_mode); self.inner.set_tick_freq(freq); - self.inner.set_max_compare_value(pulse_end); + self.inner.set_max_compare_value(unwrap!(pulse_end.try_into())); self.inner.regs_core().cr1().modify(|r| r.set_opm(true)); // Required for advanced timers, see GeneralInstance4Channel for details self.inner.enable_outputs(); @@ -211,14 +211,14 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> { /// Get the end of the pulse in ticks from the trigger. pub fn pulse_end(&self) -> u32 { - let max = self.inner.get_max_compare_value(); + let max: u32 = self.inner.get_max_compare_value().into(); assert!(max < u32::MAX); max + 1 } /// Set the end of the pulse in ticks from the trigger. pub fn set_pulse_end(&mut self, ticks: u32) { - self.inner.set_max_compare_value(ticks) + self.inner.set_max_compare_value(unwrap!(ticks.try_into())) } /// Reset the timer on each trigger @@ -327,7 +327,7 @@ pub struct OnePulseChannel<'d, T: GeneralInstance4Channel> { impl<'d, T: GeneralInstance4Channel> OnePulseChannel<'d, T> { /// Get the end of the pulse in ticks from the trigger. pub fn pulse_end(&self) -> u32 { - let max = self.inner.get_max_compare_value(); + let max: u32 = self.inner.get_max_compare_value().into(); assert!(max < u32::MAX); max + 1 } @@ -339,13 +339,13 @@ impl<'d, T: GeneralInstance4Channel> OnePulseChannel<'d, T> { /// Get the start of the pulse in ticks from the trigger. pub fn pulse_delay(&mut self) -> u32 { - self.inner.get_compare_value(self.channel) + self.inner.get_compare_value(self.channel).into() } /// Set the start of the pulse in ticks from the trigger. pub fn set_pulse_delay(&mut self, delay: u32) { assert!(delay <= self.pulse_end()); - self.inner.set_compare_value(self.channel, delay); + self.inner.set_compare_value(self.channel, unwrap!(delay.try_into())); } /// Set the pulse width in ticks. diff --git a/embassy-stm32/src/timer/pwm_input.rs b/embassy-stm32/src/timer/pwm_input.rs index 057ab011a..f2f00927d 100644 --- a/embassy-stm32/src/timer/pwm_input.rs +++ b/embassy-stm32/src/timer/pwm_input.rs @@ -91,16 +91,18 @@ impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { /// Get the period tick count pub fn get_period_ticks(&self) -> u32 { - self.inner.get_capture_value(self.channel) + self.inner.get_capture_value(self.channel).into() } /// Get the pulse width tick count pub fn get_width_ticks(&self) -> u32 { - self.inner.get_capture_value(match self.channel { - Channel::Ch1 => Channel::Ch2, - Channel::Ch2 => Channel::Ch1, - _ => panic!("Invalid channel for PWM input"), - }) + self.inner + .get_capture_value(match self.channel { + Channel::Ch1 => Channel::Ch2, + Channel::Ch2 => Channel::Ch1, + _ => panic!("Invalid channel for PWM input"), + }) + .into() } /// Get the duty cycle in 100% diff --git a/embassy-stm32/src/timer/ringbuffered.rs b/embassy-stm32/src/timer/ringbuffered.rs index e8f97bf59..f5a4328d1 100644 --- a/embassy-stm32/src/timer/ringbuffered.rs +++ b/embassy-stm32/src/timer/ringbuffered.rs @@ -25,7 +25,7 @@ use crate::dma::ringbuffer::Error; /// ``` pub struct RingBufferedPwmChannel<'d, T: GeneralInstance4Channel> { timer: ManuallyDrop>, - ring_buf: WritableRingBuffer<'d, u16>, + ring_buf: WritableRingBuffer<'d, T::Word>, channel: Channel, } @@ -33,7 +33,7 @@ impl<'d, T: GeneralInstance4Channel> RingBufferedPwmChannel<'d, T> { pub(crate) fn new( timer: ManuallyDrop>, channel: Channel, - ring_buf: WritableRingBuffer<'d, u16>, + ring_buf: WritableRingBuffer<'d, T::Word>, ) -> Self { Self { timer, @@ -55,18 +55,18 @@ impl<'d, T: GeneralInstance4Channel> RingBufferedPwmChannel<'d, T> { } /// Write elements directly to the raw buffer. This can be used to fill the buffer before starting the DMA transfer. - pub fn write_immediate(&mut self, buf: &[u16]) -> Result<(usize, usize), Error> { + pub fn write_immediate(&mut self, buf: &[T::Word]) -> Result<(usize, usize), Error> { self.ring_buf.write_immediate(buf) } /// Write elements from the ring buffer /// Return a tuple of the length written and the length remaining in the buffer - pub fn write(&mut self, buf: &[u16]) -> Result<(usize, usize), Error> { + pub fn write(&mut self, buf: &[T::Word]) -> Result<(usize, usize), Error> { self.ring_buf.write(buf) } /// Write an exact number of elements to the ringbuffer. - pub async fn write_exact(&mut self, buffer: &[u16]) -> Result { + pub async fn write_exact(&mut self, buffer: &[T::Word]) -> Result { self.ring_buf.write_exact(buffer).await } @@ -140,7 +140,7 @@ impl<'d, T: GeneralInstance4Channel> RingBufferedPwmChannel<'d, T> { /// /// This value depends on the configured frequency and the timer's clock rate from RCC. pub fn max_duty_cycle(&self) -> u16 { - let max = self.timer.get_max_compare_value(); + let max: u32 = self.timer.get_max_compare_value().into(); assert!(max < u16::MAX as u32); max as u16 + 1 } diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs index 484e9fd81..8dc84cdfa 100644 --- a/embassy-stm32/src/timer/simple_pwm.rs +++ b/embassy-stm32/src/timer/simple_pwm.rs @@ -99,7 +99,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwmChannel<'d, T> { /// /// This value depends on the configured frequency and the timer's clock rate from RCC. pub fn max_duty_cycle(&self) -> u16 { - let max = self.timer.get_max_compare_value(); + let max: u32 = self.timer.get_max_compare_value().into(); assert!(max < u16::MAX as u32); max as u16 + 1 } @@ -174,7 +174,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwmChannel<'d, T> { pub fn into_ring_buffered_channel( mut self, tx_dma: Peri<'d, impl super::UpDma>, - dma_buf: &'d mut [u16], + dma_buf: &'d mut [T::Word], ) -> RingBufferedPwmChannel<'d, T> { assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); @@ -333,7 +333,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// /// This value depends on the configured frequency and the timer's clock rate from RCC. pub fn max_duty_cycle(&self) -> u16 { - let max = self.inner.get_max_compare_value(); + let max: u32 = self.inner.get_max_compare_value().into(); assert!(max < u16::MAX as u32); max as u16 + 1 } @@ -344,7 +344,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// You will need to provide corresponding `TIMx_UP` DMA channel to use this method. /// Also be aware that embassy timers use one of timers internally. It is possible to /// switch this timer by using `time-driver-timX` feature. - pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma>, channel: Channel, duty: &[u16]) { + pub async fn waveform_up(&mut self, dma: Peri<'_, impl super::UpDma>, channel: Channel, duty: &[T::Word]) { self.inner.enable_channel(channel, true); self.inner.enable_update_dma(true); self.inner.setup_update_dma(dma, channel, duty).await; @@ -385,7 +385,7 @@ impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { dma: Peri<'_, impl super::UpDma>, starting_channel: Channel, ending_channel: Channel, - duty: &[u16], + duty: &[T::Word], ) { self.inner.enable_update_dma(true); self.inner @@ -448,16 +448,16 @@ impl<'d, T: GeneralInstance4Channel> embedded_hal_02::Pwm for SimplePwm<'d, T> { } fn get_duty(&self, channel: Self::Channel) -> Self::Duty { - self.inner.get_compare_value(channel) + self.inner.get_compare_value(channel).into() } fn get_max_duty(&self) -> Self::Duty { - self.inner.get_max_compare_value() + 1 + self.inner.get_max_compare_value().into() + 1 } fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) { assert!(duty <= self.max_duty_cycle() as u32); - self.inner.set_compare_value(channel, duty) + self.inner.set_compare_value(channel, unwrap!(duty.try_into())) } fn set_period

(&mut self, period: P) -- cgit