From 416ecc73d8211e348bf51a5cfe84075673b18963 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 29 Aug 2023 20:06:53 -0500 Subject: add qei draft --- embassy-stm32/src/timer/qei.rs | 142 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 embassy-stm32/src/timer/qei.rs (limited to 'embassy-stm32/src/timer') diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs new file mode 100644 index 000000000..fa8814722 --- /dev/null +++ b/embassy-stm32/src/timer/qei.rs @@ -0,0 +1,142 @@ +//! # Quadrature Encoder Interface +use crate::{ + gpio::PushPull, + pac, rcc, + timer::{CPin, General}, +}; + +pub trait QeiExt: Sized + Instance { + fn qei( + self, + pins: ( + impl Into<>::Ch>, + impl Into<>::Ch>, + ), + ) -> Qei; +} + +impl QeiExt for TIM { + fn qei( + self, + pins: ( + impl Into<>::Ch>, + impl Into<>::Ch>, + ), + ) -> Qei { + Qei::new(self, pins) + } +} + +/// Hardware quadrature encoder interface peripheral +pub struct Qei { + tim: TIM, + pins: ( + >::Ch, + >::Ch, + ), +} + +impl Qei { + /// Configures a TIM peripheral as a quadrature encoder interface input + pub fn new( + mut tim: TIM, + pins: ( + impl Into<>::Ch>, + impl Into<>::Ch>, + ), + ) -> Self { + // Enable and reset clock. + unsafe { + TIM::enable_unchecked(); + TIM::reset_unchecked(); + } + + let pins = (pins.0.into(), pins.1.into()); + tim.setup_qei(); + + Qei { tim, pins } + } + + /// Releases the TIM peripheral and QEI pins + #[allow(clippy::type_complexity)] + pub fn release( + self, + ) -> ( + TIM, + ( + >::Ch, + >::Ch, + ), + ) { + (self.tim, self.pins) + } + + /// Set current count number + pub fn set_count(&mut self, value: TIM::Width) -> &mut Self { + self.tim.write_count(value); + self + } +} + +impl embedded_hal::Qei for Qei { + type Count = TIM::Width; + + fn count(&self) -> Self::Count { + self.tim.read_count() + } + + fn direction(&self) -> embedded_hal::Direction { + if self.tim.read_direction() { + embedded_hal::Direction::Upcounting + } else { + embedded_hal::Direction::Downcounting + } + } +} + +pub trait Instance: crate::Sealed + rcc::Enable + rcc::Reset + General + CPin<0> + CPin<1> { + fn setup_qei(&mut self); + + fn read_direction(&self) -> bool; +} + +macro_rules! hal { + ($TIM:ty) => { + impl Instance for $TIM { + fn setup_qei(&mut self) { + // Configure TxC1 and TxC2 as captures + #[cfg(not(feature = "gpio-f410"))] + self.ccmr1_input().write(|w| w.cc1s().ti1().cc2s().ti2()); + #[cfg(feature = "gpio-f410")] + self.ccmr1_input() + .write(|w| unsafe { w.cc1s().bits(0b01).cc2s().bits(0b01) }); + // enable and configure to capture on rising edge + self.ccer.write(|w| { + w.cc1e().set_bit().cc1p().clear_bit(); + w.cc2e().set_bit().cc2p().clear_bit() + }); + self.smcr.write(|w| w.sms().encoder_mode_3()); + self.set_auto_reload(<$TIM as General>::Width::MAX as u32) + .unwrap(); + self.cr1.write(|w| w.cen().set_bit()); + } + + fn read_direction(&self) -> bool { + self.cr1.read().dir().bit_is_clear() + } + } + }; +} + +#[cfg(feature = "tim1")] +hal! { pac::TIM1 } +#[cfg(feature = "tim2")] +hal! { pac::TIM2 } +#[cfg(feature = "tim3")] +hal! { pac::TIM3 } +#[cfg(feature = "tim4")] +hal! { pac::TIM4 } +#[cfg(feature = "tim5")] +hal! { pac::TIM5 } +#[cfg(feature = "tim8")] +hal! { pac::TIM8 } -- cgit From 36ec9bcc1d4ed9beff2e866bcb5ea388538320bb Mon Sep 17 00:00:00 2001 From: Dion Dokter Date: Wed, 30 Aug 2023 19:35:15 +0200 Subject: Stm32 timer prevent hardfault --- embassy-stm32/src/timer/mod.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'embassy-stm32/src/timer') diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 4ffb2a289..b5ced45fe 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -211,6 +211,7 @@ macro_rules! impl_basic_16bit_timer { use core::convert::TryInto; let f = frequency.0; let timer_f = Self::frequency().0; + assert!(f > 0); let pclk_ticks_per_timer_period = timer_f / f; let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 16)).try_into()); let arr: u16 = unwrap!((pclk_ticks_per_timer_period / (u32::from(psc) + 1)).try_into()); @@ -255,6 +256,7 @@ macro_rules! impl_32bit_timer { fn set_frequency(&mut self, frequency: Hertz) { use core::convert::TryInto; let f = frequency.0; + assert!(f > 0); let timer_f = Self::frequency().0; let pclk_ticks_per_timer_period = (timer_f / f) as u64; let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 32)).try_into()); -- cgit From c10fb7c1c4ca40749494f4873c2144906c2f1a17 Mon Sep 17 00:00:00 2001 From: xoviat Date: Wed, 30 Aug 2023 18:10:26 -0500 Subject: stm32: implement qei --- embassy-stm32/src/timer/mod.rs | 1 + embassy-stm32/src/timer/qei.rs | 198 ++++++++++++++++------------------------- 2 files changed, 77 insertions(+), 122 deletions(-) (limited to 'embassy-stm32/src/timer') diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 4ffb2a289..6036a4561 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -1,4 +1,5 @@ pub mod complementary_pwm; +pub mod qei; pub mod simple_pwm; use stm32_metapac::timer::vals; diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs index fa8814722..c0f9288a5 100644 --- a/embassy-stm32/src/timer/qei.rs +++ b/embassy-stm32/src/timer/qei.rs @@ -1,142 +1,96 @@ -//! # Quadrature Encoder Interface -use crate::{ - gpio::PushPull, - pac, rcc, - timer::{CPin, General}, -}; - -pub trait QeiExt: Sized + Instance { - fn qei( - self, - pins: ( - impl Into<>::Ch>, - impl Into<>::Ch>, - ), - ) -> Qei; -} +use core::marker::PhantomData; -impl QeiExt for TIM { - fn qei( - self, - pins: ( - impl Into<>::Ch>, - impl Into<>::Ch>, - ), - ) -> Qei { - Qei::new(self, pins) - } +use embassy_hal_internal::{into_ref, PeripheralRef}; + +use super::*; +use crate::gpio::sealed::AFType; +use crate::gpio::AnyPin; +use crate::Peripheral; + +pub enum Direction { + Upcounting, + Downcounting, } -/// Hardware quadrature encoder interface peripheral -pub struct Qei { - tim: TIM, - pins: ( - >::Ch, - >::Ch, - ), +pub struct Ch1; +pub struct Ch2; + +pub struct QeiPin<'d, Perip, Channel> { + _pin: PeripheralRef<'d, AnyPin>, + phantom: PhantomData<(Perip, Channel)>, } -impl Qei { - /// Configures a TIM peripheral as a quadrature encoder interface input - pub fn new( - mut tim: TIM, - pins: ( - impl Into<>::Ch>, - impl Into<>::Ch>, - ), - ) -> Self { - // Enable and reset clock. - unsafe { - TIM::enable_unchecked(); - TIM::reset_unchecked(); +macro_rules! channel_impl { + ($new_chx:ident, $channel:ident, $pin_trait:ident) => { + impl<'d, Perip: CaptureCompare16bitInstance> QeiPin<'d, Perip, $channel> { + pub fn $new_chx(pin: impl Peripheral

> + 'd) -> Self { + into_ref!(pin); + critical_section::with(|_| { + pin.set_low(); + pin.set_as_af(pin.af_num(), AFType::Input); + #[cfg(gpio_v2)] + pin.set_speed(crate::gpio::Speed::VeryHigh); + }); + QeiPin { + _pin: pin.map_into(), + phantom: PhantomData, + } + } } + }; +} - let pins = (pins.0.into(), pins.1.into()); - tim.setup_qei(); +channel_impl!(new_ch1, Ch1, Channel1Pin); +channel_impl!(new_ch2, Ch2, Channel2Pin); - Qei { tim, pins } - } +pub struct SimplePwm<'d, T> { + _inner: PeripheralRef<'d, T>, +} - /// Releases the TIM peripheral and QEI pins - #[allow(clippy::type_complexity)] - pub fn release( - self, - ) -> ( - TIM, - ( - >::Ch, - >::Ch, - ), - ) { - (self.tim, self.pins) +impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { + pub fn new(tim: impl Peripheral

+ 'd, _ch1: QeiPin<'d, T, Ch1>, _ch2: QeiPin<'d, T, Ch2>) -> Self { + Self::new_inner(tim) } - /// Set current count number - pub fn set_count(&mut self, value: TIM::Width) -> &mut Self { - self.tim.write_count(value); - self - } -} + fn new_inner(tim: impl Peripheral

+ 'd) -> Self { + into_ref!(tim); -impl embedded_hal::Qei for Qei { - type Count = TIM::Width; + T::enable(); + ::reset(); - fn count(&self) -> Self::Count { - self.tim.read_count() - } + // Configure TxC1 and TxC2 as captures + T::regs_gp16().ccmr_input(0).modify(|w| { + w.set_ccs(0, vals::CcmrInputCcs::TI4); + w.set_ccs(1, vals::CcmrInputCcs::TI4); + }); - fn direction(&self) -> embedded_hal::Direction { - if self.tim.read_direction() { - embedded_hal::Direction::Upcounting - } else { - embedded_hal::Direction::Downcounting - } - } -} + // enable and configure to capture on rising edge + T::regs_gp16().ccer().modify(|w| { + w.set_cce(0, true); + w.set_cce(1, true); -pub trait Instance: crate::Sealed + rcc::Enable + rcc::Reset + General + CPin<0> + CPin<1> { - fn setup_qei(&mut self); + w.set_ccp(0, false); + w.set_ccp(1, false); + }); - fn read_direction(&self) -> bool; -} + T::regs_gp16().smcr().modify(|w| { + w.set_sms(vals::Sms::ENCODER_MODE_3); + }); -macro_rules! hal { - ($TIM:ty) => { - impl Instance for $TIM { - fn setup_qei(&mut self) { - // Configure TxC1 and TxC2 as captures - #[cfg(not(feature = "gpio-f410"))] - self.ccmr1_input().write(|w| w.cc1s().ti1().cc2s().ti2()); - #[cfg(feature = "gpio-f410")] - self.ccmr1_input() - .write(|w| unsafe { w.cc1s().bits(0b01).cc2s().bits(0b01) }); - // enable and configure to capture on rising edge - self.ccer.write(|w| { - w.cc1e().set_bit().cc1p().clear_bit(); - w.cc2e().set_bit().cc2p().clear_bit() - }); - self.smcr.write(|w| w.sms().encoder_mode_3()); - self.set_auto_reload(<$TIM as General>::Width::MAX as u32) - .unwrap(); - self.cr1.write(|w| w.cen().set_bit()); - } + T::regs_gp16().arr().modify(|w| w.set_arr(u16::MAX)); + T::regs_gp16().cr1().modify(|w| w.set_cen(true)); - fn read_direction(&self) -> bool { - self.cr1.read().dir().bit_is_clear() - } + Self { _inner: tim } + } + + pub fn read_direction(&self) -> Direction { + match T::regs_gp16().cr1().read().dir() { + vals::Dir::DOWN => Direction::Downcounting, + vals::Dir::UP => Direction::Upcounting, } - }; -} + } -#[cfg(feature = "tim1")] -hal! { pac::TIM1 } -#[cfg(feature = "tim2")] -hal! { pac::TIM2 } -#[cfg(feature = "tim3")] -hal! { pac::TIM3 } -#[cfg(feature = "tim4")] -hal! { pac::TIM4 } -#[cfg(feature = "tim5")] -hal! { pac::TIM5 } -#[cfg(feature = "tim8")] -hal! { pac::TIM8 } + pub fn count(&self) -> u16 { + T::regs_gp16().cnt().read().cnt() + } +} -- cgit From 1d87ec9cc36442542814d6dca7ae8e71068820e1 Mon Sep 17 00:00:00 2001 From: xoviat <49173759+xoviat@users.noreply.github.com> Date: Fri, 1 Sep 2023 17:30:27 -0500 Subject: stm32/qei: fix struct naming (#1852) Co-authored-by: xoviat --- embassy-stm32/src/timer/qei.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'embassy-stm32/src/timer') diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs index c0f9288a5..15f2c3a79 100644 --- a/embassy-stm32/src/timer/qei.rs +++ b/embassy-stm32/src/timer/qei.rs @@ -43,11 +43,11 @@ macro_rules! channel_impl { channel_impl!(new_ch1, Ch1, Channel1Pin); channel_impl!(new_ch2, Ch2, Channel2Pin); -pub struct SimplePwm<'d, T> { +pub struct Qei<'d, T> { _inner: PeripheralRef<'d, T>, } -impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { +impl<'d, T: CaptureCompare16bitInstance> Qei<'d, T> { pub fn new(tim: impl Peripheral

+ 'd, _ch1: QeiPin<'d, T, Ch1>, _ch2: QeiPin<'d, T, Ch2>) -> Self { Self::new_inner(tim) } -- cgit From f866735802e142530491086adcb3f173c38ec570 Mon Sep 17 00:00:00 2001 From: Daniel Berlin Date: Wed, 27 Sep 2023 20:15:24 -0400 Subject: Add support for input capture function --- embassy-stm32/src/timer/mod.rs | 231 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 231 insertions(+) (limited to 'embassy-stm32/src/timer') diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 839548a53..ea72b36ae 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -15,6 +15,7 @@ pub mod low_level { } pub(crate) mod sealed { + use super::*; pub trait Basic16bitInstance: RccPeripheral { type Interrupt: interrupt::typelevel::Interrupt; @@ -32,10 +33,16 @@ pub(crate) mod sealed { fn clear_update_interrupt(&mut self) -> bool; fn enable_update_interrupt(&mut self, enable: bool); + + fn set_autoreload_preload(&mut self, enable: vals::Arpe); } pub trait GeneralPurpose16bitInstance: Basic16bitInstance { fn regs_gp16() -> crate::pac::timer::TimGp16; + + fn set_count_direction(&mut self, direction: vals::Dir); + + fn set_clock_division(&mut self, ckd: vals::Ckd); } pub trait GeneralPurpose32bitInstance: GeneralPurpose16bitInstance { @@ -49,6 +56,16 @@ pub(crate) mod sealed { } pub trait CaptureCompare16bitInstance: GeneralPurpose16bitInstance { + fn clear_input_interrupt(&mut self, channel: Channel); + + fn enable_input_interrupt(&mut self, channel: Channel, enable: bool); + + fn set_input_capture_prescaler(&mut self, channel: Channel, val: u8); + + fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection); + + fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode); + /// Global output enable. Does not do anything on non-advanced timers. fn enable_outputs(&mut self, enable: bool); @@ -60,6 +77,8 @@ pub(crate) mod sealed { fn set_compare_value(&mut self, channel: Channel, value: u16); + fn get_capture_value(&mut self, channel: Channel) -> u16; + fn get_max_compare_value(&self) -> u16; } @@ -74,6 +93,16 @@ pub(crate) mod sealed { } pub trait CaptureCompare32bitInstance: GeneralPurpose32bitInstance { + fn clear_input_interrupt(&mut self, channel: Channel); + + fn enable_input_interrupt(&mut self, channel: Channel, enable: bool); + + fn set_input_capture_prescaler(&mut self, channel: Channel, val: u8); + + fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection); + + fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode); + fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode); fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity); @@ -82,6 +111,8 @@ pub(crate) mod sealed { fn set_compare_value(&mut self, channel: Channel, value: u32); + fn get_capture_value(&mut self, channel: Channel) -> u32; + fn get_max_compare_value(&self) -> u32; } } @@ -105,6 +136,30 @@ impl Channel { } } +#[derive(Clone, Copy)] +pub enum InputCaptureMode { + Rising, + Falling, + BothEdges, +} + +#[derive(Clone, Copy)] +pub enum InputTISelection { + Normal, + Alternate, + TRC, +} + +impl From for stm32_metapac::timer::vals::CcmrInputCcs { + fn from(tisel: InputTISelection) -> Self { + match tisel { + InputTISelection::Normal => stm32_metapac::timer::vals::CcmrInputCcs::TI4, + InputTISelection::Alternate => stm32_metapac::timer::vals::CcmrInputCcs::TI3, + InputTISelection::TRC => stm32_metapac::timer::vals::CcmrInputCcs::TRC, + } + } +} + #[derive(Clone, Copy)] pub enum OutputCompareMode { Frozen, @@ -242,6 +297,10 @@ macro_rules! impl_basic_16bit_timer { fn enable_update_interrupt(&mut self, enable: bool) { Self::regs().dier().write(|r| r.set_uie(enable)); } + + fn set_autoreload_preload(&mut self, enable: vals::Arpe) { + Self::regs().cr1().modify(|r| r.set_arpe(enable)); + } } }; } @@ -279,6 +338,51 @@ macro_rules! impl_32bit_timer { macro_rules! impl_compare_capable_16bit { ($inst:ident) => { impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { + fn clear_input_interrupt(&mut self, channel: Channel) { + use sealed::GeneralPurpose16bitInstance; + Self::regs_gp16() + .sr() + .modify(|r| r.set_ccif(channel.raw(), false)); + } + + fn enable_input_interrupt(&mut self, channel: Channel, enable: bool) { + use sealed::GeneralPurpose16bitInstance; + Self::regs_gp16() + .dier() + .modify(|r| r.set_ccie(channel.raw(), enable)); + } + fn set_input_capture_prescaler(&mut self, channel: Channel, factor: u8) { + use sealed::GeneralPurpose16bitInstance; + let raw_channel = channel.raw(); + Self::regs_gp16() + .ccmr_input(raw_channel / 2) + .modify(|r| r.set_icpsc(raw_channel % 2, factor)); + } + + fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) { + use sealed::GeneralPurpose16bitInstance; + let raw_channel = channel.raw(); + Self::regs_gp16() + .ccmr_input(raw_channel / 2) + .modify(|r| r.set_ccs(raw_channel % 2, tisel.into())); + } + fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) { + use sealed::GeneralPurpose16bitInstance; + Self::regs_gp16().ccer().modify(|r| match mode { + InputCaptureMode::Rising => { + r.set_ccnp(channel.raw(), false); + r.set_ccp(channel.raw(), false); + } + InputCaptureMode::Falling => { + r.set_ccnp(channel.raw(), false); + r.set_ccp(channel.raw(), true); + } + InputCaptureMode::BothEdges => { + r.set_ccnp(channel.raw(), true); + r.set_ccp(channel.raw(), true); + } + }); + } fn enable_outputs(&mut self, _enable: bool) {} fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) { @@ -308,6 +412,11 @@ macro_rules! impl_compare_capable_16bit { Self::regs_gp16().ccr(channel.raw()).modify(|w| w.set_ccr(value)); } + fn get_capture_value(&mut self, channel: Channel) -> u16 { + use sealed::GeneralPurpose16bitInstance; + Self::regs_gp16().ccr(channel.raw()).read().ccr() + } + fn get_max_compare_value(&self) -> u16 { use sealed::GeneralPurpose16bitInstance; Self::regs_gp16().arr().read().arr() @@ -332,6 +441,14 @@ foreach_interrupt! { fn regs_gp16() -> crate::pac::timer::TimGp16 { crate::pac::$inst } + + fn set_count_direction(&mut self, direction: vals::Dir) { + Self::regs_gp16().cr1().modify(|r| r.set_dir(direction)); + } + + fn set_clock_division(&mut self, ckd: vals::Ckd) { + Self::regs_gp16().cr1().modify(|r| r.set_ckd(ckd)); + } } }; @@ -346,6 +463,51 @@ foreach_interrupt! { impl GeneralPurpose32bitInstance for crate::peripherals::$inst {} impl sealed::CaptureCompare32bitInstance for crate::peripherals::$inst { + fn clear_input_interrupt(&mut self, channel: Channel) { + use sealed::GeneralPurpose32bitInstance; + Self::regs_gp32() + .sr() + .modify(|r| r.set_ccif(channel.raw(), false)); + } + fn enable_input_interrupt(&mut self, channel: Channel, enable: bool) { + use sealed::GeneralPurpose32bitInstance; + Self::regs_gp32() + .dier() + .modify(|r| r.set_ccie(channel.raw(), enable)); + } + fn set_input_capture_prescaler(&mut self, channel: Channel, factor: u8) { + use crate::timer::sealed::GeneralPurpose32bitInstance; + let raw_channel = channel.raw(); + Self::regs_gp32() + .ccmr_input(raw_channel / 2) + .modify(|r| r.set_icpsc(raw_channel % 2, factor)); + } + + fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) { + use crate::timer::sealed::GeneralPurpose32bitInstance; + let raw_channel = channel.raw(); + Self::regs_gp32() + .ccmr_input(raw_channel / 2) + .modify(|r| r.set_ccs(raw_channel % 2, tisel.into())); + } + + fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) { + use crate::timer::sealed::GeneralPurpose32bitInstance; + Self::regs_gp32().ccer().modify(|r| match mode { + InputCaptureMode::Rising => { + r.set_ccnp(channel.raw(), false); + r.set_ccp(channel.raw(), false); + } + InputCaptureMode::Falling => { + r.set_ccnp(channel.raw(), false); + r.set_ccp(channel.raw(), true); + } + InputCaptureMode::BothEdges => { + r.set_ccnp(channel.raw(), true); + r.set_ccp(channel.raw(), true); + } + }); + } fn set_output_compare_mode( &mut self, channel: Channel, @@ -373,6 +535,11 @@ foreach_interrupt! { Self::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(value)); } + fn get_capture_value(&mut self, channel: Channel) -> u32 { + use crate::timer::sealed::GeneralPurpose32bitInstance; + Self::regs_gp32().ccr(channel.raw()).read().ccr() + } + fn get_max_compare_value(&self) -> u32 { use crate::timer::sealed::GeneralPurpose32bitInstance; Self::regs_gp32().arr().read().arr() as u32 @@ -383,6 +550,14 @@ foreach_interrupt! { fn regs_gp16() -> crate::pac::timer::TimGp16 { unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) } } + + fn set_count_direction(&mut self, direction: vals::Dir) { + Self::regs_gp16().cr1().modify(|r| r.set_dir(direction)); + } + + fn set_clock_division(&mut self, ckd: vals::Ckd) { + Self::regs_gp16().cr1().modify(|r| r.set_ckd(ckd)); + } } }; @@ -399,6 +574,14 @@ foreach_interrupt! { fn regs_gp16() -> crate::pac::timer::TimGp16 { unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) } } + + fn set_count_direction(&mut self, direction: vals::Dir) { + Self::regs_gp16().cr1().modify(|r| r.set_dir(direction)); + } + + fn set_clock_division(&mut self, ckd: vals::Ckd) { + Self::regs_gp16().cr1().modify(|r| r.set_ckd(ckd)); + } } impl sealed::AdvancedControlInstance for crate::peripherals::$inst { @@ -408,6 +591,49 @@ foreach_interrupt! { } impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { + fn clear_input_interrupt(&mut self, channel: Channel) { + use crate::timer::sealed::AdvancedControlInstance; + Self::regs_advanced() + .sr() + .modify(|r| r.set_ccif(channel.raw(), false)); + } + fn enable_input_interrupt(&mut self, channel: Channel, enable: bool) { + use crate::timer::sealed::AdvancedControlInstance; + Self::regs_advanced() + .dier() + .modify(|r| r.set_ccie(channel.raw(), enable)); + } + fn set_input_capture_prescaler(&mut self, channel: Channel, factor: u8) { + use crate::timer::sealed::AdvancedControlInstance; + let raw_channel = channel.raw(); + Self::regs_advanced() + .ccmr_input(raw_channel / 2) + .modify(|r| r.set_icpsc(raw_channel % 2, factor)); + } + fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) { + use crate::timer::sealed::AdvancedControlInstance; + let raw_channel = channel.raw(); + Self::regs_advanced() + .ccmr_input(raw_channel / 2) + .modify(|r| r.set_ccs(raw_channel % 2, tisel.into())); + } + fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) { + use crate::timer::sealed::AdvancedControlInstance; + Self::regs_advanced().ccer().modify(|r| match mode { + InputCaptureMode::Rising => { + r.set_ccnp(channel.raw(), false); + r.set_ccp(channel.raw(), false); + } + InputCaptureMode::Falling => { + r.set_ccnp(channel.raw(), false); + r.set_ccp(channel.raw(), true); + } + InputCaptureMode::BothEdges => { + r.set_ccnp(channel.raw(), true); + r.set_ccp(channel.raw(), true); + } + }); + } fn enable_outputs(&mut self, enable: bool) { use crate::timer::sealed::AdvancedControlInstance; let r = Self::regs_advanced(); @@ -440,6 +666,11 @@ foreach_interrupt! { .modify(|w| w.set_cce(channel.raw(), enable)); } + fn get_capture_value(&mut self, channel: Channel) -> u16 { + use crate::timer::sealed::AdvancedControlInstance; + Self::regs_advanced().ccr(channel.raw()).read().ccr() + } + fn set_compare_value(&mut self, channel: Channel, value: u16) { use crate::timer::sealed::AdvancedControlInstance; Self::regs_advanced() -- cgit From 23f3889167903c6e800f056517c2c831e73ed081 Mon Sep 17 00:00:00 2001 From: Daniel Berlin Date: Thu, 28 Sep 2023 09:35:43 -0400 Subject: Add support for STM32 input capture filter --- embassy-stm32/src/timer/mod.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'embassy-stm32/src/timer') diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index ea72b36ae..1d642ed37 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -56,6 +56,8 @@ pub(crate) mod sealed { } pub trait CaptureCompare16bitInstance: GeneralPurpose16bitInstance { + fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::Icf); + fn clear_input_interrupt(&mut self, channel: Channel); fn enable_input_interrupt(&mut self, channel: Channel, enable: bool); @@ -93,6 +95,8 @@ pub(crate) mod sealed { } pub trait CaptureCompare32bitInstance: GeneralPurpose32bitInstance { + fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::Icf); + fn clear_input_interrupt(&mut self, channel: Channel); fn enable_input_interrupt(&mut self, channel: Channel, enable: bool); @@ -338,6 +342,14 @@ macro_rules! impl_32bit_timer { macro_rules! impl_compare_capable_16bit { ($inst:ident) => { impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { + fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::Icf) { + use sealed::GeneralPurpose16bitInstance; + let raw_channel = channel.raw(); + Self::regs_gp16() + .ccmr_input(raw_channel / 2) + .modify(|r| r.set_icf(raw_channel % 2, icf)); + } + fn clear_input_interrupt(&mut self, channel: Channel) { use sealed::GeneralPurpose16bitInstance; Self::regs_gp16() @@ -463,6 +475,14 @@ foreach_interrupt! { impl GeneralPurpose32bitInstance for crate::peripherals::$inst {} impl sealed::CaptureCompare32bitInstance for crate::peripherals::$inst { + fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::Icf) { + use sealed::GeneralPurpose32bitInstance; + let raw_channel = channel.raw(); + Self::regs_gp32() + .ccmr_input(raw_channel / 2) + .modify(|r| r.set_icf(raw_channel % 2, icf)); + } + fn clear_input_interrupt(&mut self, channel: Channel) { use sealed::GeneralPurpose32bitInstance; Self::regs_gp32() @@ -591,6 +611,14 @@ foreach_interrupt! { } impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { + fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::Icf) { + use crate::timer::sealed::AdvancedControlInstance; + let raw_channel = channel.raw(); + Self::regs_advanced() + .ccmr_input(raw_channel / 2) + .modify(|r| r.set_icf(raw_channel % 2, icf)); + } + fn clear_input_interrupt(&mut self, channel: Channel) { use crate::timer::sealed::AdvancedControlInstance; Self::regs_advanced() -- cgit From e70143ef8f5303b5916a160f9d43d04d7ab55cd7 Mon Sep 17 00:00:00 2001 From: Daniel Berlin Date: Thu, 28 Sep 2023 17:04:19 -0400 Subject: Forgot set_count_direction and set_clock_division in 32 bit instance --- embassy-stm32/src/timer/mod.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'embassy-stm32/src/timer') diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 1d642ed37..9b79f9b4e 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -49,6 +49,10 @@ pub(crate) mod sealed { fn regs_gp32() -> crate::pac::timer::TimGp32; fn set_frequency(&mut self, frequency: Hertz); + + fn set_count_direction(&mut self, direction: vals::Dir); + + fn set_clock_division(&mut self, ckd: vals::Ckd); } pub trait AdvancedControlInstance: GeneralPurpose16bitInstance { @@ -317,6 +321,14 @@ macro_rules! impl_32bit_timer { crate::pac::$inst } + fn set_count_direction(&mut self, direction: vals::Dir) { + Self::regs_gp32().cr1().modify(|r| r.set_dir(direction)); + } + + fn set_clock_division(&mut self, ckd: vals::Ckd) { + Self::regs_gp32().cr1().modify(|r| r.set_ckd(ckd)); + } + fn set_frequency(&mut self, frequency: Hertz) { use core::convert::TryInto; let f = frequency.0; -- cgit From dffdb9268bfb32580efe32067bab50fe62900c5f Mon Sep 17 00:00:00 2001 From: Daniel Berlin Date: Thu, 28 Sep 2023 21:56:18 -0400 Subject: Revert "Forgot set_count_direction and set_clock_division in 32 bit instance" --- embassy-stm32/src/timer/mod.rs | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'embassy-stm32/src/timer') diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 9b79f9b4e..1d642ed37 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -49,10 +49,6 @@ pub(crate) mod sealed { fn regs_gp32() -> crate::pac::timer::TimGp32; fn set_frequency(&mut self, frequency: Hertz); - - fn set_count_direction(&mut self, direction: vals::Dir); - - fn set_clock_division(&mut self, ckd: vals::Ckd); } pub trait AdvancedControlInstance: GeneralPurpose16bitInstance { @@ -321,14 +317,6 @@ macro_rules! impl_32bit_timer { crate::pac::$inst } - fn set_count_direction(&mut self, direction: vals::Dir) { - Self::regs_gp32().cr1().modify(|r| r.set_dir(direction)); - } - - fn set_clock_division(&mut self, ckd: vals::Ckd) { - Self::regs_gp32().cr1().modify(|r| r.set_ckd(ckd)); - } - fn set_frequency(&mut self, frequency: Hertz) { use core::convert::TryInto; let f = frequency.0; -- cgit