{} /// ADC instance. -#[cfg(any(adc_f1, adc_v1, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0))] +#[cfg(any(adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0))] pub trait Instance: sealed::Instance + crate::Peripheral
+ crate::rcc::RccPeripheral {}
/// ADC pin.
@@ -96,12 +97,12 @@ foreach_adc!(
crate::pac::$inst
}
- #[cfg(not(any(adc_f1, adc_v1, adc_f3_v2, adc_f3_v1_1, adc_g0)))]
+ #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0)))]
fn common_regs() -> crate::pac::adccommon::AdcCommon {
return crate::pac::$common_inst
}
- #[cfg(any(adc_f1, adc_f3, adc_v1, adc_f3_v1_1))]
+ #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
fn state() -> &'static sealed::State {
static STATE: sealed::State = sealed::State::new();
&STATE
@@ -125,7 +126,7 @@ macro_rules! impl_adc_pin {
impl crate::adc::AdcPin > + '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..9480d6972 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -1,5 +1,37 @@
//! Timers, PWM, quadrature decoder.
+//!
+//! Timer inheritance
+//!
+
+// sealed:
+//
+// Core -------------------------> 1CH -------------------------> 1CH_CMP
+// | | ^ |
+// +--> Basic_NoCr2 --> Basic +--> 2CH --> GP16 --> GP32 | +--> 2CH_CMP --> ADV
+// | | | ^ | | ^ ^
+// | | +------|--|--------------|-----------+ |
+// | +--------------------+ +--------------|-----------|---------+
+// | | | |
+// | +--------------------------------------|-----------+
+// +----------------------------------------------------+
+
+//! ```text
+//! BasicInstance --> CaptureCompare16bitInstance --+--> ComplementaryCaptureCompare16bitInstance
+//! |
+//! +--> CaptureCompare32bitInstance
+//! ```
+//!
+//! Mapping:
+//!
+//! | trait | timer |
+//! | :----------------------------------------: | ------------------------------------------------------------------------------------------------- |
+//! | [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 +51,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 +96,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 +109,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 +123,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 +143,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 +221,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 +236,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 +288,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 +323,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 +357,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 +417,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 +671,92 @@ impl From