@@ -209,47 +209,53 @@ impl RtcDriver {
209
209
210
210
let r = rtc ( ) ;
211
211
212
- let t = self . now ( ) ;
213
- if timestamp <= t {
214
- // If alarm timestamp has passed the alarm will not fire.
215
- // Disarm the alarm and return `false` to indicate that.
216
- r. intenclr ( ) . write ( |w| w. 0 = compare_n ( n) ) ;
212
+ loop {
213
+ let t = self . now ( ) ;
214
+ if timestamp <= t {
215
+ // If alarm timestamp has passed the alarm will not fire.
216
+ // Disarm the alarm and return `false` to indicate that.
217
+ r. intenclr ( ) . write ( |w| w. 0 = compare_n ( n) ) ;
217
218
218
- alarm. timestamp . set ( u64:: MAX ) ;
219
+ alarm. timestamp . set ( u64:: MAX ) ;
219
220
220
- return false ;
221
- }
221
+ return false ;
222
+ }
222
223
223
- // If it hasn't triggered yet, setup it in the compare channel.
224
-
225
- // Write the CC value regardless of whether we're going to enable it now or not.
226
- // This way, when we enable it later, the right value is already set.
227
-
228
- // nrf52 docs say:
229
- // If the COUNTER is N, writing N or N+1 to a CC register may not trigger a COMPARE event.
230
- // To workaround this, we never write a timestamp smaller than N+3.
231
- // N+2 is not safe because rtc can tick from N to N+1 between calling now() and writing cc.
232
- //
233
- // It is impossible for rtc to tick more than once because
234
- // - this code takes less time than 1 tick
235
- // - it runs with interrupts disabled so nothing else can preempt it.
236
- //
237
- // This means that an alarm can be delayed for up to 2 ticks (from t+1 to t+3), but this is allowed
238
- // by the Alarm trait contract. What's not allowed is triggering alarms *before* their scheduled time,
239
- // and we don't do that here.
240
- let safe_timestamp = timestamp. max ( t + 3 ) ;
241
- r. cc ( n) . write ( |w| w. set_compare ( safe_timestamp as u32 & 0xFFFFFF ) ) ;
242
-
243
- let diff = timestamp - t;
244
- if diff < 0xc00000 {
245
- r. intenset ( ) . write ( |w| w. 0 = compare_n ( n) ) ;
246
- } else {
247
- // If it's too far in the future, don't setup the compare channel yet.
248
- // It will be setup later by `next_period`.
249
- r. intenclr ( ) . write ( |w| w. 0 = compare_n ( n) ) ;
250
- }
224
+ // If it hasn't triggered yet, setup it in the compare channel.
225
+
226
+ // Write the CC value regardless of whether we're going to enable it now or not.
227
+ // This way, when we enable it later, the right value is already set.
228
+
229
+ // nrf52 docs say:
230
+ // If the COUNTER is N, writing N or N+1 to a CC register may not trigger a COMPARE event.
231
+ // To workaround this, we never write a timestamp smaller than N+3.
232
+ // N+2 is not safe because rtc can tick from N to N+1 between calling now() and writing cc.
233
+ //
234
+ // It is impossible for rtc to tick more than once because
235
+ // - this code takes less time than 1 tick
236
+ // - it runs with interrupts disabled so nothing else can preempt it.
237
+ //
238
+ // This means that an alarm can be delayed for up to 2 ticks (from t+1 to t+3), but this is allowed
239
+ // by the Alarm trait contract. What's not allowed is triggering alarms *before* their scheduled time,
240
+ // and we don't do that here.
241
+ let safe_timestamp = timestamp. max ( t + 3 ) ;
242
+ r. cc ( n) . write ( |w| w. set_compare ( safe_timestamp as u32 & 0xFFFFFF ) ) ;
243
+
244
+ let diff = timestamp - t;
245
+ if diff < 0xc00000 {
246
+ r. intenset ( ) . write ( |w| w. 0 = compare_n ( n) ) ;
247
+ } else {
248
+ // If it's too far in the future, don't setup the compare channel yet.
249
+ // It will be setup later by `next_period`.
250
+ r. intenclr ( ) . write ( |w| w. 0 = compare_n ( n) ) ;
251
+ }
251
252
252
- true
253
+ // If we have not passed the safe timestamp, we can be sure the alarm will be invoked. Otherwise,
254
+ // we need to retry setting the alarm.
255
+ if self . now ( ) <= safe_timestamp {
256
+ return true ;
257
+ }
258
+ }
253
259
}
254
260
}
255
261
0 commit comments