25
25
26
26
#include " hal/lp_ticker_api.h"
27
27
#include " mbed_critical.h"
28
+ #include " mbed_assert.h"
28
29
#if defined(TARGET_CORTEX_A)
29
30
#include " rtx_core_ca.h"
30
31
#else // Cortex-M
@@ -37,6 +38,9 @@ extern "C" {
37
38
#endif
38
39
}
39
40
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
+
40
44
#if (defined(NO_SYSTICK))
41
45
/* *
42
46
* Return an IRQ number that can be used in the absence of SysTick
@@ -54,17 +58,17 @@ namespace rtos {
54
58
namespace internal {
55
59
56
60
SysTimer::SysTimer () :
57
- TimerEvent (get_lp_ticker_data()), _start_time (0 ), _tick(0 )
61
+ TimerEvent (get_lp_ticker_data()), _time_us (0 ), _tick(0 )
58
62
{
59
- _start_time = ticker_read_us (_ticker_data);
63
+ _time_us = ticker_read_us (_ticker_data);
60
64
_suspend_time_passed = true ;
61
65
_suspended = false ;
62
66
}
63
67
64
68
SysTimer::SysTimer (const ticker_data_t *data) :
65
- TimerEvent (data), _start_time (0 ), _tick(0 )
69
+ TimerEvent (data), _time_us (0 ), _tick(0 )
66
70
{
67
- _start_time = ticker_read_us (_ticker_data);
71
+ _time_us = ticker_read_us (_ticker_data);
68
72
}
69
73
70
74
void SysTimer::setup_irq ()
@@ -83,14 +87,13 @@ void SysTimer::setup_irq()
83
87
84
88
void SysTimer::suspend (uint32_t ticks)
85
89
{
86
- core_util_critical_section_enter ();
87
-
90
+ // Remove ensures serialized access to SysTimer by stopping timer interrupt
88
91
remove ();
89
- schedule_tick (ticks);
92
+
90
93
_suspend_time_passed = false ;
91
94
_suspended = true ;
92
95
93
- core_util_critical_section_exit ( );
96
+ schedule_tick (ticks );
94
97
}
95
98
96
99
bool SysTimer::suspend_time_passed ()
@@ -100,43 +103,40 @@ bool SysTimer::suspend_time_passed()
100
103
101
104
uint32_t SysTimer::resume ()
102
105
{
103
- core_util_critical_section_enter ();
106
+ // Remove ensures serialized access to SysTimer by stopping timer interrupt
107
+ remove ();
104
108
105
109
_suspended = false ;
106
110
_suspend_time_passed = true ;
107
- remove ();
108
111
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 ) {
111
114
// Don't update to the current tick. Instead, update to the
112
115
// previous tick and let the SysTick handler increment it
113
116
// to the current value. This allows scheduling restart
114
117
// successfully after the OS is resumed.
115
- new_tick --;
118
+ elapsed_ticks --;
116
119
}
117
- uint32_t elapsed_ticks = new_tick - _tick ;
118
- _tick = new_tick ;
120
+ _time_us += elapsed_ticks * US_IN_TICK ;
121
+ _tick += elapsed_ticks ;
119
122
120
- core_util_critical_section_exit ();
121
123
return elapsed_ticks;
122
124
}
123
125
124
126
void SysTimer::schedule_tick (uint32_t delta)
125
127
{
126
128
core_util_critical_section_enter ();
127
129
128
- insert_absolute (_start_time + (_tick + delta) * 1000000ULL / OS_TICK_FREQ );
130
+ insert_absolute (_time_us + delta * US_IN_TICK );
129
131
130
132
core_util_critical_section_exit ();
131
133
}
132
134
133
135
void SysTimer::cancel_tick ()
134
136
{
135
- core_util_critical_section_enter ();
137
+ // Underlying call is interrupt safe
136
138
137
139
remove ();
138
-
139
- core_util_critical_section_exit ();
140
140
}
141
141
142
142
uint32_t SysTimer::get_tick ()
@@ -146,6 +146,8 @@ uint32_t SysTimer::get_tick()
146
146
147
147
us_timestamp_t SysTimer::get_time ()
148
148
{
149
+ // Underlying call is interrupt safe
150
+
149
151
return ticker_read_us (_ticker_data);
150
152
}
151
153
@@ -171,6 +173,7 @@ void SysTimer::_increment_tick()
171
173
// Protected function synchronized externally
172
174
173
175
_tick++;
176
+ _time_us += US_IN_TICK;
174
177
}
175
178
176
179
void SysTimer::handler ()
0 commit comments