Skip to content

Commit e44d94f

Browse files
committed
Add initial support for tickless RTX
Add support for tickless by replacing RTX's SysTick timer code with with code which uses an mbed timer along with suspending and resuming the kernel in the idle loop. Tickless is enabled on a per-target basis by defining the macro MBED_TICKLESS.
1 parent e12f116 commit e44d94f

File tree

3 files changed

+212
-55
lines changed

3 files changed

+212
-55
lines changed

rtos/TARGET_CORTEX/mbed_rtx_conf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636

3737
#define OS_TIMER_THREAD_STACK_SIZE 768
3838
#ifndef OS_IDLE_THREAD_STACK_SIZE
39-
#define OS_IDLE_THREAD_STACK_SIZE 256
39+
#define OS_IDLE_THREAD_STACK_SIZE 512
4040
#endif
4141

4242
#define OS_DYNAMIC_MEM_SIZE 0

rtos/TARGET_CORTEX/mbed_rtx_idle.cpp

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2006-2012 ARM Limited
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to deal
6+
* in the Software without restriction, including without limitation the rights
7+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
* copies of the Software, and to permit persons to whom the Software is
9+
* furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
* SOFTWARE.
21+
*/
22+
23+
#include "rtos/rtos_idle.h"
24+
#include "platform/mbed_sleep.h"
25+
#include "TimerEvent.h"
26+
#include "lp_ticker_api.h"
27+
#include "core_cm.h"
28+
#include "mbed_critical.h"
29+
#include "mbed_assert.h"
30+
#include <new>
31+
#include "rtx_os.h"
32+
extern "C" {
33+
#include "rtx_lib.h"
34+
}
35+
36+
using namespace mbed;
37+
38+
#ifdef MBED_TICKLESS
39+
40+
class RtosTimer : private TimerEvent {
41+
public:
42+
RtosTimer(): TimerEvent(get_lp_ticker_data()), _start_time(0), _tick(0) {
43+
_start_time = ticker_read_us(_ticker_data);
44+
// Ensure SysTick has the correct priority as it is still used
45+
// to trigger software interrupts on each tick. The period does
46+
// not matter since it will never start counting.
47+
SysTick_Setup(16);
48+
};
49+
50+
/**
51+
* Schedule an os tick to fire
52+
*
53+
* @param delta Tick to fire at relative to current tick
54+
*/
55+
void schedule_tick(uint32_t delta=1) {
56+
insert_absolute(_start_time + (_tick + delta) * 1000000 / OS_TICK_FREQ);
57+
}
58+
59+
60+
/**
61+
* Prevent any scheduled ticks from triggering
62+
*/
63+
void cancel_tick() {
64+
remove();
65+
}
66+
67+
/**
68+
* Get the current tick count
69+
*
70+
* @return The number of ticks since boot. This should match RTX's tick count
71+
*/
72+
uint32_t get_tick() {
73+
return _tick & 0xFFFFFFFF;
74+
}
75+
76+
/**
77+
* Update the internal tick count
78+
*
79+
* @return The number of ticks incremented
80+
*/
81+
uint32_t update_tick() {
82+
uint64_t new_tick = ticker_read_us(_ticker_data) * OS_TICK_FREQ / 1000000;
83+
if (new_tick > _tick) {
84+
// Don't update to the current tick. Instead, update to the
85+
// previous tick and let the SysTick handler increment it
86+
// to the current value. This allows scheduling restart
87+
// successfully after the OS is resumed.
88+
new_tick--;
89+
}
90+
uint32_t elapsed_ticks = new_tick - _tick;
91+
_tick = new_tick;
92+
return elapsed_ticks;
93+
}
94+
95+
/**
96+
* Get the time
97+
*
98+
* @return Current time in microseconds
99+
*/
100+
us_timestamp_t get_time() {
101+
return ticker_read_us(_ticker_data);
102+
}
103+
104+
~RtosTimer() {
105+
106+
};
107+
108+
protected:
109+
110+
void handler() {
111+
SCB->ICSR = SCB_ICSR_PENDSTSET_Msk;
112+
_tick++;
113+
}
114+
115+
us_timestamp_t _start_time;
116+
uint64_t _tick;
117+
};
118+
119+
static RtosTimer *os_timer;
120+
static uint64_t os_timer_data[sizeof(RtosTimer) / 8];
121+
122+
/// Setup System Timer.
123+
int32_t osRtxSysTimerSetup (void)
124+
{
125+
// Do not use SingletonPtr since this relies on the RTOS
126+
if (NULL == os_timer) {
127+
os_timer = new (os_timer_data) RtosTimer();
128+
}
129+
return -1;
130+
}
131+
132+
/// Enable System Timer.
133+
void osRtxSysTimerEnable (void)
134+
{
135+
// set to fire interrupt on next tick
136+
os_timer->schedule_tick();
137+
}
138+
139+
/// Disable System Timer.
140+
void osRtxSysTimerDisable (void)
141+
{
142+
os_timer->cancel_tick();
143+
}
144+
145+
/// Acknowledge System Timer IRQ.
146+
void osRtxSysTimerAckIRQ (void)
147+
{
148+
os_timer->schedule_tick();
149+
}
150+
151+
/// Get System Timer count.
152+
uint32_t osRtxSysTimerGetCount (void)
153+
{
154+
return os_timer->get_time() & 0xFFFFFFFF;
155+
}
156+
157+
static void default_idle_hook(void)
158+
{
159+
uint32_t elapsed_ticks = 0;
160+
161+
core_util_critical_section_enter();
162+
uint32_t ticks_to_sleep = svcRtxKernelSuspend();
163+
MBED_ASSERT(os_timer->get_tick() == svcRtxKernelGetTickCount());
164+
if (ticks_to_sleep) {
165+
os_timer->schedule_tick(ticks_to_sleep);
166+
167+
sleep_manager_lock_deep_sleep();
168+
sleep();
169+
sleep_manager_unlock_deep_sleep();
170+
171+
os_timer->cancel_tick();
172+
// calculate how long we slept
173+
elapsed_ticks = os_timer->update_tick();
174+
}
175+
svcRtxKernelResume(elapsed_ticks);
176+
core_util_critical_section_exit();
177+
}
178+
179+
#else
180+
181+
static void default_idle_hook(void)
182+
{
183+
// critical section to complete sleep with locked deepsleep
184+
core_util_critical_section_enter();
185+
sleep_manager_lock_deep_sleep();
186+
sleep();
187+
sleep_manager_unlock_deep_sleep();
188+
core_util_critical_section_exit();
189+
}
190+
191+
#endif // MBED_TICKLESS
192+
193+
static void (*idle_hook_fptr)(void) = &default_idle_hook;
194+
195+
void rtos_attach_idle_hook(void (*fptr)(void))
196+
{
197+
//Attach the specified idle hook, or the default idle hook in case of a NULL pointer
198+
if (fptr != NULL) {
199+
idle_hook_fptr = fptr;
200+
} else {
201+
idle_hook_fptr = default_idle_hook;
202+
}
203+
}
204+
205+
extern "C" void rtos_idle_loop(void)
206+
{
207+
//Continuously call the idle hook function pointer
208+
while (1) {
209+
idle_hook_fptr();
210+
}
211+
}

rtos/rtos_idle.c

Lines changed: 0 additions & 54 deletions
This file was deleted.

0 commit comments

Comments
 (0)