Skip to content

Commit e0bc631

Browse files
Merge pull request #4991 from c1728p9/tickless
Add tickless to some mbed-os devices
2 parents e5638b7 + 48a0489 commit e0bc631

File tree

7 files changed

+241
-276
lines changed

7 files changed

+241
-276
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: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
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+
#if (defined(NO_SYSTICK))
41+
/**
42+
* Return an IRQ number that can be used in the absence of SysTick
43+
*
44+
* @return Free IRQ number that can be used
45+
*/
46+
extern "C" IRQn_Type mbed_get_m0_tick_irqn(void);
47+
#endif
48+
49+
class RtosTimer : private TimerEvent {
50+
public:
51+
RtosTimer(): TimerEvent(get_lp_ticker_data()), _start_time(0), _tick(0) {
52+
_start_time = ticker_read_us(_ticker_data);
53+
#if (defined(NO_SYSTICK))
54+
NVIC_SetVector(mbed_get_m0_tick_irqn(), (uint32_t)SysTick_Handler);
55+
NVIC_SetPriority(mbed_get_m0_tick_irqn(), 0xFF); /* RTOS requires lowest priority */
56+
NVIC_EnableIRQ(mbed_get_m0_tick_irqn());
57+
#else
58+
// Ensure SysTick has the correct priority as it is still used
59+
// to trigger software interrupts on each tick. The period does
60+
// not matter since it will never start counting.
61+
SysTick_Setup(16);
62+
#endif
63+
};
64+
65+
/**
66+
* Schedule an os tick to fire
67+
*
68+
* @param delta Tick to fire at relative to current tick
69+
*/
70+
void schedule_tick(uint32_t delta=1) {
71+
insert_absolute(_start_time + (_tick + delta) * 1000000 / OS_TICK_FREQ);
72+
}
73+
74+
75+
/**
76+
* Prevent any scheduled ticks from triggering
77+
*/
78+
void cancel_tick() {
79+
remove();
80+
}
81+
82+
/**
83+
* Get the current tick count
84+
*
85+
* @return The number of ticks since boot. This should match RTX's tick count
86+
*/
87+
uint32_t get_tick() {
88+
return _tick & 0xFFFFFFFF;
89+
}
90+
91+
/**
92+
* Update the internal tick count
93+
*
94+
* @return The number of ticks incremented
95+
*/
96+
uint32_t update_tick() {
97+
uint64_t new_tick = ticker_read_us(_ticker_data) * OS_TICK_FREQ / 1000000;
98+
if (new_tick > _tick) {
99+
// Don't update to the current tick. Instead, update to the
100+
// previous tick and let the SysTick handler increment it
101+
// to the current value. This allows scheduling restart
102+
// successfully after the OS is resumed.
103+
new_tick--;
104+
}
105+
uint32_t elapsed_ticks = new_tick - _tick;
106+
_tick = new_tick;
107+
return elapsed_ticks;
108+
}
109+
110+
/**
111+
* Get the time
112+
*
113+
* @return Current time in microseconds
114+
*/
115+
us_timestamp_t get_time() {
116+
return ticker_read_us(_ticker_data);
117+
}
118+
119+
~RtosTimer() {
120+
121+
};
122+
123+
protected:
124+
125+
void handler() {
126+
#if (defined(NO_SYSTICK))
127+
NVIC_SetPendingIRQ(mbed_get_m0_tick_irqn());
128+
#else
129+
SCB->ICSR = SCB_ICSR_PENDSTSET_Msk;
130+
#endif
131+
_tick++;
132+
}
133+
134+
us_timestamp_t _start_time;
135+
uint64_t _tick;
136+
};
137+
138+
static RtosTimer *os_timer;
139+
static uint64_t os_timer_data[sizeof(RtosTimer) / 8];
140+
141+
/// Setup System Timer.
142+
int32_t osRtxSysTimerSetup (void)
143+
{
144+
// Do not use SingletonPtr since this relies on the RTOS
145+
if (NULL == os_timer) {
146+
os_timer = new (os_timer_data) RtosTimer();
147+
}
148+
return -1;
149+
}
150+
151+
/// Enable System Timer.
152+
void osRtxSysTimerEnable (void)
153+
{
154+
// set to fire interrupt on next tick
155+
os_timer->schedule_tick();
156+
}
157+
158+
/// Disable System Timer.
159+
void osRtxSysTimerDisable (void)
160+
{
161+
os_timer->cancel_tick();
162+
}
163+
164+
/// Acknowledge System Timer IRQ.
165+
void osRtxSysTimerAckIRQ (void)
166+
{
167+
os_timer->schedule_tick();
168+
}
169+
170+
/// Get System Timer count.
171+
uint32_t osRtxSysTimerGetCount (void)
172+
{
173+
return os_timer->get_time() & 0xFFFFFFFF;
174+
}
175+
176+
static void default_idle_hook(void)
177+
{
178+
uint32_t elapsed_ticks = 0;
179+
180+
core_util_critical_section_enter();
181+
uint32_t ticks_to_sleep = svcRtxKernelSuspend();
182+
MBED_ASSERT(os_timer->get_tick() == svcRtxKernelGetTickCount());
183+
if (ticks_to_sleep) {
184+
os_timer->schedule_tick(ticks_to_sleep);
185+
186+
sleep_manager_lock_deep_sleep();
187+
sleep();
188+
sleep_manager_unlock_deep_sleep();
189+
190+
os_timer->cancel_tick();
191+
// calculate how long we slept
192+
elapsed_ticks = os_timer->update_tick();
193+
}
194+
svcRtxKernelResume(elapsed_ticks);
195+
core_util_critical_section_exit();
196+
}
197+
198+
#else
199+
200+
static void default_idle_hook(void)
201+
{
202+
// critical section to complete sleep with locked deepsleep
203+
core_util_critical_section_enter();
204+
sleep_manager_lock_deep_sleep();
205+
sleep();
206+
sleep_manager_unlock_deep_sleep();
207+
core_util_critical_section_exit();
208+
}
209+
210+
#endif // MBED_TICKLESS
211+
212+
static void (*idle_hook_fptr)(void) = &default_idle_hook;
213+
214+
void rtos_attach_idle_hook(void (*fptr)(void))
215+
{
216+
//Attach the specified idle hook, or the default idle hook in case of a NULL pointer
217+
if (fptr != NULL) {
218+
idle_hook_fptr = fptr;
219+
} else {
220+
idle_hook_fptr = default_idle_hook;
221+
}
222+
}
223+
224+
extern "C" void rtos_idle_loop(void)
225+
{
226+
//Continuously call the idle hook function pointer
227+
while (1) {
228+
idle_hook_fptr();
229+
}
230+
}

rtos/rtos_idle.c

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

0 commit comments

Comments
 (0)