diff --git a/TESTS/mbed_hal/ticker/main.cpp b/TESTS/mbed_hal/ticker/main.cpp index 1779a6c788..68cc289674 100644 --- a/TESTS/mbed_hal/ticker/main.cpp +++ b/TESTS/mbed_hal/ticker/main.cpp @@ -100,7 +100,7 @@ static ticker_event_queue_t queue_stub = { static void reset_queue_stub() { queue_stub.event_handler = NULL; queue_stub.head = NULL, - queue_stub.timestamp = 0; + queue_stub.present_time = 0; queue_stub.initialized = false; } @@ -174,7 +174,7 @@ static void test_ticker_initialization() { TEST_ASSERT_TRUE(interface_stub.initialized); TEST_ASSERT_EQUAL_PTR(dummy_handler, queue_stub.event_handler); - TEST_ASSERT_EQUAL_UINT64(interface_stub.timestamp, queue_stub.timestamp); + TEST_ASSERT_EQUAL_UINT64(interface_stub.timestamp, queue_stub.present_time); TEST_ASSERT_EQUAL(1, interface_stub.set_interrupt_call); TEST_ASSERT_EQUAL_UINT32( interface_stub.timestamp + TIMESTAMP_MAX_DELTA, @@ -437,7 +437,7 @@ static void test_legacy_insert_event_overflow() { TIMESTAMP_MAX_DELTA + 1; const us_timestamp_t expected_us_timestamp = - (((queue_stub.timestamp >> 32) + 1) << 32) | expected_timestamp; + (((queue_stub.present_time >> 32) + 1) << 32) | expected_timestamp; const uint32_t expected_id = 0xDEADDEAF; ticker_insert_event( @@ -792,12 +792,12 @@ static void test_insert_event_us_outside_overflow_range() { ticker_set_handler(&ticker_stub, NULL); interface_stub.set_interrupt_call = 0; interface_stub.timestamp = 0xAAAAAAAA; - queue_stub.timestamp = 10ULL << 32 | interface_stub.timestamp; + queue_stub.present_time = 10ULL << 32 | interface_stub.timestamp; // test the end of the range ticker_event_t last_event = { 0 }; const us_timestamp_t timestamp_last_event = - queue_stub.timestamp + TIMESTAMP_MAX_DELTA; + queue_stub.present_time + TIMESTAMP_MAX_DELTA; const uint32_t id_last_event = 0xDEADDEAF; ticker_insert_event_us( @@ -816,7 +816,7 @@ static void test_insert_event_us_outside_overflow_range() { // test the beginning of the range ticker_event_t first_event = { 0 }; - const us_timestamp_t timestamp_first_event = queue_stub.timestamp + 1; + const us_timestamp_t timestamp_first_event = queue_stub.present_time + 1; const uint32_t id_first_event = 0xAAAAAAAA; ticker_insert_event_us( @@ -852,7 +852,7 @@ static void test_insert_event_us_in_overflow_range() { ticker_set_handler(&ticker_stub, NULL); interface_stub.set_interrupt_call = 0; interface_stub.timestamp = 0xAAAAAAAA; - queue_stub.timestamp = 10ULL << 32 | interface_stub.timestamp; + queue_stub.present_time = 10ULL << 32 | interface_stub.timestamp; // test the end of the range ticker_event_t last_event = { 0 }; @@ -876,11 +876,11 @@ static void test_insert_event_us_in_overflow_range() { // test the beginning of the range ++interface_stub.timestamp; - ++queue_stub.timestamp; + ++queue_stub.present_time; ticker_event_t first_event = { 0 }; const us_timestamp_t timestamp_first_event = - queue_stub.timestamp + TIMESTAMP_MAX_DELTA + 1; + queue_stub.present_time + TIMESTAMP_MAX_DELTA + 1; uint32_t id_first_event = 0xAAAAAAAA; ticker_insert_event_us(&ticker_stub, @@ -914,11 +914,11 @@ static void test_insert_event_us_underflow() { interface_stub.set_interrupt_call = 0; interface_stub.timestamp = 0xAAAAAAAA; - queue_stub.timestamp = 10ULL << 32 | interface_stub.timestamp; + queue_stub.present_time = 10ULL << 32 | interface_stub.timestamp; // test the end of the range ticker_event_t event = { 0 }; - const timestamp_t expected_timestamp = queue_stub.timestamp - 1; + const timestamp_t expected_timestamp = queue_stub.present_time - 1; const uint32_t expected_id = 0xDEADDEAF; ticker_insert_event_us( @@ -951,16 +951,16 @@ static void test_insert_event_us_head() { ticker_set_handler(&ticker_stub, NULL); interface_stub.set_interrupt_call = 0; interface_stub.timestamp = 0xAAAAAAAA; - queue_stub.timestamp = 10ULL << 32 | interface_stub.timestamp; + queue_stub.present_time = 10ULL << 32 | interface_stub.timestamp; const us_timestamp_t timestamps[] = { UINT64_MAX, - queue_stub.timestamp + TIMESTAMP_MAX_DELTA + 1, - queue_stub.timestamp + TIMESTAMP_MAX_DELTA, - queue_stub.timestamp + (TIMESTAMP_MAX_DELTA / 2), - queue_stub.timestamp + (TIMESTAMP_MAX_DELTA / 4), - queue_stub.timestamp + (TIMESTAMP_MAX_DELTA / 8), - queue_stub.timestamp + (TIMESTAMP_MAX_DELTA / 16), + queue_stub.present_time + TIMESTAMP_MAX_DELTA + 1, + queue_stub.present_time + TIMESTAMP_MAX_DELTA, + queue_stub.present_time + (TIMESTAMP_MAX_DELTA / 2), + queue_stub.present_time + (TIMESTAMP_MAX_DELTA / 4), + queue_stub.present_time + (TIMESTAMP_MAX_DELTA / 8), + queue_stub.present_time + (TIMESTAMP_MAX_DELTA / 16), }; ticker_event_t events[MBED_ARRAY_SIZE(timestamps)] = { 0 }; @@ -971,14 +971,14 @@ static void test_insert_event_us_head() { ); TEST_ASSERT_EQUAL_PTR(&events[i], queue_stub.head); - if ((timestamps[i] - queue_stub.timestamp) < TIMESTAMP_MAX_DELTA) { + if ((timestamps[i] - queue_stub.present_time) < TIMESTAMP_MAX_DELTA) { TEST_ASSERT_EQUAL_UINT32( timestamps[i], interface_stub.interrupt_timestamp ); } else { TEST_ASSERT_EQUAL_UINT32( - queue_stub.timestamp + TIMESTAMP_MAX_DELTA, + queue_stub.present_time + TIMESTAMP_MAX_DELTA, interface_stub.interrupt_timestamp ); } @@ -1464,7 +1464,7 @@ static void test_overflow_event_update() { interface_stub.set_interrupt_call = 0; for (size_t i = 0; i < 8; ++i) { - us_timestamp_t previous_timestamp = queue_stub.timestamp; + us_timestamp_t previous_timestamp = queue_stub.present_time; timestamp_t interface_timestamp = previous_timestamp + (TIMESTAMP_MAX_DELTA + i * 100); interface_stub.timestamp = interface_timestamp; @@ -1505,7 +1505,7 @@ static void test_overflow_event_update_when_spurious_interrupt() { interface_stub.set_interrupt_call = 0; for (size_t i = 0; i < 8; ++i) { - us_timestamp_t previous_timestamp = queue_stub.timestamp; + us_timestamp_t previous_timestamp = queue_stub.present_time; timestamp_t interface_timestamp = previous_timestamp + (TIMESTAMP_MAX_DELTA / (2 + i)); interface_stub.timestamp = interface_timestamp; diff --git a/hal/mbed_ticker_api.c b/hal/mbed_ticker_api.c index df2f249b80..448df82e79 100644 --- a/hal/mbed_ticker_api.c +++ b/hal/mbed_ticker_api.c @@ -18,10 +18,8 @@ #include "hal/ticker_api.h" #include "platform/mbed_critical.h" -#define MBED_MIN(x,y) (((x)<(y))?(x):(y)) - -static void update_interrupt(const ticker_data_t *const ticker); -static void update_current_timestamp(const ticker_data_t *const ticker); +static void schedule_interrupt(const ticker_data_t *const ticker); +static void update_present_time(const ticker_data_t *const ticker); /* * Initialize a ticker instance. @@ -38,11 +36,11 @@ static void initialize(const ticker_data_t *ticker) ticker->queue->event_handler = NULL; ticker->queue->head = NULL; - ticker->queue->timestamp = 0; + ticker->queue->present_time = 0; ticker->queue->initialized = true; - update_current_timestamp(ticker); - update_interrupt(ticker); + update_present_time(ticker); + schedule_interrupt(ticker); } /** @@ -54,22 +52,29 @@ static void set_handler(const ticker_data_t *const ticker, ticker_event_handler } /* - * Convert a low res timestamp to a high res timestamp. An high resolution - * timestamp is used as the reference point to convert the low res timestamp - * into an high res one. + * Convert a 32 bit timestamp into a 64 bit timestamp. + * + * A 64 bit timestamp is used as the point of time of reference while the + * timestamp to convert is relative to this point of time. + * + * The lower 32 bits of the timestamp returned will be equal to the timestamp to + * convert. * - * It is important to note that the result will **never** be in the past. If the - * value of the low res timetamp is less than the low res part of the reference - * timestamp then an overflow is - * - * @param ref: The timestamp of reference. - * @param relative_timestamp: The timestamp to convert. + * If the timestamp to convert is less than the lower 32 bits of the time + * reference then the timestamp to convert is seen as an overflowed value and + * the upper 32 bit of the timestamp returned will be equal to the upper 32 bit + * of the reference point + 1. + * Otherwise, the upper 32 bit returned will be equal to the upper 32 bit of the + * reference point. + * + * @param ref: The 64 bit timestamp of reference. + * @param timestamp: The timestamp to convert. */ -static us_timestamp_t convert_relative_timestamp(us_timestamp_t ref, timestamp_t relative_timestamp) +static us_timestamp_t convert_timestamp(us_timestamp_t ref, timestamp_t timestamp) { - bool overflow = relative_timestamp < ((timestamp_t) ref) ? true : false; + bool overflow = timestamp < ((timestamp_t) ref) ? true : false; - us_timestamp_t result = (ref & ~((us_timestamp_t)UINT32_MAX)) | relative_timestamp; + us_timestamp_t result = (ref & ~((us_timestamp_t)UINT32_MAX)) | timestamp; if (overflow) { result += (1ULL<<32); } @@ -78,38 +83,42 @@ static us_timestamp_t convert_relative_timestamp(us_timestamp_t ref, timestamp_t } /** - * update the current timestamp value of a ticker. + * Update the present timestamp value of a ticker. */ -static void update_current_timestamp(const ticker_data_t *const ticker) +static void update_present_time(const ticker_data_t *const ticker) { - ticker->queue->timestamp = convert_relative_timestamp( - ticker->queue->timestamp, + ticker->queue->present_time = convert_timestamp( + ticker->queue->present_time, ticker->interface->read() ); } /** - * update the interrupt with the appropriate timestamp. - * if there is no interrupt scheduled or the next event to execute is in more - * than MBED_TICKER_INTERRUPT_TIMESTAMP_MAX_DELTA us from now then the - * interrupt will be set to MBED_TICKER_INTERRUPT_TIMESTAMP_MAX_DELTA us from now. - * Otherwise the interrupt will be set to head->timestamp - queue->timestamp us. + * Compute the time when the interrupt has to be triggered and schedule it. + * + * If there is no event in the queue or the next event to execute is in more + * than MBED_TICKER_INTERRUPT_TIMESTAMP_MAX_DELTA us from now then the ticker + * irq will be scheduled in MBED_TICKER_INTERRUPT_TIMESTAMP_MAX_DELTA us. + * Otherwise the irq will be scheduled to happen when the running counter reach + * the timestamp of the first event in the queue. + * + * @note If there is no event in the queue then the interrupt is scheduled to + * in MBED_TICKER_INTERRUPT_TIMESTAMP_MAX_DELTA. This is necessary to keep track + * of the timer overflow. */ -static void update_interrupt(const ticker_data_t *const ticker) +static void schedule_interrupt(const ticker_data_t *const ticker) { - update_current_timestamp(ticker); - uint32_t diff = MBED_TICKER_INTERRUPT_TIMESTAMP_MAX_DELTA; + update_present_time(ticker); + uint32_t duration = MBED_TICKER_INTERRUPT_TIMESTAMP_MAX_DELTA; - if (ticker->queue->head) { - diff = MBED_MIN( - (ticker->queue->head->timestamp - ticker->queue->timestamp), - MBED_TICKER_INTERRUPT_TIMESTAMP_MAX_DELTA - ); + if (ticker->queue->head) { + us_timestamp_t event_interval = (ticker->queue->head->timestamp - ticker->queue->present_time); + if (event_interval < MBED_TICKER_INTERRUPT_TIMESTAMP_MAX_DELTA) { + duration = event_interval; + } } - ticker->interface->set_interrupt( - ticker->queue->timestamp + diff - ); + ticker->interface->set_interrupt(ticker->queue->present_time + duration); } void ticker_set_handler(const ticker_data_t *const ticker, ticker_event_handler handler) @@ -129,9 +138,9 @@ void ticker_irq_handler(const ticker_data_t *const ticker) } // update the current timestamp used by the queue - update_current_timestamp(ticker); + update_present_time(ticker); - if (ticker->queue->head->timestamp <= ticker->queue->timestamp) { + if (ticker->queue->head->timestamp <= ticker->queue->present_time) { // This event was in the past: // point to the following one and execute its handler ticker_event_t *p = ticker->queue->head; @@ -146,18 +155,17 @@ void ticker_irq_handler(const ticker_data_t *const ticker) } } - update_interrupt(ticker); + schedule_interrupt(ticker); } void ticker_insert_event(const ticker_data_t *const ticker, ticker_event_t *obj, timestamp_t timestamp, uint32_t id) { - /* disable interrupts for the duration of the function */ core_util_critical_section_enter(); // update the current timestamp - update_current_timestamp(ticker); - us_timestamp_t absolute_timestamp = convert_relative_timestamp( - ticker->queue->timestamp, + update_present_time(ticker); + us_timestamp_t absolute_timestamp = convert_timestamp( + ticker->queue->present_time, timestamp ); core_util_critical_section_exit(); @@ -171,15 +179,14 @@ void ticker_insert_event(const ticker_data_t *const ticker, ticker_event_t *obj, void ticker_insert_event_us(const ticker_data_t *const ticker, ticker_event_t *obj, us_timestamp_t timestamp, uint32_t id) { - /* disable interrupts for the duration of the function */ core_util_critical_section_enter(); // update the current timestamp - update_current_timestamp(ticker); + update_present_time(ticker); // filter out timestamp in the past - if (timestamp < ticker->queue->timestamp) { - update_interrupt(ticker); + if (timestamp < ticker->queue->present_time) { + schedule_interrupt(ticker); return; } @@ -211,7 +218,7 @@ void ticker_insert_event_us(const ticker_data_t *const ticker, ticker_event_t *o prev->next = obj; } - update_interrupt(ticker); + schedule_interrupt(ticker); core_util_critical_section_exit(); } @@ -224,7 +231,7 @@ void ticker_remove_event(const ticker_data_t *const ticker, ticker_event_t *obj) if (ticker->queue->head == obj) { // first in the list, so just drop me ticker->queue->head = obj->next; - update_interrupt(ticker); + schedule_interrupt(ticker); } else { // find the object before me, then drop me ticker_event_t* p = ticker->queue->head; @@ -247,8 +254,8 @@ timestamp_t ticker_read(const ticker_data_t *const ticker) us_timestamp_t ticker_read_us(const ticker_data_t *const ticker) { - update_current_timestamp(ticker); - return ticker->queue->timestamp; + update_present_time(ticker); + return ticker->queue->present_time; } int ticker_get_next_timestamp(const ticker_data_t *const data, timestamp_t *timestamp) diff --git a/hal/ticker_api.h b/hal/ticker_api.h index 2e65c70350..856c613710 100644 --- a/hal/ticker_api.h +++ b/hal/ticker_api.h @@ -67,7 +67,7 @@ typedef struct { typedef struct { ticker_event_handler event_handler; /**< Event handler */ ticker_event_t *head; /**< A pointer to head */ - us_timestamp_t timestamp; /**< Store the last timestamp used */ + us_timestamp_t present_time; /**< Store the timestamp used for present time */ bool initialized; /**< Indicate if the instance is initialized */ } ticker_event_queue_t; @@ -89,20 +89,20 @@ extern "C" { /** Initialize a ticker and set the event handler * - * @param data The ticker's data + * @param ticker The ticker object. * @param handler A handler to be set */ void ticker_set_handler(const ticker_data_t *const ticker, ticker_event_handler handler); /** IRQ handler that goes through the events to trigger overdue events. * - * @param data The ticker's data + * @param ticker The ticker object. */ void ticker_irq_handler(const ticker_data_t *const ticker); /** Remove an event from the queue * - * @param data The ticker's data + * @param ticker The ticker object. * @param obj The event object to be removed from the queue */ void ticker_remove_event(const ticker_data_t *const ticker, ticker_event_t *obj); @@ -120,7 +120,7 @@ void ticker_remove_event(const ticker_data_t *const ticker, ticker_event_t *obj) * @note prefer the use of ticker_insert_event_us which allows registration of * absolute timestamp. * - * @param data The ticker's data + * @param ticker The ticker object. * @param obj The event object to be inserted to the queue * @param timestamp The event's timestamp * @param id The event object @@ -134,7 +134,7 @@ void ticker_insert_event(const ticker_data_t *const ticker, ticker_event_t *obj, * @warning If an event is inserted with a timestamp less than the current * timestamp then the event will **not** be inserted. * - * @param data The ticker's data + * @param ticker The ticker object. * @param obj The event object to be inserted to the queue * @param timestamp The event's timestamp * @param id The event object @@ -146,7 +146,7 @@ void ticker_insert_event_us(const ticker_data_t *const ticker, ticker_event_t *o * @warning Return a relative timestamp because the counter wrap every 4294 * seconds. * - * @param data The ticker's data + * @param ticker The ticker object. * @return The current timestamp */ timestamp_t ticker_read(const ticker_data_t *const ticker); @@ -156,14 +156,14 @@ timestamp_t ticker_read(const ticker_data_t *const ticker); * @warning Return an absolute timestamp counting from the initialization of the * ticker. * - * @param data The ticker's data + * @param ticker The ticker object. * @return The current timestamp */ us_timestamp_t ticker_read_us(const ticker_data_t *const ticker); /** Read the next event's timestamp * - * @param data The ticker's data + * @param ticker The ticker object. * @return 1 if timestamp is pending event, 0 if there's no event pending */ int ticker_get_next_timestamp(const ticker_data_t *const ticker, timestamp_t *timestamp);