From 34b3f55200b2950332a2b0f66e1387ee65895730 Mon Sep 17 00:00:00 2001 From: Jose Alamos Date: Wed, 16 Sep 2020 16:59:22 +0200 Subject: [PATCH] pkg/openthread: migrate to event loop --- pkg/openthread/Makefile.dep | 1 + .../contrib/netdev/openthread_netdev.c | 165 ++++++------------ pkg/openthread/contrib/platform_alarm.c | 26 ++- .../contrib/platform_functions_wrapper.c | 39 +++-- pkg/openthread/contrib/platform_misc.c | 21 +++ pkg/openthread/contrib/platform_uart.c | 18 +- pkg/openthread/include/ot.h | 33 ++-- 7 files changed, 157 insertions(+), 146 deletions(-) diff --git a/pkg/openthread/Makefile.dep b/pkg/openthread/Makefile.dep index d64cdf9127..3c8eb79b19 100644 --- a/pkg/openthread/Makefile.dep +++ b/pkg/openthread/Makefile.dep @@ -3,4 +3,5 @@ USEMODULE += openthread_contrib USEMODULE += openthread_contrib_netdev USEMODULE += l2util USEMODULE += xtimer +USEMODULE += event FEATURES_REQUIRED += cpp diff --git a/pkg/openthread/contrib/netdev/openthread_netdev.c b/pkg/openthread/contrib/netdev/openthread_netdev.c index 1a15233634..9058c6f0f0 100644 --- a/pkg/openthread/contrib/netdev/openthread_netdev.c +++ b/pkg/openthread/contrib/netdev/openthread_netdev.c @@ -26,55 +26,79 @@ #include "openthread/ip6.h" #include "openthread/platform/alarm-milli.h" #include "openthread/platform/uart.h" -#include "openthread/tasklet.h" #include "openthread/thread.h" #include "random.h" #include "ot.h" +#include "event.h" #define ENABLE_DEBUG (0) #include "debug.h" -#define OPENTHREAD_QUEUE_LEN (8) -static msg_t _queue[OPENTHREAD_QUEUE_LEN]; +static otInstance *sInstance; /**< global OpenThread instance */ +static netdev_t *_dev; /**< netdev descriptor for OpenThread */ +static event_queue_t ev_queue; /**< the event queue for OpenThread */ -static kernel_pid_t _pid; -static otInstance *sInstance; - -uint8_t ot_call_command(char* command, void *arg, void* answer) { - ot_job_t job; - - job.command = command; - job.arg = arg; - job.answer = answer; - - msg_t msg, reply; - msg.type = OPENTHREAD_JOB_MSG_TYPE_EVENT; - msg.content.ptr = &job; - msg_send_receive(&msg, &reply, openthread_get_pid()); - return (uint8_t)reply.content.value; +static void _ev_isr_handler(event_t *event) +{ + (void) event; + _dev->driver->isr(_dev); } -/* OpenThread will call this when switching state from empty tasklet to non-empty tasklet. */ -void otTaskletsSignalPending(otInstance *aInstance) { - (void) aInstance; +static event_t ev_isr = { + .handler = _ev_isr_handler +}; + +event_queue_t *openthread_get_evq(void) +{ + return &ev_queue; } -static void *_openthread_event_loop(void *arg) { - (void)arg; - _pid = thread_getpid(); +otInstance* openthread_get_instance(void) +{ + return sInstance; +} - /* enable OpenThread UART */ - otPlatUartEnable(); +static void _event_cb(netdev_t *dev, netdev_event_t event) { + switch (event) { + case NETDEV_EVENT_ISR: + event_post(&ev_queue, &ev_isr); + break; + case NETDEV_EVENT_RX_COMPLETE: + DEBUG("openthread_netdev: Reception of a packet\n"); + recv_pkt(sInstance, dev); + break; + case NETDEV_EVENT_TX_COMPLETE: + case NETDEV_EVENT_TX_NOACK: + case NETDEV_EVENT_TX_MEDIUM_BUSY: + DEBUG("openthread_netdev: Transmission of a packet\n"); + send_pkt(sInstance, dev, event); + break; + default: + break; + } +} + +static void *_openthread_event_loop(void *arg) +{ + _dev = arg; + netdev_t *netdev = arg; + + event_queue_init(&ev_queue); + + netdev->driver->init(netdev); + netdev->event_callback = _event_cb; + + netopt_enable_t enable = NETOPT_ENABLE; + netdev->driver->set(netdev, NETOPT_TX_END_IRQ, &enable, sizeof(enable)); + netdev->driver->set(netdev, NETOPT_RX_END_IRQ, &enable, sizeof(enable)); /* init OpenThread */ sInstance = otInstanceInitSingle(); - msg_init_queue(_queue, OPENTHREAD_QUEUE_LEN); - netdev_t *dev; - msg_t msg, reply; + /* enable OpenThread UART */ + otPlatUartEnable(); #if defined(MODULE_OPENTHREAD_CLI) - serial_msg_t* serialBuffer; otCliUartInit(sInstance); /* Init default parameters */ otPanId panid = OPENTHREAD_PANID; @@ -91,94 +115,21 @@ static void *_openthread_event_loop(void *arg) { diagInit(sInstance); #endif - ot_job_t *job; while (1) { - otTaskletsProcess(sInstance); - if (otTaskletsArePending(sInstance) == false) { - msg_receive(&msg); - switch (msg.type) { - case OPENTHREAD_XTIMER_MSG_TYPE_EVENT: - /* Tell OpenThread a time event was received */ - otPlatAlarmMilliFired(sInstance); - break; - case OPENTHREAD_NETDEV_MSG_TYPE_EVENT: - /* Received an event from driver */ - dev = msg.content.ptr; - dev->driver->isr(dev); - break; -#ifdef MODULE_OPENTHREAD_CLI - case OPENTHREAD_SERIAL_MSG_TYPE_EVENT: - /* Tell OpenThread about the reception of a CLI command */ - serialBuffer = (serial_msg_t*)msg.content.ptr; - otPlatUartReceived((uint8_t*) serialBuffer->buf,serialBuffer->length); - serialBuffer->serial_buffer_status = OPENTHREAD_SERIAL_BUFFER_STATUS_FREE; - break; -#endif - case OPENTHREAD_JOB_MSG_TYPE_EVENT: - job = msg.content.ptr; - reply.content.value = ot_exec_command(sInstance, job->command, job->arg, job->answer); - msg_reply(&msg, &reply); - break; - } - } + event_loop(&ev_queue); } return NULL; } -static void _event_cb(netdev_t *dev, netdev_event_t event) { - switch (event) { - case NETDEV_EVENT_ISR: - { - msg_t msg; - assert(_pid != KERNEL_PID_UNDEF); - - msg.type = OPENTHREAD_NETDEV_MSG_TYPE_EVENT; - msg.content.ptr = dev; - - if (msg_send(&msg, _pid) <= 0) { - DEBUG("openthread_netdev: possibly lost interrupt.\n"); - } - break; - } - - case NETDEV_EVENT_RX_COMPLETE: - DEBUG("openthread_netdev: Reception of a packet\n"); - recv_pkt(sInstance, dev); - break; - case NETDEV_EVENT_TX_COMPLETE: - case NETDEV_EVENT_TX_NOACK: - case NETDEV_EVENT_TX_MEDIUM_BUSY: - DEBUG("openthread_netdev: Transmission of a packet\n"); - send_pkt(sInstance, dev, event); - break; - default: - break; - } -} - -/* get OpenThread thread pid */ -kernel_pid_t openthread_get_pid(void) { - return _pid; -} - /* starts OpenThread thread */ int openthread_netdev_init(char *stack, int stacksize, char priority, const char *name, netdev_t *netdev) { - netdev->driver->init(netdev); - netdev->event_callback = _event_cb; - - netopt_enable_t enable = NETOPT_ENABLE; - netdev->driver->set(netdev, NETOPT_TX_END_IRQ, &enable, sizeof(enable)); - netdev->driver->set(netdev, NETOPT_RX_END_IRQ, &enable, sizeof(enable)); - - _pid = thread_create(stack, stacksize, + if (thread_create(stack, stacksize, priority, THREAD_CREATE_STACKTEST, - _openthread_event_loop, NULL, name); - - if (_pid <= 0) { + _openthread_event_loop, netdev, name) < 0) { return -EINVAL; } - return _pid; + return 0; } diff --git a/pkg/openthread/contrib/platform_alarm.c b/pkg/openthread/contrib/platform_alarm.c index f7d50b0d4f..9410c12eac 100644 --- a/pkg/openthread/contrib/platform_alarm.c +++ b/pkg/openthread/contrib/platform_alarm.c @@ -28,8 +28,25 @@ #define ENABLE_DEBUG (0) #include "debug.h" -static xtimer_t ot_timer; -static msg_t ot_alarm_msg; +static void _ev_timer_handler(event_t *event) +{ + (void) event; + otPlatAlarmMilliFired(openthread_get_instance()); +} + +static event_t ev_timer = { + .handler = _ev_timer_handler +}; + +void _timeout_cb(void *arg) +{ + (void) arg; + event_post(openthread_get_evq(), &ev_timer); +} + +static xtimer_t ot_timer = { + .callback = _timeout_cb, +}; /** * Set the alarm to fire at @p aDt milliseconds after @p aT0. @@ -44,14 +61,13 @@ void otPlatAlarmMilliStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt) (void)aT0; DEBUG("openthread: otPlatAlarmStartAt: aT0: %" PRIu32 ", aDT: %" PRIu32 "\n", aT0, aDt); - ot_alarm_msg.type = OPENTHREAD_XTIMER_MSG_TYPE_EVENT; if (aDt == 0) { - msg_send(&ot_alarm_msg, thread_getpid()); + event_post(openthread_get_evq(), &ev_timer); } else { int dt = aDt * US_PER_MS; - xtimer_set_msg(&ot_timer, dt, &ot_alarm_msg, thread_getpid()); + xtimer_set(&ot_timer, dt); } } diff --git a/pkg/openthread/contrib/platform_functions_wrapper.c b/pkg/openthread/contrib/platform_functions_wrapper.c index 2805163593..d76640dd65 100644 --- a/pkg/openthread/contrib/platform_functions_wrapper.c +++ b/pkg/openthread/contrib/platform_functions_wrapper.c @@ -77,26 +77,37 @@ const ot_command_t otCommands[] = { "thread", &ot_thread }, }; -uint8_t ot_exec_command(otInstance *ot_instance, const char* command, void *arg, void* answer) { +void _exec_cmd(event_t *event) { + ot_job_t *job = (ot_job_t*) event; + uint8_t res = 0xFF; /* Check running thread */ - if (openthread_get_pid() == thread_getpid()) { - for (uint8_t i = 0; i < ARRAY_SIZE(otCommands); i++) { - if (strcmp(command, otCommands[i].name) == 0) { - res = (*otCommands[i].function)(ot_instance, arg, answer); - break; - } + for (uint8_t i = 0; i < ARRAY_SIZE(otCommands); i++) { + if (strcmp(job->command, otCommands[i].name) == 0) { + res = (*otCommands[i].function)(openthread_get_instance(), job->arg, job->answer); + break; } - if (res == 0xFF) { - DEBUG("Wrong ot_COMMAND name\n"); - res = 1; - } - } else { - DEBUG("ERROR: ot_exec_job needs to run in OpenThread thread\n"); } - return res; + if (res == 0xFF) { + DEBUG("Wrong ot_COMMAND name\n"); + res = 1; + } + job->status = res; } +uint8_t ot_call_command(char* command, void *arg, void* answer) +{ + ot_job_t job = {.ev.handler = _exec_cmd}; + + job.command = command; + job.arg = arg; + job.answer = answer; + + event_post(openthread_get_evq(), &job.ev); + return job.status; +} + + void output_bytes(const char* name, const uint8_t *aBytes, uint8_t aLength) { #if ENABLE_DEBUG diff --git a/pkg/openthread/contrib/platform_misc.c b/pkg/openthread/contrib/platform_misc.c index 657cce08be..e3761239c9 100644 --- a/pkg/openthread/contrib/platform_misc.c +++ b/pkg/openthread/contrib/platform_misc.c @@ -19,10 +19,31 @@ #include "openthread/platform/misc.h" #include "periph/pm.h" +#include "ot.h" +#include "openthread/tasklet.h" #define ENABLE_DEBUG (0) #include "debug.h" +static void _ev_tasklets_handler(event_t *event) +{ + (void) event; + otInstance *instance = openthread_get_instance(); + while (otTaskletsArePending(instance)) { + otTaskletsProcess(instance); + } +} + +static event_t ev_tasklet = { + .handler = _ev_tasklets_handler +}; + +/* OpenThread will call this when switching state from empty tasklet to non-empty tasklet. */ +void otTaskletsSignalPending(otInstance *aInstance) { + (void) aInstance; + event_post(openthread_get_evq(), &ev_tasklet); +} + void otPlatReset(otInstance *aInstance) { (void)aInstance; diff --git a/pkg/openthread/contrib/platform_uart.c b/pkg/openthread/contrib/platform_uart.c index 4e73a73bb8..e1fa5d6182 100644 --- a/pkg/openthread/contrib/platform_uart.c +++ b/pkg/openthread/contrib/platform_uart.c @@ -25,6 +25,7 @@ #include "periph/uart.h" #include "openthread/platform/uart.h" #include "ot.h" +#include "event.h" #define ENABLE_DEBUG (0) #include "debug.h" @@ -34,6 +35,18 @@ static serial_msg_t gSerialMessage[OPENTHREAD_NUMBER_OF_SERIAL_BUFFER]; static uint16_t frameLength = 0; +static void _ev_serial_handler(event_t *event) +{ + (void) event; + /* Tell OpenThread about the reception of a CLI command */ + otPlatUartReceived((uint8_t*)gSerialMessage[0].buf, gSerialMessage[0].length); + gSerialMessage[0].serial_buffer_status = OPENTHREAD_SERIAL_BUFFER_STATUS_FREE; +} + +static event_t ev_serial = { + .handler = _ev_serial_handler +}; + static void uart_handler(void* arg, char c) { (void)arg; @@ -47,10 +60,7 @@ static void uart_handler(void* arg, char c) { gSerialMessage[0].buf[frameLength] = c; frameLength++; gSerialMessage[0].length = frameLength; - msg_t msg; - msg.type = OPENTHREAD_SERIAL_MSG_TYPE_EVENT; - msg.content.ptr = &gSerialMessage[0]; - msg_send_int(&msg, openthread_get_pid()); + event_post(openthread_get_evq(), &ev_serial); frameLength = 0; } break; diff --git a/pkg/openthread/include/ot.h b/pkg/openthread/include/ot.h index 014dbc0b3b..c554599766 100644 --- a/pkg/openthread/include/ot.h +++ b/pkg/openthread/include/ot.h @@ -34,22 +34,7 @@ extern "C" { #include "net/netdev.h" #include "thread.h" #include "openthread/instance.h" - -/** - * @name Openthread message types - * @{ - */ -/** @brief xtimer message receiver event */ -#define OPENTHREAD_XTIMER_MSG_TYPE_EVENT (0x2235) -/** @brief message received from driver */ -#define OPENTHREAD_NETDEV_MSG_TYPE_EVENT (0x2236) -/** @brief event indicating a serial (UART) message was sent to OpenThread */ -#define OPENTHREAD_SERIAL_MSG_TYPE_EVENT (0x2237) -/** @brief event for frame reception */ -#define OPENTHREAD_MSG_TYPE_RECV (0x2238) -/** @brief event indicating an OT_JOB message */ -#define OPENTHREAD_JOB_MSG_TYPE_EVENT (0x2240) -/** @} */ +#include "event.h" /** * @name Openthread constants @@ -90,6 +75,8 @@ typedef struct { * @brief Struct containing an OpenThread job */ typedef struct { + event_t ev; /**< Event associated to the OpenThread job */ + int status; /**< Status of the job */ const char *command; /**< A pointer to the job name string. */ void *arg; /**< arg for the job **/ void *answer; /**< answer from the job **/ @@ -112,6 +99,20 @@ void recv_pkt(otInstance *aInstance, netdev_t *dev); */ void send_pkt(otInstance *aInstance, netdev_t *dev, netdev_event_t event); +/** + * @brief Get OpenThread event queue + * + * @return pointer to the event queue + */ +event_queue_t *openthread_get_evq(void); + +/** + * @brief Get pointer to the OpenThread instance + * + * @return pointer to the OpenThread instance + */ +otInstance* openthread_get_instance(void); + /** * @brief Bootstrap OpenThread */