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