mbed library sources. Supersedes mbed-src.
Dependents: Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more
Diff: hal/mbed_ticker_api.c
- Revision:
- 188:bcfe06ba3d64
- Parent:
- 187:0387e8f68319
- Child:
- 189:f392fc9709a3
diff -r 0387e8f68319 -r bcfe06ba3d64 hal/mbed_ticker_api.c --- a/hal/mbed_ticker_api.c Thu Sep 06 13:40:20 2018 +0100 +++ b/hal/mbed_ticker_api.c Thu Nov 08 11:46:34 2018 +0000 @@ -17,7 +17,7 @@ #include <stddef.h> #include "hal/ticker_api.h" #include "platform/mbed_critical.h" -#include "mbed_assert.h" +#include "platform/mbed_assert.h" static void schedule_interrupt(const ticker_data_t *const ticker); static void update_present_time(const ticker_data_t *const ticker); @@ -32,6 +32,9 @@ if (ticker->queue->initialized) { return; } + if (ticker->queue->suspended) { + return; + } ticker->interface->init(); @@ -44,7 +47,7 @@ uint8_t frequency_shifts = 0; for (uint8_t i = 31; i > 0; --i) { - if ((1 << i) == frequency) { + if ((1U << i) == frequency) { frequency_shifts = i; break; } @@ -70,6 +73,7 @@ ticker->queue->max_delta_us = max_delta_us; ticker->queue->present_time = 0; ticker->queue->dispatching = false; + ticker->queue->suspended = false; ticker->queue->initialized = true; update_present_time(ticker); @@ -121,6 +125,9 @@ static void update_present_time(const ticker_data_t *const ticker) { ticker_event_queue_t *queue = ticker->queue; + if (queue->suspended) { + return; + } uint32_t ticker_time = ticker->interface->read(); if (ticker_time == ticker->queue->tick_last_read) { // No work to do @@ -165,9 +172,9 @@ } /** - * 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; @@ -186,14 +193,14 @@ } 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; } @@ -230,7 +237,7 @@ static void schedule_interrupt(const ticker_data_t *const ticker) { ticker_event_queue_t *queue = ticker->queue; - if (ticker->queue->dispatching) { + if (queue->suspended || ticker->queue->dispatching) { // Don't schedule the next interrupt until dispatching is // finished. This prevents repeated calls to interface->set_interrupt return; @@ -249,14 +256,11 @@ 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(); @@ -285,6 +289,10 @@ core_util_critical_section_enter(); ticker->interface->clear_interrupt(); + if (ticker->queue->suspended) { + core_util_critical_section_exit(); + return; + } /* Go through all the pending TimerEvents */ ticker->queue->dispatching = true; @@ -430,3 +438,29 @@ return ret; } + +void ticker_suspend(const ticker_data_t *const ticker) +{ + core_util_critical_section_enter(); + + ticker->queue->suspended = true; + + core_util_critical_section_exit(); +} + +void ticker_resume(const ticker_data_t *const ticker) +{ + core_util_critical_section_enter(); + + ticker->queue->suspended = false; + if (ticker->queue->initialized) { + ticker->queue->tick_last_read = ticker->interface->read(); + + update_present_time(ticker); + schedule_interrupt(ticker); + } else { + initialize(ticker); + } + + core_util_critical_section_exit(); +}