From 5b90b4ca97375423cd7ce9575296a8e14b710347 Mon Sep 17 00:00:00 2001 From: ccli8 Date: Tue, 21 Aug 2018 17:15:19 +0800 Subject: [PATCH] Fix issues with LowPowerTickerWrapper 1. Complement _ticker_match_interval_passed with '_last_set_interrupt == _cur_match_time' for pass check 2. Fix 'too close' check with _min_count_until_match --- hal/LowPowerTickerWrapper.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/hal/LowPowerTickerWrapper.cpp b/hal/LowPowerTickerWrapper.cpp index 70b5190d4bd..dbeb8504352 100644 --- a/hal/LowPowerTickerWrapper.cpp +++ b/hal/LowPowerTickerWrapper.cpp @@ -207,7 +207,14 @@ void LowPowerTickerWrapper::_timeout_handler() _pending_timeout = false; timestamp_t current = _intf->read(); - if (_ticker_match_interval_passed(_last_set_interrupt, current, _cur_match_time)) { + /* Add extra check for '_last_set_interrupt == _cur_match_time' + * + * When '_last_set_interrupt == _cur_match_time', _ticker_match_interval_passed sees it as + * one-round interval rather than just-pass, so add extra check for it. In rare cases, we + * may trap in _timeout_handler/_schedule_match loop. This check can break it. + */ + if ((_last_set_interrupt == _cur_match_time) || + _ticker_match_interval_passed(_last_set_interrupt, current, _cur_match_time)) { _intf->fire_interrupt(); } else { _schedule_match(current); @@ -223,7 +230,9 @@ bool LowPowerTickerWrapper::_match_check(timestamp_t current) if (!_pending_match) { return false; } - return _ticker_match_interval_passed(_last_set_interrupt, current, _cur_match_time); + /* Add extra check for '_last_set_interrupt == _cur_match_time' as above */ + return (_last_set_interrupt == _cur_match_time) || + _ticker_match_interval_passed(_last_set_interrupt, current, _cur_match_time); } uint32_t LowPowerTickerWrapper::_lp_ticks_to_us(uint32_t ticks) @@ -245,7 +254,7 @@ void LowPowerTickerWrapper::_schedule_match(timestamp_t current) } } - uint32_t cycles_until_match = (_cur_match_time - _last_set_interrupt) & _mask; + uint32_t cycles_until_match = (_cur_match_time - current) & _mask; bool too_close = cycles_until_match < _min_count_until_match; if (!_set_interrupt_allowed) {