Skip to content

Commit 675528b

Browse files
authored
Merge pull request #6534 from c1728p9/rtos_suspend
Update idle loop to reduce calls to suspend
2 parents ef35abb + ec59cbb commit 675528b

File tree

4 files changed

+200
-53
lines changed

4 files changed

+200
-53
lines changed

TESTS/mbedmicro-rtos-mbed/systimer/main.cpp

Lines changed: 84 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "greentea-client/test_env.h"
2626
#include "unity.h"
2727
#include "utest.h"
28+
#include "ticker_api.h"
2829

2930
extern "C" {
3031
#include "rtx_lib.h"
@@ -44,7 +45,9 @@ class SysTimerTest: public rtos::internal::SysTimer {
4445
Semaphore _sem;
4546
virtual void handler()
4647
{
47-
increment_tick();
48+
core_util_critical_section_enter();
49+
_increment_tick();
50+
core_util_critical_section_exit();
4851
_sem.release();
4952
}
5053

@@ -54,6 +57,11 @@ class SysTimerTest: public rtos::internal::SysTimer {
5457
{
5558
}
5659

60+
SysTimerTest(const ticker_data_t *data) :
61+
SysTimer(data), _sem(0, 1)
62+
{
63+
}
64+
5765
virtual ~SysTimerTest()
5866
{
5967
}
@@ -64,6 +72,65 @@ class SysTimerTest: public rtos::internal::SysTimer {
6472
}
6573
};
6674

75+
timestamp_t mock_ticker_timestamp;
76+
77+
void mock_ticker_init()
78+
{
79+
}
80+
81+
uint32_t mock_ticker_read()
82+
{
83+
return mock_ticker_timestamp;
84+
}
85+
86+
void mock_ticker_disable_interrupt()
87+
{
88+
}
89+
90+
void mock_ticker_clear_interrupt()
91+
{
92+
}
93+
94+
void mock_ticker_set_interrupt(timestamp_t timestamp)
95+
{
96+
}
97+
98+
void mock_ticker_fire_interrupt()
99+
{
100+
}
101+
102+
const ticker_info_t *mock_ticker_get_info()
103+
{
104+
static const ticker_info_t mock_ticker_info = {
105+
.frequency = 1000000,
106+
.bits = 32
107+
};
108+
return &mock_ticker_info;
109+
}
110+
111+
ticker_interface_t mock_ticker_interface = {
112+
.init = mock_ticker_init,
113+
.read = mock_ticker_read,
114+
.disable_interrupt = mock_ticker_disable_interrupt,
115+
.clear_interrupt = mock_ticker_clear_interrupt,
116+
.set_interrupt = mock_ticker_set_interrupt,
117+
.fire_interrupt = mock_ticker_fire_interrupt,
118+
.get_info = mock_ticker_get_info,
119+
};
120+
121+
ticker_event_queue_t mock_ticker_event_queue;
122+
123+
const ticker_data_t mock_ticker_data = {
124+
.interface = &mock_ticker_interface,
125+
.queue = &mock_ticker_event_queue
126+
};
127+
128+
void mock_ticker_reset()
129+
{
130+
mock_ticker_timestamp = 0;
131+
memset(&mock_ticker_event_queue, 0, sizeof mock_ticker_event_queue);
132+
}
133+
67134
/** Test tick count is zero upon creation
68135
*
69136
* Given a SysTimer
@@ -79,26 +146,29 @@ void test_created_with_zero_tick_count(void)
79146
/** Test tick count is updated correctly
80147
*
81148
* Given a SysTimer
82-
* When @a update_tick method is called immediately after creation
149+
* When the @a suspend and @a resume methods are called immediately after creation
83150
* Then the tick count is not updated
84-
* When @a update_tick is called again after a delay
151+
* When @a suspend and @a resume methods are called again after a delay
85152
* Then the tick count is updated
86153
* and the number of ticks incremented is equal TEST_TICKS - 1
87-
* When @a update_tick is called again without a delay
154+
* When @a suspend and @a resume methods are called again without a delay
88155
* Then the tick count is not updated
89156
*/
90157
void test_update_tick(void)
91158
{
92-
SysTimerTest st;
93-
TEST_ASSERT_EQUAL_UINT32(0, st.update_tick());
159+
mock_ticker_reset();
160+
SysTimerTest st(&mock_ticker_data);
161+
st.suspend(TEST_TICKS * 2);
162+
TEST_ASSERT_EQUAL_UINT32(0, st.resume());
94163
TEST_ASSERT_EQUAL_UINT32(0, st.get_tick());
95-
us_timestamp_t test_ticks_elapsed_ts = st.get_time() + DELAY_US;
96164

97-
while (st.get_time() <= test_ticks_elapsed_ts) {}
98-
TEST_ASSERT_EQUAL_UINT32(TEST_TICKS - 1, st.update_tick());
165+
st.suspend(TEST_TICKS * 2);
166+
mock_ticker_timestamp = DELAY_US;
167+
TEST_ASSERT_EQUAL_UINT32(TEST_TICKS - 1, st.resume());
99168
TEST_ASSERT_EQUAL_UINT32(TEST_TICKS - 1, st.get_tick());
100169

101-
TEST_ASSERT_EQUAL_UINT32(0, st.update_tick());
170+
st.suspend(TEST_TICKS * 2);
171+
TEST_ASSERT_EQUAL_UINT32(0, st.resume());
102172
TEST_ASSERT_EQUAL_UINT32(TEST_TICKS - 1, st.get_tick());
103173
}
104174

@@ -110,12 +180,13 @@ void test_update_tick(void)
110180
*/
111181
void test_get_time(void)
112182
{
113-
SysTimerTest st;
183+
mock_ticker_reset();
184+
SysTimerTest st(&mock_ticker_data);
114185
us_timestamp_t t1 = st.get_time();
115186

116-
wait_us(DELAY_US);
187+
mock_ticker_timestamp = DELAY_US;
117188
us_timestamp_t t2 = st.get_time();
118-
TEST_ASSERT_UINT64_WITHIN(DELAY_DELTA_US, DELAY_US, t2 - t1);
189+
TEST_ASSERT_EQUAL_UINT64(DELAY_US, t2 - t1);
119190
}
120191

121192
/** Test cancel_tick

rtos/TARGET_CORTEX/SysTimer.cpp

Lines changed: 66 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#if DEVICE_LOWPOWERTIMER
2525

2626
#include "hal/lp_ticker_api.h"
27+
#include "mbed_critical.h"
2728
#include "rtx_core_cm.h"
2829
extern "C" {
2930
#include "rtx_lib.h"
@@ -43,6 +44,14 @@ namespace internal {
4344

4445
SysTimer::SysTimer() :
4546
TimerEvent(get_lp_ticker_data()), _start_time(0), _tick(0)
47+
{
48+
_start_time = ticker_read_us(_ticker_data);
49+
_suspend_time_passed = true;
50+
_suspended = false;
51+
}
52+
53+
SysTimer::SysTimer(const ticker_data_t *data) :
54+
TimerEvent(data), _start_time(0), _tick(0)
4655
{
4756
_start_time = ticker_read_us(_ticker_data);
4857
}
@@ -61,23 +70,30 @@ void SysTimer::setup_irq()
6170
#endif
6271
}
6372

64-
void SysTimer::schedule_tick(uint32_t delta)
73+
void SysTimer::suspend(uint32_t ticks)
6574
{
66-
insert_absolute(_start_time + (_tick + delta) * 1000000ULL / OS_TICK_FREQ);
67-
}
75+
core_util_critical_section_enter();
6876

69-
void SysTimer::cancel_tick()
70-
{
71-
remove();
77+
schedule_tick(ticks);
78+
_suspend_time_passed = false;
79+
_suspended = true;
80+
81+
core_util_critical_section_exit();
7282
}
7383

74-
uint32_t SysTimer::get_tick()
84+
bool SysTimer::suspend_time_passed()
7585
{
76-
return _tick & 0xFFFFFFFF;
86+
return _suspend_time_passed;
7787
}
7888

79-
uint32_t SysTimer::update_tick()
89+
uint32_t SysTimer::resume()
8090
{
91+
core_util_critical_section_enter();
92+
93+
_suspended = false;
94+
_suspend_time_passed = true;
95+
remove();
96+
8197
uint64_t new_tick = (ticker_read_us(_ticker_data) - _start_time) * OS_TICK_FREQ / 1000000;
8298
if (new_tick > _tick) {
8399
// Don't update to the current tick. Instead, update to the
@@ -88,9 +104,34 @@ uint32_t SysTimer::update_tick()
88104
}
89105
uint32_t elapsed_ticks = new_tick - _tick;
90106
_tick = new_tick;
107+
108+
core_util_critical_section_exit();
91109
return elapsed_ticks;
92110
}
93111

112+
void SysTimer::schedule_tick(uint32_t delta)
113+
{
114+
core_util_critical_section_enter();
115+
116+
insert_absolute(_start_time + (_tick + delta) * 1000000ULL / OS_TICK_FREQ);
117+
118+
core_util_critical_section_exit();
119+
}
120+
121+
void SysTimer::cancel_tick()
122+
{
123+
core_util_critical_section_enter();
124+
125+
remove();
126+
127+
core_util_critical_section_exit();
128+
}
129+
130+
uint32_t SysTimer::get_tick()
131+
{
132+
return _tick & 0xFFFFFFFF;
133+
}
134+
94135
us_timestamp_t SysTimer::get_time()
95136
{
96137
return ticker_read_us(_ticker_data);
@@ -100,24 +141,36 @@ SysTimer::~SysTimer()
100141
{
101142
}
102143

103-
void SysTimer::set_irq_pending()
144+
void SysTimer::_set_irq_pending()
104145
{
146+
// Protected function synchronized externally
147+
105148
#if (defined(NO_SYSTICK))
106149
NVIC_SetPendingIRQ(mbed_get_m0_tick_irqn());
107150
#else
108151
SCB->ICSR = SCB_ICSR_PENDSTSET_Msk;
109152
#endif
110153
}
111154

112-
void SysTimer::increment_tick()
155+
void SysTimer::_increment_tick()
113156
{
157+
// Protected function synchronized externally
158+
114159
_tick++;
115160
}
116161

117162
void SysTimer::handler()
118163
{
119-
set_irq_pending();
120-
increment_tick();
164+
core_util_critical_section_enter();
165+
166+
if (_suspended) {
167+
_suspend_time_passed = true;
168+
} else {
169+
_set_irq_pending();
170+
_increment_tick();
171+
}
172+
173+
core_util_critical_section_exit();
121174
}
122175

123176
}

rtos/TARGET_CORTEX/SysTimer.h

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,42 @@ class SysTimer: private mbed::TimerEvent, private mbed::NonCopyable<SysTimer> {
4949
public:
5050

5151
SysTimer();
52+
SysTimer(const ticker_data_t *data);
5253
virtual ~SysTimer();
5354

5455
/**
5556
* Enable an IRQ/SysTick with the correct priority.
5657
*/
5758
static void setup_irq();
5859

60+
/**
61+
* Set wakeup time and schedule a wakeup event after delta ticks
62+
*
63+
* After suspend has been called the function suspend_time_passed
64+
* can be used to determine if the suspend time has passed.
65+
*
66+
* @param delta Ticks to remain suspended
67+
*/
68+
void suspend(uint32_t delta);
69+
70+
/**
71+
* Check if the suspend time has passed
72+
*
73+
* @return true if the specified number of ticks has passed otherwise false
74+
*/
75+
bool suspend_time_passed();
76+
77+
/**
78+
* Exit suspend mode and return elapsed ticks
79+
*
80+
* Due to a scheduling issue, the number of ticks returned is decremented
81+
* by 1 so that a handler can be called and update to the current value.
82+
* This allows scheduling restart successfully after the OS is resumed.
83+
*
84+
* @return the number of elapsed ticks minus 1
85+
*/
86+
uint32_t resume();
87+
5988
/**
6089
* Schedule an os tick to fire
6190
*
@@ -77,17 +106,6 @@ class SysTimer: private mbed::TimerEvent, private mbed::NonCopyable<SysTimer> {
77106
*/
78107
uint32_t get_tick();
79108

80-
/**
81-
* Update the internal tick count
82-
*
83-
* @return The number of ticks incremented
84-
*
85-
* @note Due to a scheduling issue, the number of ticks returned is decremented
86-
* by 1 so that a handler can be called and update to the current value.
87-
* This allows scheduling restart successfully after the OS is resumed.
88-
*/
89-
uint32_t update_tick();
90-
91109
/**
92110
* Get the time
93111
*
@@ -97,10 +115,12 @@ class SysTimer: private mbed::TimerEvent, private mbed::NonCopyable<SysTimer> {
97115

98116
protected:
99117
virtual void handler();
100-
void increment_tick();
101-
static void set_irq_pending();
118+
void _increment_tick();
119+
static void _set_irq_pending();
102120
us_timestamp_t _start_time;
103121
uint64_t _tick;
122+
bool _suspend_time_passed;
123+
bool _suspended;
104124
};
105125

106126
/**

0 commit comments

Comments
 (0)