1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

pkg/openthread: migrate to event loop

This commit is contained in:
Jose Alamos 2020-09-16 16:59:22 +02:00
parent d76abc7543
commit 34b3f55200
7 changed files with 157 additions and 146 deletions

View File

@ -3,4 +3,5 @@ USEMODULE += openthread_contrib
USEMODULE += openthread_contrib_netdev
USEMODULE += l2util
USEMODULE += xtimer
USEMODULE += event
FEATURES_REQUIRED += cpp

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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
*/