Skip to content

Commit c36b58a

Browse files
committed
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.
1 parent b170e1c commit c36b58a

File tree

1 file changed

+9
-12
lines changed

1 file changed

+9
-12
lines changed

hal/mbed_ticker_api.c

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -164,9 +164,9 @@ static void update_present_time(const ticker_data_t *const ticker)
164164
}
165165

166166
/**
167-
* Given the absolute timestamp compute the hal tick timestamp.
167+
* Given the absolute timestamp compute the hal tick timestamp rounded up.
168168
*/
169-
static timestamp_t compute_tick(const ticker_data_t *const ticker, us_timestamp_t timestamp)
169+
static timestamp_t compute_tick_round_up(const ticker_data_t *const ticker, us_timestamp_t timestamp)
170170
{
171171
ticker_event_queue_t *queue = ticker->queue;
172172
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_
185185
} else if (0 != queue->frequency_shifts) {
186186
// Optimized frequencies divisible by 2
187187

188-
delta = (delta_us << ticker->queue->frequency_shifts) / 1000000;
188+
delta = ((delta_us << ticker->queue->frequency_shifts) + 1000000 - 1) / 1000000;
189189
if (delta > ticker->queue->max_delta) {
190190
delta = ticker->queue->max_delta;
191191
}
192192
} else {
193193
// General case
194194

195-
delta = delta_us * queue->frequency / 1000000;
195+
delta = (delta_us * queue->frequency + 1000000 - 1) / 1000000;
196196
if (delta > ticker->queue->max_delta) {
197197
delta = ticker->queue->max_delta;
198198
}
@@ -242,14 +242,11 @@ static void schedule_interrupt(const ticker_data_t *const ticker)
242242
return;
243243
}
244244

245-
timestamp_t match_tick = compute_tick(ticker, match_time);
246-
// The time has been checked to be future, but it could still round
247-
// to the last tick as a result of us to ticks conversion
248-
if (match_tick == queue->tick_last_read) {
249-
// Match time has already expired so fire immediately
250-
ticker->interface->fire_interrupt();
251-
return;
252-
}
245+
timestamp_t match_tick = compute_tick_round_up(ticker, match_time);
246+
247+
// The same tick should never occur since match_tick is rounded up.
248+
// If the same tick is returned scheduling will not work correctly.
249+
MBED_ASSERT(match_tick != queue->tick_last_read);
253250

254251
ticker->interface->set_interrupt(match_tick);
255252
timestamp_t cur_tick = ticker->interface->read();

0 commit comments

Comments
 (0)