From fc04d2a33caa300bce38f7d0a46f1a0c814bb613 Mon Sep 17 00:00:00 2001
From: xoviat <xoviat@users.noreply.github.com>
Date: Wed, 23 Aug 2023 19:52:32 -0500
Subject: [PATCH] rtc: get wakup irq working

---
 embassy-stm32/src/low_power.rs |  4 +++
 embassy-stm32/src/rtc/v2.rs    | 48 ++++++++++++++++++++--------------
 2 files changed, 32 insertions(+), 20 deletions(-)

diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs
index 7d5093b61..f4bf7bbea 100644
--- a/embassy-stm32/src/low_power.rs
+++ b/embassy-stm32/src/low_power.rs
@@ -7,6 +7,7 @@ use embassy_time::Duration;
 
 use crate::interrupt;
 use crate::interrupt::typelevel::Interrupt;
+use crate::pac::EXTI;
 
 const THREAD_PENDER: usize = usize::MAX;
 const THRESHOLD: Duration = Duration::from_millis(500);
@@ -28,6 +29,9 @@ pub fn stop_with_rtc(rtc: &'static Rtc) {
     crate::interrupt::typelevel::RTC_WKUP::unpend();
     unsafe { crate::interrupt::typelevel::RTC_WKUP::enable() };
 
+    EXTI.rtsr(0).modify(|w| w.set_line(22, true));
+    EXTI.imr(0).modify(|w| w.set_line(22, true));
+
     unsafe { RTC = Some(rtc) };
 }
 
diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs
index e03c7d2a0..1d4f4df30 100644
--- a/embassy-stm32/src/rtc/v2.rs
+++ b/embassy-stm32/src/rtc/v2.rs
@@ -1,3 +1,4 @@
+use defmt::Format;
 use stm32_metapac::rtc::vals::{Init, Osel, Pol};
 
 use super::{sealed, RtcClockSource, RtcConfig};
@@ -73,7 +74,7 @@ impl core::ops::Sub for RtcInstant {
 }
 
 #[allow(dead_code)]
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug, Format)]
 pub(crate) enum WakeupPrescaler {
     Div2,
     Div4,
@@ -185,17 +186,26 @@ impl super::Rtc {
         );
 
         trace!("set wakeup timer for {} ms", duration.as_millis());
+        trace!("set wakeup timer for {} ticks with pre {}", rtc_ticks, prescaler);
 
-        RTC::regs().wpr().write(|w| w.set_key(0xca));
-        RTC::regs().wpr().write(|w| w.set_key(0x53));
+        self.write(false, |regs| {
+            regs.cr().modify(|w| w.set_wutie(true));
 
-        RTC::regs().wutr().modify(|w| w.set_wut(rtc_ticks));
+            trace!("clear wute");
+            regs.cr().modify(|w| w.set_wute(false));
+            regs.isr().modify(|w| w.set_wutf(false));
 
-        RTC::regs().cr().modify(|w| {
-            w.set_wucksel(prescaler.into());
+            trace!("wait for wutwf...");
+            while !regs.isr().read().wutwf() {}
+            trace!("wait for wutwf...done");
 
-            w.set_wutie(true);
-            w.set_wute(true);
+            regs.cr().modify(|w| {
+                w.set_wucksel(prescaler.into());
+
+                w.set_wutie(true);
+            });
+
+            regs.cr().modify(|w| w.set_wute(true));
         });
 
         if !RTC::regs().cr().read().wute() {
@@ -204,6 +214,12 @@ impl super::Rtc {
             trace!("wakeup timer enabled");
         }
 
+        if !RTC::regs().cr().read().wutie() {
+            trace!("wakeup timer interrupt not enabled");
+        } else {
+            trace!("wakeup timer interrupt enabled");
+        }
+
         RtcInstant::now()
     }
 
@@ -216,19 +232,11 @@ impl super::Rtc {
     pub(crate) fn stop_wakeup_alarm(&self) -> RtcInstant {
         trace!("disable wakeup timer...");
 
-        RTC::regs().cr().modify(|w| {
-            w.set_wute(false);
+        self.write(false, |regs| {
+            regs.cr().modify(|w| w.set_wute(false));
+            regs.isr().modify(|w| w.set_wutf(false));
         });
 
-        trace!("wait for wakeup timer stop...");
-
-        // Wait for the wakeup timer to stop
-        // while !RTC::regs().isr().read().wutf() {}
-        //
-        // RTC::regs().isr().modify(|w| w.set_wutf(false));
-
-        trace!("wait for wakeup timer stop...done");
-
         RtcInstant::now()
     }
 
@@ -380,7 +388,7 @@ impl super::Rtc {
         })
     }
 
-    pub(super) fn write<F, R>(&mut self, init_mode: bool, f: F) -> R
+    pub(super) fn write<F, R>(&self, init_mode: bool, f: F) -> R
     where
         F: FnOnce(&crate::pac::rtc::Rtc) -> R,
     {