diff --git a/Makefile.dep b/Makefile.dep index dde5823a2e..9e877762ae 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -816,6 +816,10 @@ ifneq (,$(filter event_%,$(USEMODULE))) USEMODULE += event endif +ifneq (,$(filter event_thread_%,$(USEMODULE))) + USEMODULE += event_thread +endif + ifneq (,$(filter event_timeout,$(USEMODULE))) USEMODULE += xtimer endif diff --git a/sys/auto_init/auto_init.c b/sys/auto_init/auto_init.c index b72b856875..0ae1442935 100644 --- a/sys/auto_init/auto_init.c +++ b/sys/auto_init/auto_init.c @@ -118,6 +118,10 @@ void auto_init(void) #ifdef MODULE_SCHEDSTATISTICS init_schedstatistics(); #endif +#ifdef MODULE_EVENT_THREAD + extern void auto_init_event_thread(void); + auto_init_event_thread(); +#endif #ifdef MODULE_MCI DEBUG("Auto init mci module.\n"); mci_initialize(); diff --git a/sys/event/Makefile b/sys/event/Makefile index 6af7702a9e..a456b3092f 100644 --- a/sys/event/Makefile +++ b/sys/event/Makefile @@ -1,5 +1,6 @@ SRC := event.c -SUBMODULES = 1 +SUBMODULES := 1 +SUBMODULES_NOFORCE := 1 include $(RIOTBASE)/Makefile.base diff --git a/sys/event/thread.c b/sys/event/thread.c new file mode 100644 index 0000000000..999ff1371e --- /dev/null +++ b/sys/event/thread.c @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2019 Kaspar Schleiser + * 2018 Freie Universität Berlin + * 2020 Inria + * + * 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 sys_event + * @{ + * + * @file + * @brief Event Loop Thread implementation + * + * @author Hauke Petersen + * @author Kaspar Schleiser + * + * @} + */ + +#include "thread.h" +#include "event.h" +#include "event/thread.h" + +static void *_handler(void *event_queue) +{ + event_queue_claim(event_queue); + event_loop(event_queue); + + /* should be never reached */ + return NULL; +} + +void event_thread_init(event_queue_t *queue, char *stack, size_t stack_size, + unsigned priority) +{ + /* For the auto_init use case, this will be called before main gets + * started. main might already use the queues, so they need to be + * initialized at that point. + * + * They will be claimed within the handler thread. + */ + event_queue_init_detached(queue); + + thread_create(stack, stack_size, priority, 0, _handler, queue, "event"); +} + +#ifndef EVENT_THREAD_STACKSIZE_DEFAULT +# ifdef ISR_STACKSIZE +# define EVENT_THREAD_STACKSIZE_DEFAULT ISR_STACKSIZE +# else +# define EVENT_THREAD_STACKSIZE_DEFAULT THREAD_STACKSIZE_SMALL +# endif +#endif + +#ifndef EVENT_THREAD_HIGHEST_STACKSIZE +#define EVENT_THREAD_HIGHEST_STACKSIZE EVENT_THREAD_STACKSIZE_DEFAULT +#endif + +#ifndef EVENT_THREAD_HIGHEST_PRIO +#define EVENT_THREAD_HIGHEST_PRIO (0) +#endif + +#ifndef EVENT_THREAD_MEDIUM_STACKSIZE +#define EVENT_THREAD_MEDIUM_STACKSIZE EVENT_THREAD_STACKSIZE_DEFAULT +#endif +#ifndef EVENT_THREAD_MEDIUM_PRIO +#define EVENT_THREAD_MEDIUM_PRIO (THREAD_PRIORITY_MAIN - 1) +#endif + +#ifndef EVENT_THREAD_LOWEST_STACKSIZE +#define EVENT_THREAD_LOWEST_STACKSIZE EVENT_THREAD_STACKSIZE_DEFAULT +#endif +#ifndef EVENT_THREAD_LOWEST_PRIO +#define EVENT_THREAD_LOWEST_PRIO (THREAD_PRIORITY_IDLE - 1) +#endif + +#ifdef MODULE_EVENT_THREAD_HIGHEST +event_queue_t event_queue_highest; +static char _evq_highest_stack[EVENT_THREAD_HIGHEST_STACKSIZE]; +#endif + +#ifdef MODULE_EVENT_THREAD_MEDIUM +event_queue_t event_queue_medium; +static char _evq_medium_stack[EVENT_THREAD_MEDIUM_STACKSIZE]; +#endif + +#ifdef MODULE_EVENT_THREAD_LOWEST +event_queue_t event_queue_lowest; +static char _evq_lowest_stack[EVENT_THREAD_LOWEST_STACKSIZE]; +#endif + +typedef struct { + event_queue_t *queue; + char *stack; + size_t stack_size; + unsigned priority; +} event_threads_t; + +const event_threads_t _event_threads[] = { +#ifdef MODULE_EVENT_THREAD_HIGHEST + { &event_queue_highest, _evq_highest_stack, sizeof(_evq_highest_stack), + EVENT_THREAD_HIGHEST_PRIO }, +#endif +#ifdef MODULE_EVENT_THREAD_MEDIUM + { &event_queue_medium, _evq_medium_stack, sizeof(_evq_medium_stack), + EVENT_THREAD_MEDIUM_PRIO }, +#endif +#ifdef MODULE_EVENT_THREAD_LOWEST + { &event_queue_lowest, _evq_lowest_stack, sizeof(_evq_lowest_stack), + EVENT_THREAD_LOWEST_PRIO }, +#endif +}; + +void auto_init_event_thread(void) +{ + for (unsigned i = 0; i < ARRAY_SIZE(_event_threads); i++) { + event_thread_init(_event_threads[i].queue, + _event_threads[i].stack, _event_threads[i].stack_size, + _event_threads[i].priority); + } +} diff --git a/sys/include/event/thread.h b/sys/include/event/thread.h new file mode 100644 index 0000000000..251ee92ce3 --- /dev/null +++ b/sys/include/event/thread.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2020 Kaspar Schleiser + * 2020 Freie Universität Berlin + * 2020 Inria + * + * 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 sys_event + * @brief Provides utility functions for event handler threads + * + * @{ + * + * @file + * @brief Event Thread API + * + * @author Kaspar Schleiser + */ + +#ifndef EVENT_THREAD_H +#define EVENT_THREAD_H + +#include + +#include "event.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Convenience function for initializing an event queue thread + * + * @param[in] queue ptr to preallocated queue object + * @param[in] stack ptr to stack space + * @param[in] stack_size size of stack + * @param[in] priority priority to use + */ +void event_thread_init(event_queue_t *queue, char *stack, size_t stack_size, + unsigned priority); + +#ifdef MODULE_EVENT_THREAD_HIGHEST +extern event_queue_t event_queue_highest; +#define EVENT_PRIO_HIGHEST (&event_queue_highest) +#endif + +#ifdef MODULE_EVENT_THREAD_MEDIUM +extern event_queue_t event_queue_medium; +#define EVENT_PRIO_MEDIUM (&event_queue_medium) +#endif + +#ifdef MODULE_EVENT_THREAD_LOWEST +extern event_queue_t event_queue_lowest; +#define EVENT_PRIO_LOWEST (&event_queue_lowest) +#endif + +#ifdef __cplusplus +} +#endif +#endif /* EVENT_THREAD_H */ +/** @} */