mirror of https://github.com/ARMmbed/mbed-os.git
Fix double low power ticker interrupt
When computing the next set_interrupt time in the common ticker layer the absolute time in microseconds is rounded down to the closes low power tick. Because of this the low power ticker interrupt fires one cycle too early. This causes ticker_irq_handler to run even though there are no events ready to run. To prevent this unnecessary interrupt this patch changes the computation for the next set_interrupt time to round up rather than down.pull/7599/head
parent
b170e1c44d
commit
c36b58a05b
|
|
@ -164,9 +164,9 @@ static void update_present_time(const ticker_data_t *const ticker)
|
|||
}
|
||||
|
||||
/**
|
||||
* Given the absolute timestamp compute the hal tick timestamp.
|
||||
* Given the absolute timestamp compute the hal tick timestamp rounded up.
|
||||
*/
|
||||
static timestamp_t compute_tick(const ticker_data_t *const ticker, us_timestamp_t timestamp)
|
||||
static timestamp_t compute_tick_round_up(const ticker_data_t *const ticker, us_timestamp_t timestamp)
|
||||
{
|
||||
ticker_event_queue_t *queue = ticker->queue;
|
||||
us_timestamp_t delta_us = timestamp - queue->present_time;
|
||||
|
|
@ -185,14 +185,14 @@ static timestamp_t compute_tick(const ticker_data_t *const ticker, us_timestamp_
|
|||
} else if (0 != queue->frequency_shifts) {
|
||||
// Optimized frequencies divisible by 2
|
||||
|
||||
delta = (delta_us << ticker->queue->frequency_shifts) / 1000000;
|
||||
delta = ((delta_us << ticker->queue->frequency_shifts) + 1000000 - 1) / 1000000;
|
||||
if (delta > ticker->queue->max_delta) {
|
||||
delta = ticker->queue->max_delta;
|
||||
}
|
||||
} else {
|
||||
// General case
|
||||
|
||||
delta = delta_us * queue->frequency / 1000000;
|
||||
delta = (delta_us * queue->frequency + 1000000 - 1) / 1000000;
|
||||
if (delta > ticker->queue->max_delta) {
|
||||
delta = ticker->queue->max_delta;
|
||||
}
|
||||
|
|
@ -242,14 +242,11 @@ static void schedule_interrupt(const ticker_data_t *const ticker)
|
|||
return;
|
||||
}
|
||||
|
||||
timestamp_t match_tick = compute_tick(ticker, match_time);
|
||||
// The time has been checked to be future, but it could still round
|
||||
// to the last tick as a result of us to ticks conversion
|
||||
if (match_tick == queue->tick_last_read) {
|
||||
// Match time has already expired so fire immediately
|
||||
ticker->interface->fire_interrupt();
|
||||
return;
|
||||
}
|
||||
timestamp_t match_tick = compute_tick_round_up(ticker, match_time);
|
||||
|
||||
// The same tick should never occur since match_tick is rounded up.
|
||||
// If the same tick is returned scheduling will not work correctly.
|
||||
MBED_ASSERT(match_tick != queue->tick_last_read);
|
||||
|
||||
ticker->interface->set_interrupt(match_tick);
|
||||
timestamp_t cur_tick = ticker->interface->read();
|
||||
|
|
|
|||
Loading…
Reference in New Issue