mirror of
https://github.com/embassy-rs/embassy.git
synced 2025-10-01 06:10:41 +00:00
Merge pull request #3705 from embassy-rs/time-driver-fix
Ensure alarm is re-scheduled if timetamp is in the past
This commit is contained in:
commit
eaa44c3d3f
@ -209,6 +209,7 @@ impl RtcDriver {
|
|||||||
|
|
||||||
let r = rtc();
|
let r = rtc();
|
||||||
|
|
||||||
|
loop {
|
||||||
let t = self.now();
|
let t = self.now();
|
||||||
if timestamp <= t {
|
if timestamp <= t {
|
||||||
// If alarm timestamp has passed the alarm will not fire.
|
// If alarm timestamp has passed the alarm will not fire.
|
||||||
@ -230,9 +231,9 @@ impl RtcDriver {
|
|||||||
// To workaround this, we never write a timestamp smaller than N+3.
|
// To workaround this, we never write a timestamp smaller than N+3.
|
||||||
// N+2 is not safe because rtc can tick from N to N+1 between calling now() and writing cc.
|
// N+2 is not safe because rtc can tick from N to N+1 between calling now() and writing cc.
|
||||||
//
|
//
|
||||||
// It is impossible for rtc to tick more than once because
|
// Since the critical section does not guarantee that a higher prio interrupt causes
|
||||||
// - this code takes less time than 1 tick
|
// this to be delayed, we need to re-check how much time actually passed after setting the
|
||||||
// - it runs with interrupts disabled so nothing else can preempt it.
|
// alarm, and retry if we are within the unsafe interval still.
|
||||||
//
|
//
|
||||||
// This means that an alarm can be delayed for up to 2 ticks (from t+1 to t+3), but this is allowed
|
// This means that an alarm can be delayed for up to 2 ticks (from t+1 to t+3), but this is allowed
|
||||||
// by the Alarm trait contract. What's not allowed is triggering alarms *before* their scheduled time,
|
// by the Alarm trait contract. What's not allowed is triggering alarms *before* their scheduled time,
|
||||||
@ -243,13 +244,19 @@ impl RtcDriver {
|
|||||||
let diff = timestamp - t;
|
let diff = timestamp - t;
|
||||||
if diff < 0xc00000 {
|
if diff < 0xc00000 {
|
||||||
r.intenset().write(|w| w.0 = compare_n(n));
|
r.intenset().write(|w| w.0 = compare_n(n));
|
||||||
|
|
||||||
|
// If we have not passed the timestamp, we can be sure the alarm will be invoked. Otherwise,
|
||||||
|
// we need to retry setting the alarm.
|
||||||
|
if self.now() + 2 <= timestamp {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// If it's too far in the future, don't setup the compare channel yet.
|
// If it's too far in the future, don't setup the compare channel yet.
|
||||||
// It will be setup later by `next_period`.
|
// It will be setup later by `next_period`.
|
||||||
r.intenclr().write(|w| w.0 = compare_n(n));
|
r.intenclr().write(|w| w.0 = compare_n(n));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user