diff --git a/Makefile.dep b/Makefile.dep index 5e5872a9e763..184be736f58c 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -9,7 +9,8 @@ OLD_USEPKG := $(sort $(USEPKG)) # processed before RIOT ones to be evaluated before the 'default' rules. -include $(EXTERNAL_MODULE_DIRS:%=%/Makefile.dep) -# pull dependencies from sys and drivers +# pull dependencies from core, sys and drivers +include $(RIOTBASE)/core/Makefile.dep include $(RIOTBASE)/sys/Makefile.dep include $(RIOTBASE)/drivers/Makefile.dep @@ -529,6 +530,7 @@ ifneq (,$(filter cpp11-compat,$(USEMODULE))) endif ifneq (,$(filter gnrc,$(USEMODULE))) + USEMODULE += multi_tasking USEMODULE += gnrc_netapi USEMODULE += gnrc_netreg USEMODULE += gnrc_netif diff --git a/core/Makefile b/core/Makefile index 4f12366947dd..787efda47272 100644 --- a/core/Makefile +++ b/core/Makefile @@ -1,5 +1,19 @@ # exclude submodule sources from *.c wildcard source selection -SRC := $(filter-out mbox.c msg.c thread_flags.c,$(wildcard *.c)) +SUBMODULE_SRC += cond.c +SUBMODULE_SRC += kernel_init.c +SUBMODULE_SRC += mbox.c +SUBMODULE_SRC += msg.c +SUBMODULE_SRC += mutex.c +SUBMODULE_SRC += rmutex.c +SUBMODULE_SRC += sched.c +SUBMODULE_SRC += st_kernel_init.c +SUBMODULE_SRC += st_mutex.c +SUBMODULE_SRC += st_sched.c +SUBMODULE_SRC += st_thread.c +SUBMODULE_SRC += thread.c +SUBMODULE_SRC += thread_flags.c + +SRC := $(filter-out $(SUBMODULE_SRC),$(wildcard *.c)) # enable submodules SUBMODULES := 1 diff --git a/core/Makefile.dep b/core/Makefile.dep new file mode 100644 index 000000000000..0d6a0c3b614b --- /dev/null +++ b/core/Makefile.dep @@ -0,0 +1,29 @@ +MODS_MULTI_TASKING += core_cond +MODS_MULTI_TASKING += core_kernel_init +MODS_MULTI_TASKING += core_mutex +MODS_MULTI_TASKING += core_rmutex +MODS_MULTI_TASKING += core_sched +MODS_MULTI_TASKING += core_thread + +MODS_REQUIRE_MT += core_mbox +MODS_REQUIRE_MT += core_msg +MODS_REQUIRE_MT += core_thread_flags + +MODS_SINGLE_TASKING += core_st_kernel_init +MODS_SINGLE_TASKING += core_st_mutex +MODS_SINGLE_TASKING += core_st_sched +MODS_SINGLE_TASKING += core_st_thread + +# Any of these modules requires multi-tasking support +ifneq (,$(filter $(MODS_MULTI_TASKING) $(MODS_REQUIRE_MT),$(USEMODULE))) + USEMODULE += multi_tasking +endif + +ifeq (,$(filter multi_tasking,$(USEMODULE))) + USEMODULE += $(MODS_SINGLE_TASKING) +else + ifneq (,$(filter $(MODS_SINGLE_TASKING),$(USEMODULE))) + $(error Multi-tasking both enabled and disabled!) + endif + USEMODULE += $(MODS_MULTI_TASKING) +endif diff --git a/core/include/mutex.h b/core/include/mutex.h index f41a5ae9bc65..9a0ad9002d2b 100644 --- a/core/include/mutex.h +++ b/core/include/mutex.h @@ -23,6 +23,7 @@ #define MUTEX_H #include +#include #include "list.h" @@ -33,6 +34,7 @@ /** * @brief Mutex structure. Must never be modified by the user. */ +#if defined(MODULE_MULTI_TASKING) || defined(DOXYGEN) typedef struct { /** * @brief The process waiting queue of the mutex. **Must never be changed @@ -41,24 +43,38 @@ typedef struct { */ list_node_t queue; } mutex_t; +#else +typedef uint8_t mutex_t; +#endif + /** * @brief Static initializer for mutex_t. * @details This initializer is preferable to mutex_init(). */ +#if defined(MODULE_MULTI_TASKING) || defined(DOXYGEN) #define MUTEX_INIT { { NULL } } +#else +#define MUTEX_INIT 0 +#endif /** * @brief Static initializer for mutex_t with a locked mutex */ +#if defined(MODULE_MULTI_TASKING) || defined(DOXYGEN) #define MUTEX_INIT_LOCKED { { MUTEX_LOCKED } } +#else +#define MUTEX_INIT_LOCKED 1 +#endif /** * @cond INTERNAL * @brief This is the value of the mutex when locked and no threads are waiting * for it */ +#if defined(MODULE_MULTI_TASKING) || defined(DOXYGEN) #define MUTEX_LOCKED ((list_node_t *)-1) +#endif /** * @endcond */ @@ -69,10 +85,17 @@ typedef struct { * Only use the function call for dynamically allocated mutexes. * @param[out] mutex pre-allocated mutex structure, must not be NULL. */ +#if defined(MODULE_MULTI_TASKING) || defined(DOXYGEN) static inline void mutex_init(mutex_t *mutex) { mutex->queue.next = NULL; } +#else +static inline void mutex_init(mutex_t *mutex) +{ + *mutex = MUTEX_INIT; +} +#endif /** * @brief Lock a mutex, blocking or non-blocking. diff --git a/core/st_kernel_init.c b/core/st_kernel_init.c new file mode 100644 index 000000000000..fa33330d087d --- /dev/null +++ b/core/st_kernel_init.c @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2019 Otto-von-Guericke-Universität Magdeburg + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup core_internal + * @{ + * + * @file + * @brief Platform-independent kernel initilization + * + * @author Marian Buschsieweke + * + * @} + */ + +#include "kernel_init.h" +#include "log.h" + +#include "periph/pm.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +extern int main(void); +void kernel_init(void) +{ + LOG_INFO("main(): This is RIOT! (Version: " RIOT_VERSION ")\n"); + main(); + LOG_INFO("main() exited, interrupts will still be served\n"); + while (1) { + pm_set_lowest(); + } +} diff --git a/core/st_mutex.c b/core/st_mutex.c new file mode 100644 index 000000000000..43f286bfb061 --- /dev/null +++ b/core/st_mutex.c @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2013 Freie Universität Berlin + * 2015 Kaspar Schleiser + * 2019 Otto-von-Guericke-Universität Magdeburg + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup core_sync + * @{ + * + * @file + * @brief Kernel mutex implementation + * + * @author Kaspar Schleiser + * @author Joakim Nohlgård + * @author Marian Buschsieweke + * + * @} + */ + +#include "mutex.h" +#include "irq.h" +#include "thread.h" +#include "sched.h" +#include "periph/pm.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +int _mutex_lock(mutex_t *mutex, int blocking) +{ + unsigned irqstate = irq_disable(); + if (*mutex && !blocking) { + irq_restore(irqstate); + return 0; + } + + while (*mutex) { + irq_restore(irqstate); + pm_set_lowest(); + irqstate = irq_disable(); + } + + *mutex = 1; + irq_restore(irqstate); + return 1; +} + +void mutex_unlock(mutex_t *mutex) +{ + unsigned irqstate = irq_disable(); + *mutex = 0; + irq_restore(irqstate); +} + +void mutex_unlock_and_sleep(mutex_t *mutex) +{ + mutex_unlock(mutex); + pm_set_lowest(); +} diff --git a/core/st_sched.c b/core/st_sched.c new file mode 100644 index 000000000000..62b9748deccd --- /dev/null +++ b/core/st_sched.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * 2019 Otto-von-Guericke-Universität Magdeburg + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup core_sched + * @{ + * + * @file + * @brief Scheduler implementation + * + * @author Kaspar Schleiser + * @author René Kijewski + * @author Marian Buschsieweke + * + * @} + */ + +#include + +#include "sched.h" +#include "thread.h" +#include "panic.h" + +#include "log.h" + +volatile int sched_num_threads = 1; +volatile unsigned int sched_context_switch_request = 0; +volatile thread_t *sched_active_thread = NULL; +volatile kernel_pid_t sched_active_pid = 0; + +int sched_run(void) +{ + core_panic(PANIC_GENERAL_ERROR, "sched_run() called in single-threaded " + "application. This should never happen."); +} + +NORETURN void sched_task_exit(void) +{ + core_panic(PANIC_GENERAL_ERROR, "Only task in single-threaded application " + "exited. This should never happen."); +} diff --git a/core/st_thread.c b/core/st_thread.c new file mode 100644 index 000000000000..561423c34043 --- /dev/null +++ b/core/st_thread.c @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2019 Otto-von-Guericke-Universität Magdeburg + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup core_thread + * @{ + * + * @file + * @brief Mock threading implementation + * + * @author Marian Buschsieweke + * + * @} + */ + +#include +#include + +#include "irq.h" +#include "periph/pm.h" +#include "thread.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +static uint8_t sleeping = 0; + +int thread_getstatus(kernel_pid_t pid) +{ + if (pid == 0) { + return (int)STATUS_RUNNING; + } + return (int)STATUS_NOT_FOUND; +} + +const char *thread_getname(kernel_pid_t pid) +{ +#ifdef DEVELHELP + if (pid == 0) { + return "main"; + } +#endif + (void)pid; + return NULL; +} + +void thread_sleep(void) +{ + unsigned state = irq_disable(); + sleeping = 1; + while (sleeping) { + irq_restore(state); + pm_set_lowest(); + state = irq_disable(); + } + irq_restore(state); +} + +int thread_wakeup(kernel_pid_t pid) +{ + if (pid != 0) { + return (int)STATUS_NOT_FOUND; + } + unsigned old_state = irq_disable(); + + sleeping = 0; + + irq_restore(old_state); + return 1; +} + +void thread_yield(void) +{ + /* nothing to do */ +} diff --git a/cpu/msp430_common/cpu.c b/cpu/msp430_common/cpu.c index af2b8337024b..9ac7a369bb76 100644 --- a/cpu/msp430_common/cpu.c +++ b/cpu/msp430_common/cpu.c @@ -55,7 +55,6 @@ void *thread_isr_stack_start(void) NORETURN void cpu_switch_context_exit(void) { - sched_active_thread = sched_threads[0]; sched_run(); __restore_context(); diff --git a/cpu/msp430fxyz/include/periph_cpu.h b/cpu/msp430fxyz/include/periph_cpu.h index 4d4a15b5a2cc..5918237a9ea4 100644 --- a/cpu/msp430fxyz/include/periph_cpu.h +++ b/cpu/msp430fxyz/include/periph_cpu.h @@ -21,6 +21,7 @@ #ifndef PERIPH_CPU_H #define PERIPH_CPU_H +#include #include "cpu.h" #include "msp430_regs.h" diff --git a/examples/hello-world/Makefile b/examples/hello-world/Makefile index 258d8e9bafba..1be6831c640e 100644 --- a/examples/hello-world/Makefile +++ b/examples/hello-world/Makefile @@ -15,4 +15,8 @@ DEVELHELP ?= 1 # Change this to 0 show compiler invocation lines by default: QUIET ?= 1 +# Disable support for multi-tasking, which is not needed for this trivial +# application +DISABLE_MODULE += multi_tasking core_msg + include $(RIOTBASE)/Makefile.include diff --git a/makefiles/defaultmodules.inc.mk b/makefiles/defaultmodules.inc.mk index 9d8331407c8a..e4484118a44a 100644 --- a/makefiles/defaultmodules.inc.mk +++ b/makefiles/defaultmodules.inc.mk @@ -1,3 +1,3 @@ -DEFAULT_MODULE += board cpu core core_msg sys +DEFAULT_MODULE += board cpu core core_msg multi_tasking sys DEFAULT_MODULE += auto_init diff --git a/makefiles/pseudomodules.inc.mk b/makefiles/pseudomodules.inc.mk index d4057d8e78c7..2d1179a59eb7 100644 --- a/makefiles/pseudomodules.inc.mk +++ b/makefiles/pseudomodules.inc.mk @@ -42,6 +42,7 @@ PSEUDOMODULES += log PSEUDOMODULES += log_printfnoformat PSEUDOMODULES += lora PSEUDOMODULES += mpu_stack_guard +PSEUDOMODULES += multi_tasking PSEUDOMODULES += nanocoap_% PSEUDOMODULES += netdev_default PSEUDOMODULES += netif diff --git a/sys/xtimer/xtimer.c b/sys/xtimer/xtimer.c index 1ba5152dbc6c..e4235d3c2ffa 100644 --- a/sys/xtimer/xtimer.c +++ b/sys/xtimer/xtimer.c @@ -233,6 +233,7 @@ int _xtimer_msg_receive_timeout(msg_t *msg, uint32_t timeout_ticks) return _msg_wait(msg, &tmsg, &t); } +#ifdef MODULE_MULTI_TASKING static void _mutex_timeout(void *arg) { mutex_thread_t *mt = (mutex_thread_t *)arg; @@ -262,6 +263,7 @@ int xtimer_mutex_lock_timeout(mutex_t *mutex, uint64_t timeout) xtimer_remove(&t); return -mt.timeout; } +#endif /* MODULE_MULTI_TASKING */ #ifdef MODULE_CORE_THREAD_FLAGS static void _set_timeout_flag_callback(void* arg)