Skip to content

Commit 933e27d

Browse files
authored
Merge pull request #4889 from xoviat/time
cleanup low_power add_time function
2 parents 6600c2f + c3a2ea8 commit 933e27d

File tree

3 files changed

+21
-82
lines changed

3 files changed

+21
-82
lines changed

embassy-stm32/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## Unreleased - ReleaseDate
99

10+
- chore: cleanup low-power add time
1011
- fix: Allow setting SAI peripheral `frame_length` to `256`
1112
- fix: flash erase on dual-bank STM32Gxxx
1213
- feat: Add support for STM32N657X0

embassy-stm32/src/rtc/low_power.rs

Lines changed: 13 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use embassy_time::{Duration, TICK_HZ};
33

44
use super::{DateTimeError, Rtc, RtcError, bcd2_to_byte};
55
use crate::interrupt::typelevel::Interrupt;
6+
use crate::pac::rtc::vals::Wucksel;
67
use crate::peripherals::RTC;
78
use crate::rtc::{RtcTimeProvider, SealedInstance};
89

@@ -58,60 +59,16 @@ impl core::ops::Sub for RtcInstant {
5859
}
5960
}
6061

61-
#[repr(u8)]
62-
#[derive(Clone, Copy, Debug)]
63-
pub(crate) enum WakeupPrescaler {
64-
Div2 = 2,
65-
Div4 = 4,
66-
Div8 = 8,
67-
Div16 = 16,
68-
}
69-
70-
#[cfg(any(
71-
stm32f4, stm32l0, stm32g4, stm32l4, stm32l5, stm32wb, stm32h5, stm32g0, stm32u5, stm32u0, stm32wba, stm32wlex
72-
))]
73-
impl From<WakeupPrescaler> for crate::pac::rtc::vals::Wucksel {
74-
fn from(val: WakeupPrescaler) -> Self {
75-
use crate::pac::rtc::vals::Wucksel;
76-
77-
match val {
78-
WakeupPrescaler::Div2 => Wucksel::DIV2,
79-
WakeupPrescaler::Div4 => Wucksel::DIV4,
80-
WakeupPrescaler::Div8 => Wucksel::DIV8,
81-
WakeupPrescaler::Div16 => Wucksel::DIV16,
82-
}
83-
}
84-
}
85-
86-
#[cfg(any(
87-
stm32f4, stm32l0, stm32g4, stm32l4, stm32l5, stm32wb, stm32h5, stm32g0, stm32u5, stm32u0, stm32wba, stm32wlex
88-
))]
89-
impl From<crate::pac::rtc::vals::Wucksel> for WakeupPrescaler {
90-
fn from(val: crate::pac::rtc::vals::Wucksel) -> Self {
91-
use crate::pac::rtc::vals::Wucksel;
92-
93-
match val {
94-
Wucksel::DIV2 => WakeupPrescaler::Div2,
95-
Wucksel::DIV4 => WakeupPrescaler::Div4,
96-
Wucksel::DIV8 => WakeupPrescaler::Div8,
97-
Wucksel::DIV16 => WakeupPrescaler::Div16,
98-
_ => unreachable!(),
99-
}
100-
}
101-
}
102-
103-
impl WakeupPrescaler {
104-
pub fn compute_min(val: u32) -> Self {
105-
*[
106-
WakeupPrescaler::Div2,
107-
WakeupPrescaler::Div4,
108-
WakeupPrescaler::Div8,
109-
WakeupPrescaler::Div16,
110-
]
111-
.iter()
112-
.find(|psc| **psc as u32 > val)
113-
.unwrap_or(&WakeupPrescaler::Div16)
114-
}
62+
fn wucksel_compute_min(val: u32) -> (Wucksel, u32) {
63+
*[
64+
(Wucksel::DIV2, 2),
65+
(Wucksel::DIV4, 4),
66+
(Wucksel::DIV8, 8),
67+
(Wucksel::DIV16, 16),
68+
]
69+
.iter()
70+
.find(|(_, psc)| *psc as u32 > val)
71+
.unwrap_or(&(Wucksel::DIV16, 16))
11572
}
11673

11774
impl Rtc {
@@ -138,7 +95,7 @@ impl Rtc {
13895
let requested_duration = requested_duration.as_ticks().clamp(0, u32::MAX as u64);
13996
let rtc_hz = Self::frequency().0 as u64;
14097
let rtc_ticks = requested_duration * rtc_hz / TICK_HZ;
141-
let prescaler = WakeupPrescaler::compute_min((rtc_ticks / u16::MAX as u64) as u32);
98+
let (wucksel, prescaler) = wucksel_compute_min((rtc_ticks / u16::MAX as u64) as u32);
14299

143100
// adjust the rtc ticks to the prescaler and subtract one rtc tick
144101
let rtc_ticks = rtc_ticks / prescaler as u64;
@@ -159,7 +116,7 @@ impl Rtc {
159116
while !regs.icsr().read().wutwf() {}
160117
}
161118

162-
regs.cr().modify(|w| w.set_wucksel(prescaler.into()));
119+
regs.cr().modify(|w| w.set_wucksel(wucksel));
163120
regs.wutr().write(|w| w.set_wut(rtc_ticks));
164121
regs.cr().modify(|w| w.set_wute(true));
165122
regs.cr().modify(|w| w.set_wutie(true));

embassy-stm32/src/time_driver.rs

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,11 @@ fn calc_now(period: u32, counter: u16) -> u64 {
196196
((period as u64) << 15) + ((counter as u32 ^ ((period & 1) << 15)) as u64)
197197
}
198198

199+
#[cfg(feature = "low-power")]
200+
fn calc_period_counter(ticks: u64) -> (u32, u16) {
201+
(2 * (ticks >> 16) as u32 + (ticks as u16 >= 0x8000) as u32, ticks as u16)
202+
}
203+
199204
struct AlarmState {
200205
timestamp: Cell<u64>,
201206
}
@@ -358,34 +363,10 @@ impl RtcDriver {
358363
#[cfg(feature = "low-power")]
359364
/// Add the given offset to the current time
360365
fn add_time(&self, offset: embassy_time::Duration, cs: CriticalSection) {
361-
let offset = offset.as_ticks();
362-
let cnt = regs_gp16().cnt().read().cnt() as u32;
363-
let period = self.period.load(Ordering::SeqCst);
364-
365-
// Correct the race, if it exists
366-
let period = if period & 1 == 1 && cnt < u16::MAX as u32 / 2 {
367-
period + 1
368-
} else {
369-
period
370-
};
371-
372-
// Normalize to the full overflow
373-
let period = (period / 2) * 2;
374-
375-
// Add the offset
376-
let period = period + 2 * (offset / u16::MAX as u64) as u32;
377-
let cnt = cnt + (offset % u16::MAX as u64) as u32;
378-
379-
let (cnt, period) = if cnt > u16::MAX as u32 {
380-
(cnt - u16::MAX as u32, period + 2)
381-
} else {
382-
(cnt, period)
383-
};
384-
385-
let period = if cnt > u16::MAX as u32 / 2 { period + 1 } else { period };
366+
let (period, counter) = calc_period_counter(self.now() + offset.as_ticks());
386367

387368
self.period.store(period, Ordering::SeqCst);
388-
regs_gp16().cnt().write(|w| w.set_cnt(cnt as u16));
369+
regs_gp16().cnt().write(|w| w.set_cnt(counter));
389370

390371
// Now, recompute alarm
391372
let alarm = self.alarm.borrow(cs);

0 commit comments

Comments
 (0)