From 5c45723777dbd7d9d23188f5b5a2adc417e29292 Mon Sep 17 00:00:00 2001
From: Torin Cooper-Bennun <tcbennun@maxiluxsystems.com>
Date: Fri, 23 Feb 2024 14:33:25 +0000
Subject: [PATCH] stm32: timers: use TIMx_CC interrupt source for advanced
 timers

fixes (hopefully) time driver when using TIM1/8/20
---
 embassy-stm32/src/time_driver.rs | 34 ++++++++++++++++++++++++++++++++
 embassy-stm32/src/timer/mod.rs   | 19 ++++++++++++++----
 2 files changed, 49 insertions(+), 4 deletions(-)

diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs
index 8e4e606a4..37b2e7526 100644
--- a/embassy-stm32/src/time_driver.rs
+++ b/embassy-stm32/src/time_driver.rs
@@ -16,6 +16,8 @@ use crate::pac::timer::vals;
 use crate::rcc::sealed::RccPeripheral;
 #[cfg(feature = "low-power")]
 use crate::rtc::Rtc;
+#[cfg(any(time_driver_tim1, time_driver_tim8, time_driver_tim20))]
+use crate::timer::sealed::AdvancedControlInstance;
 use crate::timer::sealed::{CoreInstance, GeneralPurpose16bitInstance as Instance};
 use crate::{interrupt, peripherals};
 
@@ -76,6 +78,14 @@ foreach_interrupt! {
             DRIVER.on_interrupt()
         }
     };
+    (TIM1, timer, $block:ident, CC, $irq:ident) => {
+        #[cfg(time_driver_tim1)]
+        #[cfg(feature = "rt")]
+        #[interrupt]
+        fn $irq() {
+            DRIVER.on_interrupt()
+        }
+    };
     (TIM2, timer, $block:ident, UP, $irq:ident) => {
         #[cfg(time_driver_tim2)]
         #[cfg(feature = "rt")]
@@ -116,6 +126,14 @@ foreach_interrupt! {
             DRIVER.on_interrupt()
         }
     };
+    (TIM8, timer, $block:ident, CC, $irq:ident) => {
+        #[cfg(time_driver_tim8)]
+        #[cfg(feature = "rt")]
+        #[interrupt]
+        fn $irq() {
+            DRIVER.on_interrupt()
+        }
+    };
     (TIM9, timer, $block:ident, UP, $irq:ident) => {
         #[cfg(time_driver_tim9)]
         #[cfg(feature = "rt")]
@@ -148,6 +166,14 @@ foreach_interrupt! {
             DRIVER.on_interrupt()
         }
     };
+    (TIM20, timer, $block:ident, CC, $irq:ident) => {
+        #[cfg(time_driver_tim20)]
+        #[cfg(feature = "rt")]
+        #[interrupt]
+        fn $irq() {
+            DRIVER.on_interrupt()
+        }
+    };
     (TIM21, timer, $block:ident, UP, $irq:ident) => {
         #[cfg(time_driver_tim21)]
         #[cfg(feature = "rt")]
@@ -281,6 +307,14 @@ impl RtcDriver {
         <T as CoreInstance>::Interrupt::unpend();
         unsafe { <T as CoreInstance>::Interrupt::enable() };
 
+        #[cfg(any(time_driver_tim1, time_driver_tim8, time_driver_tim20))]
+        {
+            <T as AdvancedControlInstance>::CaptureCompareInterrupt::unpend();
+            unsafe {
+                <T as AdvancedControlInstance>::CaptureCompareInterrupt::enable();
+            }
+        }
+
         r.cr1().modify(|w| w.set_cen(true));
     }
 
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index 9397da2a1..c8f580101 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -464,6 +464,9 @@ pub(crate) mod sealed {
     pub trait AdvancedControlInstance:
         GeneralPurpose2ChannelComplementaryInstance + GeneralPurpose16bitInstance
     {
+        /// Capture compare interrupt for this timer.
+        type CaptureCompareInterrupt: interrupt::typelevel::Interrupt;
+
         /// Get access to the advanced timer registers.
         fn regs_advanced() -> crate::pac::timer::TimAdv;
 
@@ -831,8 +834,10 @@ macro_rules! impl_2ch_cmp_timer {
 
 #[allow(unused)]
 macro_rules! impl_adv_timer {
-    ($inst:ident) => {
+    ($inst:ident, $irq:ident) => {
         impl sealed::AdvancedControlInstance for crate::peripherals::$inst {
+            type CaptureCompareInterrupt = crate::interrupt::typelevel::$irq;
+
             fn regs_advanced() -> crate::pac::timer::TimAdv {
                 unsafe { crate::pac::timer::TimAdv::from_ptr(crate::pac::$inst.as_ptr()) }
             }
@@ -905,11 +910,13 @@ foreach_interrupt! {
         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_1CH_CMP, CC, $irq:ident) => {
+        impl_adv_timer!($inst, $irq);
+    };
 
 
     ($inst:ident, timer, TIM_2CH_CMP, UP, $irq:ident) => {
@@ -921,11 +928,13 @@ foreach_interrupt! {
         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_2CH_CMP, CC, $irq:ident) => {
+        impl_adv_timer!($inst, $irq);
+    };
 
 
     ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => {
@@ -937,11 +946,13 @@ foreach_interrupt! {
         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, CC, $irq:ident) => {
+        impl_adv_timer!($inst, $irq);
+    };
 }
 
 // Update Event trigger DMA for every timer