diff --git a/CHANGELOG.md b/CHANGELOG.md index b565406c..cd6a5b38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Changed + +- `timer.rs` refactoring + ## [v0.11.0] - 2025-09-09 ### Breaking changes diff --git a/src/rcc.rs b/src/rcc.rs index c8aecc45..c926d36e 100644 --- a/src/rcc.rs +++ b/src/rcc.rs @@ -4,7 +4,7 @@ use core::ops::{Deref, DerefMut}; use crate::pac::{ rcc::{self, RegisterBlock as RccRB}, - BKP, PWR, RCC, + BKP, DBGMCU, PWR, RCC, }; use crate::flash::ACR; @@ -207,6 +207,7 @@ impl Rcc { /// let clocks = rcc.freeze(rcc::Config::default(), &mut flash.acr); /// ``` #[inline(always)] + #[allow(unused)] pub fn freeze(self, cfg: impl Into, acr: &mut ACR) -> Self { let cfg = cfg.into(); let clocks = cfg.get_clocks(); @@ -544,6 +545,11 @@ pub trait Reset: RccBus { } } +/// Stop peripheral when Core is halted +pub trait StopInDebug { + fn stop_in_debug(&mut self, dbg: &mut DBGMCU, state: bool); +} + #[derive(Clone, Copy, Debug, PartialEq)] pub struct RawConfig { pub hse: Option, diff --git a/src/rcc/enable.rs b/src/rcc/enable.rs index b012b3e5..2bd7a9b4 100644 --- a/src/rcc/enable.rs +++ b/src/rcc/enable.rs @@ -54,17 +54,43 @@ macro_rules! bus { } } +macro_rules! dbgstop { + ($($PER:ident => ($bit:literal),)+) => { + $( + impl StopInDebug for crate::pac::$PER { + #[inline(always)] + fn stop_in_debug(&mut self, dbg: &mut DBGMCU, state: bool) { + unsafe { + bb::write(dbg.cr(), $bit, state); + } + } + } + )+ + } +} + #[cfg(feature = "stm32f103")] bus! { ADC2 => (APB2, 10), CAN => (APB1, 25), } +#[cfg(feature = "stm32f103")] +dbgstop! { + CAN => (14), // dbg_can1_stop +} + #[cfg(feature = "connectivity")] bus! { ADC2 => (APB2, 10), CAN1 => (APB1, 25), CAN2 => (APB1, 26), } +#[cfg(feature = "connectivity")] +dbgstop! { + CAN1 => (14), // dbg_can1_stop + CAN2 => (21), // dbg_can2_stop +} + #[cfg(feature = "has-dac")] bus! { DAC => (APB1, 29), @@ -94,6 +120,12 @@ bus! { USART3 => (APB1, 18), WWDG => (APB1, 11), } +dbgstop! { + IWDG => (8), // dbg_iwdg_stop + WWDG => (9), // dbg_wwdg_stop + I2C1 => (15), // dbg_i2c1_smbus_timeout + I2C2 => (16), // dbg_i2c2_smbus_timeout +} #[cfg(any(feature = "xl", feature = "high"))] bus! { @@ -130,16 +162,28 @@ bus! { TIM2 => (APB1, 0), TIM3 => (APB1, 1), } +dbgstop! { + TIM2 => (11), // dbg_tim2_stop + TIM3 => (12), // dbg_tim3_stop +} #[cfg(any(feature = "stm32f100", feature = "stm32f103", feature = "connectivity"))] bus! { TIM1 => (APB2, 11), } +#[cfg(any(feature = "stm32f100", feature = "stm32f103", feature = "connectivity"))] +dbgstop! { + TIM1 => (10), // dbg_tim1_stop +} #[cfg(any(feature = "stm32f100", feature = "high", feature = "connectivity"))] bus! { TIM6 => (APB1, 4), } +#[cfg(any(feature = "stm32f100", feature = "high", feature = "connectivity"))] +dbgstop! { + TIM6 => (19), // dbg_tim6_stop +} #[cfg(any( all(feature = "high", any(feature = "stm32f101", feature = "stm32f103")), @@ -148,6 +192,13 @@ bus! { bus! { TIM7 => (APB1, 5), } +#[cfg(any( + all(feature = "high", any(feature = "stm32f101", feature = "stm32f103")), + any(feature = "stm32f100", feature = "connectivity") +))] +dbgstop! { + TIM7 => (20), // dbg_tim7_stop +} #[cfg(feature = "stm32f100")] bus! { @@ -155,16 +206,30 @@ bus! { TIM16 => (APB2, 17), TIM17 => (APB2, 18), } +#[cfg(feature = "stm32f100")] +dbgstop! { + TIM15 => (22), // dbg_tim15_stop + TIM16 => (23), // dbg_tim16_stop + TIM17 => (24), // dbg_tim17_stop +} #[cfg(feature = "medium")] bus! { TIM4 => (APB1, 2), } +#[cfg(feature = "medium")] +dbgstop! { + TIM4 => (13), // dbg_tim4_stop +} #[cfg(any(feature = "high", feature = "connectivity"))] bus! { TIM5 => (APB1, 3), } +#[cfg(any(feature = "high", feature = "connectivity"))] +dbgstop! { + TIM5 => (18), // dbg_tim5_stop +} #[cfg(any(feature = "xl", all(feature = "stm32f100", feature = "high")))] bus! { @@ -172,11 +237,21 @@ bus! { TIM13 => (APB1, 7), TIM14 => (APB1, 8), } +#[cfg(any(feature = "xl", all(feature = "stm32f100", feature = "high")))] +dbgstop! { + TIM12 => (25), // dbg_tim12_stop + TIM13 => (26), // dbg_tim13_stop + TIM14 => (27), // dbg_tim14_stop +} #[cfg(all(feature = "stm32f103", feature = "high"))] bus! { TIM8 => (APB2, 13), } +#[cfg(all(feature = "stm32f103", feature = "high"))] +dbgstop! { + TIM8 => (17), // dbg_tim8_stop +} #[cfg(feature = "xl")] bus! { @@ -184,6 +259,12 @@ bus! { TIM10 => (APB2, 20), TIM11 => (APB2, 21), } +#[cfg(feature = "xl")] +dbgstop! { + TIM9 => (28), // dbg_tim9_stop + TIM10 => (29), // dbg_tim10_stop + TIM11 => (30), // dbg_tim11_stop +} #[cfg(feature = "stm32f103")] // feature = "stm32f102" bus! { diff --git a/src/timer.rs b/src/timer.rs index a0e3b73d..ffa5c00a 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -90,6 +90,28 @@ pub enum Channel { C4 = 3, } +/// Compare/PWM polarity +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Polarity { + ActiveHigh, + ActiveLow, +} + +/// Capture polarity +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum CapturePolarity { + ActiveHigh, + ActiveLow, + ActiveBoth, +} + +/// Output Idle state +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum IdleState { + Reset, + Set, +} + /// Interrupt events #[derive(Clone, Copy, PartialEq, Eq)] pub enum SysEvent { @@ -258,8 +280,82 @@ pub enum Ocm { PwmMode2 = 7, } +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[repr(u8)] +/// Capture mode +/// Enum for configuring the mode of the Capture channels (CC1S, CC2S, CC3S, CC4S). +/// Defines how each channel is used in Input Capture mode, considering TI1, TI2, TI3, and TI4. +pub enum CaptureMode { + /// Input Capture on the corresponding channel (e.g., CC1 -> TI1, CC2 -> TI2, etc.). + InputCapture = 1, + /// Input Capture on the inverted channel (e.g., CC1 -> TI2, CC2 -> TI1, CC3 -> TI4, CC4 -> TI3). + InvChannelInputCapture = 2, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[repr(u8)] +/// Enum for configuring the Input Capture prescaler. +/// Determines how many input events are required for one capture. +pub enum CapturePrescaler { + /// No prescaler (00): Capture every input event. + No = 0, + /// Prescaler 2 (01): Capture every second input event. + Two = 1, + /// Prescaler 4 (10): Capture every fourth input event. + Four = 2, + /// Prescaler 8 (11): Capture every eighth input event. + Eight = 3, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[repr(u8)] +/// Enum representing the input capture filter settings. +pub enum CaptureFilter { + /// No filter, sampling frequency = fDTS, N = 1 + NoFilter, + /// Sampling frequency = fCK_INT, N = 2 + FckIntN2, + /// Sampling frequency = fCK_INT, N = 4 + FckIntN4, + /// Sampling frequency = fCK_INT, N = 8 + FckIntN8, + /// Sampling frequency = fDTS/2, N = 6 + FdtsDiv2N6, + /// Sampling frequency = fDTS/2, N = 8 + FdtsDiv2N8, + /// Sampling frequency = fDTS/4, N = 6 + FdtsDiv4N6, + /// Sampling frequency = fDTS/4, N = 8 + FdtsDiv4N8, + /// Sampling frequency = fDTS/8, N = 6 + FdtsDiv8N6, + /// Sampling frequency = fDTS/8, N = 8 + FdtsDiv8N8, + /// Sampling frequency = fDTS/16, N = 5 + FdtsDiv16N5, + /// Sampling frequency = fDTS/16, N = 6 + FdtsDiv16N6, + /// Sampling frequency = fDTS/16, N = 8 + FdtsDiv16N8, + /// Sampling frequency = fDTS/32, N = 5 + FdtsDiv32N5, + /// Sampling frequency = fDTS/32, N = 6 + FdtsDiv32N6, + /// Sampling frequency = fDTS/32, N = 8 + FdtsDiv32N8, +} + +// Center-aligned mode selection +pub use pac::tim1::cr1::CMS as CenterAlignedMode; + mod sealed { - use super::{Channel, Event, Ocm, DBG}; + use super::{ + CaptureFilter, CaptureMode, CapturePolarity, CapturePrescaler, CenterAlignedMode, Event, + IdleState, Ocm, Polarity, + }; pub trait General { type Width: Into + From; fn max_auto_reload() -> u32; @@ -267,8 +363,7 @@ mod sealed { fn set_auto_reload(&mut self, arr: u32) -> Result<(), super::Error>; fn read_auto_reload() -> u32; fn enable_preload(&mut self, b: bool); - fn enable_counter(&mut self); - fn disable_counter(&mut self); + fn enable_counter(&mut self, b: bool); fn is_counter_enabled(&self) -> bool; fn reset_counter(&mut self); fn set_prescaler(&mut self, psc: u16); @@ -280,16 +375,42 @@ mod sealed { fn read_count(&self) -> Self::Width; fn start_one_pulse(&mut self); fn cr1_reset(&mut self); - fn stop_in_debug(&mut self, dbg: &mut DBG, state: bool); + fn cnt_reset(&mut self); } - pub trait WithPwm: General { + pub trait WithChannel: General { const CH_NUMBER: u8; + const COMP_CH_NUMBER: u8; fn read_cc_value(channel: u8) -> u32; fn set_cc_value(channel: u8, value: u32); - fn preload_output_channel_in_mode(&mut self, channel: Channel, mode: Ocm); - fn start_pwm(&mut self); fn enable_channel(channel: u8, b: bool); + fn set_channel_polarity(channel: u8, p: Polarity); + fn set_nchannel_polarity(channel: u8, p: Polarity); + + fn set_capture_channel_polarity(channel: u8, p: CapturePolarity); + } + + #[allow(unused)] + pub trait Advanced: WithChannel { + fn enable_nchannel(channel: u8, b: bool); + fn set_dtg_value(value: u8); + fn read_dtg_value() -> u8; + fn idle_state(channel: u8, comp: bool, s: IdleState); + fn set_cms(mode: CenterAlignedMode); + } + + pub trait WithPwm: WithChannel { + fn preload_output_channel_in_mode(&mut self, c: u8, mode: Ocm); + fn freeze_output_channel(&mut self, c: u8); + fn start_pwm(&mut self); + } + + #[allow(unused)] + pub trait WithCapture: WithChannel { + fn preload_capture(&mut self, c: u8, mode: CaptureMode); + fn prescaler_capture(&mut self, c: u8, psc: CapturePrescaler); + fn filter_capture(&mut self, c: u8, filter: CaptureFilter); + fn start_capture(&mut self); } pub trait MasterTimer: General { @@ -297,288 +418,355 @@ mod sealed { fn master_mode(&mut self, mode: Self::Mms); } } -pub(crate) use sealed::{General, MasterTimer, WithPwm}; +pub(crate) use sealed::{Advanced, General, MasterTimer, WithCapture, WithChannel, WithPwm}; pub trait Instance: - crate::Sealed + rcc::Enable + rcc::Reset + rcc::BusTimerClock + General + crate::Sealed + rcc::Enable + rcc::Reset + rcc::BusTimerClock + rcc::StopInDebug + General { } macro_rules! hal { - ($($TIM:ty: [ + ($TIM:ty: [ $Timer:ident, $bits:ty, - $dbg_timX_stop:ident, - $(c: ($cnum:ident $(, $aoe:ident)?),)? + $(c: ($cnum:tt, $ncnum:tt $(, $aoe:ident)?),)? $(m: $timbase:ident,)? - ],)+) => { - $( - impl Instance for $TIM { } - pub type $Timer = Timer<$TIM>; + ]) => { + impl Instance for $TIM { } + pub type $Timer = Timer<$TIM>; - impl General for $TIM { - type Width = $bits; + impl General for $TIM { + type Width = $bits; - #[inline(always)] - fn max_auto_reload() -> u32 { - <$bits>::MAX as u32 - } - #[inline(always)] - unsafe fn set_auto_reload_unchecked(&mut self, arr: u32) { - self.arr().write(|w| w.bits(arr)); + #[inline(always)] + fn max_auto_reload() -> u32 { + <$bits>::MAX as u32 + } + #[inline(always)] + unsafe fn set_auto_reload_unchecked(&mut self, arr: u32) { + self.arr().write(|w| w.bits(arr)); + } + #[inline(always)] + fn set_auto_reload(&mut self, arr: u32) -> Result<(), Error> { + // Note: Make it impossible to set the ARR value to 0, since this + // would cause an infinite loop. + if arr > 0 && arr <= Self::max_auto_reload() { + Ok(unsafe { self.set_auto_reload_unchecked(arr) }) + } else { + Err(Error::WrongAutoReload) } - #[inline(always)] - fn set_auto_reload(&mut self, arr: u32) -> Result<(), Error> { - // Note: Make it impossible to set the ARR value to 0, since this - // would cause an infinite loop. - if arr > 0 && arr <= Self::max_auto_reload() { - Ok(unsafe { self.set_auto_reload_unchecked(arr) }) + } + #[inline(always)] + fn read_auto_reload() -> u32 { + let tim = unsafe { &*<$TIM>::ptr() }; + tim.arr().read().bits() + } + #[inline(always)] + fn enable_preload(&mut self, b: bool) { + self.cr1().modify(|_, w| w.arpe().bit(b)); + } + #[inline(always)] + fn enable_counter(&mut self, b: bool) { + self.cr1().modify(|_, w| w.cen().bit(b)); + } + #[inline(always)] + fn is_counter_enabled(&self) -> bool { + self.cr1().read().cen().is_enabled() + } + #[inline(always)] + fn reset_counter(&mut self) { + self.cnt().reset(); + } + #[inline(always)] + fn set_prescaler(&mut self, psc: u16) { + self.psc().write(|w| w.psc().set(psc) ); + } + #[inline(always)] + fn read_prescaler(&self) -> u16 { + self.psc().read().psc().bits() + } + #[inline(always)] + fn trigger_update(&mut self) { + // Sets the URS bit to prevent an interrupt from being triggered by + // the UG bit + self.cr1().modify(|_, w| w.urs().set_bit()); + self.egr().write(|w| w.ug().set_bit()); + self.cr1().modify(|_, w| w.urs().clear_bit()); + } + #[inline(always)] + fn clear_interrupt_flag(&mut self, event: Event) { + self.sr().write(|w| unsafe { w.bits(0xffff & !event.bits()) }); + } + #[inline(always)] + fn listen_interrupt(&mut self, event: Event, b: bool) { + self.dier().modify(|r, w| unsafe { w.bits( + if b { + r.bits() | event.bits() } else { - Err(Error::WrongAutoReload) + r.bits() & !event.bits() } - } + ) }); + } + #[inline(always)] + fn get_interrupt_flag(&self) -> Event { + Event::from_bits_truncate(self.sr().read().bits()) + } + #[inline(always)] + fn read_count(&self) -> Self::Width { + self.cnt().read().bits() as Self::Width + } + #[inline(always)] + fn start_one_pulse(&mut self) { + self.cr1().modify(|_, w| w.opm().set_bit().cen().set_bit()); + } + #[inline(always)] + fn cr1_reset(&mut self) { + self.cr1().reset(); + } + #[inline(always)] + fn cnt_reset(&mut self) { + self.cnt().reset(); + } + } + $( + impl WithChannel for $TIM { + const CH_NUMBER: u8 = $cnum; + const COMP_CH_NUMBER: u8 = $ncnum; + #[inline(always)] - fn read_auto_reload() -> u32 { + fn read_cc_value(c: u8) -> u32 { let tim = unsafe { &*<$TIM>::ptr() }; - tim.arr().read().bits() - } - #[inline(always)] - fn enable_preload(&mut self, b: bool) { - self.cr1().modify(|_, w| w.arpe().bit(b)); - } - #[inline(always)] - fn enable_counter(&mut self) { - self.cr1().modify(|_, w| w.cen().set_bit()); - } - #[inline(always)] - fn disable_counter(&mut self) { - self.cr1().modify(|_, w| w.cen().clear_bit()); - } - #[inline(always)] - fn is_counter_enabled(&self) -> bool { - self.cr1().read().cen().is_enabled() - } - #[inline(always)] - fn reset_counter(&mut self) { - self.cnt().reset(); + if c < Self::CH_NUMBER { + tim.ccr(c as usize).read().bits() + } else { + 0 + } } + #[inline(always)] - fn set_prescaler(&mut self, psc: u16) { - self.psc().write(|w| w.psc().set(psc) ); + fn set_cc_value(c: u8, value: u32) { + let tim = unsafe { &*<$TIM>::ptr() }; + if c < Self::CH_NUMBER { + tim.ccr(c as usize).write(|w| unsafe { w.bits(value) }); + } } + #[inline(always)] - fn read_prescaler(&self) -> u16 { - self.psc().read().psc().bits() + fn enable_channel(c: u8, b: bool) { + let tim = unsafe { &*<$TIM>::ptr() }; + if c < Self::CH_NUMBER { + unsafe { bb::write(tim.ccer(), c*4, b); } + } } + #[inline(always)] - fn trigger_update(&mut self) { - // Sets the URS bit to prevent an interrupt from being triggered by - // the UG bit - self.cr1().modify(|_, w| w.urs().set_bit()); - self.egr().write(|w| w.ug().set_bit()); - self.cr1().modify(|_, w| w.urs().clear_bit()); + fn set_channel_polarity(c: u8, p: Polarity) { + let tim = unsafe { &*<$TIM>::ptr() }; + if c < Self::CH_NUMBER { + unsafe { bb::write(tim.ccer(), c*4 + 1, p == Polarity::ActiveLow); } + } } + #[inline(always)] - fn clear_interrupt_flag(&mut self, event: Event) { - self.sr().write(|w| unsafe { w.bits(0xffff & !event.bits()) }); + fn set_nchannel_polarity(c: u8, p: Polarity) { + let tim = unsafe { &*<$TIM>::ptr() }; + if c < Self::COMP_CH_NUMBER { + unsafe { bb::write(tim.ccer(), c*4 + 3, p == Polarity::ActiveLow); } + } } + #[inline(always)] - fn listen_interrupt(&mut self, event: Event, b: bool) { - self.dier().modify(|r, w| unsafe { w.bits( - if b { - r.bits() | event.bits() - } else { - r.bits() & !event.bits() + fn set_capture_channel_polarity(c: u8, p: CapturePolarity) { + let tim = unsafe { &*<$TIM>::ptr() }; + if c < Self::CH_NUMBER { + match p { + CapturePolarity::ActiveLow => { + tim.ccer().modify(|r, w| { + if c < Self::COMP_CH_NUMBER { + unsafe { w.bits(r.bits() & !(1 << (c*4 + 3))); } + } + w.ccp(c).set_bit() + }); + } + CapturePolarity::ActiveHigh => { + tim.ccer().modify(|r, w| { + if c < Self::COMP_CH_NUMBER { + unsafe { w.bits(r.bits() & !(1 << (c*4 + 3))); } + } + w.ccp(c).clear_bit() + }); + } + CapturePolarity::ActiveBoth => { + tim.ccer().modify(|r, w| { + if c < Self::COMP_CH_NUMBER { + unsafe { w.bits(r.bits() | (1 << (c*4 + 3))); } + } + w.ccp(c).set_bit() + }); + } } - ) }); - } - #[inline(always)] - fn get_interrupt_flag(&self) -> Event { - Event::from_bits_truncate(self.sr().read().bits()) - } - #[inline(always)] - fn read_count(&self) -> Self::Width { - self.cnt().read().bits() as Self::Width - } - #[inline(always)] - fn start_one_pulse(&mut self) { - self.cr1().modify(|_, w| w.opm().set_bit().cen().set_bit()); - } - #[inline(always)] - fn cr1_reset(&mut self) { - self.cr1().reset(); - } - #[inline(always)] - fn stop_in_debug(&mut self, dbg: &mut DBG, state: bool) { - dbg.cr().modify(|_, w| w.$dbg_timX_stop().bit(state)); + + } } } - $(with_pwm!($TIM: $cnum $(, $aoe)?);)? - $(impl MasterTimer for $TIM { - type Mms = pac::$timbase::cr2::MMS; - fn master_mode(&mut self, mode: Self::Mms) { - self.cr2().modify(|_,w| w.mms().variant(mode)); + $( + impl Advanced for $TIM { + fn enable_nchannel(c: u8, b: bool) { + let $aoe = (); + let tim = unsafe { &*<$TIM>::ptr() }; + if c < Self::COMP_CH_NUMBER { + unsafe { bb::write(tim.ccer(), c*4 + 2, b); } + } + } + fn set_dtg_value(value: u8) { + let tim = unsafe { &*<$TIM>::ptr() }; + tim.bdtr().modify(|_,w| w.dtg().set(value)); + } + fn read_dtg_value() -> u8 { + let tim = unsafe { &*<$TIM>::ptr() }; + tim.bdtr().read().dtg().bits() + } + fn idle_state(c: u8, comp: bool, s: IdleState) { + let tim = unsafe { &*<$TIM>::ptr() }; + if !comp { + if c < Self::CH_NUMBER { + unsafe { bb::write(tim.cr2(), c*2 + 8, s == IdleState::Set); } + } + } else { + if c < Self::COMP_CH_NUMBER { + unsafe { bb::write(tim.cr2(), c*2 + 9, s == IdleState::Set); } + } + } + } + #[inline(always)] + fn set_cms(cms: CenterAlignedMode) { + let tim = unsafe { &*<$TIM>::ptr() }; + tim.cr1().write(|w| w.cms().variant(cms)); + } } - })? - )+ - } -} + )? -macro_rules! with_pwm { - ($TIM:ty: CH1) => { - impl WithPwm for $TIM { - const CH_NUMBER: u8 = 1; + with_output!($TIM: $cnum $(, $aoe)?); + )? - #[inline(always)] - fn read_cc_value(channel: u8) -> u32 { - let tim = unsafe { &*<$TIM>::ptr() }; - if channel < Self::CH_NUMBER { - tim.ccr(channel as usize).read().bits() - } else { - 0 - } + $(impl MasterTimer for $TIM { + type Mms = pac::$timbase::cr2::MMS; + fn master_mode(&mut self, mode: Self::Mms) { + self.cr2().modify(|_,w| w.mms().variant(mode)); } + })? + } +} +macro_rules! with_output { + ($TIM:ty: [$($Cx:literal, $ccmrx_input:ident, $ccmrx_output:ident, $ccxs:ident, $dc:literal;)+] $(, $aoe:ident)?) => { + impl WithPwm for $TIM { #[inline(always)] - fn set_cc_value(channel: u8, value: u32) { - let tim = unsafe { &*<$TIM>::ptr() }; - #[allow(unused_unsafe)] - if channel < Self::CH_NUMBER { - tim.ccr(channel as usize).write(|w| unsafe { w.bits(value) }); + fn preload_output_channel_in_mode(&mut self, c: u8, mode: Ocm) { + match c { + $( + $Cx => { + let c = c-$dc; + self.$ccmrx_output() + .modify(|_, w| w.ocpe(c).set_bit().ocm(c).set(mode as _) ); + } + )+ + #[allow(unreachable_patterns)] + _ => {}, } } - - #[inline(always)] - fn preload_output_channel_in_mode(&mut self, channel: Channel, mode: Ocm) { - match channel { - Channel::C1 => { - self.ccmr1_output() - .modify(|_, w| w.oc1pe().set_bit().oc1m().set(mode as _) ); + fn freeze_output_channel(&mut self, c: u8) { + match c { + $( + $Cx => { + let c = c-$dc; + self.$ccmrx_output() + .modify(|_, w| w.ocpe(c).clear_bit().ocm(c).set(Ocm::Frozen as _) ); + } + )+ + #[allow(unreachable_patterns)] + _ => {}, } - _ => {}, - } } #[inline(always)] fn start_pwm(&mut self) { + $(let $aoe = self.bdtr().modify(|_, w| w.aoe().set_bit());)? self.cr1().modify(|_, w| w.cen().set_bit()); } - - #[inline(always)] - fn enable_channel(c: u8, b: bool) { - let tim = unsafe { &*<$TIM>::ptr() }; - if c < Self::CH_NUMBER { - unsafe { bb::write(tim.ccer(), c*4, b); } - } - } } - }; - ($TIM:ty: CH2) => { - impl WithPwm for $TIM { - const CH_NUMBER: u8 = 2; + impl WithCapture for $TIM { #[inline(always)] - fn read_cc_value(channel: u8) -> u32 { - let tim = unsafe { &*<$TIM>::ptr() }; - if channel < Self::CH_NUMBER { - tim.ccr(channel as usize).read().bits() - } else { - 0 + fn preload_capture(&mut self, c: u8, mode: CaptureMode) { + match c { + $( + $Cx => { + self.$ccmrx_input() + .modify(|_, w| unsafe { w.$ccxs().bits(mode as _) } ); + } + )+ + #[allow(unreachable_patterns)] + _ => {}, } } #[inline(always)] - fn set_cc_value(channel: u8, value: u32) { - let tim = unsafe { &*<$TIM>::ptr() }; - #[allow(unused_unsafe)] - if channel < Self::CH_NUMBER { - tim.ccr(channel as usize).write(|w| unsafe { w.bits(value) }); + fn prescaler_capture(&mut self, c: u8, psc: CapturePrescaler) { + match c { + $( + $Cx => { + let c = c-$dc; + self.$ccmrx_input() + .modify(|_, w| unsafe { w.icpsc(c).bits(psc as _) } ); + } + )+ + #[allow(unreachable_patterns)] + _ => {}, } } - #[inline(always)] - fn preload_output_channel_in_mode(&mut self, channel: Channel, mode: Ocm) { - match channel { - Channel::C1 => { - self.ccmr1_output() - .modify(|_, w| w.oc1pe().set_bit().oc1m().set(mode as _) ); - } - Channel::C2 => { - self.ccmr1_output() - .modify(|_, w| w.oc2pe().set_bit().oc2m().set(mode as _) ); - } + fn filter_capture(&mut self, c: u8, filter: CaptureFilter) { + match c { + $( + $Cx => { + let c = c-$dc; + self.$ccmrx_input() + .modify(|_, w| unsafe { w.icf(c).bits(filter as _) } ); + } + )+ + #[allow(unreachable_patterns)] _ => {}, } } - #[inline(always)] - fn start_pwm(&mut self) { - self.cr1().modify(|_, w| w.cen().set_bit()); - } - - #[inline(always)] - fn enable_channel(c: u8, b: bool) { - let tim = unsafe { &*<$TIM>::ptr() }; - if c < Self::CH_NUMBER { - unsafe { bb::write(tim.ccer(), c*4, b); } - } - } - } - }; - ($TIM:ty: CH4 $(, $aoe:ident)?) => { - impl WithPwm for $TIM { - const CH_NUMBER: u8 = 4; #[inline(always)] - fn read_cc_value(channel: u8) -> u32 { - let tim = unsafe { &*<$TIM>::ptr() }; - tim.ccr(channel as usize).read().bits() - } - - #[inline(always)] - fn set_cc_value(channel: u8, value: u32) { - let tim = unsafe { &*<$TIM>::ptr() }; - tim.ccr(channel as usize).write(|w| unsafe { w.bits(value) }); - } - - #[inline(always)] - fn preload_output_channel_in_mode(&mut self, channel: Channel, mode: Ocm) { - match channel { - Channel::C1 => { - self.ccmr1_output() - .modify(|_, w| w.oc1pe().set_bit().oc1m().set(mode as _) ); - } - Channel::C2 => { - self.ccmr1_output() - .modify(|_, w| w.oc2pe().set_bit().oc2m().set(mode as _) ); - } - Channel::C3 => { - self.ccmr2_output() - .modify(|_, w| w.oc3pe().set_bit().oc3m().set(mode as _) ); - } - Channel::C4 => { - self.ccmr2_output() - .modify(|_, w| w.oc4pe().set_bit().oc4m().set(mode as _) ); - } - } - } - - #[inline(always)] - fn start_pwm(&mut self) { - $(let $aoe = self.bdtr().modify(|_, w| w.aoe().set_bit());)? + fn start_capture(&mut self) { self.cr1().modify(|_, w| w.cen().set_bit()); } - - #[inline(always)] - fn enable_channel(c: u8, b: bool) { - let tim = unsafe { &*<$TIM>::ptr() }; - if c < Self::CH_NUMBER { - unsafe { bb::write(tim.ccer(), c*4, b); } - } - } } - } + }; + ($TIM:ty: 1) => { + with_output!($TIM: [ + 0, ccmr1_input, ccmr1_output, cc1s, 0; + ]); + }; + ($TIM:ty: 2) => { + with_output!($TIM: [ + 0, ccmr1_input, ccmr1_output, cc1s, 0; + 1, ccmr1_input, ccmr1_output, cc2s, 0; + ]); + }; + ($TIM:ty: 4 $(, $aoe:ident)?) => { + with_output!($TIM: [ + 0, ccmr1_input, ccmr1_output, cc1s, 0; + 1, ccmr1_input, ccmr1_output, cc2s, 0; + 2, ccmr2_input, ccmr2_output, cc3s, 2; + 3, ccmr2_input, ccmr2_output, cc4s, 2; + ] $(, $aoe)?); + }; } impl Timer { @@ -738,70 +926,47 @@ const fn compute_arr_presc(freq: u32, clock: u32) -> (u16, u32) { (psc as u16, arr) } -hal!( - pac::TIM2: [Timer2, u16, dbg_tim2_stop, c: (CH4), m: tim2,], - pac::TIM3: [Timer3, u16, dbg_tim3_stop, c: (CH4), m: tim2,], -); - #[cfg(any(feature = "stm32f100", feature = "stm32f103", feature = "connectivity"))] -hal!( - pac::TIM1: [Timer1, u16, dbg_tim1_stop, c: (CH4, _aoe), m: tim1,], -); +hal!(pac::TIM1: [Timer1, u16, c: (4, 4, _aoe), m: tim1,]); + +hal!(pac::TIM2: [Timer2, u16, c: (4, 0), m: tim2,]); +hal!(pac::TIM3: [Timer3, u16, c: (4, 0), m: tim2,]); + +#[cfg(feature = "medium")] +hal!(pac::TIM4: [Timer4, u16, c: (4, 0), m: tim2,]); + +#[cfg(any(feature = "high", feature = "connectivity"))] +hal!(pac::TIM5: [Timer5, u16, c: (4, 0), m: tim2,]); #[cfg(any(feature = "stm32f100", feature = "high", feature = "connectivity"))] -hal! { - pac::TIM6: [Timer6, u16, dbg_tim6_stop, m: tim6,], -} +hal!(pac::TIM6: [Timer6, u16, m: tim6,]); #[cfg(any( all(feature = "high", any(feature = "stm32f101", feature = "stm32f103")), any(feature = "stm32f100", feature = "connectivity") ))] -hal! { - pac::TIM7: [Timer7, u16, dbg_tim7_stop, m: tim6,], -} - -#[cfg(feature = "stm32f100")] -hal! { - pac::TIM15: [Timer15, u16, dbg_tim15_stop, c: (CH2),], - pac::TIM16: [Timer16, u16, dbg_tim16_stop, c: (CH1),], - pac::TIM17: [Timer17, u16, dbg_tim17_stop, c: (CH1),], -} - -#[cfg(feature = "medium")] -hal! { - pac::TIM4: [Timer4, u16, dbg_tim4_stop, c: (CH4), m: tim2,], -} - -#[cfg(any(feature = "high", feature = "connectivity"))] -hal! { - pac::TIM5: [Timer5, u16, dbg_tim5_stop, c: (CH4), m: tim2,], -} +hal!(pac::TIM7: [Timer7, u16, m: tim6,]); #[cfg(all(feature = "stm32f103", feature = "high"))] -hal! { - pac::TIM8: [Timer8, u16, dbg_tim8_stop, c: (CH4, _aoe), m: tim1,], -} +hal!(pac::TIM8: [Timer8, u16, c: (4, 4, _aoe), m: tim1,]); -//TODO: restore these timers once stm32-rs has been updated -/* - * dbg_tim(12-13)_stop fields missing from 103 xl in stm32-rs - * dbg_tim(9-10)_stop fields missing from 101 xl in stm32-rs -#[cfg(any( - feature = "xl", - all( - feature = "stm32f100", - feature = "high", -)))] -hal! { - TIM12: (tim12, dbg_tim12_stop), - TIM13: (tim13, dbg_tim13_stop), - TIM14: (tim14, dbg_tim14_stop), -} #[cfg(feature = "xl")] -hal! { - TIM9: (tim9, dbg_tim9_stop), - TIM10: (tim10, dbg_tim10_stop), - TIM11: (tim11, dbg_tim11_stop), -} -*/ +hal!(pac::TIM9: [Timer9, u16, c: (2, 2),]); +#[cfg(feature = "xl")] +hal!(pac::TIM10: [Timer10, u16, c: (1, 1),]); +#[cfg(feature = "xl")] +hal!(pac::TIM11: [Timer11, u16, c: (1, 1),]); + +#[cfg(any(feature = "xl", all(feature = "stm32f100", feature = "high")))] +hal!(pac::TIM12: [Timer12, u16, c: (2, 2),]); +#[cfg(any(feature = "xl", all(feature = "stm32f100", feature = "high")))] +hal!(pac::TIM13: [Timer13, u16, c: (1, 1),]); +#[cfg(any(feature = "xl", all(feature = "stm32f100", feature = "high")))] +hal!(pac::TIM14: [Timer14, u16, c: (1, 1),]); + +#[cfg(feature = "stm32f100")] +hal!(pac::TIM15: [Timer15, u16, c: (2, 2),]); +#[cfg(feature = "stm32f100")] +hal!(pac::TIM16: [Timer16, u16, c: (1, 1),]); +#[cfg(feature = "stm32f100")] +hal!(pac::TIM17: [Timer17, u16, c: (1, 1),]); diff --git a/src/timer/counter.rs b/src/timer/counter.rs index 2f811434..8fa59572 100644 --- a/src/timer/counter.rs +++ b/src/timer/counter.rs @@ -32,7 +32,7 @@ impl CounterHz { impl CounterHz { pub fn start(&mut self, timeout: Hertz) -> Result<(), Error> { // pause - self.tim.disable_counter(); + self.tim.enable_counter(false); self.tim.clear_interrupt_flag(Event::Update); @@ -47,7 +47,7 @@ impl CounterHz { self.tim.trigger_update(); // start counter - self.tim.enable_counter(); + self.tim.enable_counter(true); Ok(()) } @@ -67,14 +67,14 @@ impl CounterHz { } // disable counter - self.tim.disable_counter(); + self.tim.enable_counter(false); Ok(()) } /// Restarts the timer in count down mode with user-defined prescaler and auto-reload register pub fn start_raw(&mut self, psc: u16, arr: u16) { // pause - self.tim.disable_counter(); + self.tim.enable_counter(false); self.tim.set_prescaler(psc); @@ -84,7 +84,7 @@ impl CounterHz { self.tim.trigger_update(); // start counter - self.tim.enable_counter(); + self.tim.enable_counter(true); } /// Retrieves the content of the prescaler register. The real prescaler is this value + 1. @@ -160,7 +160,7 @@ impl Counter { pub fn start(&mut self, timeout: TimerDurationU32) -> Result<(), Error> { // pause - self.tim.disable_counter(); + self.tim.enable_counter(false); self.tim.clear_interrupt_flag(Event::Update); @@ -173,7 +173,7 @@ impl Counter { self.tim.trigger_update(); // start counter - self.tim.enable_counter(); + self.tim.enable_counter(true); Ok(()) } @@ -193,7 +193,7 @@ impl Counter { } // disable counter - self.tim.disable_counter(); + self.tim.enable_counter(false); Ok(()) } } diff --git a/src/timer/pwm.rs b/src/timer/pwm.rs index 4a102336..c693980e 100644 --- a/src/timer/pwm.rs +++ b/src/timer/pwm.rs @@ -303,19 +303,19 @@ impl Timer { if PINS::C1 { self.tim - .preload_output_channel_in_mode(Channel::C1, Ocm::PwmMode1); + .preload_output_channel_in_mode(Channel::C1 as u8, Ocm::PwmMode1); } if PINS::C2 && TIM::CH_NUMBER > 1 { self.tim - .preload_output_channel_in_mode(Channel::C2, Ocm::PwmMode1); + .preload_output_channel_in_mode(Channel::C2 as u8, Ocm::PwmMode1); } if PINS::C3 && TIM::CH_NUMBER > 2 { self.tim - .preload_output_channel_in_mode(Channel::C3, Ocm::PwmMode1); + .preload_output_channel_in_mode(Channel::C3 as u8, Ocm::PwmMode1); } if PINS::C4 && TIM::CH_NUMBER > 3 { self.tim - .preload_output_channel_in_mode(Channel::C4, Ocm::PwmMode1); + .preload_output_channel_in_mode(Channel::C4 as u8, Ocm::PwmMode1); } // The reference manual is a bit ambiguous about when enabling this bit is really @@ -449,19 +449,19 @@ impl FTimer { if PINS::C1 { self.tim - .preload_output_channel_in_mode(Channel::C1, Ocm::PwmMode1); + .preload_output_channel_in_mode(Channel::C1 as u8, Ocm::PwmMode1); } if PINS::C2 && TIM::CH_NUMBER > 1 { self.tim - .preload_output_channel_in_mode(Channel::C2, Ocm::PwmMode1); + .preload_output_channel_in_mode(Channel::C2 as u8, Ocm::PwmMode1); } if PINS::C3 && TIM::CH_NUMBER > 2 { self.tim - .preload_output_channel_in_mode(Channel::C3, Ocm::PwmMode1); + .preload_output_channel_in_mode(Channel::C3 as u8, Ocm::PwmMode1); } if PINS::C4 && TIM::CH_NUMBER > 3 { self.tim - .preload_output_channel_in_mode(Channel::C4, Ocm::PwmMode1); + .preload_output_channel_in_mode(Channel::C4 as u8, Ocm::PwmMode1); } // The reference manual is a bit ambiguous about when enabling this bit is really