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:
parent
d76abc7543
commit
34b3f55200
@ -3,4 +3,5 @@ USEMODULE += openthread_contrib
|
||||
USEMODULE += openthread_contrib_netdev
|
||||
USEMODULE += l2util
|
||||
USEMODULE += xtimer
|
||||
USEMODULE += event
|
||||
FEATURES_REQUIRED += cpp
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user