From d6636ca11669c60925acb08c32d488c481ee1581 Mon Sep 17 00:00:00 2001
From: eZio Pan <eziopan@qq.com>
Date: Tue, 30 Jan 2024 16:54:06 +0800
Subject: [PATCH 01/10] minor fix

---
 embassy-stm32/src/dma/ringbuffer.rs | 1 +
 1 file changed, 1 insertion(+)

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 {

From dc4898ca89d2130158acf1ced1f8cb3b25efe4b8 Mon Sep 17 00:00:00 2001
From: eZio Pan <eziopan@qq.com>
Date: Tue, 30 Jan 2024 16:53:39 +0800
Subject: [PATCH 02/10] update timer mod after stm32-metapac timer_v2

---
 embassy-stm32/Cargo.toml                     |   4 +-
 embassy-stm32/src/time_driver.rs             |   8 +-
 embassy-stm32/src/timer/complementary_pwm.rs |   2 +-
 embassy-stm32/src/timer/mod.rs               | 526 ++++++++++++++-----
 embassy-stm32/src/timer/qei.rs               |   2 +-
 embassy-stm32/src/timer/simple_pwm.rs        |   6 +-
 examples/stm32h7/src/bin/dac_dma.rs          |  14 +-
 examples/stm32l4/src/bin/dac_dma.rs          |  14 +-
 8 files changed, 433 insertions(+), 143 deletions(-)

diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 61d70b732..c6bc27f89 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", rev = "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/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..0470e3048 100644
--- a/embassy-stm32/src/timer/complementary_pwm.rs
+++ b/embassy-stm32/src/timer/complementary_pwm.rs
@@ -52,7 +52,7 @@ pub struct ComplementaryPwm<'d, T> {
     inner: PeripheralRef<'d, T>,
 }
 
-impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
+impl<'d, T: GeneralPurpose16bitInstance + ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
     /// Create a new complementary PWM driver.
     #[allow(clippy::too_many_arguments)]
     pub fn new(
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index 210bf7153..f66b4d094 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -1,5 +1,19 @@
 //! Timers, PWM, quadrature decoder.
 
+// Timer inheritance
+//
+//                       CaptureCompare16bitInstance       ComplementaryCaptureCompare16bitInstance
+//                                  v                                v
+// Core -------------------------> 1CH -------------------------> 1CH_CMP
+//   |                              |                              ^   |
+//   +--> Basic_NoCr2 --> Basic     +--> 2CH --> GP16 --> GP32     |   +--> 2CH_CMP --> ADV
+//            |             |             |      ^  |              |           ^         ^
+//            |             |             +------|--|--------------|-----------+         |
+//            |             +--------------------+  +--------------|-----------|---------+
+//            |             |                                      |           |
+//            |             +--------------------------------------|-----------+
+//            +----------------------------------------------------+
+
 pub mod complementary_pwm;
 pub mod qei;
 pub mod simple_pwm;
@@ -19,32 +33,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 +78,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 +91,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 +105,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 +125,67 @@ 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));
+        }
+    }
+
+    /// 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 +198,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);
@@ -149,11 +212,6 @@ pub(crate) mod sealed {
             let cr1 = Self::regs_gp16().cr1().read();
             (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.
@@ -196,36 +254,67 @@ pub(crate) mod sealed {
         }
     }
 
+    /// 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;
+
+        /// Enable timer outputs.
+        fn enable_outputs(&mut self) {
+            Self::regs_1ch_cmp().bdtr().modify(|w| w.set_moe(true));
+        }
+    }
+
+    /// Gneral-purpose 2 channel with one complementary 16-bit timer instance.
+    pub trait GeneralPurpose2ChannelComplementaryInstance:
+        BasicInstance + 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;
+    }
+
     /// Advanced control timer instance.
-    pub trait AdvancedControlInstance: GeneralPurpose16bitInstance {
+    pub trait AdvancedControlInstance:
+        GeneralPurpose2ChannelComplementaryInstance + 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 {
+    pub trait CaptureCompare16bitInstance: GeneralPurpose1ChannelInstance {
         /// 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()
+            Self::regs_1ch()
                 .ccmr_input(raw_channel / 2)
                 .modify(|r| r.set_icf(raw_channel % 2, icf));
         }
 
         /// Clear input interrupt.
         fn clear_input_interrupt(&mut self, channel: Channel) {
-            Self::regs_gp16().sr().modify(|r| r.set_ccif(channel.index(), false));
+            Self::regs_1ch().sr().modify(|r| r.set_ccif(channel.index(), false));
         }
 
         /// Enable input interrupt.
         fn enable_input_interrupt(&mut self, channel: Channel, enable: bool) {
-            Self::regs_gp16().dier().modify(|r| r.set_ccie(channel.index(), enable));
+            Self::regs_1ch().dier().modify(|r| r.set_ccie(channel.index(), enable));
         }
 
         /// Set input capture prescaler.
         fn set_input_capture_prescaler(&mut self, channel: Channel, factor: u8) {
             let raw_channel = channel.index();
-            Self::regs_gp16()
+            Self::regs_1ch()
                 .ccmr_input(raw_channel / 2)
                 .modify(|r| r.set_icpsc(raw_channel % 2, factor));
         }
@@ -233,14 +322,14 @@ pub(crate) mod sealed {
         /// Set input TI selection.
         fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) {
             let raw_channel = channel.index();
-            Self::regs_gp16()
+            Self::regs_1ch()
                 .ccmr_input(raw_channel / 2)
                 .modify(|r| r.set_ccs(raw_channel % 2, tisel.into()));
         }
 
         /// Set input capture mode.
         fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) {
-            Self::regs_gp16().ccer().modify(|r| match mode {
+            Self::regs_1ch().ccer().modify(|r| match mode {
                 InputCaptureMode::Rising => {
                     r.set_ccnp(channel.index(), false);
                     r.set_ccp(channel.index(), false);
@@ -256,12 +345,9 @@ 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 r = Self::regs_1ch();
             let raw_channel: usize = channel.index();
             r.ccmr_output(raw_channel / 2)
                 .modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
@@ -269,45 +355,45 @@ pub(crate) mod sealed {
 
         /// Set output polarity.
         fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
-            Self::regs_gp16()
+            Self::regs_1ch()
                 .ccer()
                 .modify(|w| w.set_ccp(channel.index(), polarity.into()));
         }
 
         /// Enable/disable a channel.
         fn enable_channel(&mut self, channel: Channel, enable: bool) {
-            Self::regs_gp16().ccer().modify(|w| w.set_cce(channel.index(), enable));
+            Self::regs_1ch().ccer().modify(|w| w.set_cce(channel.index(), enable));
         }
 
         /// Get enable/disable state of a channel
         fn get_channel_enable_state(&self, channel: Channel) -> bool {
-            Self::regs_gp16().ccer().read().cce(channel.index())
+            Self::regs_1ch().ccer().read().cce(channel.index())
         }
 
         /// Set compare value for a channel.
         fn set_compare_value(&mut self, channel: Channel, value: u16) {
-            Self::regs_gp16().ccr(channel.index()).modify(|w| w.set_ccr(value));
+            Self::regs_1ch().ccr(channel.index()).modify(|w| w.set_ccr(value));
         }
 
         /// Get capture value for a channel.
         fn get_capture_value(&mut self, channel: Channel) -> u16 {
-            Self::regs_gp16().ccr(channel.index()).read().ccr()
+            Self::regs_1ch().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()
+            Self::regs_1ch().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()
+            Self::regs_1ch().ccr(channel.index()).read().ccr()
         }
 
         /// Set output compare preload.
         fn set_output_compare_preload(&mut self, channel: Channel, preload: bool) {
             let channel_index = channel.index();
-            Self::regs_gp16()
+            Self::regs_1ch()
                 .ccmr_output(channel_index / 2)
                 .modify(|w| w.set_ocpe(channel_index % 2, preload));
         }
@@ -334,27 +420,29 @@ pub(crate) mod sealed {
     }
 
     /// Capture/Compare 16-bit timer instance with complementary pin support.
-    pub trait ComplementaryCaptureCompare16bitInstance: CaptureCompare16bitInstance + AdvancedControlInstance {
+    pub trait ComplementaryCaptureCompare16bitInstance:
+        CaptureCompare16bitInstance + GeneralPurpose1ChannelComplementaryInstance
+    {
         /// Set complementary output polarity.
         fn set_complementary_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
-            Self::regs_advanced()
+            Self::regs_1ch_cmp()
                 .ccer()
                 .modify(|w| w.set_ccnp(channel.index(), polarity.into()));
         }
 
         /// 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));
+            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_advanced().bdtr().modify(|w| w.set_dtg(value));
+            Self::regs_1ch_cmp().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()
+            Self::regs_1ch_cmp()
                 .ccer()
                 .modify(|w| w.set_ccne(channel.index(), enable));
         }
@@ -571,11 +659,29 @@ impl From<OutputPolarity> for bool {
     }
 }
 
-/// Basic 16-bit timer instance.
-pub trait Basic16bitInstance: sealed::Basic16bitInstance + 'static {}
+/// Virtual Core 16-bit timer instance.
+pub trait CoreInstance: sealed::CoreInstance + 'static {}
 
-/// Gneral-purpose 16-bit timer instance.
-pub trait GeneralPurpose16bitInstance: sealed::GeneralPurpose16bitInstance + Basic16bitInstance + 'static {}
+/// Virtual Basic 16-bit timer without CR2 register instance.
+pub trait BasicNoCr2Instance: sealed::BasicNoCr2Instance + CoreInstance + 'static {}
+
+/// Basic 16-bit timer instance.
+pub trait BasicInstance: sealed::BasicInstance + BasicNoCr2Instance + 'static {}
+
+/// 1 channel 16-bit instance.
+pub trait GeneralPurpose1ChannelInstance: sealed::GeneralPurpose1ChannelInstance + CoreInstance + 'static {}
+
+/// 2 channel 16-bit instance.
+pub trait GeneralPurpose2ChannelInstance:
+    sealed::GeneralPurpose2ChannelInstance + GeneralPurpose1ChannelInstance + 'static
+{
+}
+
+/// General-purpose 16-bit timer instance.
+pub trait GeneralPurpose16bitInstance:
+    sealed::GeneralPurpose16bitInstance + BasicInstance + GeneralPurpose2ChannelInstance + 'static
+{
+}
 
 /// Gneral-purpose 32-bit timer instance.
 pub trait GeneralPurpose32bitInstance:
@@ -583,18 +689,39 @@ pub trait GeneralPurpose32bitInstance:
 {
 }
 
+/// General-purpose 1 channel with one complementary 16-bit timer instance.
+pub trait GeneralPurpose1ChannelComplementaryInstance:
+    sealed::GeneralPurpose1ChannelComplementaryInstance + GeneralPurpose1ChannelInstance + 'static
+{
+}
+
+/// General-purpose 2 channel with one complementary 16-bit timer instance.
+pub trait GeneralPurpose2ChannelComplementaryInstance:
+    sealed::GeneralPurpose2ChannelComplementaryInstance
+    + BasicInstance
+    + GeneralPurpose1ChannelComplementaryInstance
+    + 'static
+{
+}
+
 /// Advanced control timer instance.
-pub trait AdvancedControlInstance: sealed::AdvancedControlInstance + GeneralPurpose16bitInstance + 'static {}
+pub trait AdvancedControlInstance:
+    sealed::AdvancedControlInstance + GeneralPurpose2ChannelComplementaryInstance + GeneralPurpose16bitInstance + 'static
+{
+}
 
 /// Capture/Compare 16-bit timer instance.
 pub trait CaptureCompare16bitInstance:
-    sealed::CaptureCompare16bitInstance + GeneralPurpose16bitInstance + 'static
+    sealed::CaptureCompare16bitInstance + GeneralPurpose1ChannelInstance + 'static
 {
 }
 
 /// Capture/Compare 16-bit timer instance with complementary pin support.
 pub trait ComplementaryCaptureCompare16bitInstance:
-    sealed::ComplementaryCaptureCompare16bitInstance + CaptureCompare16bitInstance + AdvancedControlInstance + 'static
+    sealed::ComplementaryCaptureCompare16bitInstance
+    + CaptureCompare16bitInstance
+    + GeneralPurpose1ChannelComplementaryInstance
+    + 'static
 {
 }
 
@@ -621,12 +748,34 @@ pin_trait!(BreakInput2Comparator1Pin, CaptureCompare16bitInstance);
 pin_trait!(BreakInput2Comparator2Pin, CaptureCompare16bitInstance);
 
 #[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 +783,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_gp_16bit_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_gp_32bit_timer {
     ($inst:ident) => {
         impl sealed::GeneralPurpose32bitInstance for crate::peripherals::$inst {
             fn regs_gp32() -> crate::pac::timer::TimGp32 {
@@ -644,84 +826,194 @@ macro_rules! impl_32bit_timer {
     };
 }
 
+#[allow(unused)]
+macro_rules! impl_1ch_cmp_timer {
+    ($inst:ident) => {
+        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()) }
+            }
+        }
+    };
+}
+
 #[allow(unused)]
 macro_rules! impl_compare_capable_16bit {
     ($inst:ident) => {
-        impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst {
-            fn enable_outputs(&mut self) {}
-        }
+        impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst {}
+    };
+}
+
+#[allow(unused)]
+macro_rules! impl_compare_capable_32bit {
+    ($inst:ident) => {
+        impl sealed::CaptureCompare32bitInstance for crate::peripherals::$inst {}
+    };
+}
+
+#[allow(unused)]
+macro_rules! impl_compare_capable_complementary_16bit {
+    ($inst:ident) => {
+        impl sealed::ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {}
     };
 }
 
 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 CoreInstance for crate::peripherals::$inst {}
+        impl BasicNoCr2Instance for crate::peripherals::$inst{}
+        impl BasicInstance for crate::peripherals::$inst {}
+    };
+
+    ($inst:ident, timer, TIM_1CH, UP, $irq:ident) => {
+        impl_core_timer!($inst, $irq);
+        impl_1ch_timer!($inst);
+        impl_compare_capable_16bit!($inst);
+        impl CoreInstance for crate::peripherals::$inst {}
+        impl GeneralPurpose1ChannelInstance for crate::peripherals::$inst {}
+        impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
+    };
+
+
+    ($inst:ident, timer, TIM_2CH, UP, $irq:ident) => {
+        impl_core_timer!($inst, $irq);
+        impl_1ch_timer!($inst);
+        impl_compare_capable_16bit!($inst);
+        impl_2ch_timer!($inst);
+        impl CoreInstance for crate::peripherals::$inst {}
+        impl GeneralPurpose1ChannelInstance for crate::peripherals::$inst {}
+        impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
+        impl GeneralPurpose2ChannelInstance 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_compare_capable_16bit!($inst);
+        impl_2ch_timer!($inst);
+        impl_gp_16bit_timer!($inst);
+        impl CoreInstance for crate::peripherals::$inst {}
+        impl BasicNoCr2Instance for crate::peripherals::$inst{}
+        impl BasicInstance for crate::peripherals::$inst {}
+        impl GeneralPurpose1ChannelInstance for crate::peripherals::$inst {}
+        impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
+        impl GeneralPurpose2ChannelInstance for crate::peripherals::$inst {}
+        impl GeneralPurpose16bitInstance for crate::peripherals::$inst {}
     };
 
     ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => {
-        impl_basic_16bit_timer!($inst, $irq);
-        impl_32bit_timer!($inst);
+        impl_core_timer!($inst, $irq);
+        impl_basic_no_cr2_timer!($inst);
+        impl_basic_timer!($inst);
+        impl_1ch_timer!($inst);
         impl_compare_capable_16bit!($inst);
-        impl Basic16bitInstance for crate::peripherals::$inst {}
+        impl_compare_capable_32bit!($inst);
+        impl_2ch_timer!($inst);
+        impl_gp_16bit_timer!($inst);
+        impl_gp_32bit_timer!($inst);
+        impl CoreInstance for crate::peripherals::$inst {}
+        impl BasicNoCr2Instance for crate::peripherals::$inst{}
+        impl BasicInstance for crate::peripherals::$inst {}
+        impl GeneralPurpose1ChannelInstance for crate::peripherals::$inst {}
         impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
         impl CaptureCompare32bitInstance for crate::peripherals::$inst {}
+        impl GeneralPurpose2ChannelInstance 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);
+    ($inst:ident, timer, TIM_1CH_CMP, UP, $irq:ident) => {
+        impl_core_timer!($inst, $irq);
+        impl_basic_no_cr2_timer!($inst);
+        impl_1ch_timer!($inst);
+        impl_compare_capable_16bit!($inst);
+        impl_1ch_cmp_timer!($inst);
+        impl_compare_capable_complementary_16bit!($inst);
+        impl CoreInstance for crate::peripherals::$inst {}
+        impl BasicNoCr2Instance for crate::peripherals::$inst{}
+        impl GeneralPurpose1ChannelInstance for crate::peripherals::$inst {}
+        impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
+        impl GeneralPurpose1ChannelComplementaryInstance for crate::peripherals::$inst {}
+        impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {}
+    };
 
-        impl Basic16bitInstance for crate::peripherals::$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_compare_capable_16bit!($inst);
+        impl_1ch_cmp_timer!($inst);
+        impl_compare_capable_complementary_16bit!($inst);
+        impl_2ch_cmp_timer!($inst);
+        impl CoreInstance for crate::peripherals::$inst {}
+        impl BasicNoCr2Instance for crate::peripherals::$inst{}
+        impl BasicInstance for crate::peripherals::$inst {}
+        impl GeneralPurpose1ChannelInstance for crate::peripherals::$inst {}
+        impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
+        impl GeneralPurpose1ChannelComplementaryInstance for crate::peripherals::$inst {}
+        impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {}
+        impl GeneralPurpose2ChannelComplementaryInstance 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_compare_capable_16bit!($inst);
+        impl_1ch_cmp_timer!($inst);
+        impl_gp_16bit_timer!($inst);
+        impl_compare_capable_complementary_16bit!($inst);
+        impl_2ch_cmp_timer!($inst);
+        impl_adv_timer!($inst);
+        impl CoreInstance for crate::peripherals::$inst {}
+        impl BasicNoCr2Instance for crate::peripherals::$inst{}
+        impl BasicInstance for crate::peripherals::$inst {}
+        impl GeneralPurpose1ChannelInstance for crate::peripherals::$inst {}
+        impl GeneralPurpose2ChannelInstance for crate::peripherals::$inst {}
         impl GeneralPurpose16bitInstance for crate::peripherals::$inst {}
         impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
+        impl GeneralPurpose1ChannelComplementaryInstance for crate::peripherals::$inst {}
         impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {}
+        impl GeneralPurpose2ChannelComplementaryInstance 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
-            }
-        }
     };
 }
 
 // Update Event trigger DMA for every timer
-dma_trait!(UpDma, Basic16bitInstance);
+dma_trait!(UpDma, BasicNoCr2Instance);
 
 dma_trait!(Ch1Dma, CaptureCompare16bitInstance);
 dma_trait!(Ch2Dma, CaptureCompare16bitInstance);
diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs
index 59efb72ba..75e5ab12a 100644
--- a/embassy-stm32/src/timer/qei.rs
+++ b/embassy-stm32/src/timer/qei.rs
@@ -57,7 +57,7 @@ pub struct Qei<'d, T> {
     _inner: PeripheralRef<'d, T>,
 }
 
-impl<'d, T: CaptureCompare16bitInstance> Qei<'d, T> {
+impl<'d, T: GeneralPurpose16bitInstance + CaptureCompare16bitInstance> Qei<'d, T> {
     /// Create a new quadrature decoder driver.
     pub fn new(tim: impl Peripheral<P = T> + 'd, _ch1: QeiPin<'d, T, Ch1>, _ch2: QeiPin<'d, T, Ch2>) -> Self {
         Self::new_inner(tim)
diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs
index 0b4c1225f..1c665d456 100644
--- a/embassy-stm32/src/timer/simple_pwm.rs
+++ b/embassy-stm32/src/timer/simple_pwm.rs
@@ -59,7 +59,7 @@ pub struct SimplePwm<'d, T> {
     inner: PeripheralRef<'d, T>,
 }
 
-impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
+impl<'d, T: GeneralPurpose16bitInstance + CaptureCompare16bitInstance> SimplePwm<'d, T> {
     /// Create a new simple PWM driver.
     pub fn new(
         tim: impl Peripheral<P = T> + 'd,
@@ -84,8 +84,6 @@ 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| {
@@ -202,7 +200,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);
     });

From 53bf0332e9e862fa5c09a1e9ab9a6d7116219ed7 Mon Sep 17 00:00:00 2001
From: Dario Nieuwenhuis <dirbaio@dirbaio.net>
Date: Sat, 10 Feb 2024 00:00:26 +0100
Subject: [PATCH 03/10] asdkf

---
 embassy-stm32/Cargo.toml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index c6bc27f89..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", rev = "stm32-data-028efe4e6e0719b661cbdf8ffda3341e4d63d0df" }
+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"

From d538829f2f3542c78ee9eb218c0b5c982acfb46b Mon Sep 17 00:00:00 2001
From: eZio Pan <eziopan@qq.com>
Date: Thu, 1 Feb 2024 17:10:47 +0800
Subject: [PATCH 04/10] add methods with macro

---
 embassy-stm32/src/timer/complementary_pwm.rs  |  52 +-
 embassy-stm32/src/timer/mod.rs                | 522 ++++++++----------
 embassy-stm32/src/timer/qei.rs                |   4 +-
 embassy-stm32/src/timer/simple_pwm.rs         |  40 +-
 .../stm32h7/src/bin/low_level_timer_api.rs    |   4 +-
 5 files changed, 298 insertions(+), 324 deletions(-)

diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs
index 0470e3048..b9cd044c9 100644
--- a/embassy-stm32/src/timer/complementary_pwm.rs
+++ b/embassy-stm32/src/timer/complementary_pwm.rs
@@ -1,6 +1,7 @@
 //! PWM driver with complementary output support.
 
 use core::marker::PhantomData;
+use core::ops::{Deref, DerefMut};
 
 use embassy_hal_internal::{into_ref, PeripheralRef};
 use stm32_metapac::timer::vals::Ckd;
@@ -23,7 +24,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: AdvancedControlInstance> 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);
@@ -52,7 +53,7 @@ pub struct ComplementaryPwm<'d, T> {
     inner: PeripheralRef<'d, T>,
 }
 
-impl<'d, T: GeneralPurpose16bitInstance + ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
+impl<'d, T: AdvancedControlInstance> ComplementaryPwm<'d, T> {
     /// Create a new complementary PWM driver.
     #[allow(clippy::too_many_arguments)]
     pub fn new(
@@ -84,27 +85,30 @@ impl<'d, T: GeneralPurpose16bitInstance + ComplementaryCaptureCompare16bitInstan
 
         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| {
+                sealed::GeneralPurpose16bitInstance::set_output_compare_mode(
+                    this.inner.deref_mut(),
+                    channel,
+                    OutputCompareMode::PwmMode1,
+                );
+                sealed::GeneralPurpose16bitInstance::set_output_compare_preload(this.inner.deref_mut(), channel, true);
+            });
+
         this
     }
 
     /// Enable the given channel.
     pub fn enable(&mut self, channel: Channel) {
-        self.inner.enable_channel(channel, true);
-        self.inner.enable_complementary_channel(channel, true);
+        sealed::GeneralPurpose16bitInstance::enable_channel(self.inner.deref_mut(), channel, true);
+        sealed::AdvancedControlInstance::enable_complementary_channel(self.inner.deref_mut(), channel, true);
     }
 
     /// Disable the given channel.
     pub fn disable(&mut self, channel: Channel) {
-        self.inner.enable_complementary_channel(channel, false);
-        self.inner.enable_channel(channel, false);
+        sealed::AdvancedControlInstance::enable_complementary_channel(self.inner.deref_mut(), channel, false);
+        sealed::GeneralPurpose16bitInstance::enable_channel(self.inner.deref_mut(), channel, false);
     }
 
     /// Set PWM frequency.
@@ -132,13 +136,13 @@ impl<'d, T: GeneralPurpose16bitInstance + ComplementaryCaptureCompare16bitInstan
     /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included.
     pub fn set_duty(&mut self, channel: Channel, duty: u16) {
         assert!(duty <= self.get_max_duty());
-        self.inner.set_compare_value(channel, duty)
+        sealed::GeneralPurpose16bitInstance::set_compare_value(self.inner.deref_mut(), channel, duty)
     }
 
     /// Set the output polarity for a given channel.
     pub fn set_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
-        self.inner.set_output_polarity(channel, polarity);
-        self.inner.set_complementary_output_polarity(channel, polarity);
+        sealed::GeneralPurpose16bitInstance::set_output_polarity(self.inner.deref_mut(), channel, polarity);
+        sealed::AdvancedControlInstance::set_complementary_output_polarity(self.inner.deref_mut(), channel, polarity);
     }
 
     /// Set the dead time as a proportion of max_duty
@@ -150,19 +154,19 @@ impl<'d, T: GeneralPurpose16bitInstance + ComplementaryCaptureCompare16bitInstan
     }
 }
 
-impl<'d, T: ComplementaryCaptureCompare16bitInstance> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> {
+impl<'d, T: AdvancedControlInstance> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> {
     type Channel = Channel;
     type Time = Hertz;
     type Duty = u16;
 
     fn disable(&mut self, channel: Self::Channel) {
-        self.inner.enable_complementary_channel(channel, false);
-        self.inner.enable_channel(channel, false);
+        sealed::AdvancedControlInstance::enable_complementary_channel(self.inner.deref_mut(), channel, false);
+        sealed::GeneralPurpose16bitInstance::enable_channel(self.inner.deref_mut(), channel, false);
     }
 
     fn enable(&mut self, channel: Self::Channel) {
-        self.inner.enable_channel(channel, true);
-        self.inner.enable_complementary_channel(channel, true);
+        sealed::GeneralPurpose16bitInstance::enable_channel(self.inner.deref_mut(), channel, true);
+        sealed::AdvancedControlInstance::enable_complementary_channel(self.inner.deref_mut(), channel, true);
     }
 
     fn get_period(&self) -> Self::Time {
@@ -170,7 +174,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> embedded_hal_02::Pwm for C
     }
 
     fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
-        self.inner.get_compare_value(channel)
+        sealed::GeneralPurpose16bitInstance::get_compare_value(self.inner.deref(), channel)
     }
 
     fn get_max_duty(&self) -> Self::Duty {
@@ -179,7 +183,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> embedded_hal_02::Pwm for C
 
     fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
         assert!(duty <= self.get_max_duty());
-        self.inner.set_compare_value(channel, duty)
+        sealed::GeneralPurpose16bitInstance::set_compare_value(self.inner.deref_mut(), channel, duty)
     }
 
     fn set_period<P>(&mut self, period: P)
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index f66b4d094..2f5d5770a 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -2,8 +2,6 @@
 
 // Timer inheritance
 //
-//                       CaptureCompare16bitInstance       ComplementaryCaptureCompare16bitInstance
-//                                  v                                v
 // Core -------------------------> 1CH -------------------------> 1CH_CMP
 //   |                              |                              ^   |
 //   +--> Basic_NoCr2 --> Basic     +--> 2CH --> GP16 --> GP32     |   +--> 2CH_CMP --> ADV
@@ -33,6 +31,156 @@ pub mod low_level {
 pub(crate) mod sealed {
     use super::*;
 
+    macro_rules! add_capture_compare_common_methods {
+        ($regs:ident) => {
+            /// Set input capture filter.
+            fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::FilterValue) {
+                let raw_channel = channel.index();
+                Self::$regs()
+                    .ccmr_input(raw_channel / 2)
+                    .modify(|r| r.set_icf(raw_channel % 2, icf));
+            }
+
+            /// Clear input interrupt.
+            fn clear_input_interrupt(&mut self, channel: Channel) {
+                Self::$regs().sr().modify(|r| r.set_ccif(channel.index(), false));
+            }
+
+            /// Enable input interrupt.
+            fn enable_input_interrupt(&mut self, channel: Channel, enable: bool) {
+                Self::$regs()
+                    .dier()
+                    .modify(|r| r.set_ccie(channel.index(), enable));
+            }
+
+            /// Set input capture prescaler.
+            fn set_input_capture_prescaler(&mut self, channel: Channel, factor: u8) {
+                let raw_channel = channel.index();
+                Self::$regs()
+                    .ccmr_input(raw_channel / 2)
+                    .modify(|r| r.set_icpsc(raw_channel % 2, factor));
+            }
+
+            /// Set input TI selection.
+            fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) {
+                let raw_channel = channel.index();
+                Self::$regs()
+                    .ccmr_input(raw_channel / 2)
+                    .modify(|r| r.set_ccs(raw_channel % 2, tisel.into()));
+            }
+
+            /// Set input capture mode.
+            fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) {
+                Self::$regs().ccer().modify(|r| match mode {
+                    InputCaptureMode::Rising => {
+                        r.set_ccnp(channel.index(), false);
+                        r.set_ccp(channel.index(), false);
+                    }
+                    InputCaptureMode::Falling => {
+                        r.set_ccnp(channel.index(), false);
+                        r.set_ccp(channel.index(), true);
+                    }
+                    InputCaptureMode::BothEdges => {
+                        r.set_ccnp(channel.index(), true);
+                        r.set_ccp(channel.index(), true);
+                    }
+                });
+            }
+
+            /// Set output compare mode.
+            fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) {
+                let r = Self::$regs();
+                let raw_channel: usize = channel.index();
+                r.ccmr_output(raw_channel / 2)
+                    .modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
+            }
+
+            /// Set output polarity.
+            fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
+                Self::$regs()
+                    .ccer()
+                    .modify(|w| w.set_ccp(channel.index(), polarity.into()));
+            }
+
+            /// Enable/disable a channel.
+            fn enable_channel(&mut self, channel: Channel, enable: bool) {
+                Self::$regs()
+                    .ccer()
+                    .modify(|w| w.set_cce(channel.index(), enable));
+            }
+
+            /// Get enable/disable state of a channel
+            fn get_channel_enable_state(&self, channel: Channel) -> bool {
+                Self::$regs().ccer().read().cce(channel.index())
+            }
+
+            /// Set compare value for a channel.
+            fn set_compare_value(&mut self, channel: Channel, value: u16) {
+                Self::$regs().ccr(channel.index()).modify(|w| w.set_ccr(value));
+            }
+
+            /// Get capture value for a channel.
+            fn get_capture_value(&mut self, channel: Channel) -> u16 {
+                Self::$regs().ccr(channel.index()).read().ccr()
+            }
+
+            /// Get compare value for a channel.
+            fn get_compare_value(&self, channel: Channel) -> u16 {
+                Self::$regs().ccr(channel.index()).read().ccr()
+            }
+
+            /// Set output compare preload.
+            fn set_output_compare_preload(&mut self, channel: Channel, preload: bool) {
+                let channel_index = channel.index();
+                Self::regs_1ch()
+                    .ccmr_output(channel_index / 2)
+                    .modify(|w| w.set_ocpe(channel_index % 2, preload));
+            }
+        };
+    }
+
+    macro_rules! add_capture_compare_dma_methods {
+        ($regs:ident) => {
+            /// Get capture compare DMA selection
+            fn get_cc_dma_selection(&self) -> super::vals::Ccds {
+                Self::$regs().cr2().read().ccds()
+            }
+
+            /// Set capture compare DMA selection
+            fn set_cc_dma_selection(&mut self, ccds: super::vals::Ccds) {
+                Self::$regs().cr2().modify(|w| w.set_ccds(ccds))
+            }
+
+            /// Get capture compare DMA enable state
+            fn get_cc_dma_enable_state(&self, channel: Channel) -> bool {
+                Self::$regs().dier().read().ccde(channel.index())
+            }
+
+            /// Set capture compare DMA enable state
+            fn set_cc_dma_enable_state(&mut self, channel: Channel, ccde: bool) {
+                Self::$regs().dier().modify(|w| w.set_ccde(channel.index(), ccde))
+            }
+        };
+    }
+
+    macro_rules! add_complementary_capture_compare_methods {
+        ($regs:ident) => {
+            /// Set complementary output polarity.
+            fn set_complementary_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
+                Self::$regs()
+                    .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()
+                    .ccer()
+                    .modify(|w| w.set_ccne(channel.index(), enable));
+            }
+        };
+    }
+
     /// Virtual Core 16-bit timer instance.  
     pub trait CoreInstance: RccPeripheral {
         /// Interrupt for this timer.
@@ -171,6 +319,13 @@ pub(crate) mod sealed {
         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()
+        }
+
+        add_capture_compare_common_methods!(regs_1ch);
     }
 
     /// Gneral-purpose 1 channel 16-bit  timer instance.
@@ -182,6 +337,8 @@ pub(crate) mod sealed {
         /// for a given set of capabilities, and having it transparently work with
         /// more capable timers.
         fn regs_2ch() -> crate::pac::timer::Tim2ch;
+
+        add_capture_compare_common_methods!(regs_2ch);
     }
 
     /// Gneral-purpose 16-bit timer instance.
@@ -212,6 +369,9 @@ pub(crate) mod sealed {
             let cr1 = Self::regs_gp16().cr1().read();
             (cr1.cms(), cr1.dir()).into()
         }
+
+        add_capture_compare_common_methods!(regs_gp16);
+        add_capture_compare_dma_methods!(regs_gp16);
     }
 
     /// Gneral-purpose 32-bit timer instance.
@@ -252,204 +412,7 @@ pub(crate) mod sealed {
 
             timer_f / arr / (psc + 1)
         }
-    }
 
-    /// 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;
-
-        /// Enable timer outputs.
-        fn enable_outputs(&mut self) {
-            Self::regs_1ch_cmp().bdtr().modify(|w| w.set_moe(true));
-        }
-    }
-
-    /// Gneral-purpose 2 channel with one complementary 16-bit timer instance.
-    pub trait GeneralPurpose2ChannelComplementaryInstance:
-        BasicInstance + 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;
-    }
-
-    /// Advanced control timer instance.
-    pub trait AdvancedControlInstance:
-        GeneralPurpose2ChannelComplementaryInstance + GeneralPurpose16bitInstance
-    {
-        /// Get access to the advanced timer registers.
-        fn regs_advanced() -> crate::pac::timer::TimAdv;
-    }
-
-    /// Capture/Compare 16-bit timer instance.
-    pub trait CaptureCompare16bitInstance: GeneralPurpose1ChannelInstance {
-        /// Set input capture filter.
-        fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::FilterValue) {
-            let raw_channel = channel.index();
-            Self::regs_1ch()
-                .ccmr_input(raw_channel / 2)
-                .modify(|r| r.set_icf(raw_channel % 2, icf));
-        }
-
-        /// Clear input interrupt.
-        fn clear_input_interrupt(&mut self, channel: Channel) {
-            Self::regs_1ch().sr().modify(|r| r.set_ccif(channel.index(), false));
-        }
-
-        /// Enable input interrupt.
-        fn enable_input_interrupt(&mut self, channel: Channel, enable: bool) {
-            Self::regs_1ch().dier().modify(|r| r.set_ccie(channel.index(), enable));
-        }
-
-        /// Set input capture prescaler.
-        fn set_input_capture_prescaler(&mut self, channel: Channel, factor: u8) {
-            let raw_channel = channel.index();
-            Self::regs_1ch()
-                .ccmr_input(raw_channel / 2)
-                .modify(|r| r.set_icpsc(raw_channel % 2, factor));
-        }
-
-        /// Set input TI selection.
-        fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) {
-            let raw_channel = channel.index();
-            Self::regs_1ch()
-                .ccmr_input(raw_channel / 2)
-                .modify(|r| r.set_ccs(raw_channel % 2, tisel.into()));
-        }
-
-        /// Set input capture mode.
-        fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) {
-            Self::regs_1ch().ccer().modify(|r| match mode {
-                InputCaptureMode::Rising => {
-                    r.set_ccnp(channel.index(), false);
-                    r.set_ccp(channel.index(), false);
-                }
-                InputCaptureMode::Falling => {
-                    r.set_ccnp(channel.index(), false);
-                    r.set_ccp(channel.index(), true);
-                }
-                InputCaptureMode::BothEdges => {
-                    r.set_ccnp(channel.index(), true);
-                    r.set_ccp(channel.index(), true);
-                }
-            });
-        }
-
-        /// Set output compare mode.
-        fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) {
-            let r = Self::regs_1ch();
-            let raw_channel: usize = channel.index();
-            r.ccmr_output(raw_channel / 2)
-                .modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
-        }
-
-        /// Set output polarity.
-        fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
-            Self::regs_1ch()
-                .ccer()
-                .modify(|w| w.set_ccp(channel.index(), polarity.into()));
-        }
-
-        /// Enable/disable a channel.
-        fn enable_channel(&mut self, channel: Channel, enable: bool) {
-            Self::regs_1ch().ccer().modify(|w| w.set_cce(channel.index(), enable));
-        }
-
-        /// Get enable/disable state of a channel
-        fn get_channel_enable_state(&self, channel: Channel) -> bool {
-            Self::regs_1ch().ccer().read().cce(channel.index())
-        }
-
-        /// Set compare value for a channel.
-        fn set_compare_value(&mut self, channel: Channel, value: u16) {
-            Self::regs_1ch().ccr(channel.index()).modify(|w| w.set_ccr(value));
-        }
-
-        /// Get capture value for a channel.
-        fn get_capture_value(&mut self, channel: Channel) -> u16 {
-            Self::regs_1ch().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_1ch().arr().read().arr()
-        }
-
-        /// Get compare value for a channel.
-        fn get_compare_value(&self, channel: Channel) -> u16 {
-            Self::regs_1ch().ccr(channel.index()).read().ccr()
-        }
-
-        /// Set output compare preload.
-        fn set_output_compare_preload(&mut self, channel: Channel, preload: bool) {
-            let channel_index = channel.index();
-            Self::regs_1ch()
-                .ccmr_output(channel_index / 2)
-                .modify(|w| w.set_ocpe(channel_index % 2, preload));
-        }
-
-        /// Get capture compare DMA selection
-        fn get_cc_dma_selection(&self) -> super::vals::Ccds {
-            Self::regs_gp16().cr2().read().ccds()
-        }
-
-        /// Set capture compare DMA selection
-        fn set_cc_dma_selection(&mut self, ccds: super::vals::Ccds) {
-            Self::regs_gp16().cr2().modify(|w| w.set_ccds(ccds))
-        }
-
-        /// Get capture compare DMA enable state
-        fn get_cc_dma_enable_state(&self, channel: Channel) -> bool {
-            Self::regs_gp16().dier().read().ccde(channel.index())
-        }
-
-        /// Set capture compare DMA enable state
-        fn set_cc_dma_enable_state(&mut self, channel: Channel, ccde: bool) {
-            Self::regs_gp16().dier().modify(|w| w.set_ccde(channel.index(), ccde))
-        }
-    }
-
-    /// Capture/Compare 16-bit timer instance with complementary pin support.
-    pub trait ComplementaryCaptureCompare16bitInstance:
-        CaptureCompare16bitInstance + GeneralPurpose1ChannelComplementaryInstance
-    {
-        /// Set complementary output polarity.
-        fn set_complementary_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
-            Self::regs_1ch_cmp()
-                .ccer()
-                .modify(|w| w.set_ccnp(channel.index(), polarity.into()));
-        }
-
-        /// 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/disable a complementary channel.
-        fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) {
-            Self::regs_1ch_cmp()
-                .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));
@@ -470,6 +433,59 @@ pub(crate) mod sealed {
             Self::regs_gp32().ccr(channel.index()).read().ccr()
         }
     }
+
+    /// 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));
+        }
+
+        add_complementary_capture_compare_methods!(regs_1ch_cmp);
+    }
+
+    /// 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;
+
+        add_complementary_capture_compare_methods!(regs_2ch_cmp);
+    }
+
+    /// Advanced control timer instance.
+    pub trait AdvancedControlInstance:
+        GeneralPurpose2ChannelComplementaryInstance + GeneralPurpose16bitInstance
+    {
+        /// Get access to the advanced timer registers.
+        fn regs_advanced() -> crate::pac::timer::TimAdv;
+
+        add_complementary_capture_compare_methods!(regs_advanced);
+    }
 }
 
 /// Timer channel.
@@ -699,6 +715,7 @@ pub trait GeneralPurpose1ChannelComplementaryInstance:
 pub trait GeneralPurpose2ChannelComplementaryInstance:
     sealed::GeneralPurpose2ChannelComplementaryInstance
     + BasicInstance
+    + GeneralPurpose2ChannelInstance
     + GeneralPurpose1ChannelComplementaryInstance
     + 'static
 {
@@ -710,42 +727,30 @@ pub trait AdvancedControlInstance:
 {
 }
 
-/// Capture/Compare 16-bit timer instance.
-pub trait CaptureCompare16bitInstance:
-    sealed::CaptureCompare16bitInstance + GeneralPurpose1ChannelInstance + 'static
-{
-}
+pin_trait!(Channel1Pin, GeneralPurpose1ChannelInstance);
+pin_trait!(Channel2Pin, GeneralPurpose2ChannelInstance);
+pin_trait!(Channel3Pin, GeneralPurpose16bitInstance);
+pin_trait!(Channel4Pin, GeneralPurpose16bitInstance);
 
-/// Capture/Compare 16-bit timer instance with complementary pin support.
-pub trait ComplementaryCaptureCompare16bitInstance:
-    sealed::ComplementaryCaptureCompare16bitInstance
-    + CaptureCompare16bitInstance
-    + GeneralPurpose1ChannelComplementaryInstance
-    + 'static
-{
-}
+#[cfg(not(stm32l0))]
+pin_trait!(ExternalTriggerPin, GeneralPurpose16bitInstance);
 
-/// Capture/Compare 32-bit timer instance.
-pub trait CaptureCompare32bitInstance:
-    sealed::CaptureCompare32bitInstance + CaptureCompare16bitInstance + GeneralPurpose32bitInstance + 'static
-{
-}
+#[cfg(stm32l0)]
+pin_trait!(ExternalTriggerPin, GeneralPurpose2ChannelInstance);
 
-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);
+pin_trait!(Channel1ComplementaryPin, GeneralPurpose1ChannelComplementaryInstance);
+pin_trait!(Channel2ComplementaryPin, GeneralPurpose2ChannelComplementaryInstance);
+pin_trait!(Channel3ComplementaryPin, AdvancedControlInstance);
+pin_trait!(Channel4ComplementaryPin, AdvancedControlInstance);
+
+pin_trait!(BreakInputPin, GeneralPurpose1ChannelComplementaryInstance);
+pin_trait!(BreakInput2Pin, GeneralPurpose2ChannelComplementaryInstance);
+
+pin_trait!(BreakInputComparator1Pin, GeneralPurpose1ChannelComplementaryInstance);
+pin_trait!(BreakInputComparator2Pin, AdvancedControlInstance);
+
+pin_trait!(BreakInput2Comparator1Pin, AdvancedControlInstance);
+pin_trait!(BreakInput2Comparator2Pin, AdvancedControlInstance);
 
 #[allow(unused)]
 macro_rules! impl_core_timer {
@@ -859,27 +864,6 @@ macro_rules! impl_adv_timer {
     };
 }
 
-#[allow(unused)]
-macro_rules! impl_compare_capable_16bit {
-    ($inst:ident) => {
-        impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst {}
-    };
-}
-
-#[allow(unused)]
-macro_rules! impl_compare_capable_32bit {
-    ($inst:ident) => {
-        impl sealed::CaptureCompare32bitInstance for crate::peripherals::$inst {}
-    };
-}
-
-#[allow(unused)]
-macro_rules! impl_compare_capable_complementary_16bit {
-    ($inst:ident) => {
-        impl sealed::ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {}
-    };
-}
-
 foreach_interrupt! {
 
     ($inst:ident, timer, TIM_BASIC, UP, $irq:ident) => {
@@ -894,21 +878,17 @@ foreach_interrupt! {
     ($inst:ident, timer, TIM_1CH, UP, $irq:ident) => {
         impl_core_timer!($inst, $irq);
         impl_1ch_timer!($inst);
-        impl_compare_capable_16bit!($inst);
         impl CoreInstance for crate::peripherals::$inst {}
         impl GeneralPurpose1ChannelInstance for crate::peripherals::$inst {}
-        impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
     };
 
 
     ($inst:ident, timer, TIM_2CH, UP, $irq:ident) => {
         impl_core_timer!($inst, $irq);
         impl_1ch_timer!($inst);
-        impl_compare_capable_16bit!($inst);
         impl_2ch_timer!($inst);
         impl CoreInstance for crate::peripherals::$inst {}
         impl GeneralPurpose1ChannelInstance for crate::peripherals::$inst {}
-        impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
         impl GeneralPurpose2ChannelInstance for crate::peripherals::$inst {}
     };
 
@@ -917,14 +897,12 @@ foreach_interrupt! {
         impl_basic_no_cr2_timer!($inst);
         impl_basic_timer!($inst);
         impl_1ch_timer!($inst);
-        impl_compare_capable_16bit!($inst);
         impl_2ch_timer!($inst);
         impl_gp_16bit_timer!($inst);
         impl CoreInstance for crate::peripherals::$inst {}
         impl BasicNoCr2Instance for crate::peripherals::$inst{}
         impl BasicInstance for crate::peripherals::$inst {}
         impl GeneralPurpose1ChannelInstance for crate::peripherals::$inst {}
-        impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
         impl GeneralPurpose2ChannelInstance for crate::peripherals::$inst {}
         impl GeneralPurpose16bitInstance for crate::peripherals::$inst {}
     };
@@ -934,8 +912,6 @@ foreach_interrupt! {
         impl_basic_no_cr2_timer!($inst);
         impl_basic_timer!($inst);
         impl_1ch_timer!($inst);
-        impl_compare_capable_16bit!($inst);
-        impl_compare_capable_32bit!($inst);
         impl_2ch_timer!($inst);
         impl_gp_16bit_timer!($inst);
         impl_gp_32bit_timer!($inst);
@@ -943,8 +919,6 @@ foreach_interrupt! {
         impl BasicNoCr2Instance for crate::peripherals::$inst{}
         impl BasicInstance for crate::peripherals::$inst {}
         impl GeneralPurpose1ChannelInstance for crate::peripherals::$inst {}
-        impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
-        impl CaptureCompare32bitInstance for crate::peripherals::$inst {}
         impl GeneralPurpose2ChannelInstance for crate::peripherals::$inst {}
         impl GeneralPurpose16bitInstance for crate::peripherals::$inst {}
         impl GeneralPurpose32bitInstance for crate::peripherals::$inst {}
@@ -954,15 +928,11 @@ foreach_interrupt! {
         impl_core_timer!($inst, $irq);
         impl_basic_no_cr2_timer!($inst);
         impl_1ch_timer!($inst);
-        impl_compare_capable_16bit!($inst);
         impl_1ch_cmp_timer!($inst);
-        impl_compare_capable_complementary_16bit!($inst);
         impl CoreInstance for crate::peripherals::$inst {}
         impl BasicNoCr2Instance for crate::peripherals::$inst{}
         impl GeneralPurpose1ChannelInstance for crate::peripherals::$inst {}
-        impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
         impl GeneralPurpose1ChannelComplementaryInstance for crate::peripherals::$inst {}
-        impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {}
     };
 
 
@@ -971,17 +941,15 @@ foreach_interrupt! {
         impl_basic_no_cr2_timer!($inst);
         impl_basic_timer!($inst);
         impl_1ch_timer!($inst);
-        impl_compare_capable_16bit!($inst);
+        impl_2ch_timer!($inst);
         impl_1ch_cmp_timer!($inst);
-        impl_compare_capable_complementary_16bit!($inst);
         impl_2ch_cmp_timer!($inst);
         impl CoreInstance for crate::peripherals::$inst {}
         impl BasicNoCr2Instance for crate::peripherals::$inst{}
         impl BasicInstance for crate::peripherals::$inst {}
         impl GeneralPurpose1ChannelInstance for crate::peripherals::$inst {}
-        impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
+        impl GeneralPurpose2ChannelInstance for crate::peripherals::$inst {}
         impl GeneralPurpose1ChannelComplementaryInstance for crate::peripherals::$inst {}
-        impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {}
         impl GeneralPurpose2ChannelComplementaryInstance for crate::peripherals::$inst {}
     };
 
@@ -992,10 +960,8 @@ foreach_interrupt! {
         impl_basic_timer!($inst);
         impl_1ch_timer!($inst);
         impl_2ch_timer!($inst);
-        impl_compare_capable_16bit!($inst);
         impl_1ch_cmp_timer!($inst);
         impl_gp_16bit_timer!($inst);
-        impl_compare_capable_complementary_16bit!($inst);
         impl_2ch_cmp_timer!($inst);
         impl_adv_timer!($inst);
         impl CoreInstance for crate::peripherals::$inst {}
@@ -1004,9 +970,7 @@ foreach_interrupt! {
         impl GeneralPurpose1ChannelInstance for crate::peripherals::$inst {}
         impl GeneralPurpose2ChannelInstance for crate::peripherals::$inst {}
         impl GeneralPurpose16bitInstance for crate::peripherals::$inst {}
-        impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
         impl GeneralPurpose1ChannelComplementaryInstance for crate::peripherals::$inst {}
-        impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {}
         impl GeneralPurpose2ChannelComplementaryInstance for crate::peripherals::$inst {}
         impl AdvancedControlInstance for crate::peripherals::$inst {}
     };
@@ -1015,7 +979,7 @@ foreach_interrupt! {
 // Update Event trigger DMA for every timer
 dma_trait!(UpDma, BasicNoCr2Instance);
 
-dma_trait!(Ch1Dma, CaptureCompare16bitInstance);
-dma_trait!(Ch2Dma, CaptureCompare16bitInstance);
-dma_trait!(Ch3Dma, CaptureCompare16bitInstance);
-dma_trait!(Ch4Dma, CaptureCompare16bitInstance);
+dma_trait!(Ch1Dma, GeneralPurpose1ChannelInstance);
+dma_trait!(Ch2Dma, GeneralPurpose2ChannelInstance);
+dma_trait!(Ch3Dma, GeneralPurpose16bitInstance);
+dma_trait!(Ch4Dma, GeneralPurpose16bitInstance);
diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs
index 75e5ab12a..7e56312bb 100644
--- a/embassy-stm32/src/timer/qei.rs
+++ b/embassy-stm32/src/timer/qei.rs
@@ -30,7 +30,7 @@ pub struct QeiPin<'d, T, Channel> {
 
 macro_rules! channel_impl {
     ($new_chx:ident, $channel:ident, $pin_trait:ident) => {
-        impl<'d, T: CaptureCompare16bitInstance> QeiPin<'d, T, $channel> {
+        impl<'d, T: GeneralPurpose16bitInstance> QeiPin<'d, T, $channel> {
             #[doc = concat!("Create a new ", stringify!($channel), " QEI pin instance.")]
             pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd) -> Self {
                 into_ref!(pin);
@@ -57,7 +57,7 @@ pub struct Qei<'d, T> {
     _inner: PeripheralRef<'d, T>,
 }
 
-impl<'d, T: GeneralPurpose16bitInstance + CaptureCompare16bitInstance> Qei<'d, T> {
+impl<'d, T: GeneralPurpose16bitInstance> Qei<'d, T> {
     /// Create a new quadrature decoder driver.
     pub fn new(tim: impl Peripheral<P = T> + 'd, _ch1: QeiPin<'d, T, Ch1>, _ch2: QeiPin<'d, T, Ch2>) -> Self {
         Self::new_inner(tim)
diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs
index 1c665d456..088d02c97 100644
--- a/embassy-stm32/src/timer/simple_pwm.rs
+++ b/embassy-stm32/src/timer/simple_pwm.rs
@@ -1,6 +1,7 @@
 //! Simple PWM driver.
 
 use core::marker::PhantomData;
+use core::ops::{Deref, DerefMut};
 
 use embassy_hal_internal::{into_ref, PeripheralRef};
 
@@ -30,7 +31,7 @@ pub struct PwmPin<'d, T, C> {
 
 macro_rules! channel_impl {
     ($new_chx:ident, $channel:ident, $pin_trait:ident) => {
-        impl<'d, T: CaptureCompare16bitInstance> PwmPin<'d, T, $channel> {
+        impl<'d, T: GeneralPurpose16bitInstance> PwmPin<'d, T, $channel> {
             #[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance.")]
             pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd, output_type: OutputType) -> Self {
                 into_ref!(pin);
@@ -59,7 +60,7 @@ pub struct SimplePwm<'d, T> {
     inner: PeripheralRef<'d, T>,
 }
 
-impl<'d, T: GeneralPurpose16bitInstance + CaptureCompare16bitInstance> SimplePwm<'d, T> {
+impl<'d, T: GeneralPurpose16bitInstance> SimplePwm<'d, T> {
     /// Create a new simple PWM driver.
     pub fn new(
         tim: impl Peripheral<P = T> + 'd,
@@ -87,8 +88,13 @@ impl<'d, T: GeneralPurpose16bitInstance + CaptureCompare16bitInstance> SimplePwm
         [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)
+                sealed::GeneralPurpose16bitInstance::set_output_compare_mode(
+                    this.inner.deref_mut(),
+                    channel,
+                    OutputCompareMode::PwmMode1,
+                );
+
+                sealed::GeneralPurpose16bitInstance::set_output_compare_preload(this.inner.deref_mut(), channel, true);
             });
 
         this
@@ -96,17 +102,17 @@ impl<'d, T: GeneralPurpose16bitInstance + CaptureCompare16bitInstance> SimplePwm
 
     /// Enable the given channel.
     pub fn enable(&mut self, channel: Channel) {
-        self.inner.enable_channel(channel, true);
+        sealed::GeneralPurpose16bitInstance::enable_channel(self.inner.deref_mut(), channel, true);
     }
 
     /// Disable the given channel.
     pub fn disable(&mut self, channel: Channel) {
-        self.inner.enable_channel(channel, false);
+        sealed::GeneralPurpose16bitInstance::enable_channel(self.inner.deref_mut(), channel, false);
     }
 
     /// Check whether given channel is enabled
     pub fn is_enabled(&self, channel: Channel) -> bool {
-        self.inner.get_channel_enable_state(channel)
+        sealed::GeneralPurpose16bitInstance::get_channel_enable_state(self.inner.deref(), channel)
     }
 
     /// Set PWM frequency.
@@ -134,24 +140,24 @@ impl<'d, T: GeneralPurpose16bitInstance + CaptureCompare16bitInstance> SimplePwm
     /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included.
     pub fn set_duty(&mut self, channel: Channel, duty: u16) {
         assert!(duty <= self.get_max_duty());
-        self.inner.set_compare_value(channel, duty)
+        sealed::GeneralPurpose16bitInstance::set_compare_value(self.inner.deref_mut(), channel, duty)
     }
 
     /// Get the duty for a given channel.
     ///
     /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included.
     pub fn get_duty(&self, channel: Channel) -> u16 {
-        self.inner.get_compare_value(channel)
+        sealed::GeneralPurpose16bitInstance::get_compare_value(self.inner.deref(), channel)
     }
 
     /// Set the output polarity for a given channel.
     pub fn set_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
-        self.inner.set_output_polarity(channel, polarity);
+        sealed::GeneralPurpose16bitInstance::set_output_polarity(self.inner.deref_mut(), channel, polarity);
     }
 
     /// Set the output compare mode for a given channel.
     pub fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) {
-        self.inner.set_output_compare_mode(channel, mode);
+        sealed::GeneralPurpose16bitInstance::set_output_compare_mode(self.inner.deref_mut(), channel, mode);
     }
 
     /// Generate a sequence of PWM waveform
@@ -226,7 +232,7 @@ impl<'d, T: GeneralPurpose16bitInstance + CaptureCompare16bitInstance> SimplePwm
 
 macro_rules! impl_waveform_chx {
     ($fn_name:ident, $dma_ch:ident, $cc_ch:ident) => {
-        impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
+        impl<'d, T: GeneralPurpose16bitInstance> SimplePwm<'d, T> {
             /// Generate a sequence of PWM waveform
             ///
             /// Note:
@@ -313,17 +319,17 @@ impl_waveform_chx!(waveform_ch2, Ch2Dma, Ch2);
 impl_waveform_chx!(waveform_ch3, Ch3Dma, Ch3);
 impl_waveform_chx!(waveform_ch4, Ch4Dma, Ch4);
 
-impl<'d, T: CaptureCompare16bitInstance> embedded_hal_02::Pwm for SimplePwm<'d, T> {
+impl<'d, T: GeneralPurpose16bitInstance> embedded_hal_02::Pwm for SimplePwm<'d, T> {
     type Channel = Channel;
     type Time = Hertz;
     type Duty = u16;
 
     fn disable(&mut self, channel: Self::Channel) {
-        self.inner.enable_channel(channel, false);
+        sealed::GeneralPurpose16bitInstance::enable_channel(self.inner.deref_mut(), channel, false);
     }
 
     fn enable(&mut self, channel: Self::Channel) {
-        self.inner.enable_channel(channel, true);
+        sealed::GeneralPurpose16bitInstance::enable_channel(self.inner.deref_mut(), channel, true);
     }
 
     fn get_period(&self) -> Self::Time {
@@ -331,7 +337,7 @@ impl<'d, T: CaptureCompare16bitInstance> embedded_hal_02::Pwm for SimplePwm<'d,
     }
 
     fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
-        self.inner.get_compare_value(channel)
+        sealed::GeneralPurpose16bitInstance::get_compare_value(self.inner.deref(), channel)
     }
 
     fn get_max_duty(&self) -> Self::Duty {
@@ -340,7 +346,7 @@ impl<'d, T: CaptureCompare16bitInstance> embedded_hal_02::Pwm for SimplePwm<'d,
 
     fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
         assert!(duty <= self.get_max_duty());
-        self.inner.set_compare_value(channel, duty)
+        sealed::GeneralPurpose16bitInstance::set_compare_value(self.inner.deref_mut(), channel, duty)
     }
 
     fn set_period<P>(&mut self, period: P)
diff --git a/examples/stm32h7/src/bin/low_level_timer_api.rs b/examples/stm32h7/src/bin/low_level_timer_api.rs
index cc508c3cf..0be3eccb7 100644
--- a/examples/stm32h7/src/bin/low_level_timer_api.rs
+++ b/examples/stm32h7/src/bin/low_level_timer_api.rs
@@ -56,11 +56,11 @@ async fn main(_spawner: Spawner) {
         Timer::after_millis(300).await;
     }
 }
-pub struct SimplePwm32<'d, T: CaptureCompare32bitInstance> {
+pub struct SimplePwm32<'d, T: GeneralPurpose32bitInstance> {
     inner: PeripheralRef<'d, T>,
 }
 
-impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> {
+impl<'d, T: GeneralPurpose32bitInstance> SimplePwm32<'d, T> {
     pub fn new(
         tim: impl Peripheral<P = T> + 'd,
         ch1: impl Peripheral<P = impl Channel1Pin<T>> + 'd,

From 5b646bc3bd0c4a2cd9acf6a59b3a76f2bbcb0bfb Mon Sep 17 00:00:00 2001
From: eZio Pan <eziopan@qq.com>
Date: Thu, 1 Feb 2024 23:04:39 +0800
Subject: [PATCH 05/10] stm32-timer: L0 is special

---
 embassy-stm32/src/timer/mod.rs | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index 2f5d5770a..8be96b414 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -12,6 +12,7 @@
 //            |             +--------------------------------------|-----------+
 //            +----------------------------------------------------+
 
+#[cfg(not(any(stm32l0, stm32l1)))]
 pub mod complementary_pwm;
 pub mod qei;
 pub mod simple_pwm;
@@ -163,6 +164,7 @@ pub(crate) mod sealed {
         };
     }
 
+    #[cfg(not(any(stm32l0, stm32l1)))]
     macro_rules! add_complementary_capture_compare_methods {
         ($regs:ident) => {
             /// Set complementary output polarity.
@@ -374,6 +376,7 @@ pub(crate) mod sealed {
         add_capture_compare_dma_methods!(regs_gp16);
     }
 
+    #[cfg(not(any(stm32l0)))]
     /// Gneral-purpose 32-bit timer instance.
     pub trait GeneralPurpose32bitInstance: GeneralPurpose16bitInstance {
         /// Get access to the general purpose 32bit timer registers.
@@ -434,6 +437,7 @@ pub(crate) mod sealed {
         }
     }
 
+    #[cfg(not(any(stm32l0, stm32l1)))]
     /// 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.
@@ -462,6 +466,7 @@ pub(crate) mod sealed {
         add_complementary_capture_compare_methods!(regs_1ch_cmp);
     }
 
+    #[cfg(not(any(stm32l0, stm32l1)))]
     /// Gneral-purpose 2 channel with one complementary 16-bit timer instance.
     pub trait GeneralPurpose2ChannelComplementaryInstance:
         BasicInstance + GeneralPurpose2ChannelInstance + GeneralPurpose1ChannelComplementaryInstance
@@ -477,6 +482,7 @@ pub(crate) mod sealed {
         add_complementary_capture_compare_methods!(regs_2ch_cmp);
     }
 
+    #[cfg(not(any(stm32l0, stm32l1)))]
     /// Advanced control timer instance.
     pub trait AdvancedControlInstance:
         GeneralPurpose2ChannelComplementaryInstance + GeneralPurpose16bitInstance
@@ -699,18 +705,21 @@ pub trait GeneralPurpose16bitInstance:
 {
 }
 
+#[cfg(not(stm32l0))]
 /// Gneral-purpose 32-bit timer instance.
 pub trait GeneralPurpose32bitInstance:
     sealed::GeneralPurpose32bitInstance + GeneralPurpose16bitInstance + 'static
 {
 }
 
+#[cfg(not(any(stm32l0, stm32l1)))]
 /// General-purpose 1 channel with one complementary 16-bit timer instance.
 pub trait GeneralPurpose1ChannelComplementaryInstance:
     sealed::GeneralPurpose1ChannelComplementaryInstance + GeneralPurpose1ChannelInstance + 'static
 {
 }
 
+#[cfg(not(any(stm32l0, stm32l1)))]
 /// General-purpose 2 channel with one complementary 16-bit timer instance.
 pub trait GeneralPurpose2ChannelComplementaryInstance:
     sealed::GeneralPurpose2ChannelComplementaryInstance
@@ -721,6 +730,7 @@ pub trait GeneralPurpose2ChannelComplementaryInstance:
 {
 }
 
+#[cfg(not(any(stm32l0, stm32l1)))]
 /// Advanced control timer instance.
 pub trait AdvancedControlInstance:
     sealed::AdvancedControlInstance + GeneralPurpose2ChannelComplementaryInstance + GeneralPurpose16bitInstance + 'static
@@ -738,18 +748,28 @@ pin_trait!(ExternalTriggerPin, GeneralPurpose16bitInstance);
 #[cfg(stm32l0)]
 pin_trait!(ExternalTriggerPin, GeneralPurpose2ChannelInstance);
 
+#[cfg(not(any(stm32l0, stm32l1)))]
 pin_trait!(Channel1ComplementaryPin, GeneralPurpose1ChannelComplementaryInstance);
+#[cfg(not(any(stm32l0, stm32l1)))]
 pin_trait!(Channel2ComplementaryPin, GeneralPurpose2ChannelComplementaryInstance);
+#[cfg(not(any(stm32l0, stm32l1)))]
 pin_trait!(Channel3ComplementaryPin, AdvancedControlInstance);
+#[cfg(not(any(stm32l0, stm32l1)))]
 pin_trait!(Channel4ComplementaryPin, AdvancedControlInstance);
 
+#[cfg(not(any(stm32l0, stm32l1)))]
 pin_trait!(BreakInputPin, GeneralPurpose1ChannelComplementaryInstance);
+#[cfg(not(any(stm32l0, stm32l1)))]
 pin_trait!(BreakInput2Pin, GeneralPurpose2ChannelComplementaryInstance);
 
+#[cfg(not(any(stm32l0, stm32l1)))]
 pin_trait!(BreakInputComparator1Pin, GeneralPurpose1ChannelComplementaryInstance);
+#[cfg(not(any(stm32l0, stm32l1)))]
 pin_trait!(BreakInputComparator2Pin, AdvancedControlInstance);
 
+#[cfg(not(any(stm32l0, stm32l1)))]
 pin_trait!(BreakInput2Comparator1Pin, AdvancedControlInstance);
+#[cfg(not(any(stm32l0, stm32l1)))]
 pin_trait!(BreakInput2Comparator2Pin, AdvancedControlInstance);
 
 #[allow(unused)]

From 319f10da5daff415ad2dac17f4eed43313455167 Mon Sep 17 00:00:00 2001
From: eZio Pan <eziopan@qq.com>
Date: Thu, 1 Feb 2024 23:41:32 +0800
Subject: [PATCH 06/10] stm32-timer: filter out c0, f1 and f37x

---
 embassy-stm32/src/timer/mod.rs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index 8be96b414..be5c6cf29 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -376,7 +376,7 @@ pub(crate) mod sealed {
         add_capture_compare_dma_methods!(regs_gp16);
     }
 
-    #[cfg(not(any(stm32l0)))]
+    #[cfg(not(any(stm32f1, stm32l0, stm32c0)))]
     /// Gneral-purpose 32-bit timer instance.
     pub trait GeneralPurpose32bitInstance: GeneralPurpose16bitInstance {
         /// Get access to the general purpose 32bit timer registers.
@@ -705,7 +705,7 @@ pub trait GeneralPurpose16bitInstance:
 {
 }
 
-#[cfg(not(stm32l0))]
+#[cfg(not(any(stm32f1, stm32l0, stm32c0)))]
 /// Gneral-purpose 32-bit timer instance.
 pub trait GeneralPurpose32bitInstance:
     sealed::GeneralPurpose32bitInstance + GeneralPurpose16bitInstance + 'static
@@ -730,7 +730,7 @@ pub trait GeneralPurpose2ChannelComplementaryInstance:
 {
 }
 
-#[cfg(not(any(stm32l0, stm32l1)))]
+#[cfg(not(any(stm32f37, stm32l0, stm32l1)))]
 /// Advanced control timer instance.
 pub trait AdvancedControlInstance:
     sealed::AdvancedControlInstance + GeneralPurpose2ChannelComplementaryInstance + GeneralPurpose16bitInstance + 'static

From b3cdf3a040ae97923e84eca525505f7eff55e870 Mon Sep 17 00:00:00 2001
From: eZio Pan <eziopan@qq.com>
Date: Fri, 2 Feb 2024 14:52:54 +0800
Subject: [PATCH 07/10] bug fix

---
 embassy-stm32/src/timer/mod.rs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index be5c6cf29..3e303a6cf 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -90,9 +90,9 @@ pub(crate) mod sealed {
 
             /// Set output compare mode.
             fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) {
-                let r = Self::$regs();
                 let raw_channel: usize = channel.index();
-                r.ccmr_output(raw_channel / 2)
+                Self::$regs()
+                    .ccmr_output(raw_channel / 2)
                     .modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
             }
 
@@ -133,7 +133,7 @@ pub(crate) mod sealed {
             /// Set output compare preload.
             fn set_output_compare_preload(&mut self, channel: Channel, preload: bool) {
                 let channel_index = channel.index();
-                Self::regs_1ch()
+                Self::$regs()
                     .ccmr_output(channel_index / 2)
                     .modify(|w| w.set_ocpe(channel_index % 2, preload));
             }

From 6c690ab259ed15eece329a53a7147e7780f53cf3 Mon Sep 17 00:00:00 2001
From: eZio Pan <eziopan@qq.com>
Date: Fri, 2 Feb 2024 17:45:51 +0800
Subject: [PATCH 08/10] restore original public API of timer, but keep new PAC

---
 embassy-stm32/src/timer/complementary_pwm.rs  |  41 +-
 embassy-stm32/src/timer/mod.rs                | 525 ++++++++----------
 embassy-stm32/src/timer/qei.rs                |   4 +-
 embassy-stm32/src/timer/simple_pwm.rs         |  39 +-
 .../stm32h7/src/bin/low_level_timer_api.rs    |   4 +-
 5 files changed, 274 insertions(+), 339 deletions(-)

diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs
index b9cd044c9..72f1ec864 100644
--- a/embassy-stm32/src/timer/complementary_pwm.rs
+++ b/embassy-stm32/src/timer/complementary_pwm.rs
@@ -1,7 +1,6 @@
 //! PWM driver with complementary output support.
 
 use core::marker::PhantomData;
-use core::ops::{Deref, DerefMut};
 
 use embassy_hal_internal::{into_ref, PeripheralRef};
 use stm32_metapac::timer::vals::Ckd;
@@ -24,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: AdvancedControlInstance> 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);
@@ -53,7 +52,7 @@ pub struct ComplementaryPwm<'d, T> {
     inner: PeripheralRef<'d, T>,
 }
 
-impl<'d, T: AdvancedControlInstance> ComplementaryPwm<'d, T> {
+impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
     /// Create a new complementary PWM driver.
     #[allow(clippy::too_many_arguments)]
     pub fn new(
@@ -88,12 +87,8 @@ impl<'d, T: AdvancedControlInstance> ComplementaryPwm<'d, T> {
         [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4]
             .iter()
             .for_each(|&channel| {
-                sealed::GeneralPurpose16bitInstance::set_output_compare_mode(
-                    this.inner.deref_mut(),
-                    channel,
-                    OutputCompareMode::PwmMode1,
-                );
-                sealed::GeneralPurpose16bitInstance::set_output_compare_preload(this.inner.deref_mut(), channel, true);
+                this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1);
+                this.inner.set_output_compare_preload(channel, true);
             });
 
         this
@@ -101,14 +96,14 @@ impl<'d, T: AdvancedControlInstance> ComplementaryPwm<'d, T> {
 
     /// Enable the given channel.
     pub fn enable(&mut self, channel: Channel) {
-        sealed::GeneralPurpose16bitInstance::enable_channel(self.inner.deref_mut(), channel, true);
-        sealed::AdvancedControlInstance::enable_complementary_channel(self.inner.deref_mut(), channel, true);
+        self.inner.enable_channel(channel, true);
+        self.inner.enable_complementary_channel(channel, true);
     }
 
     /// Disable the given channel.
     pub fn disable(&mut self, channel: Channel) {
-        sealed::AdvancedControlInstance::enable_complementary_channel(self.inner.deref_mut(), channel, false);
-        sealed::GeneralPurpose16bitInstance::enable_channel(self.inner.deref_mut(), channel, false);
+        self.inner.enable_complementary_channel(channel, false);
+        self.inner.enable_channel(channel, false);
     }
 
     /// Set PWM frequency.
@@ -136,13 +131,13 @@ impl<'d, T: AdvancedControlInstance> ComplementaryPwm<'d, T> {
     /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included.
     pub fn set_duty(&mut self, channel: Channel, duty: u16) {
         assert!(duty <= self.get_max_duty());
-        sealed::GeneralPurpose16bitInstance::set_compare_value(self.inner.deref_mut(), channel, duty)
+        self.inner.set_compare_value(channel, duty)
     }
 
     /// Set the output polarity for a given channel.
     pub fn set_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
-        sealed::GeneralPurpose16bitInstance::set_output_polarity(self.inner.deref_mut(), channel, polarity);
-        sealed::AdvancedControlInstance::set_complementary_output_polarity(self.inner.deref_mut(), channel, polarity);
+        self.inner.set_output_polarity(channel, polarity);
+        self.inner.set_complementary_output_polarity(channel, polarity);
     }
 
     /// Set the dead time as a proportion of max_duty
@@ -154,19 +149,19 @@ impl<'d, T: AdvancedControlInstance> ComplementaryPwm<'d, T> {
     }
 }
 
-impl<'d, T: AdvancedControlInstance> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> {
+impl<'d, T: ComplementaryCaptureCompare16bitInstance> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> {
     type Channel = Channel;
     type Time = Hertz;
     type Duty = u16;
 
     fn disable(&mut self, channel: Self::Channel) {
-        sealed::AdvancedControlInstance::enable_complementary_channel(self.inner.deref_mut(), channel, false);
-        sealed::GeneralPurpose16bitInstance::enable_channel(self.inner.deref_mut(), channel, false);
+        self.inner.enable_complementary_channel(channel, false);
+        self.inner.enable_channel(channel, false);
     }
 
     fn enable(&mut self, channel: Self::Channel) {
-        sealed::GeneralPurpose16bitInstance::enable_channel(self.inner.deref_mut(), channel, true);
-        sealed::AdvancedControlInstance::enable_complementary_channel(self.inner.deref_mut(), channel, true);
+        self.inner.enable_channel(channel, true);
+        self.inner.enable_complementary_channel(channel, true);
     }
 
     fn get_period(&self) -> Self::Time {
@@ -174,7 +169,7 @@ impl<'d, T: AdvancedControlInstance> embedded_hal_02::Pwm for ComplementaryPwm<'
     }
 
     fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
-        sealed::GeneralPurpose16bitInstance::get_compare_value(self.inner.deref(), channel)
+        self.inner.get_compare_value(channel)
     }
 
     fn get_max_duty(&self) -> Self::Duty {
@@ -183,7 +178,7 @@ impl<'d, T: AdvancedControlInstance> embedded_hal_02::Pwm for ComplementaryPwm<'
 
     fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
         assert!(duty <= self.get_max_duty());
-        sealed::GeneralPurpose16bitInstance::set_compare_value(self.inner.deref_mut(), channel, duty)
+        self.inner.set_compare_value(channel, duty)
     }
 
     fn set_period<P>(&mut self, period: P)
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index 3e303a6cf..5f40be957 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -1,6 +1,8 @@
 //! Timers, PWM, quadrature decoder.
 
-// Timer inheritance
+//! Timer inheritance
+
+// sealed:
 //
 // Core -------------------------> 1CH -------------------------> 1CH_CMP
 //   |                              |                              ^   |
@@ -12,7 +14,18 @@
 //            |             +--------------------------------------|-----------+
 //            +----------------------------------------------------+
 
-#[cfg(not(any(stm32l0, stm32l1)))]
+//! BasicInstance --> CaptureCompare16bitInstance --+--> ComplementaryCaptureCompare16bitInstance  
+//!                                                 |  
+//!                                                 +--> CaptureCompare32bitInstance  
+//!
+//! mapping:
+//!
+//! Basic Timer --> BasicInstance  
+//! 1-channel Timer, 2-channel Timer, General Purpose 16-bit Timer --> CaptureCompare16bitInstance  
+//! General Purpose 32-bit Timer --> CaptureCompare32bitInstance  
+//! 1-channel with one complentary Timer, 2-channel with one complentary Timer, Advance Control Timer --> ComplementaryCaptureCompare16bitInstance  
+
+#[cfg(not(stm32l0))]
 pub mod complementary_pwm;
 pub mod qei;
 pub mod simple_pwm;
@@ -32,157 +45,6 @@ pub mod low_level {
 pub(crate) mod sealed {
     use super::*;
 
-    macro_rules! add_capture_compare_common_methods {
-        ($regs:ident) => {
-            /// Set input capture filter.
-            fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::FilterValue) {
-                let raw_channel = channel.index();
-                Self::$regs()
-                    .ccmr_input(raw_channel / 2)
-                    .modify(|r| r.set_icf(raw_channel % 2, icf));
-            }
-
-            /// Clear input interrupt.
-            fn clear_input_interrupt(&mut self, channel: Channel) {
-                Self::$regs().sr().modify(|r| r.set_ccif(channel.index(), false));
-            }
-
-            /// Enable input interrupt.
-            fn enable_input_interrupt(&mut self, channel: Channel, enable: bool) {
-                Self::$regs()
-                    .dier()
-                    .modify(|r| r.set_ccie(channel.index(), enable));
-            }
-
-            /// Set input capture prescaler.
-            fn set_input_capture_prescaler(&mut self, channel: Channel, factor: u8) {
-                let raw_channel = channel.index();
-                Self::$regs()
-                    .ccmr_input(raw_channel / 2)
-                    .modify(|r| r.set_icpsc(raw_channel % 2, factor));
-            }
-
-            /// Set input TI selection.
-            fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) {
-                let raw_channel = channel.index();
-                Self::$regs()
-                    .ccmr_input(raw_channel / 2)
-                    .modify(|r| r.set_ccs(raw_channel % 2, tisel.into()));
-            }
-
-            /// Set input capture mode.
-            fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) {
-                Self::$regs().ccer().modify(|r| match mode {
-                    InputCaptureMode::Rising => {
-                        r.set_ccnp(channel.index(), false);
-                        r.set_ccp(channel.index(), false);
-                    }
-                    InputCaptureMode::Falling => {
-                        r.set_ccnp(channel.index(), false);
-                        r.set_ccp(channel.index(), true);
-                    }
-                    InputCaptureMode::BothEdges => {
-                        r.set_ccnp(channel.index(), true);
-                        r.set_ccp(channel.index(), true);
-                    }
-                });
-            }
-
-            /// Set output compare mode.
-            fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) {
-                let raw_channel: usize = channel.index();
-                Self::$regs()
-                    .ccmr_output(raw_channel / 2)
-                    .modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
-            }
-
-            /// Set output polarity.
-            fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
-                Self::$regs()
-                    .ccer()
-                    .modify(|w| w.set_ccp(channel.index(), polarity.into()));
-            }
-
-            /// Enable/disable a channel.
-            fn enable_channel(&mut self, channel: Channel, enable: bool) {
-                Self::$regs()
-                    .ccer()
-                    .modify(|w| w.set_cce(channel.index(), enable));
-            }
-
-            /// Get enable/disable state of a channel
-            fn get_channel_enable_state(&self, channel: Channel) -> bool {
-                Self::$regs().ccer().read().cce(channel.index())
-            }
-
-            /// Set compare value for a channel.
-            fn set_compare_value(&mut self, channel: Channel, value: u16) {
-                Self::$regs().ccr(channel.index()).modify(|w| w.set_ccr(value));
-            }
-
-            /// Get capture value for a channel.
-            fn get_capture_value(&mut self, channel: Channel) -> u16 {
-                Self::$regs().ccr(channel.index()).read().ccr()
-            }
-
-            /// Get compare value for a channel.
-            fn get_compare_value(&self, channel: Channel) -> u16 {
-                Self::$regs().ccr(channel.index()).read().ccr()
-            }
-
-            /// Set output compare preload.
-            fn set_output_compare_preload(&mut self, channel: Channel, preload: bool) {
-                let channel_index = channel.index();
-                Self::$regs()
-                    .ccmr_output(channel_index / 2)
-                    .modify(|w| w.set_ocpe(channel_index % 2, preload));
-            }
-        };
-    }
-
-    macro_rules! add_capture_compare_dma_methods {
-        ($regs:ident) => {
-            /// Get capture compare DMA selection
-            fn get_cc_dma_selection(&self) -> super::vals::Ccds {
-                Self::$regs().cr2().read().ccds()
-            }
-
-            /// Set capture compare DMA selection
-            fn set_cc_dma_selection(&mut self, ccds: super::vals::Ccds) {
-                Self::$regs().cr2().modify(|w| w.set_ccds(ccds))
-            }
-
-            /// Get capture compare DMA enable state
-            fn get_cc_dma_enable_state(&self, channel: Channel) -> bool {
-                Self::$regs().dier().read().ccde(channel.index())
-            }
-
-            /// Set capture compare DMA enable state
-            fn set_cc_dma_enable_state(&mut self, channel: Channel, ccde: bool) {
-                Self::$regs().dier().modify(|w| w.set_ccde(channel.index(), ccde))
-            }
-        };
-    }
-
-    #[cfg(not(any(stm32l0, stm32l1)))]
-    macro_rules! add_complementary_capture_compare_methods {
-        ($regs:ident) => {
-            /// Set complementary output polarity.
-            fn set_complementary_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
-                Self::$regs()
-                    .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()
-                    .ccer()
-                    .modify(|w| w.set_ccne(channel.index(), enable));
-            }
-        };
-    }
-
     /// Virtual Core 16-bit timer instance.  
     pub trait CoreInstance: RccPeripheral {
         /// Interrupt for this timer.
@@ -326,8 +188,6 @@ pub(crate) mod sealed {
         fn get_max_compare_value(&self) -> u16 {
             Self::regs_1ch().arr().read().arr()
         }
-
-        add_capture_compare_common_methods!(regs_1ch);
     }
 
     /// Gneral-purpose 1 channel 16-bit  timer instance.
@@ -339,8 +199,6 @@ pub(crate) mod sealed {
         /// for a given set of capabilities, and having it transparently work with
         /// more capable timers.
         fn regs_2ch() -> crate::pac::timer::Tim2ch;
-
-        add_capture_compare_common_methods!(regs_2ch);
     }
 
     /// Gneral-purpose 16-bit timer instance.
@@ -372,11 +230,128 @@ pub(crate) mod sealed {
             (cr1.cms(), cr1.dir()).into()
         }
 
-        add_capture_compare_common_methods!(regs_gp16);
-        add_capture_compare_dma_methods!(regs_gp16);
+        /// Set input capture filter.
+        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)
+                .modify(|r| r.set_icf(raw_channel % 2, icf));
+        }
+
+        /// Clear input interrupt.
+        fn clear_input_interrupt(&mut self, channel: Channel) {
+            Self::regs_gp16().sr().modify(|r| r.set_ccif(channel.index(), false));
+        }
+
+        /// Enable input interrupt.
+        fn enable_input_interrupt(&mut self, channel: Channel, enable: bool) {
+            Self::regs_gp16().dier().modify(|r| r.set_ccie(channel.index(), enable));
+        }
+
+        /// Set input capture prescaler.
+        fn set_input_capture_prescaler(&mut self, channel: Channel, factor: u8) {
+            let raw_channel = channel.index();
+            Self::regs_gp16()
+                .ccmr_input(raw_channel / 2)
+                .modify(|r| r.set_icpsc(raw_channel % 2, factor));
+        }
+
+        /// Set input TI selection.
+        fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) {
+            let raw_channel = channel.index();
+            Self::regs_gp16()
+                .ccmr_input(raw_channel / 2)
+                .modify(|r| r.set_ccs(raw_channel % 2, tisel.into()));
+        }
+
+        /// Set input capture mode.
+        fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) {
+            Self::regs_gp16().ccer().modify(|r| match mode {
+                InputCaptureMode::Rising => {
+                    r.set_ccnp(channel.index(), false);
+                    r.set_ccp(channel.index(), false);
+                }
+                InputCaptureMode::Falling => {
+                    r.set_ccnp(channel.index(), false);
+                    r.set_ccp(channel.index(), true);
+                }
+                InputCaptureMode::BothEdges => {
+                    r.set_ccnp(channel.index(), true);
+                    r.set_ccp(channel.index(), true);
+                }
+            });
+        }
+
+        /// Set output compare mode.
+        fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) {
+            let raw_channel: usize = channel.index();
+            Self::regs_gp16()
+                .ccmr_output(raw_channel / 2)
+                .modify(|w| w.set_ocm(raw_channel % 2, mode.into()));
+        }
+
+        /// Set output polarity.
+        fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
+            Self::regs_gp16()
+                .ccer()
+                .modify(|w| w.set_ccp(channel.index(), polarity.into()));
+        }
+
+        /// Enable/disable a channel.
+        fn enable_channel(&mut self, channel: Channel, enable: bool) {
+            Self::regs_gp16().ccer().modify(|w| w.set_cce(channel.index(), enable));
+        }
+
+        /// Get enable/disable state of a channel
+        fn get_channel_enable_state(&self, channel: Channel) -> bool {
+            Self::regs_gp16().ccer().read().cce(channel.index())
+        }
+
+        /// Set compare value for a channel.
+        fn set_compare_value(&mut self, channel: Channel, value: u16) {
+            Self::regs_gp16().ccr(channel.index()).modify(|w| w.set_ccr(value));
+        }
+
+        /// Get capture value for a channel.
+        fn get_capture_value(&mut self, channel: Channel) -> u16 {
+            Self::regs_gp16().ccr(channel.index()).read().ccr()
+        }
+
+        /// Get compare value for a channel.
+        fn get_compare_value(&self, channel: Channel) -> u16 {
+            Self::regs_gp16().ccr(channel.index()).read().ccr()
+        }
+
+        /// Set output compare preload.
+        fn set_output_compare_preload(&mut self, channel: Channel, preload: bool) {
+            let channel_index = channel.index();
+            Self::regs_gp16()
+                .ccmr_output(channel_index / 2)
+                .modify(|w| w.set_ocpe(channel_index % 2, preload));
+        }
+
+        /// Get capture compare DMA selection
+        fn get_cc_dma_selection(&self) -> super::vals::Ccds {
+            Self::regs_gp16().cr2().read().ccds()
+        }
+
+        /// Set capture compare DMA selection
+        fn set_cc_dma_selection(&mut self, ccds: super::vals::Ccds) {
+            Self::regs_gp16().cr2().modify(|w| w.set_ccds(ccds))
+        }
+
+        /// Get capture compare DMA enable state
+        fn get_cc_dma_enable_state(&self, channel: Channel) -> bool {
+            Self::regs_gp16().dier().read().ccde(channel.index())
+        }
+
+        /// Set capture compare DMA enable state
+        fn set_cc_dma_enable_state(&mut self, channel: Channel, ccde: bool) {
+            Self::regs_gp16().dier().modify(|w| w.set_ccde(channel.index(), ccde))
+        }
     }
 
-    #[cfg(not(any(stm32f1, stm32l0, stm32c0)))]
+    #[cfg(not(stm32l0))]
     /// Gneral-purpose 32-bit timer instance.
     pub trait GeneralPurpose32bitInstance: GeneralPurpose16bitInstance {
         /// Get access to the general purpose 32bit timer registers.
@@ -437,7 +412,7 @@ pub(crate) mod sealed {
         }
     }
 
-    #[cfg(not(any(stm32l0, stm32l1)))]
+    #[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.
@@ -462,11 +437,9 @@ pub(crate) mod sealed {
         fn enable_outputs(&mut self) {
             Self::regs_1ch_cmp().bdtr().modify(|w| w.set_moe(true));
         }
-
-        add_complementary_capture_compare_methods!(regs_1ch_cmp);
     }
 
-    #[cfg(not(any(stm32l0, stm32l1)))]
+    #[cfg(not(stm32l0))]
     /// Gneral-purpose 2 channel with one complementary 16-bit timer instance.
     pub trait GeneralPurpose2ChannelComplementaryInstance:
         BasicInstance + GeneralPurpose2ChannelInstance + GeneralPurpose1ChannelComplementaryInstance
@@ -478,11 +451,9 @@ pub(crate) mod sealed {
         /// for a given set of capabilities, and having it transparently work with
         /// more capable timers.
         fn regs_2ch_cmp() -> crate::pac::timer::Tim2chCmp;
-
-        add_complementary_capture_compare_methods!(regs_2ch_cmp);
     }
 
-    #[cfg(not(any(stm32l0, stm32l1)))]
+    #[cfg(not(stm32l0))]
     /// Advanced control timer instance.
     pub trait AdvancedControlInstance:
         GeneralPurpose2ChannelComplementaryInstance + GeneralPurpose16bitInstance
@@ -490,7 +461,19 @@ pub(crate) mod sealed {
         /// Get access to the advanced timer registers.
         fn regs_advanced() -> crate::pac::timer::TimAdv;
 
-        add_complementary_capture_compare_methods!(regs_advanced);
+        /// 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));
+        }
     }
 }
 
@@ -681,96 +664,66 @@ impl From<OutputPolarity> for bool {
     }
 }
 
-/// Virtual Core 16-bit timer instance.
-pub trait CoreInstance: sealed::CoreInstance + 'static {}
-
-/// Virtual Basic 16-bit timer without CR2 register instance.
-pub trait BasicNoCr2Instance: sealed::BasicNoCr2Instance + CoreInstance + 'static {}
-
 /// Basic 16-bit timer instance.
-pub trait BasicInstance: sealed::BasicInstance + BasicNoCr2Instance + 'static {}
-
-/// 1 channel 16-bit instance.
-pub trait GeneralPurpose1ChannelInstance: sealed::GeneralPurpose1ChannelInstance + CoreInstance + 'static {}
-
-/// 2 channel 16-bit instance.
-pub trait GeneralPurpose2ChannelInstance:
-    sealed::GeneralPurpose2ChannelInstance + GeneralPurpose1ChannelInstance + 'static
-{
-}
+pub trait BasicInstance: sealed::BasicInstance + sealed::BasicNoCr2Instance + sealed::CoreInstance + 'static {}
 
 /// General-purpose 16-bit timer instance.
-pub trait GeneralPurpose16bitInstance:
-    sealed::GeneralPurpose16bitInstance + BasicInstance + GeneralPurpose2ChannelInstance + 'static
-{
-}
-
-#[cfg(not(any(stm32f1, stm32l0, stm32c0)))]
-/// Gneral-purpose 32-bit timer instance.
-pub trait GeneralPurpose32bitInstance:
-    sealed::GeneralPurpose32bitInstance + GeneralPurpose16bitInstance + 'static
-{
-}
-
-#[cfg(not(any(stm32l0, stm32l1)))]
-/// General-purpose 1 channel with one complementary 16-bit timer instance.
-pub trait GeneralPurpose1ChannelComplementaryInstance:
-    sealed::GeneralPurpose1ChannelComplementaryInstance + GeneralPurpose1ChannelInstance + 'static
-{
-}
-
-#[cfg(not(any(stm32l0, stm32l1)))]
-/// General-purpose 2 channel with one complementary 16-bit timer instance.
-pub trait GeneralPurpose2ChannelComplementaryInstance:
-    sealed::GeneralPurpose2ChannelComplementaryInstance
-    + BasicInstance
-    + GeneralPurpose2ChannelInstance
-    + GeneralPurpose1ChannelComplementaryInstance
+pub trait CaptureCompare16bitInstance:
+    BasicInstance
+    + sealed::GeneralPurpose2ChannelInstance
+    + sealed::GeneralPurpose1ChannelInstance
+    + sealed::GeneralPurpose16bitInstance
     + 'static
 {
 }
 
-#[cfg(not(any(stm32f37, stm32l0, stm32l1)))]
-/// Advanced control timer instance.
-pub trait AdvancedControlInstance:
-    sealed::AdvancedControlInstance + GeneralPurpose2ChannelComplementaryInstance + GeneralPurpose16bitInstance + 'static
+#[cfg(not(stm32l0))]
+/// Gneral-purpose 32-bit timer instance.
+pub trait CaptureCompare32bitInstance:
+    sealed::GeneralPurpose32bitInstance + CaptureCompare16bitInstance + 'static
 {
 }
 
-pin_trait!(Channel1Pin, GeneralPurpose1ChannelInstance);
-pin_trait!(Channel2Pin, GeneralPurpose2ChannelInstance);
-pin_trait!(Channel3Pin, GeneralPurpose16bitInstance);
-pin_trait!(Channel4Pin, GeneralPurpose16bitInstance);
+#[cfg(not(stm32l0))]
+/// Advanced control timer instance.
+pub trait ComplementaryCaptureCompare16bitInstance:
+    CaptureCompare16bitInstance
+    + sealed::GeneralPurpose1ChannelComplementaryInstance
+    + sealed::GeneralPurpose2ChannelComplementaryInstance
+    + sealed::AdvancedControlInstance
+    + 'static
+{
+}
+
+pin_trait!(Channel1Pin, CaptureCompare16bitInstance);
+pin_trait!(Channel2Pin, CaptureCompare16bitInstance);
+pin_trait!(Channel3Pin, CaptureCompare16bitInstance);
+pin_trait!(Channel4Pin, CaptureCompare16bitInstance);
+pin_trait!(ExternalTriggerPin, CaptureCompare16bitInstance);
 
 #[cfg(not(stm32l0))]
-pin_trait!(ExternalTriggerPin, GeneralPurpose16bitInstance);
+pin_trait!(Channel1ComplementaryPin, ComplementaryCaptureCompare16bitInstance);
+#[cfg(not(stm32l0))]
+pin_trait!(Channel2ComplementaryPin, ComplementaryCaptureCompare16bitInstance);
+#[cfg(not(stm32l0))]
+pin_trait!(Channel3ComplementaryPin, ComplementaryCaptureCompare16bitInstance);
+#[cfg(not(stm32l0))]
+pin_trait!(Channel4ComplementaryPin, ComplementaryCaptureCompare16bitInstance);
 
-#[cfg(stm32l0)]
-pin_trait!(ExternalTriggerPin, GeneralPurpose2ChannelInstance);
+#[cfg(not(stm32l0))]
+pin_trait!(BreakInputPin, ComplementaryCaptureCompare16bitInstance);
+#[cfg(not(stm32l0))]
+pin_trait!(BreakInput2Pin, ComplementaryCaptureCompare16bitInstance);
 
-#[cfg(not(any(stm32l0, stm32l1)))]
-pin_trait!(Channel1ComplementaryPin, GeneralPurpose1ChannelComplementaryInstance);
-#[cfg(not(any(stm32l0, stm32l1)))]
-pin_trait!(Channel2ComplementaryPin, GeneralPurpose2ChannelComplementaryInstance);
-#[cfg(not(any(stm32l0, stm32l1)))]
-pin_trait!(Channel3ComplementaryPin, AdvancedControlInstance);
-#[cfg(not(any(stm32l0, stm32l1)))]
-pin_trait!(Channel4ComplementaryPin, AdvancedControlInstance);
+#[cfg(not(stm32l0))]
+pin_trait!(BreakInputComparator1Pin, ComplementaryCaptureCompare16bitInstance);
+#[cfg(not(stm32l0))]
+pin_trait!(BreakInputComparator2Pin, ComplementaryCaptureCompare16bitInstance);
 
-#[cfg(not(any(stm32l0, stm32l1)))]
-pin_trait!(BreakInputPin, GeneralPurpose1ChannelComplementaryInstance);
-#[cfg(not(any(stm32l0, stm32l1)))]
-pin_trait!(BreakInput2Pin, GeneralPurpose2ChannelComplementaryInstance);
-
-#[cfg(not(any(stm32l0, stm32l1)))]
-pin_trait!(BreakInputComparator1Pin, GeneralPurpose1ChannelComplementaryInstance);
-#[cfg(not(any(stm32l0, stm32l1)))]
-pin_trait!(BreakInputComparator2Pin, AdvancedControlInstance);
-
-#[cfg(not(any(stm32l0, stm32l1)))]
-pin_trait!(BreakInput2Comparator1Pin, AdvancedControlInstance);
-#[cfg(not(any(stm32l0, stm32l1)))]
-pin_trait!(BreakInput2Comparator2Pin, AdvancedControlInstance);
+#[cfg(not(stm32l0))]
+pin_trait!(BreakInput2Comparator1Pin, ComplementaryCaptureCompare16bitInstance);
+#[cfg(not(stm32l0))]
+pin_trait!(BreakInput2Comparator2Pin, ComplementaryCaptureCompare16bitInstance);
 
 #[allow(unused)]
 macro_rules! impl_core_timer {
@@ -830,7 +783,7 @@ macro_rules! impl_2ch_timer {
 }
 
 #[allow(unused)]
-macro_rules! impl_gp_16bit_timer {
+macro_rules! impl_gp16_timer {
     ($inst:ident) => {
         impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst {
             fn regs_gp16() -> crate::pac::timer::TimGp16 {
@@ -841,7 +794,7 @@ macro_rules! impl_gp_16bit_timer {
 }
 
 #[allow(unused)]
-macro_rules! impl_gp_32bit_timer {
+macro_rules! impl_gp32_timer {
     ($inst:ident) => {
         impl sealed::GeneralPurpose32bitInstance for crate::peripherals::$inst {
             fn regs_gp32() -> crate::pac::timer::TimGp32 {
@@ -890,26 +843,30 @@ foreach_interrupt! {
         impl_core_timer!($inst, $irq);
         impl_basic_no_cr2_timer!($inst);
         impl_basic_timer!($inst);
-        impl CoreInstance for crate::peripherals::$inst {}
-        impl BasicNoCr2Instance for crate::peripherals::$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 CoreInstance for crate::peripherals::$inst {}
-        impl GeneralPurpose1ChannelInstance for crate::peripherals::$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 CoreInstance for crate::peripherals::$inst {}
-        impl GeneralPurpose1ChannelInstance for crate::peripherals::$inst {}
-        impl GeneralPurpose2ChannelInstance for crate::peripherals::$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) => {
@@ -918,13 +875,9 @@ foreach_interrupt! {
         impl_basic_timer!($inst);
         impl_1ch_timer!($inst);
         impl_2ch_timer!($inst);
-        impl_gp_16bit_timer!($inst);
-        impl CoreInstance for crate::peripherals::$inst {}
-        impl BasicNoCr2Instance for crate::peripherals::$inst{}
+        impl_gp16_timer!($inst);
         impl BasicInstance for crate::peripherals::$inst {}
-        impl GeneralPurpose1ChannelInstance for crate::peripherals::$inst {}
-        impl GeneralPurpose2ChannelInstance for crate::peripherals::$inst {}
-        impl GeneralPurpose16bitInstance for crate::peripherals::$inst {}
+        impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
     };
 
     ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => {
@@ -933,26 +886,26 @@ foreach_interrupt! {
         impl_basic_timer!($inst);
         impl_1ch_timer!($inst);
         impl_2ch_timer!($inst);
-        impl_gp_16bit_timer!($inst);
-        impl_gp_32bit_timer!($inst);
-        impl CoreInstance for crate::peripherals::$inst {}
-        impl BasicNoCr2Instance for crate::peripherals::$inst{}
+        impl_gp16_timer!($inst);
+        impl_gp32_timer!($inst);
         impl BasicInstance for crate::peripherals::$inst {}
-        impl GeneralPurpose1ChannelInstance for crate::peripherals::$inst {}
-        impl GeneralPurpose2ChannelInstance for crate::peripherals::$inst {}
-        impl GeneralPurpose16bitInstance for crate::peripherals::$inst {}
-        impl GeneralPurpose32bitInstance for crate::peripherals::$inst {}
+        impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
+        impl CaptureCompare32bitInstance 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 CoreInstance for crate::peripherals::$inst {}
-        impl BasicNoCr2Instance for crate::peripherals::$inst{}
-        impl GeneralPurpose1ChannelInstance for crate::peripherals::$inst {}
-        impl GeneralPurpose1ChannelComplementaryInstance for crate::peripherals::$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 {}
     };
 
 
@@ -962,15 +915,13 @@ foreach_interrupt! {
         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 CoreInstance for crate::peripherals::$inst {}
-        impl BasicNoCr2Instance for crate::peripherals::$inst{}
+        impl_adv_timer!($inst);
         impl BasicInstance for crate::peripherals::$inst {}
-        impl GeneralPurpose1ChannelInstance for crate::peripherals::$inst {}
-        impl GeneralPurpose2ChannelInstance for crate::peripherals::$inst {}
-        impl GeneralPurpose1ChannelComplementaryInstance for crate::peripherals::$inst {}
-        impl GeneralPurpose2ChannelComplementaryInstance for crate::peripherals::$inst {}
+        impl CaptureCompare16bitInstance for crate::peripherals::$inst {}
+        impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {}
     };
 
 
@@ -980,26 +931,20 @@ foreach_interrupt! {
         impl_basic_timer!($inst);
         impl_1ch_timer!($inst);
         impl_2ch_timer!($inst);
+        impl_gp16_timer!($inst);
         impl_1ch_cmp_timer!($inst);
-        impl_gp_16bit_timer!($inst);
         impl_2ch_cmp_timer!($inst);
         impl_adv_timer!($inst);
-        impl CoreInstance for crate::peripherals::$inst {}
-        impl BasicNoCr2Instance for crate::peripherals::$inst{}
         impl BasicInstance for crate::peripherals::$inst {}
-        impl GeneralPurpose1ChannelInstance for crate::peripherals::$inst {}
-        impl GeneralPurpose2ChannelInstance for crate::peripherals::$inst {}
-        impl GeneralPurpose16bitInstance for crate::peripherals::$inst {}
-        impl GeneralPurpose1ChannelComplementaryInstance for crate::peripherals::$inst {}
-        impl GeneralPurpose2ChannelComplementaryInstance for crate::peripherals::$inst {}
-        impl AdvancedControlInstance 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, BasicNoCr2Instance);
+dma_trait!(UpDma, BasicInstance);
 
-dma_trait!(Ch1Dma, GeneralPurpose1ChannelInstance);
-dma_trait!(Ch2Dma, GeneralPurpose2ChannelInstance);
-dma_trait!(Ch3Dma, GeneralPurpose16bitInstance);
-dma_trait!(Ch4Dma, GeneralPurpose16bitInstance);
+dma_trait!(Ch1Dma, CaptureCompare16bitInstance);
+dma_trait!(Ch2Dma, CaptureCompare16bitInstance);
+dma_trait!(Ch3Dma, CaptureCompare16bitInstance);
+dma_trait!(Ch4Dma, CaptureCompare16bitInstance);
diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs
index 7e56312bb..59efb72ba 100644
--- a/embassy-stm32/src/timer/qei.rs
+++ b/embassy-stm32/src/timer/qei.rs
@@ -30,7 +30,7 @@ pub struct QeiPin<'d, T, Channel> {
 
 macro_rules! channel_impl {
     ($new_chx:ident, $channel:ident, $pin_trait:ident) => {
-        impl<'d, T: GeneralPurpose16bitInstance> QeiPin<'d, T, $channel> {
+        impl<'d, T: CaptureCompare16bitInstance> QeiPin<'d, T, $channel> {
             #[doc = concat!("Create a new ", stringify!($channel), " QEI pin instance.")]
             pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd) -> Self {
                 into_ref!(pin);
@@ -57,7 +57,7 @@ pub struct Qei<'d, T> {
     _inner: PeripheralRef<'d, T>,
 }
 
-impl<'d, T: GeneralPurpose16bitInstance> Qei<'d, T> {
+impl<'d, T: CaptureCompare16bitInstance> Qei<'d, T> {
     /// Create a new quadrature decoder driver.
     pub fn new(tim: impl Peripheral<P = T> + 'd, _ch1: QeiPin<'d, T, Ch1>, _ch2: QeiPin<'d, T, Ch2>) -> Self {
         Self::new_inner(tim)
diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs
index 088d02c97..1acba504e 100644
--- a/embassy-stm32/src/timer/simple_pwm.rs
+++ b/embassy-stm32/src/timer/simple_pwm.rs
@@ -1,7 +1,6 @@
 //! Simple PWM driver.
 
 use core::marker::PhantomData;
-use core::ops::{Deref, DerefMut};
 
 use embassy_hal_internal::{into_ref, PeripheralRef};
 
@@ -31,7 +30,7 @@ pub struct PwmPin<'d, T, C> {
 
 macro_rules! channel_impl {
     ($new_chx:ident, $channel:ident, $pin_trait:ident) => {
-        impl<'d, T: GeneralPurpose16bitInstance> PwmPin<'d, T, $channel> {
+        impl<'d, T: CaptureCompare16bitInstance> PwmPin<'d, T, $channel> {
             #[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance.")]
             pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd, output_type: OutputType) -> Self {
                 into_ref!(pin);
@@ -60,7 +59,7 @@ pub struct SimplePwm<'d, T> {
     inner: PeripheralRef<'d, T>,
 }
 
-impl<'d, T: GeneralPurpose16bitInstance> SimplePwm<'d, T> {
+impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
     /// Create a new simple PWM driver.
     pub fn new(
         tim: impl Peripheral<P = T> + 'd,
@@ -88,13 +87,9 @@ impl<'d, T: GeneralPurpose16bitInstance> SimplePwm<'d, T> {
         [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4]
             .iter()
             .for_each(|&channel| {
-                sealed::GeneralPurpose16bitInstance::set_output_compare_mode(
-                    this.inner.deref_mut(),
-                    channel,
-                    OutputCompareMode::PwmMode1,
-                );
+                this.inner.set_output_compare_mode(channel, OutputCompareMode::PwmMode1);
 
-                sealed::GeneralPurpose16bitInstance::set_output_compare_preload(this.inner.deref_mut(), channel, true);
+                this.inner.set_output_compare_preload(channel, true);
             });
 
         this
@@ -102,17 +97,17 @@ impl<'d, T: GeneralPurpose16bitInstance> SimplePwm<'d, T> {
 
     /// Enable the given channel.
     pub fn enable(&mut self, channel: Channel) {
-        sealed::GeneralPurpose16bitInstance::enable_channel(self.inner.deref_mut(), channel, true);
+        self.inner.enable_channel(channel, true);
     }
 
     /// Disable the given channel.
     pub fn disable(&mut self, channel: Channel) {
-        sealed::GeneralPurpose16bitInstance::enable_channel(self.inner.deref_mut(), channel, false);
+        self.inner.enable_channel(channel, false);
     }
 
     /// Check whether given channel is enabled
     pub fn is_enabled(&self, channel: Channel) -> bool {
-        sealed::GeneralPurpose16bitInstance::get_channel_enable_state(self.inner.deref(), channel)
+        self.inner.get_channel_enable_state(channel)
     }
 
     /// Set PWM frequency.
@@ -140,24 +135,24 @@ impl<'d, T: GeneralPurpose16bitInstance> SimplePwm<'d, T> {
     /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included.
     pub fn set_duty(&mut self, channel: Channel, duty: u16) {
         assert!(duty <= self.get_max_duty());
-        sealed::GeneralPurpose16bitInstance::set_compare_value(self.inner.deref_mut(), channel, duty)
+        self.inner.set_compare_value(channel, duty)
     }
 
     /// Get the duty for a given channel.
     ///
     /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included.
     pub fn get_duty(&self, channel: Channel) -> u16 {
-        sealed::GeneralPurpose16bitInstance::get_compare_value(self.inner.deref(), channel)
+        self.inner.get_compare_value(channel)
     }
 
     /// Set the output polarity for a given channel.
     pub fn set_polarity(&mut self, channel: Channel, polarity: OutputPolarity) {
-        sealed::GeneralPurpose16bitInstance::set_output_polarity(self.inner.deref_mut(), channel, polarity);
+        self.inner.set_output_polarity(channel, polarity);
     }
 
     /// Set the output compare mode for a given channel.
     pub fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) {
-        sealed::GeneralPurpose16bitInstance::set_output_compare_mode(self.inner.deref_mut(), channel, mode);
+        self.inner.set_output_compare_mode(channel, mode);
     }
 
     /// Generate a sequence of PWM waveform
@@ -232,7 +227,7 @@ impl<'d, T: GeneralPurpose16bitInstance> SimplePwm<'d, T> {
 
 macro_rules! impl_waveform_chx {
     ($fn_name:ident, $dma_ch:ident, $cc_ch:ident) => {
-        impl<'d, T: GeneralPurpose16bitInstance> SimplePwm<'d, T> {
+        impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
             /// Generate a sequence of PWM waveform
             ///
             /// Note:
@@ -319,17 +314,17 @@ impl_waveform_chx!(waveform_ch2, Ch2Dma, Ch2);
 impl_waveform_chx!(waveform_ch3, Ch3Dma, Ch3);
 impl_waveform_chx!(waveform_ch4, Ch4Dma, Ch4);
 
-impl<'d, T: GeneralPurpose16bitInstance> embedded_hal_02::Pwm for SimplePwm<'d, T> {
+impl<'d, T: CaptureCompare16bitInstance> embedded_hal_02::Pwm for SimplePwm<'d, T> {
     type Channel = Channel;
     type Time = Hertz;
     type Duty = u16;
 
     fn disable(&mut self, channel: Self::Channel) {
-        sealed::GeneralPurpose16bitInstance::enable_channel(self.inner.deref_mut(), channel, false);
+        self.inner.enable_channel(channel, false);
     }
 
     fn enable(&mut self, channel: Self::Channel) {
-        sealed::GeneralPurpose16bitInstance::enable_channel(self.inner.deref_mut(), channel, true);
+        self.inner.enable_channel(channel, true);
     }
 
     fn get_period(&self) -> Self::Time {
@@ -337,7 +332,7 @@ impl<'d, T: GeneralPurpose16bitInstance> embedded_hal_02::Pwm for SimplePwm<'d,
     }
 
     fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
-        sealed::GeneralPurpose16bitInstance::get_compare_value(self.inner.deref(), channel)
+        self.inner.get_compare_value(channel)
     }
 
     fn get_max_duty(&self) -> Self::Duty {
@@ -346,7 +341,7 @@ impl<'d, T: GeneralPurpose16bitInstance> embedded_hal_02::Pwm for SimplePwm<'d,
 
     fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
         assert!(duty <= self.get_max_duty());
-        sealed::GeneralPurpose16bitInstance::set_compare_value(self.inner.deref_mut(), channel, duty)
+        self.inner.set_compare_value(channel, duty)
     }
 
     fn set_period<P>(&mut self, period: P)
diff --git a/examples/stm32h7/src/bin/low_level_timer_api.rs b/examples/stm32h7/src/bin/low_level_timer_api.rs
index 0be3eccb7..cc508c3cf 100644
--- a/examples/stm32h7/src/bin/low_level_timer_api.rs
+++ b/examples/stm32h7/src/bin/low_level_timer_api.rs
@@ -56,11 +56,11 @@ async fn main(_spawner: Spawner) {
         Timer::after_millis(300).await;
     }
 }
-pub struct SimplePwm32<'d, T: GeneralPurpose32bitInstance> {
+pub struct SimplePwm32<'d, T: CaptureCompare32bitInstance> {
     inner: PeripheralRef<'d, T>,
 }
 
-impl<'d, T: GeneralPurpose32bitInstance> SimplePwm32<'d, T> {
+impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> {
     pub fn new(
         tim: impl Peripheral<P = T> + 'd,
         ch1: impl Peripheral<P = impl Channel1Pin<T>> + 'd,

From 0f94006be3aa099d0a6039d51834562e51f91580 Mon Sep 17 00:00:00 2001
From: eZio Pan <eziopan@qq.com>
Date: Sat, 3 Feb 2024 17:30:00 +0800
Subject: [PATCH 09/10] doc fix

---
 embassy-stm32/src/timer/mod.rs | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index 5f40be957..9780c005c 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -20,10 +20,10 @@
 //!
 //! mapping:
 //!
-//! Basic Timer --> BasicInstance  
-//! 1-channel Timer, 2-channel Timer, General Purpose 16-bit Timer --> CaptureCompare16bitInstance  
-//! General Purpose 32-bit Timer --> CaptureCompare32bitInstance  
-//! 1-channel with one complentary Timer, 2-channel with one complentary Timer, Advance Control Timer --> ComplementaryCaptureCompare16bitInstance  
+//! 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;
@@ -667,7 +667,8 @@ impl From<OutputPolarity> for bool {
 /// Basic 16-bit timer instance.
 pub trait BasicInstance: sealed::BasicInstance + sealed::BasicNoCr2Instance + sealed::CoreInstance + 'static {}
 
-/// General-purpose 16-bit timer instance.
+// It's just a General-purpose 16-bit timer instance.
+/// Capture Compare timer instance.
 pub trait CaptureCompare16bitInstance:
     BasicInstance
     + sealed::GeneralPurpose2ChannelInstance
@@ -678,14 +679,16 @@ pub trait CaptureCompare16bitInstance:
 }
 
 #[cfg(not(stm32l0))]
-/// Gneral-purpose 32-bit timer instance.
+// It's just a General-purpose 32-bit timer instance.
+/// Capture Compare 32-bit timer instance.
 pub trait CaptureCompare32bitInstance:
-    sealed::GeneralPurpose32bitInstance + CaptureCompare16bitInstance + 'static
+    CaptureCompare16bitInstance + sealed::GeneralPurpose32bitInstance + 'static
 {
 }
 
 #[cfg(not(stm32l0))]
-/// Advanced control timer instance.
+// It's just a Advanced Control timer instance.
+/// Complementary Capture Compare 32-bit timer instance.
 pub trait ComplementaryCaptureCompare16bitInstance:
     CaptureCompare16bitInstance
     + sealed::GeneralPurpose1ChannelComplementaryInstance

From 8fd803a5fe0af8cc9d648ba2efba755b502f08e9 Mon Sep 17 00:00:00 2001
From: eZio Pan <eziopan@qq.com>
Date: Sun, 4 Feb 2024 15:14:02 +0800
Subject: [PATCH 10/10] use cfg_if to reduce macro condition

---
 embassy-stm32/src/timer/mod.rs | 34 ++++++++++++++--------------------
 1 file changed, 14 insertions(+), 20 deletions(-)

diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index 9780c005c..0118395a7 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -704,29 +704,23 @@ pin_trait!(Channel3Pin, CaptureCompare16bitInstance);
 pin_trait!(Channel4Pin, CaptureCompare16bitInstance);
 pin_trait!(ExternalTriggerPin, CaptureCompare16bitInstance);
 
-#[cfg(not(stm32l0))]
-pin_trait!(Channel1ComplementaryPin, ComplementaryCaptureCompare16bitInstance);
-#[cfg(not(stm32l0))]
-pin_trait!(Channel2ComplementaryPin, ComplementaryCaptureCompare16bitInstance);
-#[cfg(not(stm32l0))]
-pin_trait!(Channel3ComplementaryPin, ComplementaryCaptureCompare16bitInstance);
-#[cfg(not(stm32l0))]
-pin_trait!(Channel4ComplementaryPin, ComplementaryCaptureCompare16bitInstance);
+cfg_if::cfg_if! {
+    if #[cfg(not(stm32l0))] {
+        pin_trait!(Channel1ComplementaryPin, ComplementaryCaptureCompare16bitInstance);
+        pin_trait!(Channel2ComplementaryPin, ComplementaryCaptureCompare16bitInstance);
+        pin_trait!(Channel3ComplementaryPin, ComplementaryCaptureCompare16bitInstance);
+        pin_trait!(Channel4ComplementaryPin, ComplementaryCaptureCompare16bitInstance);
 
-#[cfg(not(stm32l0))]
-pin_trait!(BreakInputPin, ComplementaryCaptureCompare16bitInstance);
-#[cfg(not(stm32l0))]
-pin_trait!(BreakInput2Pin, ComplementaryCaptureCompare16bitInstance);
+        pin_trait!(BreakInputPin, ComplementaryCaptureCompare16bitInstance);
+        pin_trait!(BreakInput2Pin, ComplementaryCaptureCompare16bitInstance);
 
-#[cfg(not(stm32l0))]
-pin_trait!(BreakInputComparator1Pin, ComplementaryCaptureCompare16bitInstance);
-#[cfg(not(stm32l0))]
-pin_trait!(BreakInputComparator2Pin, ComplementaryCaptureCompare16bitInstance);
+        pin_trait!(BreakInputComparator1Pin, ComplementaryCaptureCompare16bitInstance);
+        pin_trait!(BreakInputComparator2Pin, ComplementaryCaptureCompare16bitInstance);
 
-#[cfg(not(stm32l0))]
-pin_trait!(BreakInput2Comparator1Pin, ComplementaryCaptureCompare16bitInstance);
-#[cfg(not(stm32l0))]
-pin_trait!(BreakInput2Comparator2Pin, ComplementaryCaptureCompare16bitInstance);
+        pin_trait!(BreakInput2Comparator1Pin, ComplementaryCaptureCompare16bitInstance);
+        pin_trait!(BreakInput2Comparator2Pin, ComplementaryCaptureCompare16bitInstance);
+    }
+}
 
 #[allow(unused)]
 macro_rules! impl_core_timer {