From b8a7632de12060e0f0dc834b58154580b079ebed Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Tue, 1 Aug 2023 08:10:25 +0300 Subject: [PATCH] timer initial & fixes --- src/gpio/alt/c0.rs | 194 +++++++++++++++++++++--------------------- src/rcc/enable.rs | 1 + src/serial/usart.rs | 31 +++++-- src/spi.rs | 2 +- src/timer/mod.rs | 13 +-- src/timer/opm.rs | 13 ++- src/timer/pins.rs | 10 ++- src/timer/pwm.rs | 21 ++--- src/timer/qei.rs | 203 +++++++++++++++++++++++++------------------- 9 files changed, 266 insertions(+), 222 deletions(-) diff --git a/src/gpio/alt/c0.rs b/src/gpio/alt/c0.rs index a143bb3..452bbd2 100644 --- a/src/gpio/alt/c0.rs +++ b/src/gpio/alt/c0.rs @@ -396,6 +396,103 @@ pub mod tim1 { } } +pub mod tim3 { + use super::*; + + pin! { + default:PushPull for [ + PA6<1>, + + #[cfg(feature = "gpio-c0xx_453")] + PB4<1>, + + PB6<12>, + + PB7<11>, + + #[cfg(feature = "gpio-c0xx_453")] + PB8<3>, + + #[cfg(feature = "gpio-c0xx_453")] + PC6<1>, + ], + + default:PushPull for [ + PA7<1>, + + #[cfg(feature = "gpio-c0xx_453")] + PB3<3>, + + #[cfg(feature = "gpio-c0xx_453")] + PB5<1>, + + PB6<13>, + + #[cfg(feature = "gpio-c0xx_453")] + PB9<3>, + + #[cfg(feature = "gpio-c0xx_453")] + PC7<1>, + + PC14<11>, + ], + + default:PushPull for [ + PA8<11>, + + #[cfg(feature = "gpio-c0xx_453")] + PB0<1>, + + #[cfg(feature = "gpio-c0xx_453")] + PB5<3>, + + PB6<3>, + + PC15<3>, + ], + + default:PushPull for [ + PA8<12>, + + #[cfg(feature = "gpio-c0xx_453")] + PB1<1>, + + PB7<3>, + ], + } + + pin! { + for [ + PA2<3>, + + PA9<3>, + + PA13<3>, + + #[cfg(feature = "gpio-c0xx_453")] + PD2<1>, + ], + + } + + use crate::pac::TIM3 as TIM; + impl TimCPin<0> for TIM { + type Ch = Ch1; + } + impl TimCPin<1> for TIM { + type Ch = Ch2; + } + impl TimCPin<2> for TIM { + type Ch = Ch3; + } + impl TimCPin<3> for TIM { + type Ch = Ch4; + } + impl TimEtr for TIM { + type Etr = Etr; + } +} + pub mod tim14 { use super::*; @@ -518,103 +615,6 @@ pub mod tim17 { } } -pub mod tim3 { - use super::*; - - pin! { - default:PushPull for [ - PA6<1>, - - #[cfg(feature = "gpio-c0xx_453")] - PB4<1>, - - PB6<12>, - - PB7<11>, - - #[cfg(feature = "gpio-c0xx_453")] - PB8<3>, - - #[cfg(feature = "gpio-c0xx_453")] - PC6<1>, - ], - - default:PushPull for [ - PA7<1>, - - #[cfg(feature = "gpio-c0xx_453")] - PB3<3>, - - #[cfg(feature = "gpio-c0xx_453")] - PB5<1>, - - PB6<13>, - - #[cfg(feature = "gpio-c0xx_453")] - PB9<3>, - - #[cfg(feature = "gpio-c0xx_453")] - PC7<1>, - - PC14<11>, - ], - - default:PushPull for [ - PA8<11>, - - #[cfg(feature = "gpio-c0xx_453")] - PB0<1>, - - #[cfg(feature = "gpio-c0xx_453")] - PB5<3>, - - PB6<3>, - - PC15<3>, - ], - - default:PushPull for [ - PA8<12>, - - #[cfg(feature = "gpio-c0xx_453")] - PB1<1>, - - PB7<3>, - ], - } - - pin! { - for [ - PA2<3>, - - PA9<3>, - - PA13<3>, - - #[cfg(feature = "gpio-c0xx_453")] - PD2<1>, - ], - - } - - use crate::pac::TIM3 as TIM; - impl TimCPin<0> for TIM { - type Ch = Ch1; - } - impl TimCPin<1> for TIM { - type Ch = Ch2; - } - impl TimCPin<2> for TIM { - type Ch = Ch3; - } - impl TimCPin<3> for TIM { - type Ch = Ch4; - } - impl TimEtr for TIM { - type Etr = Etr; - } -} - pub mod usart1 { use super::*; diff --git a/src/rcc/enable.rs b/src/rcc/enable.rs index 50e5795..6594d26 100644 --- a/src/rcc/enable.rs +++ b/src/rcc/enable.rs @@ -99,6 +99,7 @@ macro_rules! bus_reset { macro_rules! bus { ($($PER:ident => ($busX:ty, $($en:ident)?, $($smen:ident)?, $($rst:ident)?),)+) => { $( + impl crate::Sealed for crate::pac::$PER {} impl RccBus for crate::stm32::$PER { type Bus = $busX; } diff --git a/src/serial/usart.rs b/src/serial/usart.rs index b3f7ba2..2a43c00 100644 --- a/src/serial/usart.rs +++ b/src/serial/usart.rs @@ -1,5 +1,5 @@ -use core::fmt; use core::marker::PhantomData; +use core::{fmt, ops::Deref}; use crate::gpio::{ alt::{SerialAsync as CommonPins, SerialRs485 as Rs485}, @@ -72,14 +72,27 @@ impl Event { } } -impl crate::Sealed for pac::USART1 {} -impl crate::Sealed for pac::USART2 {} - -pub trait Instance: crate::Sealed + rcc::Enable + rcc::Reset + CommonPins + Rs485 { - type RegisterBlock; +impl Instance for pac::USART1 { + fn ptr() -> *const pac::usart1::RegisterBlock { + pac::USART1::ptr() + } +} +impl Instance for pac::USART2 { + fn ptr() -> *const pac::usart1::RegisterBlock { + pac::USART2::ptr() + } +} +pub trait Instance: + crate::Sealed + + rcc::Enable + + rcc::Reset + + CommonPins + + Rs485 + + Deref +{ #[doc(hidden)] - fn ptr() -> *const Self::RegisterBlock; + fn ptr() -> *const pac::usart1::RegisterBlock; } /// Serial receiver @@ -149,7 +162,7 @@ impl SerialExt for USART { } } -impl fmt::Write for Serial +impl fmt::Write for Serial where Serial: hal::serial::Write, { @@ -159,7 +172,7 @@ where } } -impl fmt::Write for Tx +impl fmt::Write for Tx where Tx: hal::serial::Write, { diff --git a/src/spi.rs b/src/spi.rs index be41a86..93246a1 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -140,7 +140,7 @@ impl Spi { } pub fn release(self) -> (SPI, (SPI::Sck, SPI::Miso, SPI::Mosi)) { - (self.spi, self.pins.release()) + (self.spi, self.pins) } } diff --git a/src/timer/mod.rs b/src/timer/mod.rs index 905966a..2f353d6 100644 --- a/src/timer/mod.rs +++ b/src/timer/mod.rs @@ -2,7 +2,6 @@ use crate::rcc::*; use crate::stm32::*; use crate::time::{Hertz, MicroSecond}; -use core::marker::PhantomData; use cortex_m::peripheral::syst::SystClkSource; use cortex_m::peripheral::SYST; use hal::timer::{CountDown, Periodic}; @@ -21,10 +20,14 @@ pub struct Timer { tim: TIM, } -pub struct Channel1; -pub struct Channel2; -pub struct Channel3; -pub struct Channel4; +#[allow(non_upper_case_globals)] +pub const Channel1: u8 = 0; +#[allow(non_upper_case_globals)] +pub const Channel2: u8 = 1; +#[allow(non_upper_case_globals)] +pub const Channel3: u8 = 2; +#[allow(non_upper_case_globals)] +pub const Channel4: u8 = 3; /// System timer impl Timer { diff --git a/src/timer/opm.rs b/src/timer/opm.rs index e8fdde3..3cbdcce 100644 --- a/src/timer/opm.rs +++ b/src/timer/opm.rs @@ -1,8 +1,9 @@ //! # One-pulse Mode +use crate::gpio::alt::TimCPin; +use crate::gpio::PushPull; use crate::rcc::*; use crate::stm32::*; use crate::time::{Hertz, MicroSecond}; -use crate::timer::pins::TimerPin; use crate::timer::*; use core::marker::PhantomData; use fugit::RateExtU32; @@ -11,9 +12,8 @@ pub trait OpmExt: Sized { fn opm(self, period: MicroSecond, rcc: &mut Rcc) -> Opm; } -pub struct OpmPin { +pub struct OpmPin { tim: PhantomData, - channel: PhantomData, delay: u32, } @@ -23,14 +23,13 @@ pub struct Opm { } impl Opm { - pub fn bind_pin(&self, pin: PIN) -> OpmPin + pub fn bind_pin(&self, pin: impl Into) -> OpmPin where - PIN: TimerPin, + TIM: TimCPin = PIN>, { - pin.setup(); + let _ = pin.into(); OpmPin { tim: PhantomData, - channel: PhantomData, delay: 1, } } diff --git a/src/timer/pins.rs b/src/timer/pins.rs index 1b68b40..d855fe0 100644 --- a/src/timer/pins.rs +++ b/src/timer/pins.rs @@ -1,10 +1,12 @@ +/* use crate::gpio::*; use crate::gpio::{AltFunction, DefaultMode}; use crate::stm32::*; use crate::timer::*; pub trait TimerPin { - type Channel; + #[allow(non_upper_case_globals)] + const Channel: u8; fn setup(&self); fn release(self) -> Self; @@ -28,10 +30,11 @@ impl> TriggerPin { } macro_rules! timer_pins { - ($TIMX:ident, [ $(($ch:ty, $pin:ty, $af_mode:expr),)+ ]) => { + ($TIMX:ident, [ $(($ch:ident, $pin:ty, $af_mode:expr),)+ ]) => { $( impl TimerPin<$TIMX> for $pin { - type Channel = $ch; + #[allow(non_upper_case_globals)] + const Channel: u8 = $ch; fn setup(&self) { self.set_alt_mode($af_mode); @@ -173,3 +176,4 @@ timer_pins!(TIM17, [ timer_pins!(TIM17, [ (Channel1, PB7, AltFunction::AF2), ]); +*/ diff --git a/src/timer/pwm.rs b/src/timer/pwm.rs index c6131bf..665fa28 100644 --- a/src/timer/pwm.rs +++ b/src/timer/pwm.rs @@ -1,10 +1,11 @@ //! # Pulse Width Modulation use core::marker::PhantomData; +use crate::gpio::alt::TimCPin; +use crate::gpio::PushPull; use crate::rcc::*; use crate::stm32::*; use crate::time::Hertz; -use crate::timer::pins::TimerPin; use crate::timer::*; pub enum OutputCompareMode { @@ -29,9 +30,8 @@ pub struct Pwm { tim: TIM, } -pub struct PwmPin { +pub struct PwmPin { tim: PhantomData, - channel: PhantomData, } pub trait PwmExt: Sized { @@ -43,15 +43,12 @@ pub trait PwmPinMode { } impl Pwm { - pub fn bind_pin(&self, pin: PIN) -> PwmPin + pub fn bind_pin(&self, pin: impl Into) -> PwmPin where - PIN: TimerPin, + TIM: TimCPin = PIN>, { - pin.setup(); - PwmPin { - tim: PhantomData, - channel: PhantomData, - } + let _ = pin.into(); + PwmPin { tim: PhantomData } } } @@ -140,7 +137,7 @@ macro_rules! pwm_q { macro_rules! pwm_hal { ($($TIMX:ident: - ($CH:ty, $ccxe:ident, $ccmrx_output:ident, $ocxpe:ident, $ocxm:ident, $ccrx:ident, $ccrx_l:ident, $ccrx_h:ident),)+ + ($CH:ident, $ccxe:ident, $ccmrx_output:ident, $ocxpe:ident, $ocxm:ident, $ccrx:ident, $ccrx_l:ident, $ccrx_h:ident),)+ ) => { $( impl hal::PwmPin for PwmPin<$TIMX, $CH> { @@ -178,7 +175,7 @@ macro_rules! pwm_hal { macro_rules! pwm_advanced_hal { ($($TIMX:ident: ( - $CH:ty, + $CH:ident, $ccxe:ident $(: $ccxne:ident)*, $ccmrx_output:ident, $ocxpe:ident, diff --git a/src/timer/qei.rs b/src/timer/qei.rs index 00539fe..e93415e 100644 --- a/src/timer/qei.rs +++ b/src/timer/qei.rs @@ -1,110 +1,137 @@ //! Quadrature Encoder Interface -use crate::hal::{self, Direction}; -use crate::rcc::*; +use crate::gpio::{alt::TimCPin as CPin, PushPull}; +use crate::pac; +use crate::rcc::{self, Rcc}; + +pub trait QeiExt: Sized + Instance { + fn qei( + self, + pins: ( + impl Into<>::Ch>, + impl Into<>::Ch>, + ), + rcc: &mut Rcc, + ) -> Qei; +} -use crate::timer::pins::TimerPin; -use crate::timer::*; +impl QeiExt for TIM { + fn qei( + self, + pins: ( + impl Into<>::Ch>, + impl Into<>::Ch>, + ), + rcc: &mut Rcc, + ) -> Qei { + Qei::new(self, pins, rcc) + } +} -pub struct Qei { +/// Hardware quadrature encoder interface peripheral +pub struct Qei { tim: TIM, - pins: PINS, + pins: ( + >::Ch, + >::Ch, + ), } -pub trait QeiPins { - fn setup(&self); - fn release(self) -> Self; +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>, + ), + rcc: &mut Rcc, + ) -> Self { + // enable and reset peripheral to a clean slate state + TIM::enable(rcc); + TIM::reset(rcc); + + tim.setup_qei(); + let pins = (pins.0.into(), pins.1.into()); + tim.start(); + + 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) + } } -impl QeiPins for (P1, P2) -where - P1: TimerPin, - P2: TimerPin, -{ - fn setup(&self) { - self.0.setup(); - self.1.setup(); +impl embedded_hal::Qei for Qei { + type Count = u16; + + fn count(&self) -> u16 { + self.tim.read_count() } - fn release(self) -> Self { - (self.0.release(), self.1.release()) + fn direction(&self) -> embedded_hal::Direction { + if self.tim.read_direction() { + embedded_hal::Direction::Upcounting + } else { + embedded_hal::Direction::Downcounting + } } } -pub trait QeiExt -where - PINS: QeiPins, -{ - fn qei(self, pins: PINS, rcc: &mut Rcc) -> Qei; +pub trait Instance: crate::Sealed + rcc::Enable + rcc::Reset + CPin<0> + CPin<1> { + fn setup_qei(&mut self); + fn start(&mut self); + fn read_direction(&self) -> bool; } -macro_rules! qei { - ($($TIMX:ident: ($tim:ident, $arr:ident, $cnt:ident),)+) => { - $( - impl Qei<$TIMX, PINS> where PINS: QeiPins<$TIMX> { - fn $tim(tim: $TIMX, pins: PINS, rcc: &mut Rcc) -> Self { - // enable and reset peripheral to a clean slate state - $TIMX::enable(rcc); - $TIMX::reset(rcc); - - // Configure TxC1 and TxC2 as captures - tim.ccmr1_output().write(|w| unsafe { w.cc1s().bits(0b01).cc2s().bits(0b01) }); - - // Encoder mode 2. - tim.smcr.write(|w| unsafe { w.sms1().bits(0b010) }); - - // Enable and configure to capture on rising edge - tim.ccer.write(|w| { - w.cc1e() - .set_bit() - .cc2e() - .set_bit() - .cc1p() - .clear_bit() - .cc2p() - .clear_bit() - .cc1np() - .clear_bit() - .cc2np() - .clear_bit() - }); - - pins.setup(); - - tim.cr1.write(|w| w.cen().set_bit()); - Qei { tim, pins } - } - - pub fn release(self) -> ($TIMX, PINS) { - (self.tim, self.pins.release()) - } +macro_rules! hal { + ($TIM:ty) => { + impl Instance for $TIM { + fn setup_qei(&mut self) { + // Configure TxC1 and TxC2 as captures + self.ccmr1_output() + .write(|w| unsafe { w.cc1s().bits(0b01).cc2s().bits(0b01) }); + + // Encoder mode 2. + self.smcr.write(|w| unsafe { w.sms1().bits(0b010) }); + + // Enable and configure to capture on rising edge + self.ccer.write(|w| { + w.cc1e() + .set_bit() + .cc2e() + .set_bit() + .cc1p() + .clear_bit() + .cc2p() + .clear_bit() + .cc1np() + .clear_bit() + .cc2np() + .clear_bit() + }); } - impl hal::Qei for Qei<$TIMX, PINS> { - type Count = u16; - - fn count(&self) -> u16 { - self.tim.cnt.read().$cnt().bits() - } - - fn direction(&self) -> Direction { - if self.tim.cr1.read().dir().bit_is_clear() { - hal::Direction::Upcounting - } else { - hal::Direction::Downcounting - } - } + fn start(&mut self) { + self.cr1.write(|w| w.cen().set_bit()); } - impl QeiExt<$TIMX, PINS> for $TIMX where PINS: QeiPins<$TIMX> { - fn qei(self, pins: PINS, rcc: &mut Rcc) -> Qei<$TIMX, PINS> { - Qei::$tim(self, pins, rcc) - } + fn read_direction(&self) -> bool { + self.cr1.read().dir().bit_is_clear() } - )+ - } + } + }; } -qei! { - TIM1: (tim1, arr, cnt), - TIM3: (tim3, arr, cnt), -} +hal! { pac::TIM1 } +hal! { pac::TIM3 }