diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 61d70b732..eb67404d3 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -68,7 +68,7 @@ rand_core = "0.6.3" sdio-host = "0.5.0" critical-section = "1.1" #stm32-metapac = { version = "15" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-d7c933984fe0cbd120b6aaa7742bd585f89fa786" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-028efe4e6e0719b661cbdf8ffda3341e4d63d0df" } vcell = "0.1.3" bxcan = "0.7.0" nb = "1.0.0" @@ -89,7 +89,7 @@ critical-section = { version = "1.1", features = ["std"] } proc-macro2 = "1.0.36" quote = "1.0.15" #stm32-metapac = { version = "15", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-d7c933984fe0cbd120b6aaa7742bd585f89fa786", default-features = false, features = ["metadata"]} +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-028efe4e6e0719b661cbdf8ffda3341e4d63d0df", default-features = false, features = ["metadata"]} [features] diff --git a/embassy-stm32/src/dma/ringbuffer.rs b/embassy-stm32/src/dma/ringbuffer.rs index c5b42060a..23f1d67d5 100644 --- a/embassy-stm32/src/dma/ringbuffer.rs +++ b/embassy-stm32/src/dma/ringbuffer.rs @@ -37,6 +37,7 @@ pub struct ReadableDmaRingBuffer<'a, W: Word> { } #[derive(Debug, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct OverrunError; pub trait DmaCtrl { diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs index 320b29ddb..29ff4a736 100644 --- a/embassy-stm32/src/time_driver.rs +++ b/embassy-stm32/src/time_driver.rs @@ -14,7 +14,7 @@ use crate::pac::timer::vals; use crate::rcc::sealed::RccPeripheral; #[cfg(feature = "low-power")] use crate::rtc::Rtc; -use crate::timer::sealed::{Basic16bitInstance as BasicInstance, GeneralPurpose16bitInstance as Instance}; +use crate::timer::sealed::{CoreInstance, GeneralPurpose16bitInstance as Instance}; use crate::{interrupt, peripherals}; // NOTE regarding ALARM_COUNT: @@ -234,8 +234,8 @@ impl RtcDriver { w.set_ccie(0, true); }); - <T as BasicInstance>::Interrupt::unpend(); - unsafe { <T as BasicInstance>::Interrupt::enable() }; + <T as CoreInstance>::Interrupt::unpend(); + unsafe { <T as CoreInstance>::Interrupt::enable() }; r.cr1().modify(|w| w.set_cen(true)); } @@ -251,7 +251,7 @@ impl RtcDriver { // Clear all interrupt flags. Bits in SR are "write 0 to clear", so write the bitwise NOT. // Other approaches such as writing all zeros, or RMWing won't work, they can // miss interrupts. - r.sr().write_value(regs::SrGp(!sr.0)); + r.sr().write_value(regs::SrGp16(!sr.0)); // Overflow if sr.uif() { diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs index eddce0404..72f1ec864 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs @@ -23,7 +23,7 @@ pub struct ComplementaryPwmPin<'d, T, C> { macro_rules! complementary_channel_impl { ($new_chx:ident, $channel:ident, $pin_trait:ident) => { - impl<'d, T: CaptureCompare16bitInstance> ComplementaryPwmPin<'d, T, $channel> { + impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwmPin<'d, T, $channel> { #[doc = concat!("Create a new ", stringify!($channel), " complementary PWM pin instance.")] pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd, output_type: OutputType) -> Self { into_ref!(pin); @@ -84,14 +84,13 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { this.inner.enable_outputs(); - this.inner - .set_output_compare_mode(Channel::Ch1, OutputCompareMode::PwmMode1); - this.inner - .set_output_compare_mode(Channel::Ch2, OutputCompareMode::PwmMode1); - this.inner - .set_output_compare_mode(Channel::Ch3, OutputCompareMode::PwmMode1); - this.inner - .set_output_compare_mode(Channel::Ch4, OutputCompareMode::PwmMode1); + [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4] + .iter() + .for_each(|&channel| { + this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1); + this.inner.set_output_compare_preload(channel, true); + }); + this } diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 210bf7153..0118395a7 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -1,5 +1,31 @@ //! Timers, PWM, quadrature decoder. +//! Timer inheritance + +// sealed: +// +// Core -------------------------> 1CH -------------------------> 1CH_CMP +// | | ^ | +// +--> Basic_NoCr2 --> Basic +--> 2CH --> GP16 --> GP32 | +--> 2CH_CMP --> ADV +// | | | ^ | | ^ ^ +// | | +------|--|--------------|-----------+ | +// | +--------------------+ +--------------|-----------|---------+ +// | | | | +// | +--------------------------------------|-----------+ +// +----------------------------------------------------+ + +//! BasicInstance --> CaptureCompare16bitInstance --+--> ComplementaryCaptureCompare16bitInstance +//! | +//! +--> CaptureCompare32bitInstance +//! +//! mapping: +//! +//! BasicInstance --> Basic Timer +//! CaptureCompare16bitInstance --> 1-channel Timer, 2-channel Timer, General Purpose 16-bit Timer +//! CaptureCompare32bitInstance --> General Purpose 32-bit Timer +//! ComplementaryCaptureCompare16bitInstance --> 1-channel with one complentary Timer, 2-channel with one complentary Timer, Advance Control Timer + +#[cfg(not(stm32l0))] pub mod complementary_pwm; pub mod qei; pub mod simple_pwm; @@ -19,32 +45,32 @@ pub mod low_level { pub(crate) mod sealed { use super::*; - /// Basic 16-bit timer instance. - pub trait Basic16bitInstance: RccPeripheral { + /// Virtual Core 16-bit timer instance. + pub trait CoreInstance: RccPeripheral { /// Interrupt for this timer. type Interrupt: interrupt::typelevel::Interrupt; - /// Get access to the basic 16bit timer registers. + /// Get access to the virutal core 16bit timer registers. /// /// Note: This works even if the timer is more capable, because registers /// for the less capable timers are a subset. This allows writing a driver /// for a given set of capabilities, and having it transparently work with /// more capable timers. - fn regs() -> crate::pac::timer::TimBasic; + fn regs_core() -> crate::pac::timer::TimCore; /// Start the timer. fn start(&mut self) { - Self::regs().cr1().modify(|r| r.set_cen(true)); + Self::regs_core().cr1().modify(|r| r.set_cen(true)); } /// Stop the timer. fn stop(&mut self) { - Self::regs().cr1().modify(|r| r.set_cen(false)); + Self::regs_core().cr1().modify(|r| r.set_cen(false)); } /// Reset the counter value to 0 fn reset(&mut self) { - Self::regs().cnt().write(|r| r.set_cnt(0)); + Self::regs_core().cnt().write(|r| r.set_cnt(0)); } /// Set the frequency of how many times per second the timer counts up to the max value or down to 0. @@ -64,7 +90,7 @@ pub(crate) mod sealed { // 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(); + let regs = Self::regs_core(); regs.psc().write(|r| r.set_psc(psc)); regs.arr().write(|r| r.set_arr(arr)); @@ -77,7 +103,7 @@ pub(crate) mod sealed { /// /// Returns whether the update interrupt flag was set. fn clear_update_interrupt(&mut self) -> bool { - let regs = Self::regs(); + let regs = Self::regs_core(); let sr = regs.sr().read(); if sr.uif() { regs.sr().modify(|r| { @@ -91,29 +117,19 @@ pub(crate) mod sealed { /// Enable/disable the update interrupt. fn enable_update_interrupt(&mut self, enable: bool) { - Self::regs().dier().modify(|r| r.set_uie(enable)); - } - - /// Enable/disable the update dma. - fn enable_update_dma(&mut self, enable: bool) { - Self::regs().dier().modify(|r| r.set_ude(enable)); - } - - /// Get the update dma enable/disable state. - fn get_update_dma_state(&self) -> bool { - Self::regs().dier().read().ude() + Self::regs_core().dier().modify(|r| r.set_uie(enable)); } /// Enable/disable autoreload preload. fn set_autoreload_preload(&mut self, enable: bool) { - Self::regs().cr1().modify(|r| r.set_arpe(enable)); + Self::regs_core().cr1().modify(|r| r.set_arpe(enable)); } /// Get the timer frequency. fn get_frequency(&self) -> Hertz { let timer_f = Self::frequency(); - let regs = Self::regs(); + let regs = Self::regs_core(); let arr = regs.arr().read().arr(); let psc = regs.psc().read().psc(); @@ -121,8 +137,72 @@ pub(crate) mod sealed { } } + /// Virtual Basic without CR2 16-bit timer instance. + pub trait BasicNoCr2Instance: CoreInstance { + /// Get access to the Baisc 16bit timer registers. + /// + /// Note: This works even if the timer is more capable, because registers + /// for the less capable timers are a subset. This allows writing a driver + /// for a given set of capabilities, and having it transparently work with + /// more capable timers. + fn regs_basic_no_cr2() -> crate::pac::timer::TimBasicNoCr2; + + /// Enable/disable the update dma. + fn enable_update_dma(&mut self, enable: bool) { + Self::regs_basic_no_cr2().dier().modify(|r| r.set_ude(enable)); + } + + /// Get the update dma enable/disable state. + fn get_update_dma_state(&self) -> bool { + Self::regs_basic_no_cr2().dier().read().ude() + } + } + + /// Basic 16-bit timer instance. + pub trait BasicInstance: BasicNoCr2Instance { + /// Get access to the Baisc 16bit timer registers. + /// + /// Note: This works even if the timer is more capable, because registers + /// for the less capable timers are a subset. This allows writing a driver + /// for a given set of capabilities, and having it transparently work with + /// more capable timers. + fn regs_basic() -> crate::pac::timer::TimBasic; + } + + /// Gneral-purpose 1 channel 16-bit timer instance. + pub trait GeneralPurpose1ChannelInstance: CoreInstance { + /// Get access to the general purpose 1 channel 16bit timer registers. + /// + /// Note: This works even if the timer is more capable, because registers + /// for the less capable timers are a subset. This allows writing a driver + /// for a given set of capabilities, and having it transparently work with + /// more capable timers. + fn regs_1ch() -> crate::pac::timer::Tim1ch; + + /// Set clock divider. + fn set_clock_division(&mut self, ckd: vals::Ckd) { + Self::regs_1ch().cr1().modify(|r| r.set_ckd(ckd)); + } + + /// Get max compare value. This depends on the timer frequency and the clock frequency from RCC. + fn get_max_compare_value(&self) -> u16 { + Self::regs_1ch().arr().read().arr() + } + } + + /// Gneral-purpose 1 channel 16-bit timer instance. + pub trait GeneralPurpose2ChannelInstance: GeneralPurpose1ChannelInstance { + /// Get access to the general purpose 2 channel 16bit timer registers. + /// + /// Note: This works even if the timer is more capable, because registers + /// for the less capable timers are a subset. This allows writing a driver + /// for a given set of capabilities, and having it transparently work with + /// more capable timers. + fn regs_2ch() -> crate::pac::timer::Tim2ch; + } + /// Gneral-purpose 16-bit timer instance. - pub trait GeneralPurpose16bitInstance: Basic16bitInstance { + pub trait GeneralPurpose16bitInstance: BasicInstance + GeneralPurpose2ChannelInstance { /// Get access to the general purpose 16bit timer registers. /// /// Note: This works even if the timer is more capable, because registers @@ -135,7 +215,7 @@ pub(crate) mod sealed { fn set_counting_mode(&mut self, mode: CountingMode) { let (cms, dir) = mode.into(); - let timer_enabled = Self::regs().cr1().read().cen(); + let timer_enabled = Self::regs_core().cr1().read().cen(); // Changing from edge aligned to center aligned (and vice versa) is not allowed while the timer is running. // Changing direction is discouraged while the timer is running. assert!(!timer_enabled); @@ -150,62 +230,8 @@ pub(crate) mod sealed { (cr1.cms(), cr1.dir()).into() } - /// Set clock divider. - fn set_clock_division(&mut self, ckd: vals::Ckd) { - Self::regs_gp16().cr1().modify(|r| r.set_ckd(ckd)); - } - } - - /// Gneral-purpose 32-bit timer instance. - pub trait GeneralPurpose32bitInstance: GeneralPurpose16bitInstance { - /// Get access to the general purpose 32bit timer registers. - /// - /// Note: This works even if the timer is more capable, because registers - /// for the less capable timers are a subset. This allows writing a driver - /// for a given set of capabilities, and having it transparently work with - /// more capable timers. - fn regs_gp32() -> crate::pac::timer::TimGp32; - - /// Set timer frequency. - fn set_frequency(&mut self, frequency: Hertz) { - 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()); - let arr: u32 = unwrap!((pclk_ticks_per_timer_period / (psc as u64 + 1)).try_into()); - - let regs = Self::regs_gp32(); - regs.psc().write(|r| r.set_psc(psc)); - regs.arr().write(|r| r.set_arr(arr)); - - regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); - regs.egr().write(|r| r.set_ug(true)); - regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); - } - - /// Get timer frequency. - fn get_frequency(&self) -> Hertz { - let timer_f = Self::frequency(); - - let regs = Self::regs_gp32(); - let arr = regs.arr().read().arr(); - let psc = regs.psc().read().psc(); - - timer_f / arr / (psc + 1) - } - } - - /// Advanced control timer instance. - pub trait AdvancedControlInstance: GeneralPurpose16bitInstance { - /// Get access to the advanced timer registers. - fn regs_advanced() -> crate::pac::timer::TimAdv; - } - - /// Capture/Compare 16-bit timer instance. - pub trait CaptureCompare16bitInstance: GeneralPurpose16bitInstance { /// Set input capture filter. - fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::Icf) { + fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::FilterValue) { let raw_channel = channel.index(); Self::regs_gp16() .ccmr_input(raw_channel / 2) @@ -256,14 +282,11 @@ pub(crate) mod sealed { }); } - /// Enable timer outputs. - fn enable_outputs(&mut self); - /// Set output compare mode. fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) { - let r = Self::regs_gp16(); let raw_channel: usize = channel.index(); - r.ccmr_output(raw_channel / 2) + Self::regs_gp16() + .ccmr_output(raw_channel / 2) .modify(|w| w.set_ocm(raw_channel % 2, mode.into())); } @@ -294,11 +317,6 @@ pub(crate) mod sealed { Self::regs_gp16().ccr(channel.index()).read().ccr() } - /// Get max compare value. This depends on the timer frequency and the clock frequency from RCC. - fn get_max_compare_value(&self) -> u16 { - Self::regs_gp16().arr().read().arr() - } - /// Get compare value for a channel. fn get_compare_value(&self, channel: Channel) -> u16 { Self::regs_gp16().ccr(channel.index()).read().ccr() @@ -333,35 +351,46 @@ pub(crate) mod sealed { } } - /// Capture/Compare 16-bit timer instance with complementary pin support. - pub trait ComplementaryCaptureCompare16bitInstance: CaptureCompare16bitInstance + AdvancedControlInstance { - /// Set complementary output polarity. - fn set_complementary_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) { - Self::regs_advanced() - .ccer() - .modify(|w| w.set_ccnp(channel.index(), polarity.into())); + #[cfg(not(stm32l0))] + /// Gneral-purpose 32-bit timer instance. + pub trait GeneralPurpose32bitInstance: GeneralPurpose16bitInstance { + /// Get access to the general purpose 32bit timer registers. + /// + /// Note: This works even if the timer is more capable, because registers + /// for the less capable timers are a subset. This allows writing a driver + /// for a given set of capabilities, and having it transparently work with + /// more capable timers. + fn regs_gp32() -> crate::pac::timer::TimGp32; + + /// Set timer frequency. + fn set_frequency(&mut self, frequency: Hertz) { + 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()); + let arr: u32 = unwrap!((pclk_ticks_per_timer_period / (psc as u64 + 1)).try_into()); + + let regs = Self::regs_gp32(); + regs.psc().write(|r| r.set_psc(psc)); + regs.arr().write(|r| r.set_arr(arr)); + + regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); + regs.egr().write(|r| r.set_ug(true)); + regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); } - /// Set clock divider for the dead time. - fn set_dead_time_clock_division(&mut self, value: vals::Ckd) { - Self::regs_advanced().cr1().modify(|w| w.set_ckd(value)); + /// Get timer frequency. + fn get_frequency(&self) -> Hertz { + let timer_f = Self::frequency(); + + let regs = Self::regs_gp32(); + let arr = regs.arr().read().arr(); + let psc = regs.psc().read().psc(); + + timer_f / arr / (psc + 1) } - /// Set dead time, as a fraction of the max duty value. - fn set_dead_time_value(&mut self, value: u8) { - Self::regs_advanced().bdtr().modify(|w| w.set_dtg(value)); - } - - /// Enable/disable a complementary channel. - fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) { - Self::regs_advanced() - .ccer() - .modify(|w| w.set_ccne(channel.index(), enable)); - } - } - - /// Capture/Compare 32-bit timer instance. - pub trait CaptureCompare32bitInstance: GeneralPurpose32bitInstance + CaptureCompare16bitInstance { /// Set comapre value for a channel. fn set_compare_value(&mut self, channel: Channel, value: u32) { Self::regs_gp32().ccr(channel.index()).modify(|w| w.set_ccr(value)); @@ -382,6 +411,70 @@ pub(crate) mod sealed { Self::regs_gp32().ccr(channel.index()).read().ccr() } } + + #[cfg(not(stm32l0))] + /// Gneral-purpose 1 channel with one complementary 16-bit timer instance. + pub trait GeneralPurpose1ChannelComplementaryInstance: BasicNoCr2Instance + GeneralPurpose1ChannelInstance { + /// Get access to the general purpose 1 channel with one complementary 16bit timer registers. + /// + /// Note: This works even if the timer is more capable, because registers + /// for the less capable timers are a subset. This allows writing a driver + /// for a given set of capabilities, and having it transparently work with + /// more capable timers. + fn regs_1ch_cmp() -> crate::pac::timer::Tim1chCmp; + + /// Set clock divider for the dead time. + fn set_dead_time_clock_division(&mut self, value: vals::Ckd) { + Self::regs_1ch_cmp().cr1().modify(|w| w.set_ckd(value)); + } + + /// Set dead time, as a fraction of the max duty value. + fn set_dead_time_value(&mut self, value: u8) { + Self::regs_1ch_cmp().bdtr().modify(|w| w.set_dtg(value)); + } + + /// Enable timer outputs. + fn enable_outputs(&mut self) { + Self::regs_1ch_cmp().bdtr().modify(|w| w.set_moe(true)); + } + } + + #[cfg(not(stm32l0))] + /// Gneral-purpose 2 channel with one complementary 16-bit timer instance. + pub trait GeneralPurpose2ChannelComplementaryInstance: + BasicInstance + GeneralPurpose2ChannelInstance + GeneralPurpose1ChannelComplementaryInstance + { + /// Get access to the general purpose 2 channel with one complementary 16bit timer registers. + /// + /// Note: This works even if the timer is more capable, because registers + /// for the less capable timers are a subset. This allows writing a driver + /// for a given set of capabilities, and having it transparently work with + /// more capable timers. + fn regs_2ch_cmp() -> crate::pac::timer::Tim2chCmp; + } + + #[cfg(not(stm32l0))] + /// Advanced control timer instance. + pub trait AdvancedControlInstance: + GeneralPurpose2ChannelComplementaryInstance + GeneralPurpose16bitInstance + { + /// Get access to the advanced timer registers. + fn regs_advanced() -> crate::pac::timer::TimAdv; + + /// Set complementary output polarity. + fn set_complementary_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) { + Self::regs_advanced() + .ccer() + .modify(|w| w.set_ccnp(channel.index(), polarity.into())); + } + + /// Enable/disable a complementary channel. + fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) { + Self::regs_advanced() + .ccer() + .modify(|w| w.set_ccne(channel.index(), enable)); + } + } } /// Timer channel. @@ -572,61 +665,92 @@ impl From<OutputPolarity> for bool { } /// Basic 16-bit timer instance. -pub trait Basic16bitInstance: sealed::Basic16bitInstance + 'static {} +pub trait BasicInstance: sealed::BasicInstance + sealed::BasicNoCr2Instance + sealed::CoreInstance + 'static {} -/// Gneral-purpose 16-bit timer instance. -pub trait GeneralPurpose16bitInstance: sealed::GeneralPurpose16bitInstance + Basic16bitInstance + 'static {} - -/// Gneral-purpose 32-bit timer instance. -pub trait GeneralPurpose32bitInstance: - sealed::GeneralPurpose32bitInstance + GeneralPurpose16bitInstance + 'static -{ -} - -/// Advanced control timer instance. -pub trait AdvancedControlInstance: sealed::AdvancedControlInstance + GeneralPurpose16bitInstance + 'static {} - -/// Capture/Compare 16-bit timer instance. +// It's just a General-purpose 16-bit timer instance. +/// Capture Compare timer instance. pub trait CaptureCompare16bitInstance: - sealed::CaptureCompare16bitInstance + GeneralPurpose16bitInstance + 'static + BasicInstance + + sealed::GeneralPurpose2ChannelInstance + + sealed::GeneralPurpose1ChannelInstance + + sealed::GeneralPurpose16bitInstance + + 'static { } -/// Capture/Compare 16-bit timer instance with complementary pin support. -pub trait ComplementaryCaptureCompare16bitInstance: - sealed::ComplementaryCaptureCompare16bitInstance + CaptureCompare16bitInstance + AdvancedControlInstance + 'static -{ -} - -/// Capture/Compare 32-bit timer instance. +#[cfg(not(stm32l0))] +// It's just a General-purpose 32-bit timer instance. +/// Capture Compare 32-bit timer instance. pub trait CaptureCompare32bitInstance: - sealed::CaptureCompare32bitInstance + CaptureCompare16bitInstance + GeneralPurpose32bitInstance + 'static + CaptureCompare16bitInstance + sealed::GeneralPurpose32bitInstance + 'static +{ +} + +#[cfg(not(stm32l0))] +// It's just a Advanced Control timer instance. +/// Complementary Capture Compare 32-bit timer instance. +pub trait ComplementaryCaptureCompare16bitInstance: + CaptureCompare16bitInstance + + sealed::GeneralPurpose1ChannelComplementaryInstance + + sealed::GeneralPurpose2ChannelComplementaryInstance + + sealed::AdvancedControlInstance + + 'static { } pin_trait!(Channel1Pin, CaptureCompare16bitInstance); -pin_trait!(Channel1ComplementaryPin, CaptureCompare16bitInstance); pin_trait!(Channel2Pin, CaptureCompare16bitInstance); -pin_trait!(Channel2ComplementaryPin, CaptureCompare16bitInstance); pin_trait!(Channel3Pin, CaptureCompare16bitInstance); -pin_trait!(Channel3ComplementaryPin, CaptureCompare16bitInstance); pin_trait!(Channel4Pin, CaptureCompare16bitInstance); -pin_trait!(Channel4ComplementaryPin, CaptureCompare16bitInstance); pin_trait!(ExternalTriggerPin, CaptureCompare16bitInstance); -pin_trait!(BreakInputPin, CaptureCompare16bitInstance); -pin_trait!(BreakInputComparator1Pin, CaptureCompare16bitInstance); -pin_trait!(BreakInputComparator2Pin, CaptureCompare16bitInstance); -pin_trait!(BreakInput2Pin, CaptureCompare16bitInstance); -pin_trait!(BreakInput2Comparator1Pin, CaptureCompare16bitInstance); -pin_trait!(BreakInput2Comparator2Pin, CaptureCompare16bitInstance); + +cfg_if::cfg_if! { + if #[cfg(not(stm32l0))] { + pin_trait!(Channel1ComplementaryPin, ComplementaryCaptureCompare16bitInstance); + pin_trait!(Channel2ComplementaryPin, ComplementaryCaptureCompare16bitInstance); + pin_trait!(Channel3ComplementaryPin, ComplementaryCaptureCompare16bitInstance); + pin_trait!(Channel4ComplementaryPin, ComplementaryCaptureCompare16bitInstance); + + pin_trait!(BreakInputPin, ComplementaryCaptureCompare16bitInstance); + pin_trait!(BreakInput2Pin, ComplementaryCaptureCompare16bitInstance); + + pin_trait!(BreakInputComparator1Pin, ComplementaryCaptureCompare16bitInstance); + pin_trait!(BreakInputComparator2Pin, ComplementaryCaptureCompare16bitInstance); + + pin_trait!(BreakInput2Comparator1Pin, ComplementaryCaptureCompare16bitInstance); + pin_trait!(BreakInput2Comparator2Pin, ComplementaryCaptureCompare16bitInstance); + } +} #[allow(unused)] -macro_rules! impl_basic_16bit_timer { +macro_rules! impl_core_timer { ($inst:ident, $irq:ident) => { - impl sealed::Basic16bitInstance for crate::peripherals::$inst { + impl sealed::CoreInstance for crate::peripherals::$inst { type Interrupt = crate::interrupt::typelevel::$irq; - fn regs() -> crate::pac::timer::TimBasic { + fn regs_core() -> crate::pac::timer::TimCore { + unsafe { crate::pac::timer::TimCore::from_ptr(crate::pac::$inst.as_ptr()) } + } + } + }; +} + +#[allow(unused)] +macro_rules! impl_basic_no_cr2_timer { + ($inst:ident) => { + impl sealed::BasicNoCr2Instance for crate::peripherals::$inst { + fn regs_basic_no_cr2() -> crate::pac::timer::TimBasicNoCr2 { + unsafe { crate::pac::timer::TimBasicNoCr2::from_ptr(crate::pac::$inst.as_ptr()) } + } + } + }; +} + +#[allow(unused)] +macro_rules! impl_basic_timer { + ($inst:ident) => { + impl sealed::BasicInstance for crate::peripherals::$inst { + fn regs_basic() -> crate::pac::timer::TimBasic { unsafe { crate::pac::timer::TimBasic::from_ptr(crate::pac::$inst.as_ptr()) } } } @@ -634,7 +758,40 @@ macro_rules! impl_basic_16bit_timer { } #[allow(unused)] -macro_rules! impl_32bit_timer { +macro_rules! impl_1ch_timer { + ($inst:ident) => { + impl sealed::GeneralPurpose1ChannelInstance for crate::peripherals::$inst { + fn regs_1ch() -> crate::pac::timer::Tim1ch { + unsafe { crate::pac::timer::Tim1ch::from_ptr(crate::pac::$inst.as_ptr()) } + } + } + }; +} + +#[allow(unused)] +macro_rules! impl_2ch_timer { + ($inst:ident) => { + impl sealed::GeneralPurpose2ChannelInstance for crate::peripherals::$inst { + fn regs_2ch() -> crate::pac::timer::Tim2ch { + unsafe { crate::pac::timer::Tim2ch::from_ptr(crate::pac::$inst.as_ptr()) } + } + } + }; +} + +#[allow(unused)] +macro_rules! impl_gp16_timer { + ($inst:ident) => { + impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { + fn regs_gp16() -> crate::pac::timer::TimGp16 { + unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) } + } + } + }; +} + +#[allow(unused)] +macro_rules! impl_gp32_timer { ($inst:ident) => { impl sealed::GeneralPurpose32bitInstance for crate::peripherals::$inst { fn regs_gp32() -> crate::pac::timer::TimGp32 { @@ -645,83 +802,144 @@ macro_rules! impl_32bit_timer { } #[allow(unused)] -macro_rules! impl_compare_capable_16bit { +macro_rules! impl_1ch_cmp_timer { ($inst:ident) => { - impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { - fn enable_outputs(&mut self) {} + impl sealed::GeneralPurpose1ChannelComplementaryInstance for crate::peripherals::$inst { + fn regs_1ch_cmp() -> crate::pac::timer::Tim1chCmp { + unsafe { crate::pac::timer::Tim1chCmp::from_ptr(crate::pac::$inst.as_ptr()) } + } + } + }; +} + +#[allow(unused)] +macro_rules! impl_2ch_cmp_timer { + ($inst:ident) => { + impl sealed::GeneralPurpose2ChannelComplementaryInstance for crate::peripherals::$inst { + fn regs_2ch_cmp() -> crate::pac::timer::Tim2chCmp { + unsafe { crate::pac::timer::Tim2chCmp::from_ptr(crate::pac::$inst.as_ptr()) } + } + } + }; +} + +#[allow(unused)] +macro_rules! impl_adv_timer { + ($inst:ident) => { + impl sealed::AdvancedControlInstance for crate::peripherals::$inst { + fn regs_advanced() -> crate::pac::timer::TimAdv { + unsafe { crate::pac::timer::TimAdv::from_ptr(crate::pac::$inst.as_ptr()) } + } } }; } foreach_interrupt! { - ($inst:ident, timer, TIM_BASIC, UP, $irq:ident) => { - impl_basic_16bit_timer!($inst, $irq); - impl Basic16bitInstance for crate::peripherals::$inst {} - }; - ($inst:ident, timer, TIM_GP16, UP, $irq:ident) => { - impl_basic_16bit_timer!($inst, $irq); - impl_compare_capable_16bit!($inst); - impl Basic16bitInstance for crate::peripherals::$inst {} - impl GeneralPurpose16bitInstance for crate::peripherals::$inst {} - impl CaptureCompare16bitInstance for crate::peripherals::$inst {} - impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { - fn regs_gp16() -> crate::pac::timer::TimGp16 { - crate::pac::$inst - } - } + ($inst:ident, timer, TIM_BASIC, UP, $irq:ident) => { + impl_core_timer!($inst, $irq); + impl_basic_no_cr2_timer!($inst); + impl_basic_timer!($inst); + impl BasicInstance for crate::peripherals::$inst {} + }; + + ($inst:ident, timer, TIM_1CH, UP, $irq:ident) => { + impl_core_timer!($inst, $irq); + impl_basic_no_cr2_timer!($inst); + impl_basic_timer!($inst); + impl_1ch_timer!($inst); + impl_2ch_timer!($inst); + impl_gp16_timer!($inst); + impl BasicInstance for crate::peripherals::$inst {} + impl CaptureCompare16bitInstance for crate::peripherals::$inst {} + }; + + + ($inst:ident, timer, TIM_2CH, UP, $irq:ident) => { + impl_core_timer!($inst, $irq); + impl_basic_no_cr2_timer!($inst); + impl_basic_timer!($inst); + impl_1ch_timer!($inst); + impl_2ch_timer!($inst); + impl_gp16_timer!($inst); + impl BasicInstance for crate::peripherals::$inst {} + impl CaptureCompare16bitInstance for crate::peripherals::$inst {} + }; + + ($inst:ident, timer, TIM_GP16, UP, $irq:ident) => { + impl_core_timer!($inst, $irq); + impl_basic_no_cr2_timer!($inst); + impl_basic_timer!($inst); + impl_1ch_timer!($inst); + impl_2ch_timer!($inst); + impl_gp16_timer!($inst); + impl BasicInstance for crate::peripherals::$inst {} + impl CaptureCompare16bitInstance for crate::peripherals::$inst {} }; ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => { - impl_basic_16bit_timer!($inst, $irq); - impl_32bit_timer!($inst); - impl_compare_capable_16bit!($inst); - impl Basic16bitInstance for crate::peripherals::$inst {} + impl_core_timer!($inst, $irq); + impl_basic_no_cr2_timer!($inst); + impl_basic_timer!($inst); + impl_1ch_timer!($inst); + impl_2ch_timer!($inst); + impl_gp16_timer!($inst); + impl_gp32_timer!($inst); + impl BasicInstance for crate::peripherals::$inst {} impl CaptureCompare16bitInstance for crate::peripherals::$inst {} impl CaptureCompare32bitInstance for crate::peripherals::$inst {} - impl GeneralPurpose16bitInstance for crate::peripherals::$inst {} - impl GeneralPurpose32bitInstance for crate::peripherals::$inst {} - impl sealed::CaptureCompare32bitInstance for crate::peripherals::$inst {} - - impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { - fn regs_gp16() -> crate::pac::timer::TimGp16 { - unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) } - } - } }; - ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => { - impl_basic_16bit_timer!($inst, $irq); - - impl Basic16bitInstance for crate::peripherals::$inst {} - impl GeneralPurpose16bitInstance for crate::peripherals::$inst {} + ($inst:ident, timer, TIM_1CH_CMP, UP, $irq:ident) => { + impl_core_timer!($inst, $irq); + impl_basic_no_cr2_timer!($inst); + impl_basic_timer!($inst); + impl_1ch_timer!($inst); + impl_2ch_timer!($inst); + impl_gp16_timer!($inst); + impl_1ch_cmp_timer!($inst); + impl_2ch_cmp_timer!($inst); + impl_adv_timer!($inst); + impl BasicInstance for crate::peripherals::$inst {} impl CaptureCompare16bitInstance for crate::peripherals::$inst {} impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {} - impl AdvancedControlInstance for crate::peripherals::$inst {} - impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { - fn enable_outputs(&mut self) { - use crate::timer::sealed::AdvancedControlInstance; - let r = Self::regs_advanced(); - r.bdtr().modify(|w| w.set_moe(true)); - } - } - impl sealed::ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {} - impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { - fn regs_gp16() -> crate::pac::timer::TimGp16 { - unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) } - } - } + }; - impl sealed::AdvancedControlInstance for crate::peripherals::$inst { - fn regs_advanced() -> crate::pac::timer::TimAdv { - crate::pac::$inst - } - } + + ($inst:ident, timer, TIM_2CH_CMP, UP, $irq:ident) => { + impl_core_timer!($inst, $irq); + impl_basic_no_cr2_timer!($inst); + impl_basic_timer!($inst); + impl_1ch_timer!($inst); + impl_2ch_timer!($inst); + impl_gp16_timer!($inst); + impl_1ch_cmp_timer!($inst); + impl_2ch_cmp_timer!($inst); + impl_adv_timer!($inst); + impl BasicInstance for crate::peripherals::$inst {} + impl CaptureCompare16bitInstance for crate::peripherals::$inst {} + impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {} + }; + + + ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => { + impl_core_timer!($inst, $irq); + impl_basic_no_cr2_timer!($inst); + impl_basic_timer!($inst); + impl_1ch_timer!($inst); + impl_2ch_timer!($inst); + impl_gp16_timer!($inst); + impl_1ch_cmp_timer!($inst); + impl_2ch_cmp_timer!($inst); + impl_adv_timer!($inst); + impl BasicInstance for crate::peripherals::$inst {} + impl CaptureCompare16bitInstance for crate::peripherals::$inst {} + impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {} }; } // Update Event trigger DMA for every timer -dma_trait!(UpDma, Basic16bitInstance); +dma_trait!(UpDma, BasicInstance); dma_trait!(Ch1Dma, CaptureCompare16bitInstance); dma_trait!(Ch2Dma, CaptureCompare16bitInstance); diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs index 0b4c1225f..1acba504e 100644 --- a/embassy-stm32/src/timer/simple_pwm.rs +++ b/embassy-stm32/src/timer/simple_pwm.rs @@ -84,13 +84,12 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { this.set_frequency(freq); this.inner.start(); - this.inner.enable_outputs(); - [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4] .iter() .for_each(|&channel| { this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1); - this.inner.set_output_compare_preload(channel, true) + + this.inner.set_output_compare_preload(channel, true); }); this @@ -202,7 +201,7 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { &mut dma, req, duty, - T::regs_gp16().ccr(channel.index()).as_ptr() as *mut _, + T::regs_1ch().ccr(channel.index()).as_ptr() as *mut _, dma_transfer_option, ) .await diff --git a/examples/stm32h7/src/bin/dac_dma.rs b/examples/stm32h7/src/bin/dac_dma.rs index 8e5c41a43..d88bd838f 100644 --- a/examples/stm32h7/src/bin/dac_dma.rs +++ b/examples/stm32h7/src/bin/dac_dma.rs @@ -8,7 +8,7 @@ use embassy_stm32::pac::timer::vals::Mms; use embassy_stm32::peripherals::{DAC1, DMA1_CH3, DMA1_CH4, TIM6, TIM7}; use embassy_stm32::rcc::low_level::RccPeripheral; use embassy_stm32::time::Hertz; -use embassy_stm32::timer::low_level::Basic16bitInstance; +use embassy_stm32::timer::low_level::BasicInstance; use micromath::F32Ext; use {defmt_rtt as _, panic_probe as _}; @@ -75,9 +75,9 @@ async fn dac_task1(mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { dac.enable(); TIM6::enable_and_reset(); - TIM6::regs().arr().modify(|w| w.set_arr(reload as u16 - 1)); - TIM6::regs().cr2().modify(|w| w.set_mms(Mms::UPDATE)); - TIM6::regs().cr1().modify(|w| { + TIM6::regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); + TIM6::regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); + TIM6::regs_basic().cr1().modify(|w| { w.set_opm(false); w.set_cen(true); }); @@ -112,9 +112,9 @@ async fn dac_task2(mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { } TIM7::enable_and_reset(); - TIM7::regs().arr().modify(|w| w.set_arr(reload as u16 - 1)); - TIM7::regs().cr2().modify(|w| w.set_mms(Mms::UPDATE)); - TIM7::regs().cr1().modify(|w| { + TIM7::regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); + TIM7::regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); + TIM7::regs_basic().cr1().modify(|w| { w.set_opm(false); w.set_cen(true); }); diff --git a/examples/stm32l4/src/bin/dac_dma.rs b/examples/stm32l4/src/bin/dac_dma.rs index 8e5098557..f227812cd 100644 --- a/examples/stm32l4/src/bin/dac_dma.rs +++ b/examples/stm32l4/src/bin/dac_dma.rs @@ -8,7 +8,7 @@ use embassy_stm32::pac::timer::vals::Mms; use embassy_stm32::peripherals::{DAC1, DMA1_CH3, DMA1_CH4, TIM6, TIM7}; use embassy_stm32::rcc::low_level::RccPeripheral; use embassy_stm32::time::Hertz; -use embassy_stm32::timer::low_level::Basic16bitInstance; +use embassy_stm32::timer::low_level::BasicInstance; use micromath::F32Ext; use {defmt_rtt as _, panic_probe as _}; @@ -46,9 +46,9 @@ async fn dac_task1(mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { dac.enable(); TIM6::enable_and_reset(); - TIM6::regs().arr().modify(|w| w.set_arr(reload as u16 - 1)); - TIM6::regs().cr2().modify(|w| w.set_mms(Mms::UPDATE)); - TIM6::regs().cr1().modify(|w| { + TIM6::regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); + TIM6::regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); + TIM6::regs_basic().cr1().modify(|w| { w.set_opm(false); w.set_cen(true); }); @@ -83,9 +83,9 @@ async fn dac_task2(mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { } TIM7::enable_and_reset(); - TIM7::regs().arr().modify(|w| w.set_arr(reload as u16 - 1)); - TIM7::regs().cr2().modify(|w| w.set_mms(Mms::UPDATE)); - TIM7::regs().cr1().modify(|w| { + TIM7::regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); + TIM7::regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); + TIM7::regs_basic().cr1().modify(|w| { w.set_opm(false); w.set_cen(true); });