Merge pull request #15038 from jia200x/pr/openthread/refactor
pkg/openthread: migrate to event loop
This commit is contained in:
commit
a2cf40aa76
@ -3,4 +3,5 @@ USEMODULE += openthread_contrib
|
|||||||
USEMODULE += openthread_contrib_netdev
|
USEMODULE += openthread_contrib_netdev
|
||||||
USEMODULE += l2util
|
USEMODULE += l2util
|
||||||
USEMODULE += xtimer
|
USEMODULE += xtimer
|
||||||
|
USEMODULE += event
|
||||||
FEATURES_REQUIRED += cpp
|
FEATURES_REQUIRED += cpp
|
||||||
|
|||||||
@ -26,55 +26,79 @@
|
|||||||
#include "openthread/ip6.h"
|
#include "openthread/ip6.h"
|
||||||
#include "openthread/platform/alarm-milli.h"
|
#include "openthread/platform/alarm-milli.h"
|
||||||
#include "openthread/platform/uart.h"
|
#include "openthread/platform/uart.h"
|
||||||
#include "openthread/tasklet.h"
|
|
||||||
#include "openthread/thread.h"
|
#include "openthread/thread.h"
|
||||||
#include "random.h"
|
#include "random.h"
|
||||||
#include "ot.h"
|
#include "ot.h"
|
||||||
|
#include "event.h"
|
||||||
|
|
||||||
#define ENABLE_DEBUG (0)
|
#define ENABLE_DEBUG (0)
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
#define OPENTHREAD_QUEUE_LEN (8)
|
static otInstance *sInstance; /**< global OpenThread instance */
|
||||||
static msg_t _queue[OPENTHREAD_QUEUE_LEN];
|
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 void _ev_isr_handler(event_t *event)
|
||||||
static otInstance *sInstance;
|
{
|
||||||
|
(void) event;
|
||||||
uint8_t ot_call_command(char* command, void *arg, void* answer) {
|
_dev->driver->isr(_dev);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OpenThread will call this when switching state from empty tasklet to non-empty tasklet. */
|
static event_t ev_isr = {
|
||||||
void otTaskletsSignalPending(otInstance *aInstance) {
|
.handler = _ev_isr_handler
|
||||||
(void) aInstance;
|
};
|
||||||
|
|
||||||
|
event_queue_t *openthread_get_evq(void)
|
||||||
|
{
|
||||||
|
return &ev_queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *_openthread_event_loop(void *arg) {
|
otInstance* openthread_get_instance(void)
|
||||||
(void)arg;
|
{
|
||||||
_pid = thread_getpid();
|
return sInstance;
|
||||||
|
}
|
||||||
|
|
||||||
/* enable OpenThread UART */
|
static void _event_cb(netdev_t *dev, netdev_event_t event) {
|
||||||
otPlatUartEnable();
|
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 */
|
/* init OpenThread */
|
||||||
sInstance = otInstanceInitSingle();
|
sInstance = otInstanceInitSingle();
|
||||||
|
|
||||||
msg_init_queue(_queue, OPENTHREAD_QUEUE_LEN);
|
/* enable OpenThread UART */
|
||||||
netdev_t *dev;
|
otPlatUartEnable();
|
||||||
msg_t msg, reply;
|
|
||||||
|
|
||||||
#if defined(MODULE_OPENTHREAD_CLI)
|
#if defined(MODULE_OPENTHREAD_CLI)
|
||||||
serial_msg_t* serialBuffer;
|
|
||||||
otCliUartInit(sInstance);
|
otCliUartInit(sInstance);
|
||||||
/* Init default parameters */
|
/* Init default parameters */
|
||||||
otPanId panid = OPENTHREAD_PANID;
|
otPanId panid = OPENTHREAD_PANID;
|
||||||
@ -91,94 +115,21 @@ static void *_openthread_event_loop(void *arg) {
|
|||||||
diagInit(sInstance);
|
diagInit(sInstance);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ot_job_t *job;
|
|
||||||
while (1) {
|
while (1) {
|
||||||
otTaskletsProcess(sInstance);
|
event_loop(&ev_queue);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
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 */
|
/* starts OpenThread thread */
|
||||||
int openthread_netdev_init(char *stack, int stacksize, char priority,
|
int openthread_netdev_init(char *stack, int stacksize, char priority,
|
||||||
const char *name, netdev_t *netdev) {
|
const char *name, netdev_t *netdev) {
|
||||||
netdev->driver->init(netdev);
|
if (thread_create(stack, stacksize,
|
||||||
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,
|
|
||||||
priority, THREAD_CREATE_STACKTEST,
|
priority, THREAD_CREATE_STACKTEST,
|
||||||
_openthread_event_loop, NULL, name);
|
_openthread_event_loop, netdev, name) < 0) {
|
||||||
|
|
||||||
if (_pid <= 0) {
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _pid;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,8 +28,25 @@
|
|||||||
#define ENABLE_DEBUG (0)
|
#define ENABLE_DEBUG (0)
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
static xtimer_t ot_timer;
|
static void _ev_timer_handler(event_t *event)
|
||||||
static msg_t ot_alarm_msg;
|
{
|
||||||
|
(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.
|
* 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;
|
(void)aT0;
|
||||||
|
|
||||||
DEBUG("openthread: otPlatAlarmStartAt: aT0: %" PRIu32 ", aDT: %" PRIu32 "\n", aT0, aDt);
|
DEBUG("openthread: otPlatAlarmStartAt: aT0: %" PRIu32 ", aDT: %" PRIu32 "\n", aT0, aDt);
|
||||||
ot_alarm_msg.type = OPENTHREAD_XTIMER_MSG_TYPE_EVENT;
|
|
||||||
|
|
||||||
if (aDt == 0) {
|
if (aDt == 0) {
|
||||||
msg_send(&ot_alarm_msg, thread_getpid());
|
event_post(openthread_get_evq(), &ev_timer);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int dt = aDt * US_PER_MS;
|
int dt = aDt * US_PER_MS;
|
||||||
xtimer_set_msg(&ot_timer, dt, &ot_alarm_msg, thread_getpid());
|
xtimer_set(&ot_timer, dt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -77,13 +77,14 @@ const ot_command_t otCommands[] =
|
|||||||
{ "thread", &ot_thread },
|
{ "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;
|
uint8_t res = 0xFF;
|
||||||
/* Check running thread */
|
/* Check running thread */
|
||||||
if (openthread_get_pid() == thread_getpid()) {
|
|
||||||
for (uint8_t i = 0; i < ARRAY_SIZE(otCommands); i++) {
|
for (uint8_t i = 0; i < ARRAY_SIZE(otCommands); i++) {
|
||||||
if (strcmp(command, otCommands[i].name) == 0) {
|
if (strcmp(job->command, otCommands[i].name) == 0) {
|
||||||
res = (*otCommands[i].function)(ot_instance, arg, answer);
|
res = (*otCommands[i].function)(openthread_get_instance(), job->arg, job->answer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,12 +92,22 @@ uint8_t ot_exec_command(otInstance *ot_instance, const char* command, void *arg,
|
|||||||
DEBUG("Wrong ot_COMMAND name\n");
|
DEBUG("Wrong ot_COMMAND name\n");
|
||||||
res = 1;
|
res = 1;
|
||||||
}
|
}
|
||||||
} else {
|
job->status = res;
|
||||||
DEBUG("ERROR: ot_exec_job needs to run in OpenThread thread\n");
|
|
||||||
}
|
|
||||||
return 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)
|
void output_bytes(const char* name, const uint8_t *aBytes, uint8_t aLength)
|
||||||
{
|
{
|
||||||
#if ENABLE_DEBUG
|
#if ENABLE_DEBUG
|
||||||
|
|||||||
@ -19,10 +19,31 @@
|
|||||||
|
|
||||||
#include "openthread/platform/misc.h"
|
#include "openthread/platform/misc.h"
|
||||||
#include "periph/pm.h"
|
#include "periph/pm.h"
|
||||||
|
#include "ot.h"
|
||||||
|
#include "openthread/tasklet.h"
|
||||||
|
|
||||||
#define ENABLE_DEBUG (0)
|
#define ENABLE_DEBUG (0)
|
||||||
#include "debug.h"
|
#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 otPlatReset(otInstance *aInstance)
|
||||||
{
|
{
|
||||||
(void)aInstance;
|
(void)aInstance;
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
#include "periph/uart.h"
|
#include "periph/uart.h"
|
||||||
#include "openthread/platform/uart.h"
|
#include "openthread/platform/uart.h"
|
||||||
#include "ot.h"
|
#include "ot.h"
|
||||||
|
#include "event.h"
|
||||||
|
|
||||||
#define ENABLE_DEBUG (0)
|
#define ENABLE_DEBUG (0)
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
@ -34,6 +35,18 @@
|
|||||||
static serial_msg_t gSerialMessage[OPENTHREAD_NUMBER_OF_SERIAL_BUFFER];
|
static serial_msg_t gSerialMessage[OPENTHREAD_NUMBER_OF_SERIAL_BUFFER];
|
||||||
static uint16_t frameLength = 0;
|
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) {
|
static void uart_handler(void* arg, char c) {
|
||||||
(void)arg;
|
(void)arg;
|
||||||
|
|
||||||
@ -47,10 +60,7 @@ static void uart_handler(void* arg, char c) {
|
|||||||
gSerialMessage[0].buf[frameLength] = c;
|
gSerialMessage[0].buf[frameLength] = c;
|
||||||
frameLength++;
|
frameLength++;
|
||||||
gSerialMessage[0].length = frameLength;
|
gSerialMessage[0].length = frameLength;
|
||||||
msg_t msg;
|
event_post(openthread_get_evq(), &ev_serial);
|
||||||
msg.type = OPENTHREAD_SERIAL_MSG_TYPE_EVENT;
|
|
||||||
msg.content.ptr = &gSerialMessage[0];
|
|
||||||
msg_send_int(&msg, openthread_get_pid());
|
|
||||||
frameLength = 0;
|
frameLength = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -34,22 +34,7 @@ extern "C" {
|
|||||||
#include "net/netdev.h"
|
#include "net/netdev.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
#include "openthread/instance.h"
|
#include "openthread/instance.h"
|
||||||
|
#include "event.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)
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name Openthread constants
|
* @name Openthread constants
|
||||||
@ -90,6 +75,8 @@ typedef struct {
|
|||||||
* @brief Struct containing an OpenThread job
|
* @brief Struct containing an OpenThread job
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
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. */
|
const char *command; /**< A pointer to the job name string. */
|
||||||
void *arg; /**< arg for the job **/
|
void *arg; /**< arg for the job **/
|
||||||
void *answer; /**< answer from 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);
|
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
|
* @brief Bootstrap OpenThread
|
||||||
*/
|
*/
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user