core: make idle thread optional

This commit is contained in:
Kaspar Schleiser 2020-06-04 21:52:57 +02:00
parent 22d44d0763
commit e3f6c0f340
5 changed files with 38 additions and 10 deletions

View File

@ -1074,6 +1074,9 @@ FEATURES_REQUIRED += $(filter arch_%,$(FEATURES_PROVIDED))
# always select CPU core features # always select CPU core features
FEATURES_REQUIRED += $(filter cpu_core_%,$(FEATURES_PROVIDED)) FEATURES_REQUIRED += $(filter cpu_core_%,$(FEATURES_PROVIDED))
# don't use idle thread if architecture has needed support
FEATURES_OPTIONAL += no_idle_thread
ifneq (,$(filter ecc_%,$(USEMODULE))) ifneq (,$(filter ecc_%,$(USEMODULE)))
USEMODULE += ecc USEMODULE += ecc
endif endif

View File

@ -203,8 +203,22 @@ extern clist_node_t sched_runqueues[SCHED_PRIO_LEVELS];
*/ */
NORETURN void sched_task_exit(void); NORETURN void sched_task_exit(void);
#if IS_USED(MODULE_SCHED_CB) || defined(DOXYGEN) /**
* @brief Set CPU to idle mode (CPU dependent)
*
* Only used when there's no idle thread.
*
* This function will be called by the scheduler when there's no runnable thread.
* It will be called from ISR context, and *must* allow other ISR handlers to be run.
* E.g., on Cortex-M, the PendSV priority is temporarily lowered (set to higher
* value) in order to enable other exceptions to be run.
*
* This function should also invoke setting a low power mode, e.g., by calling
* 'pm_set_lowest()'.
*/
void sched_arch_idle(void);
#if IS_USED(MODULE_SCHED_CB) || defined(DOXYGEN)
/** /**
* @brief Scheduler run callback * @brief Scheduler run callback
* *

View File

@ -53,6 +53,9 @@ static void *main_trampoline(void *arg)
return NULL; return NULL;
} }
static char main_stack[THREAD_STACKSIZE_MAIN];
static char idle_stack[THREAD_STACKSIZE_IDLE];
static void *idle_thread(void *arg) static void *idle_thread(void *arg)
{ {
(void)arg; (void)arg;
@ -64,17 +67,17 @@ static void *idle_thread(void *arg)
return NULL; return NULL;
} }
static char main_stack[THREAD_STACKSIZE_MAIN];
static char idle_stack[THREAD_STACKSIZE_IDLE];
void kernel_init(void) void kernel_init(void)
{ {
irq_disable(); irq_disable();
thread_create(idle_stack, sizeof(idle_stack), if (IS_USED(MODULE_CORE_IDLE_THREAD)) {
THREAD_PRIORITY_IDLE, thread_create(idle_stack, sizeof(idle_stack),
THREAD_CREATE_WOUT_YIELD | THREAD_CREATE_STACKTEST, THREAD_PRIORITY_IDLE,
idle_thread, NULL, "idle"); THREAD_CREATE_WOUT_YIELD | THREAD_CREATE_STACKTEST,
idle_thread, NULL, "idle");
}
thread_create(main_stack, sizeof(main_stack), thread_create(main_stack, sizeof(main_stack),
THREAD_PRIORITY_MAIN, THREAD_PRIORITY_MAIN,

View File

@ -80,11 +80,14 @@ int __attribute__((used)) sched_run(void)
{ {
sched_context_switch_request = 0; sched_context_switch_request = 0;
#ifndef MODULE_CORE_IDLE_THREAD
while (!runqueue_bitcache) {
sched_arch_idle();
}
#endif
thread_t *active_thread = (thread_t *)sched_active_thread; thread_t *active_thread = (thread_t *)sched_active_thread;
/* The bitmask in runqueue_bitcache is never empty,
* since the threading should not be started before at least the idle thread was started.
*/
int nextrq = bitarithm_lsb(runqueue_bitcache); int nextrq = bitarithm_lsb(runqueue_bitcache);
thread_t *next_thread = container_of(sched_runqueues[nextrq].next->next, thread_t *next_thread = container_of(sched_runqueues[nextrq].next->next,
thread_t, rq_entry); thread_t, rq_entry);

View File

@ -28,3 +28,8 @@ endif
# select cortexm_svc pseudomodule if the corresponding feature is used # select cortexm_svc pseudomodule if the corresponding feature is used
USEMODULE += $(filter cortexm_svc, $(FEATURES_USED)) USEMODULE += $(filter cortexm_svc, $(FEATURES_USED))
# select core_idle_thread if the feature no_idle_thread is *not* used
ifeq (, $(filter no_idle_thread, $(FEATURES_USED)))
USEMODULE += core_idle_thread
endif