Skip to content

Commit a8e0bbd

Browse files
committed
rtos: add tickless support
Add tickless support to the rtos idle loop. Using low power ticker and RTOS suspend/resume functionality. We set the next event according to the kernel, and wake-up within this period. If lowpower ticker is not available, we fallback to the previous only sleep function.
1 parent 4a99b3b commit a8e0bbd

File tree

1 file changed

+40
-4
lines changed

1 file changed

+40
-4
lines changed

rtos/rtos_idle.c

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,50 @@
2222

2323
#include "rtos/rtos_idle.h"
2424
#include "platform/mbed_sleep.h"
25+
#include "mbed_critical.h"
26+
#include "hal/ticker_api.h"
27+
#include "hal/lp_ticker_api.h"
28+
#include "cmsis_os2.h"
29+
#include <limits.h>
30+
31+
static ticker_event_t idle_loop_event;
32+
33+
void idle_loop_handler(uint32_t id)
34+
{
35+
(void)id;
36+
}
2537

2638
static void default_idle_hook(void)
2739
{
28-
/* Sleep: ideally, we should put the chip to sleep.
29-
Unfortunately, this usually requires disconnecting the interface chip (debugger).
30-
This can be done, but it would break the local file system.
31-
*/
40+
#if DEVICE_LOWPOWERTIMER
41+
uint32_t tick_freq = osKernelGetTickFreq();
42+
timestamp_t time_in_sleep = 0UL;
43+
44+
uint32_t ticks_to_sleep = osKernelSuspend();
45+
if (ticks_to_sleep) {
46+
core_util_critical_section_enter();
47+
uint64_t us_to_sleep = ticks_to_sleep * tick_freq;
48+
// Calculate the maximum period we can sleep and stay within
49+
uint64_t max_us_sleep = (UINT_MAX / tick_freq) * tick_freq;
50+
if (us_to_sleep > max_us_sleep) {
51+
us_to_sleep = max_us_sleep;
52+
}
53+
54+
const ticker_data_t *lp_ticker_data = get_lp_ticker_data();
55+
ticker_remove_event(lp_ticker_data, &idle_loop_event);
56+
ticker_set_handler(lp_ticker_data, &idle_loop_handler);
57+
timestamp_t start_time = lp_ticker_read();
58+
ticker_insert_event_us(lp_ticker_data, &idle_loop_event, us_to_sleep, (uint32_t)&idle_loop_event);
59+
60+
sleep();
61+
core_util_critical_section_exit();
62+
// calculate how long we slept
63+
time_in_sleep = lp_ticker_read() - start_time;
64+
}
65+
osKernelResume(time_in_sleep / tick_freq);
66+
#else
3267
sleep();
68+
#endif
3369
}
3470
static void (*idle_hook_fptr)(void) = &default_idle_hook;
3571

0 commit comments

Comments
 (0)