diff options
| author | xoviat <[email protected]> | 2023-08-24 01:30:17 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-08-24 01:30:17 +0000 |
| commit | 2a6b743b9e8dbeef6b02320b2485f3f1efe4a337 (patch) | |
| tree | 6ecb235b98bb67c9b064fca2b47e035fbeeb234e | |
| parent | bed1f07c15455f7c88364a06b8c94b3c781c2f68 (diff) | |
| parent | ecc305bbfe1007f9daa4d6a585dfc66f6ca69218 (diff) | |
Merge pull request #1814 from xoviat/rtc-lp
stm32: add low-power mod
| -rw-r--r-- | embassy-stm32/Cargo.toml | 5 | ||||
| -rw-r--r-- | embassy-stm32/build.rs | 4 | ||||
| -rw-r--r-- | embassy-stm32/src/lib.rs | 2 | ||||
| -rw-r--r-- | embassy-stm32/src/low_power.rs | 139 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/mod.rs | 21 | ||||
| -rw-r--r-- | embassy-stm32/src/rtc/v2.rs | 65 |
6 files changed, 186 insertions, 50 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index fe5dc443a..150014afe 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml | |||
| @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" | |||
| 8 | src_base = "https://github.com/embassy-rs/embassy/blob/embassy-stm32-v$VERSION/embassy-stm32/src/" | 8 | src_base = "https://github.com/embassy-rs/embassy/blob/embassy-stm32-v$VERSION/embassy-stm32/src/" |
| 9 | src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-stm32/src/" | 9 | src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-stm32/src/" |
| 10 | 10 | ||
| 11 | features = ["nightly", "defmt", "unstable-pac", "unstable-traits", "exti", "time-driver-any", "time"] | 11 | features = ["nightly", "defmt", "unstable-pac", "unstable-traits", "exti", "time-driver-any", "time", "low-power"] |
| 12 | flavors = [ | 12 | flavors = [ |
| 13 | { regex_feature = "stm32f0.*", target = "thumbv6m-none-eabi" }, | 13 | { regex_feature = "stm32f0.*", target = "thumbv6m-none-eabi" }, |
| 14 | { regex_feature = "stm32f1.*", target = "thumbv7m-none-eabi" }, | 14 | { regex_feature = "stm32f1.*", target = "thumbv7m-none-eabi" }, |
| @@ -38,6 +38,7 @@ embassy-hal-internal = {version = "0.1.0", path = "../embassy-hal-internal", fea | |||
| 38 | embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } | 38 | embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } |
| 39 | embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" } | 39 | embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" } |
| 40 | embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional = true } | 40 | embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional = true } |
| 41 | embassy-executor = { version = "0.3.0", path = "../embassy-executor", optional = true } | ||
| 41 | 42 | ||
| 42 | embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } | 43 | embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } |
| 43 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1", optional = true} | 44 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1", optional = true} |
| @@ -88,6 +89,8 @@ rt = ["stm32-metapac/rt"] | |||
| 88 | defmt = ["dep:defmt", "bxcan/unstable-defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-internal/defmt", "embedded-io-async?/defmt-03", "embassy-usb-driver?/defmt", "embassy-net-driver/defmt", "embassy-time?/defmt"] | 89 | defmt = ["dep:defmt", "bxcan/unstable-defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-internal/defmt", "embedded-io-async?/defmt-03", "embassy-usb-driver?/defmt", "embassy-net-driver/defmt", "embassy-time?/defmt"] |
| 89 | 90 | ||
| 90 | exti = [] | 91 | exti = [] |
| 92 | low-power = [ "dep:embassy-executor", "embassy-executor/arch-cortex-m" ] | ||
| 93 | embassy-executor = [] | ||
| 91 | 94 | ||
| 92 | ## Automatically generate `memory.x` file using [`stm32-metapac`](https://docs.rs/stm32-metapac/) | 95 | ## Automatically generate `memory.x` file using [`stm32-metapac`](https://docs.rs/stm32-metapac/) |
| 93 | memory-x = ["stm32-metapac/memory-x"] | 96 | memory-x = ["stm32-metapac/memory-x"] |
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 8a731620f..6c364f7bb 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs | |||
| @@ -356,6 +356,8 @@ fn main() { | |||
| 356 | } | 356 | } |
| 357 | fn enable() { | 357 | fn enable() { |
| 358 | critical_section::with(|_| { | 358 | critical_section::with(|_| { |
| 359 | #[cfg(feature = "low-power")] | ||
| 360 | crate::rcc::clock_refcount_add(); | ||
| 359 | crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true)); | 361 | crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true)); |
| 360 | #after_enable | 362 | #after_enable |
| 361 | }) | 363 | }) |
| @@ -363,6 +365,8 @@ fn main() { | |||
| 363 | fn disable() { | 365 | fn disable() { |
| 364 | critical_section::with(|_| { | 366 | critical_section::with(|_| { |
| 365 | crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false)); | 367 | crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false)); |
| 368 | #[cfg(feature = "low-power")] | ||
| 369 | crate::rcc::clock_refcount_sub(); | ||
| 366 | }) | 370 | }) |
| 367 | } | 371 | } |
| 368 | fn reset() { | 372 | fn reset() { |
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index adb3054d8..8c87ea7d5 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs | |||
| @@ -47,6 +47,8 @@ pub mod i2c; | |||
| 47 | pub mod i2s; | 47 | pub mod i2s; |
| 48 | #[cfg(stm32wb)] | 48 | #[cfg(stm32wb)] |
| 49 | pub mod ipcc; | 49 | pub mod ipcc; |
| 50 | #[cfg(feature = "low-power")] | ||
| 51 | pub mod low_power; | ||
| 50 | #[cfg(quadspi)] | 52 | #[cfg(quadspi)] |
| 51 | pub mod qspi; | 53 | pub mod qspi; |
| 52 | #[cfg(rng)] | 54 | #[cfg(rng)] |
diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs new file mode 100644 index 000000000..7814fa384 --- /dev/null +++ b/embassy-stm32/src/low_power.rs | |||
| @@ -0,0 +1,139 @@ | |||
| 1 | use core::arch::asm; | ||
| 2 | use core::marker::PhantomData; | ||
| 3 | |||
| 4 | use cortex_m::peripheral::SCB; | ||
| 5 | use embassy_executor::*; | ||
| 6 | use embassy_time::Duration; | ||
| 7 | |||
| 8 | use crate::interrupt; | ||
| 9 | use crate::interrupt::typelevel::Interrupt; | ||
| 10 | use crate::pac::EXTI; | ||
| 11 | use crate::rcc::low_power_ready; | ||
| 12 | |||
| 13 | const THREAD_PENDER: usize = usize::MAX; | ||
| 14 | const THRESHOLD: Duration = Duration::from_millis(500); | ||
| 15 | |||
| 16 | use crate::rtc::{Rtc, RtcInstant}; | ||
| 17 | |||
| 18 | static mut RTC: Option<&'static Rtc> = None; | ||
| 19 | |||
| 20 | foreach_interrupt! { | ||
| 21 | (RTC, rtc, $block:ident, WKUP, $irq:ident) => { | ||
| 22 | #[interrupt] | ||
| 23 | unsafe fn $irq() { | ||
| 24 | Executor::on_wakeup_irq(); | ||
| 25 | } | ||
| 26 | }; | ||
| 27 | } | ||
| 28 | |||
| 29 | pub fn stop_with_rtc(rtc: &'static Rtc) { | ||
| 30 | crate::interrupt::typelevel::RTC_WKUP::unpend(); | ||
| 31 | unsafe { crate::interrupt::typelevel::RTC_WKUP::enable() }; | ||
| 32 | |||
| 33 | EXTI.rtsr(0).modify(|w| w.set_line(22, true)); | ||
| 34 | EXTI.imr(0).modify(|w| w.set_line(22, true)); | ||
| 35 | |||
| 36 | unsafe { RTC = Some(rtc) }; | ||
| 37 | } | ||
| 38 | |||
| 39 | pub fn start_wakeup_alarm(requested_duration: embassy_time::Duration) -> RtcInstant { | ||
| 40 | unsafe { RTC }.unwrap().start_wakeup_alarm(requested_duration) | ||
| 41 | } | ||
| 42 | |||
| 43 | pub fn stop_wakeup_alarm() -> RtcInstant { | ||
| 44 | unsafe { RTC }.unwrap().stop_wakeup_alarm() | ||
| 45 | } | ||
| 46 | |||
| 47 | /// Thread mode executor, using WFE/SEV. | ||
| 48 | /// | ||
| 49 | /// This is the simplest and most common kind of executor. It runs on | ||
| 50 | /// thread mode (at the lowest priority level), and uses the `WFE` ARM instruction | ||
| 51 | /// to sleep when it has no more work to do. When a task is woken, a `SEV` instruction | ||
| 52 | /// is executed, to make the `WFE` exit from sleep and poll the task. | ||
| 53 | /// | ||
| 54 | /// This executor allows for ultra low power consumption for chips where `WFE` | ||
| 55 | /// triggers low-power sleep without extra steps. If your chip requires extra steps, | ||
| 56 | /// you may use [`raw::Executor`] directly to program custom behavior. | ||
| 57 | pub struct Executor { | ||
| 58 | inner: raw::Executor, | ||
| 59 | not_send: PhantomData<*mut ()>, | ||
| 60 | } | ||
| 61 | |||
| 62 | impl Executor { | ||
| 63 | /// Create a new Executor. | ||
| 64 | pub fn new() -> Self { | ||
| 65 | Self { | ||
| 66 | inner: raw::Executor::new(THREAD_PENDER as *mut ()), | ||
| 67 | not_send: PhantomData, | ||
| 68 | } | ||
| 69 | } | ||
| 70 | |||
| 71 | unsafe fn on_wakeup_irq() { | ||
| 72 | info!("on wakeup irq"); | ||
| 73 | |||
| 74 | cortex_m::asm::bkpt(); | ||
| 75 | } | ||
| 76 | |||
| 77 | fn time_until_next_alarm(&self) -> Duration { | ||
| 78 | Duration::from_secs(3) | ||
| 79 | } | ||
| 80 | |||
| 81 | fn get_scb() -> SCB { | ||
| 82 | unsafe { cortex_m::Peripherals::steal() }.SCB | ||
| 83 | } | ||
| 84 | |||
| 85 | fn configure_pwr(&self) { | ||
| 86 | trace!("configure_pwr"); | ||
| 87 | |||
| 88 | if !low_power_ready() { | ||
| 89 | return; | ||
| 90 | } | ||
| 91 | |||
| 92 | let time_until_next_alarm = self.time_until_next_alarm(); | ||
| 93 | if time_until_next_alarm < THRESHOLD { | ||
| 94 | return; | ||
| 95 | } | ||
| 96 | |||
| 97 | trace!("low power stop required"); | ||
| 98 | |||
| 99 | critical_section::with(|_| { | ||
| 100 | trace!("executor: set wakeup alarm..."); | ||
| 101 | |||
| 102 | start_wakeup_alarm(time_until_next_alarm); | ||
| 103 | |||
| 104 | trace!("low power wait for rtc ready..."); | ||
| 105 | |||
| 106 | Self::get_scb().set_sleepdeep(); | ||
| 107 | }); | ||
| 108 | } | ||
| 109 | |||
| 110 | /// Run the executor. | ||
| 111 | /// | ||
| 112 | /// The `init` closure is called with a [`Spawner`] that spawns tasks on | ||
| 113 | /// this executor. Use it to spawn the initial task(s). After `init` returns, | ||
| 114 | /// the executor starts running the tasks. | ||
| 115 | /// | ||
| 116 | /// To spawn more tasks later, you may keep copies of the [`Spawner`] (it is `Copy`), | ||
| 117 | /// for example by passing it as an argument to the initial tasks. | ||
| 118 | /// | ||
| 119 | /// This function requires `&'static mut self`. This means you have to store the | ||
| 120 | /// Executor instance in a place where it'll live forever and grants you mutable | ||
| 121 | /// access. There's a few ways to do this: | ||
| 122 | /// | ||
| 123 | /// - a [StaticCell](https://docs.rs/static_cell/latest/static_cell/) (safe) | ||
| 124 | /// - a `static mut` (unsafe) | ||
| 125 | /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe) | ||
| 126 | /// | ||
| 127 | /// This function never returns. | ||
| 128 | pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! { | ||
| 129 | init(self.inner.spawner()); | ||
| 130 | |||
| 131 | loop { | ||
| 132 | unsafe { | ||
| 133 | self.inner.poll(); | ||
| 134 | self.configure_pwr(); | ||
| 135 | asm!("wfe"); | ||
| 136 | }; | ||
| 137 | } | ||
| 138 | } | ||
| 139 | } | ||
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index ac9ae9c6a..3c75923e5 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs | |||
| @@ -26,6 +26,8 @@ use crate::time::Hertz; | |||
| 26 | #[cfg_attr(any(rcc_h5, rcc_h50), path = "h5.rs")] | 26 | #[cfg_attr(any(rcc_h5, rcc_h50), path = "h5.rs")] |
| 27 | mod _version; | 27 | mod _version; |
| 28 | pub use _version::*; | 28 | pub use _version::*; |
| 29 | #[cfg(feature = "low-power")] | ||
| 30 | use atomic_polyfill::{AtomicU32, Ordering}; | ||
| 29 | 31 | ||
| 30 | #[derive(Clone, Copy, Debug)] | 32 | #[derive(Clone, Copy, Debug)] |
| 31 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 33 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| @@ -79,6 +81,25 @@ pub struct Clocks { | |||
| 79 | pub rtc: Option<Hertz>, | 81 | pub rtc: Option<Hertz>, |
| 80 | } | 82 | } |
| 81 | 83 | ||
| 84 | #[cfg(feature = "low-power")] | ||
| 85 | static CLOCK_REFCOUNT: AtomicU32 = AtomicU32::new(0); | ||
| 86 | |||
| 87 | #[cfg(feature = "low-power")] | ||
| 88 | pub fn low_power_ready() -> bool { | ||
| 89 | CLOCK_REFCOUNT.load(Ordering::SeqCst) == 0 | ||
| 90 | } | ||
| 91 | |||
| 92 | #[cfg(feature = "low-power")] | ||
| 93 | pub(crate) fn clock_refcount_add() { | ||
| 94 | // We don't check for overflow because constructing more than u32 peripherals is unlikely | ||
| 95 | CLOCK_REFCOUNT.fetch_add(1, Ordering::Relaxed); | ||
| 96 | } | ||
| 97 | |||
| 98 | #[cfg(feature = "low-power")] | ||
| 99 | pub(crate) fn clock_refcount_sub() { | ||
| 100 | assert!(CLOCK_REFCOUNT.fetch_sub(1, Ordering::Relaxed) != 0); | ||
| 101 | } | ||
| 102 | |||
| 82 | /// Frozen clock frequencies | 103 | /// Frozen clock frequencies |
| 83 | /// | 104 | /// |
| 84 | /// The existence of this value indicates that the clock configuration can no longer be changed | 105 | /// The existence of this value indicates that the clock configuration can no longer be changed |
diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 53d0161d6..bcb127ecb 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs | |||
| @@ -44,25 +44,15 @@ impl core::ops::Sub for RtcInstant { | |||
| 44 | fn sub(self, rhs: Self) -> Self::Output { | 44 | fn sub(self, rhs: Self) -> Self::Output { |
| 45 | use embassy_time::{Duration, TICK_HZ}; | 45 | use embassy_time::{Duration, TICK_HZ}; |
| 46 | 46 | ||
| 47 | trace!("self st: {}", self.st); | ||
| 48 | trace!("other st: {}", rhs.st); | ||
| 49 | |||
| 50 | trace!("self ssr: {}", self.ssr); | ||
| 51 | trace!("other ssr: {}", rhs.ssr); | ||
| 52 | |||
| 53 | let st = if self.st < rhs.st { self.st + 60 } else { self.st }; | 47 | let st = if self.st < rhs.st { self.st + 60 } else { self.st }; |
| 54 | 48 | ||
| 55 | trace!("self st: {}", st); | 49 | // TODO: read prescaler |
| 56 | 50 | ||
| 57 | let self_ticks = st as u32 * 256 + (255 - self.ssr as u32); | 51 | let self_ticks = st as u32 * 256 + (255 - self.ssr as u32); |
| 58 | let other_ticks = rhs.st as u32 * 256 + (255 - rhs.ssr as u32); | 52 | let other_ticks = rhs.st as u32 * 256 + (255 - rhs.ssr as u32); |
| 59 | let rtc_ticks = self_ticks - other_ticks; | 53 | let rtc_ticks = self_ticks - other_ticks; |
| 60 | 54 | ||
| 61 | trace!("self ticks: {}", self_ticks); | 55 | trace!("self, other, rtc ticks: {}, {}, {}", self_ticks, other_ticks, rtc_ticks); |
| 62 | trace!("other ticks: {}", other_ticks); | ||
| 63 | trace!("rtc ticks: {}", rtc_ticks); | ||
| 64 | |||
| 65 | // TODO: read prescaler | ||
| 66 | 56 | ||
| 67 | Duration::from_ticks( | 57 | Duration::from_ticks( |
| 68 | ((((st as u32 * 256 + (255u32 - self.ssr as u32)) - (rhs.st as u32 * 256 + (255u32 - rhs.ssr as u32))) | 58 | ((((st as u32 * 256 + (255u32 - self.ssr as u32)) - (rhs.st as u32 * 256 + (255u32 - rhs.ssr as u32))) |
| @@ -73,7 +63,7 @@ impl core::ops::Sub for RtcInstant { | |||
| 73 | } | 63 | } |
| 74 | 64 | ||
| 75 | #[allow(dead_code)] | 65 | #[allow(dead_code)] |
| 76 | #[derive(Clone, Copy)] | 66 | #[derive(Clone, Copy, Debug)] |
| 77 | pub(crate) enum WakeupPrescaler { | 67 | pub(crate) enum WakeupPrescaler { |
| 78 | Div2, | 68 | Div2, |
| 79 | Div4, | 69 | Div4, |
| @@ -162,10 +152,9 @@ impl super::Rtc { | |||
| 162 | /// | 152 | /// |
| 163 | /// note: this api is exposed for testing purposes until low power is implemented. | 153 | /// note: this api is exposed for testing purposes until low power is implemented. |
| 164 | /// it is not intended to be public | 154 | /// it is not intended to be public |
| 165 | pub fn start_wakeup_alarm(requested_duration: embassy_time::Duration) -> RtcInstant { | 155 | pub(crate) fn start_wakeup_alarm(&self, requested_duration: embassy_time::Duration) -> RtcInstant { |
| 166 | use embassy_time::{Duration, TICK_HZ}; | 156 | use embassy_time::{Duration, TICK_HZ}; |
| 167 | 157 | ||
| 168 | use crate::interrupt::typelevel::Interrupt; | ||
| 169 | use crate::rcc::get_freqs; | 158 | use crate::rcc::get_freqs; |
| 170 | 159 | ||
| 171 | let rtc_hz = unsafe { get_freqs() }.rtc.unwrap().0 as u64; | 160 | let rtc_hz = unsafe { get_freqs() }.rtc.unwrap().0 as u64; |
| @@ -187,27 +176,17 @@ impl super::Rtc { | |||
| 187 | 176 | ||
| 188 | trace!("set wakeup timer for {} ms", duration.as_millis()); | 177 | trace!("set wakeup timer for {} ms", duration.as_millis()); |
| 189 | 178 | ||
| 190 | RTC::regs().wpr().write(|w| w.set_key(0xca)); | 179 | self.write(false, |regs| { |
| 191 | RTC::regs().wpr().write(|w| w.set_key(0x53)); | 180 | regs.cr().modify(|w| w.set_wutie(true)); |
| 192 | |||
| 193 | RTC::regs().wutr().modify(|w| w.set_wut(rtc_ticks)); | ||
| 194 | 181 | ||
| 195 | RTC::regs().cr().modify(|w| { | 182 | regs.cr().modify(|w| w.set_wute(false)); |
| 196 | w.set_wucksel(prescaler.into()); | 183 | regs.isr().modify(|w| w.set_wutf(false)); |
| 184 | while !regs.isr().read().wutwf() {} | ||
| 197 | 185 | ||
| 198 | w.set_wutie(true); | 186 | regs.cr().modify(|w| w.set_wucksel(prescaler.into())); |
| 199 | w.set_wute(true); | 187 | regs.cr().modify(|w| w.set_wute(true)); |
| 200 | }); | 188 | }); |
| 201 | 189 | ||
| 202 | if !RTC::regs().cr().read().wute() { | ||
| 203 | trace!("wakeup timer not enabled"); | ||
| 204 | } else { | ||
| 205 | trace!("wakeup timer enabled"); | ||
| 206 | } | ||
| 207 | |||
| 208 | crate::interrupt::typelevel::RTC_WKUP::unpend(); | ||
| 209 | unsafe { crate::interrupt::typelevel::RTC_WKUP::enable() }; | ||
| 210 | |||
| 211 | RtcInstant::now() | 190 | RtcInstant::now() |
| 212 | } | 191 | } |
| 213 | 192 | ||
| @@ -217,26 +196,14 @@ impl super::Rtc { | |||
| 217 | /// | 196 | /// |
| 218 | /// note: this api is exposed for testing purposes until low power is implemented. | 197 | /// note: this api is exposed for testing purposes until low power is implemented. |
| 219 | /// it is not intended to be public | 198 | /// it is not intended to be public |
| 220 | pub fn stop_wakeup_alarm() -> RtcInstant { | 199 | pub(crate) fn stop_wakeup_alarm(&self) -> RtcInstant { |
| 221 | use crate::interrupt::typelevel::Interrupt; | ||
| 222 | |||
| 223 | crate::interrupt::typelevel::RTC_WKUP::disable(); | ||
| 224 | |||
| 225 | trace!("disable wakeup timer..."); | 200 | trace!("disable wakeup timer..."); |
| 226 | 201 | ||
| 227 | RTC::regs().cr().modify(|w| { | 202 | self.write(false, |regs| { |
| 228 | w.set_wute(false); | 203 | regs.cr().modify(|w| w.set_wute(false)); |
| 204 | regs.isr().modify(|w| w.set_wutf(false)); | ||
| 229 | }); | 205 | }); |
| 230 | 206 | ||
| 231 | trace!("wait for wakeup timer stop..."); | ||
| 232 | |||
| 233 | // Wait for the wakeup timer to stop | ||
| 234 | // while !RTC::regs().isr().read().wutf() {} | ||
| 235 | // | ||
| 236 | // RTC::regs().isr().modify(|w| w.set_wutf(false)); | ||
| 237 | |||
| 238 | trace!("wait for wakeup timer stop...done"); | ||
| 239 | |||
| 240 | RtcInstant::now() | 207 | RtcInstant::now() |
| 241 | } | 208 | } |
| 242 | 209 | ||
| @@ -388,7 +355,7 @@ impl super::Rtc { | |||
| 388 | }) | 355 | }) |
| 389 | } | 356 | } |
| 390 | 357 | ||
| 391 | pub(super) fn write<F, R>(&mut self, init_mode: bool, f: F) -> R | 358 | pub(super) fn write<F, R>(&self, init_mode: bool, f: F) -> R |
| 392 | where | 359 | where |
| 393 | F: FnOnce(&crate::pac::rtc::Rtc) -> R, | 360 | F: FnOnce(&crate::pac::rtc::Rtc) -> R, |
| 394 | { | 361 | { |
