2525
2626#include " hal/lp_ticker_api.h"
2727#include " mbed_critical.h"
28+ #include " mbed_assert.h"
2829#if defined(TARGET_CORTEX_A)
2930#include " rtx_core_ca.h"
3031#else // Cortex-M
@@ -37,6 +38,9 @@ extern "C" {
3738#endif
3839}
3940
41+ #define US_IN_TICK (1000000 / OS_TICK_FREQ)
42+ MBED_STATIC_ASSERT (1000000 % OS_TICK_FREQ == 0 , " OS_TICK_FREQ must be a divisor of 1000000 for correct tick calculations" );
43+
4044#if (defined(NO_SYSTICK))
4145/* *
4246 * Return an IRQ number that can be used in the absence of SysTick
@@ -54,17 +58,17 @@ namespace rtos {
5458namespace internal {
5559
5660SysTimer::SysTimer () :
57- TimerEvent (get_lp_ticker_data()), _start_time (0 ), _tick(0 )
61+ TimerEvent (get_lp_ticker_data()), _time_us (0 ), _tick(0 )
5862{
59- _start_time = ticker_read_us (_ticker_data);
63+ _time_us = ticker_read_us (_ticker_data);
6064 _suspend_time_passed = true ;
6165 _suspended = false ;
6266}
6367
6468SysTimer::SysTimer (const ticker_data_t *data) :
65- TimerEvent (data), _start_time (0 ), _tick(0 )
69+ TimerEvent (data), _time_us (0 ), _tick(0 )
6670{
67- _start_time = ticker_read_us (_ticker_data);
71+ _time_us = ticker_read_us (_ticker_data);
6872}
6973
7074void SysTimer::setup_irq ()
@@ -83,14 +87,13 @@ void SysTimer::setup_irq()
8387
8488void SysTimer::suspend (uint32_t ticks)
8589{
86- core_util_critical_section_enter ();
87-
90+ // Remove ensures serialized access to SysTimer by stopping timer interrupt
8891 remove ();
89- schedule_tick (ticks);
92+
9093 _suspend_time_passed = false ;
9194 _suspended = true ;
9295
93- core_util_critical_section_exit ( );
96+ schedule_tick (ticks );
9497}
9598
9699bool SysTimer::suspend_time_passed ()
@@ -100,43 +103,40 @@ bool SysTimer::suspend_time_passed()
100103
101104uint32_t SysTimer::resume ()
102105{
103- core_util_critical_section_enter ();
106+ // Remove ensures serialized access to SysTimer by stopping timer interrupt
107+ remove ();
104108
105109 _suspended = false ;
106110 _suspend_time_passed = true ;
107- remove ();
108111
109- uint64_t new_tick = (ticker_read_us (_ticker_data) - _start_time) * OS_TICK_FREQ / 1000000 ;
110- if (new_tick > _tick ) {
112+ uint64_t elapsed_ticks = (ticker_read_us (_ticker_data) - _time_us) / US_IN_TICK ;
113+ if (elapsed_ticks > 0 ) {
111114 // Don't update to the current tick. Instead, update to the
112115 // previous tick and let the SysTick handler increment it
113116 // to the current value. This allows scheduling restart
114117 // successfully after the OS is resumed.
115- new_tick --;
118+ elapsed_ticks --;
116119 }
117- uint32_t elapsed_ticks = new_tick - _tick ;
118- _tick = new_tick ;
120+ _time_us += elapsed_ticks * US_IN_TICK ;
121+ _tick += elapsed_ticks ;
119122
120- core_util_critical_section_exit ();
121123 return elapsed_ticks;
122124}
123125
124126void SysTimer::schedule_tick (uint32_t delta)
125127{
126128 core_util_critical_section_enter ();
127129
128- insert_absolute (_start_time + (_tick + delta) * 1000000ULL / OS_TICK_FREQ );
130+ insert_absolute (_time_us + delta * US_IN_TICK );
129131
130132 core_util_critical_section_exit ();
131133}
132134
133135void SysTimer::cancel_tick ()
134136{
135- core_util_critical_section_enter ();
137+ // Underlying call is interrupt safe
136138
137139 remove ();
138-
139- core_util_critical_section_exit ();
140140}
141141
142142uint32_t SysTimer::get_tick ()
@@ -146,6 +146,8 @@ uint32_t SysTimer::get_tick()
146146
147147us_timestamp_t SysTimer::get_time ()
148148{
149+ // Underlying call is interrupt safe
150+
149151 return ticker_read_us (_ticker_data);
150152}
151153
@@ -171,6 +173,7 @@ void SysTimer::_increment_tick()
171173 // Protected function synchronized externally
172174
173175 _tick++;
176+ _time_us += US_IN_TICK;
174177}
175178
176179void SysTimer::handler ()
0 commit comments