Merge pull request #9786 from c1728p9/tickless_optimization

Optimize tickless tick computation
pull/9856/head
Cruz Monrreal 2019-02-26 23:22:04 -06:00 committed by GitHub
commit 3352b431b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 24 additions and 21 deletions

View File

@ -25,6 +25,7 @@
#include "hal/lp_ticker_api.h" #include "hal/lp_ticker_api.h"
#include "mbed_critical.h" #include "mbed_critical.h"
#include "mbed_assert.h"
#if defined(TARGET_CORTEX_A) #if defined(TARGET_CORTEX_A)
#include "rtx_core_ca.h" #include "rtx_core_ca.h"
#else//Cortex-M #else//Cortex-M
@ -37,6 +38,9 @@ extern "C" {
#endif #endif
} }
#define US_IN_TICK (1000000 / OS_TICK_FREQ)
MBED_STATIC_ASSERT(1000000 % OS_TICK_FREQ == 0, "OS_TICK_FREQ must be a divisor of 1000000 for correct tick calculations");
#if (defined(NO_SYSTICK)) #if (defined(NO_SYSTICK))
/** /**
* Return an IRQ number that can be used in the absence of SysTick * Return an IRQ number that can be used in the absence of SysTick
@ -54,17 +58,17 @@ namespace rtos {
namespace internal { namespace internal {
SysTimer::SysTimer() : SysTimer::SysTimer() :
TimerEvent(get_lp_ticker_data()), _start_time(0), _tick(0) TimerEvent(get_lp_ticker_data()), _time_us(0), _tick(0)
{ {
_start_time = ticker_read_us(_ticker_data); _time_us = ticker_read_us(_ticker_data);
_suspend_time_passed = true; _suspend_time_passed = true;
_suspended = false; _suspended = false;
} }
SysTimer::SysTimer(const ticker_data_t *data) : SysTimer::SysTimer(const ticker_data_t *data) :
TimerEvent(data), _start_time(0), _tick(0) TimerEvent(data), _time_us(0), _tick(0)
{ {
_start_time = ticker_read_us(_ticker_data); _time_us = ticker_read_us(_ticker_data);
} }
void SysTimer::setup_irq() void SysTimer::setup_irq()
@ -83,14 +87,13 @@ void SysTimer::setup_irq()
void SysTimer::suspend(uint32_t ticks) void SysTimer::suspend(uint32_t ticks)
{ {
core_util_critical_section_enter(); // Remove ensures serialized access to SysTimer by stopping timer interrupt
remove(); remove();
schedule_tick(ticks);
_suspend_time_passed = false; _suspend_time_passed = false;
_suspended = true; _suspended = true;
core_util_critical_section_exit(); schedule_tick(ticks);
} }
bool SysTimer::suspend_time_passed() bool SysTimer::suspend_time_passed()
@ -100,24 +103,23 @@ bool SysTimer::suspend_time_passed()
uint32_t SysTimer::resume() uint32_t SysTimer::resume()
{ {
core_util_critical_section_enter(); // Remove ensures serialized access to SysTimer by stopping timer interrupt
remove();
_suspended = false; _suspended = false;
_suspend_time_passed = true; _suspend_time_passed = true;
remove();
uint64_t new_tick = (ticker_read_us(_ticker_data) - _start_time) * OS_TICK_FREQ / 1000000; uint64_t elapsed_ticks = (ticker_read_us(_ticker_data) - _time_us) / US_IN_TICK;
if (new_tick > _tick) { if (elapsed_ticks > 0) {
// Don't update to the current tick. Instead, update to the // Don't update to the current tick. Instead, update to the
// previous tick and let the SysTick handler increment it // previous tick and let the SysTick handler increment it
// to the current value. This allows scheduling restart // to the current value. This allows scheduling restart
// successfully after the OS is resumed. // successfully after the OS is resumed.
new_tick--; elapsed_ticks--;
} }
uint32_t elapsed_ticks = new_tick - _tick; _time_us += elapsed_ticks * US_IN_TICK;
_tick = new_tick; _tick += elapsed_ticks;
core_util_critical_section_exit();
return elapsed_ticks; return elapsed_ticks;
} }
@ -125,18 +127,16 @@ void SysTimer::schedule_tick(uint32_t delta)
{ {
core_util_critical_section_enter(); core_util_critical_section_enter();
insert_absolute(_start_time + (_tick + delta) * 1000000ULL / OS_TICK_FREQ); insert_absolute(_time_us + delta * US_IN_TICK);
core_util_critical_section_exit(); core_util_critical_section_exit();
} }
void SysTimer::cancel_tick() void SysTimer::cancel_tick()
{ {
core_util_critical_section_enter(); // Underlying call is interrupt safe
remove(); remove();
core_util_critical_section_exit();
} }
uint32_t SysTimer::get_tick() uint32_t SysTimer::get_tick()
@ -146,6 +146,8 @@ uint32_t SysTimer::get_tick()
us_timestamp_t SysTimer::get_time() us_timestamp_t SysTimer::get_time()
{ {
// Underlying call is interrupt safe
return ticker_read_us(_ticker_data); return ticker_read_us(_ticker_data);
} }
@ -171,6 +173,7 @@ void SysTimer::_increment_tick()
// Protected function synchronized externally // Protected function synchronized externally
_tick++; _tick++;
_time_us += US_IN_TICK;
} }
void SysTimer::handler() void SysTimer::handler()

View File

@ -117,7 +117,7 @@ protected:
virtual void handler(); virtual void handler();
void _increment_tick(); void _increment_tick();
static void _set_irq_pending(); static void _set_irq_pending();
us_timestamp_t _start_time; us_timestamp_t _time_us;
uint64_t _tick; uint64_t _tick;
bool _suspend_time_passed; bool _suspend_time_passed;
bool _suspended; bool _suspended;