aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2021-01-13 03:17:58 +0100
committerDario Nieuwenhuis <[email protected]>2021-01-13 03:17:58 +0100
commit6963b314a246b245aabe1cedf6e1efec0b91e00b (patch)
treeab9f1f17b99dc9efabbbae46279d0d263dc621b2
parent5229a1991c0ac0a4eafa8a321a80aee21af96a2e (diff)
nrf/rtc: fix race when setting alarms too close to now.
-rw-r--r--embassy-nrf/src/rtc.rs17
1 files changed, 6 insertions, 11 deletions
diff --git a/embassy-nrf/src/rtc.rs b/embassy-nrf/src/rtc.rs
index f431339ff..015583943 100644
--- a/embassy-nrf/src/rtc.rs
+++ b/embassy-nrf/src/rtc.rs
@@ -182,18 +182,13 @@ impl<T: Instance> RTC<T> {
182 182
183 let diff = timestamp - t; 183 let diff = timestamp - t;
184 if diff < 0xc00000 { 184 if diff < 0xc00000 {
185 self.rtc.cc[n].write(|w| unsafe { w.bits(timestamp as u32 & 0xFFFFFF) }); 185 // nrf52 docs say:
186 // If the COUNTER is N, writing N or N+1 to a CC register may not trigger a COMPARE event.
187 // To workaround this, we never write a timestamp smaller than N+3.
188 // N+2 is not safe because rtc can tick from N to N+1 between calling now() and writing cc.
189 let safe_timestamp = timestamp.max(t + 3);
190 self.rtc.cc[n].write(|w| unsafe { w.bits(safe_timestamp as u32 & 0xFFFFFF) });
186 self.rtc.intenset.write(|w| unsafe { w.bits(compare_n(n)) }); 191 self.rtc.intenset.write(|w| unsafe { w.bits(compare_n(n)) });
187
188 // We may have been preempted for arbitrary time between checking if `at` is in the past
189 // and setting the cc. In that case, we don't know if the cc has triggered.
190 // So, we check again just in case.
191
192 let t = self.now();
193 if timestamp <= t {
194 self.trigger_alarm(n, cs);
195 return;
196 }
197 } else { 192 } else {
198 self.rtc.intenclr.write(|w| unsafe { w.bits(compare_n(n)) }); 193 self.rtc.intenclr.write(|w| unsafe { w.bits(compare_n(n)) });
199 } 194 }