From 3923dffffc04187dbd3f834d44befcfaf19f1b5d Mon Sep 17 00:00:00 2001 From: James Devine Date: Mon, 25 Apr 2016 11:30:28 +0100 Subject: [PATCH] microbit-dal: increase granularity of the system wide timer Added an mbed Timer instance to maintain a microsecond level timestamp. Added a function system_timer_current_time_us() which now returns the time since power on in microseconds. MicroBitEvents now call system_timer_current_time_us() giving microsecond level timestamps. --- inc/core/MicroBitSystemTimer.h | 19 +++++++++- inc/types/MicroBitEvent.h | 2 +- source/core/MicroBitSystemTimer.cpp | 57 +++++++++++++++++++++++------ source/types/MicroBitEvent.cpp | 4 +- 4 files changed, 66 insertions(+), 16 deletions(-) diff --git a/inc/core/MicroBitSystemTimer.h b/inc/core/MicroBitSystemTimer.h index 5815f36..718db19 100644 --- a/inc/core/MicroBitSystemTimer.h +++ b/inc/core/MicroBitSystemTimer.h @@ -43,7 +43,7 @@ DEALINGS IN THE SOFTWARE. #include "MicroBitComponent.h" /** - * Initialises the system wide timer. + * Initialises a system wide timer, used to drive the various components used in the runtime. * * This must be called before any components register to receive periodic periodic callbacks. * @@ -69,12 +69,27 @@ int system_timer_set_period(int period); */ int system_timer_get_period(); +/** + * Updates the current time in microseconds, since power on. + * + * If the mbed Timer hasn't been initialised, it will be initialised + * on the first call to this function. + */ +inline void update_time(); + /** * Determines the time since the device was powered on. * * @return the current time since power on in milliseconds */ -unsigned long system_timer_current_time(); +uint64_t system_timer_current_time(); + +/** + * Determines the time since the device was powered on. + * + * @return the current time since power on in microseconds + */ +uint64_t system_timer_current_time_us(); /** * Timer callback. Called from interrupt context, once per period. diff --git a/inc/types/MicroBitEvent.h b/inc/types/MicroBitEvent.h index 65420fd..c226420 100644 --- a/inc/types/MicroBitEvent.h +++ b/inc/types/MicroBitEvent.h @@ -52,7 +52,7 @@ class MicroBitEvent uint16_t source; // ID of the MicroBit Component that generated the event e.g. MICROBIT_ID_BUTTON_A. uint16_t value; // Component specific code indicating the cause of the event. - uint32_t timestamp; // Time at which the event was generated. ms since power on. + uint64_t timestamp; // Time at which the event was generated. us since power on. /** * Constructor. diff --git a/source/core/MicroBitSystemTimer.cpp b/source/core/MicroBitSystemTimer.cpp index ec8073a..f745c78 100644 --- a/source/core/MicroBitSystemTimer.cpp +++ b/source/core/MicroBitSystemTimer.cpp @@ -42,18 +42,21 @@ DEALINGS IN THE SOFTWARE. * Time since power on. Measured in milliseconds. * When stored as an unsigned long, this gives us approx 50 days between rollover, which is ample. :-) */ -static unsigned long ticks = 0; +static uint64_t time_us = 0; static unsigned int tick_period = 0; // Array of components which are iterated during a system tick static MicroBitComponent* systemTickComponents[MICROBIT_SYSTEM_COMPONENTS]; // Periodic callback interrupt -static Ticker *timer = NULL; +static Ticker *ticker = NULL; + +// System timer. +static Timer *timer = NULL; /** - * Initialises the system wide timer. + * Initialises a system wide timer, used to drive the various components used in the runtime. * * This must be called before any components register to receive periodic periodic callbacks. * @@ -63,8 +66,14 @@ static Ticker *timer = NULL; */ int system_timer_init(int period) { + if (ticker == NULL) + ticker = new Ticker(); + if (timer == NULL) - timer = new Ticker(); + { + timer = new Timer(); + timer->start(); + } return system_timer_set_period(period); } @@ -83,11 +92,11 @@ int system_timer_set_period(int period) // If a timer is already running, ensure it is disabled before reconfiguring. if (tick_period) - timer->detach(); + ticker->detach(); // register a period callback to drive the scheduler and any other registered components. tick_period = period; - timer->attach_us(system_timer_tick, period * 1000); + ticker->attach_us(system_timer_tick, period * 1000); return MICROBIT_OK; } @@ -102,14 +111,41 @@ int system_timer_get_period() return tick_period; } +/** + * Updates the current time in microseconds, since power on. + * + * If the mbed Timer hasn't been initialised, it will be initialised + * on the first call to this function. + */ +void update_time() +{ + // If we haven't been initialized, bring up the timer with the default period. + if (timer == NULL || ticker == NULL) + system_timer_init(SYSTEM_TICK_PERIOD_MS); + + time_us += timer->read_us(); + timer->reset(); +} + /** * Determines the time since the device was powered on. * * @return the current time since power on in milliseconds */ -unsigned long system_timer_current_time() +uint64_t system_timer_current_time() { - return ticks; + return system_timer_current_time_us() / 1000; +} + +/** + * Determines the time since the device was powered on. + * + * @return the current time since power on in microseconds + */ +uint64_t system_timer_current_time_us() +{ + update_time(); + return time_us; } /** @@ -120,8 +156,7 @@ unsigned long system_timer_current_time() */ void system_timer_tick() { - // increment our real-time counter. - ticks += system_timer_get_period(); + update_time(); // Update any components registered for a callback for(int i = 0; i < MICROBIT_SYSTEM_COMPONENTS; i++) @@ -144,7 +179,7 @@ int system_timer_add_component(MicroBitComponent *component) int i = 0; // If we haven't been initialized, bring up the timer with the default period. - if (timer == NULL) + if (timer == NULL || ticker == NULL) system_timer_init(SYSTEM_TICK_PERIOD_MS); while(systemTickComponents[i] != NULL && i < MICROBIT_SYSTEM_COMPONENTS) diff --git a/source/types/MicroBitEvent.cpp b/source/types/MicroBitEvent.cpp index 3b3442a..e8eaccb 100644 --- a/source/types/MicroBitEvent.cpp +++ b/source/types/MicroBitEvent.cpp @@ -58,7 +58,7 @@ MicroBitEvent::MicroBitEvent(uint16_t source, uint16_t value, MicroBitEventLaunc { this->source = source; this->value = value; - this->timestamp = system_timer_current_time(); + this->timestamp = system_timer_current_time_us(); if(mode != CREATE_ONLY) this->fire(); @@ -71,7 +71,7 @@ MicroBitEvent::MicroBitEvent() { this->source = 0; this->value = 0; - this->timestamp = system_timer_current_time(); + this->timestamp = system_timer_current_time_us(); } /**