@@ -207,7 +207,14 @@ void LowPowerTickerWrapper::_timeout_handler()
207
207
_pending_timeout = false ;
208
208
209
209
timestamp_t current = _intf->read ();
210
- if (_ticker_match_interval_passed (_last_set_interrupt, current, _cur_match_time)) {
210
+ /* Add extra check for '_last_set_interrupt == _cur_match_time'
211
+ *
212
+ * When '_last_set_interrupt == _cur_match_time', _ticker_match_interval_passed sees it as
213
+ * one-round interval rather than just-pass, so add extra check for it. In rare cases, we
214
+ * may trap in _timeout_handler/_schedule_match loop. This check can break it.
215
+ */
216
+ if ((_last_set_interrupt == _cur_match_time) ||
217
+ _ticker_match_interval_passed (_last_set_interrupt, current, _cur_match_time)) {
211
218
_intf->fire_interrupt ();
212
219
} else {
213
220
_schedule_match (current);
@@ -223,7 +230,9 @@ bool LowPowerTickerWrapper::_match_check(timestamp_t current)
223
230
if (!_pending_match) {
224
231
return false ;
225
232
}
226
- return _ticker_match_interval_passed (_last_set_interrupt, current, _cur_match_time);
233
+ /* Add extra check for '_last_set_interrupt == _cur_match_time' as above */
234
+ return (_last_set_interrupt == _cur_match_time) ||
235
+ _ticker_match_interval_passed (_last_set_interrupt, current, _cur_match_time);
227
236
}
228
237
229
238
uint32_t LowPowerTickerWrapper::_lp_ticks_to_us (uint32_t ticks)
@@ -245,7 +254,7 @@ void LowPowerTickerWrapper::_schedule_match(timestamp_t current)
245
254
}
246
255
}
247
256
248
- uint32_t cycles_until_match = (_cur_match_time - _last_set_interrupt ) & _mask;
257
+ uint32_t cycles_until_match = (_cur_match_time - current ) & _mask;
249
258
bool too_close = cycles_until_match < _min_count_until_match;
250
259
251
260
if (!_set_interrupt_allowed) {
0 commit comments