diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000000..0b1ce11d9981 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "pkg/openthread/source"] + path = pkg/openthread/source + url = https://github.com/Hyungsin/openthread.git + branch = openthread-v1.0 diff --git a/Makefile.dep b/Makefile.dep index 59a25739bf1e..19723a480562 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -641,8 +641,12 @@ ifneq (,$(filter random,$(USEMODULE))) endif endif +ifneq (,$(filter openthread,$(USEPKG))) + USEMODULE += openthread_contrib + USEMODULE += mbedcrypto +endif + ifneq (,$(filter openthread_contrib,$(USEMODULE))) - USEMODULE += openthread_contrib_netdev FEATURES_REQUIRED += cpp endif diff --git a/core/include/debug.h b/core/include/debug.h index 7b4c77bdb002..e61223772b36 100644 --- a/core/include/debug.h +++ b/core/include/debug.h @@ -59,8 +59,18 @@ extern "C" { puts("Cannot debug, stack too small"); \ } \ } while (0) +#define DEBUG_VPRINT(format, arg) \ + do { \ + if ((sched_active_thread == NULL) || (sched_active_thread->stack_size > THREAD_EXTRA_STACKSIZE_PRINTF)) { \ + vprintf(format, arg); \ + } \ + else { \ + puts("Cannot debug, stack too small"); \ + } \ + } while (0) #else #define DEBUG_PRINT(...) printf(__VA_ARGS__) +#define DEBUG_VPRINT(format, arg) vprintf(format, arg) #endif /** @@ -93,8 +103,10 @@ extern "C" { * @note Another name for ::DEBUG_PRINT */ #define DEBUG(...) DEBUG_PRINT(__VA_ARGS__) +#define DEBUG_V(format, arg) DEBUG_VPRINT(format, arg) #else #define DEBUG(...) +#define DEBUG_V(format, arg) #endif /** @} */ diff --git a/drivers/at86rf2xx/at86rf2xx_netdev.c b/drivers/at86rf2xx/at86rf2xx_netdev.c index b95e6a1bd0c0..a2065e33d63a 100644 --- a/drivers/at86rf2xx/at86rf2xx_netdev.c +++ b/drivers/at86rf2xx/at86rf2xx_netdev.c @@ -61,7 +61,15 @@ static void _irq_handler(void *arg) netdev_t *dev = (netdev_t *) arg; if (dev->event_callback) { +#if MODULE_OPENTHREAD + if (((at86rf2xx_t *) dev)->netdev.flags & AT86RF2XX_OPT_TELL_TX_END) { + dev->event_callback(dev, NETDEV_EVENT_ISR2); + } else { + dev->event_callback(dev, NETDEV_EVENT_ISR); + } +#else dev->event_callback(dev, NETDEV_EVENT_ISR); +#endif } } @@ -595,6 +603,14 @@ static void _isr(netdev_t *netdev) dev->idle_state = AT86RF2XX_STATE_RX_AACK_ON; } #endif +#endif +#if MODULE_OPENTHREAD + /* Wake up for a while when receiving an ACK with pending bit */ + if (trac_status == AT86RF2XX_TRX_STATE__TRAC_SUCCESS_DATA_PENDING) { + dev->idle_state = AT86RF2XX_STATE_RX_AACK_ON; + } else { + dev->idle_state = AT86RF2XX_STATE_SLEEP; + } #endif at86rf2xx_set_state(dev, dev->idle_state); DEBUG("[at86rf2xx] return to state 0x%x\n", dev->idle_state); diff --git a/drivers/include/net/netdev.h b/drivers/include/net/netdev.h index ee4f1f9d4683..72dfdd172e67 100644 --- a/drivers/include/net/netdev.h +++ b/drivers/include/net/netdev.h @@ -223,6 +223,7 @@ enum { */ typedef enum { NETDEV_EVENT_ISR, /**< driver needs it's ISR handled */ + NETDEV_EVENT_ISR2, /**< driver needs it's another ISR handled */ NETDEV_EVENT_RX_STARTED, /**< started to receive a packet */ NETDEV_EVENT_RX_COMPLETE, /**< finished receiving a packet */ NETDEV_EVENT_RX_DATAREQ, /**< receiving a dataReq packet */ diff --git a/pkg/openthread/Makefile b/pkg/openthread/Makefile index 8d59f1dec345..94e96ef37e4f 100644 --- a/pkg/openthread/Makefile +++ b/pkg/openthread/Makefile @@ -1,22 +1,31 @@ PKG_NAME=openthread -PKG_URL=https://github.com/openthread/openthread.git -PKG_VERSION=fbfd76a990b81f007957e1bd774e51bce742e53e -PKG_BUILDDIR ?= $(BINDIRBASE)/pkg/$(BOARD)/$(PKG_NAME) - -$(info Compile OpenThread for FTD device) -OPENTHREAD_ARGS+= --enable-cli-app=ftd --enable-application-coap +PKG_BUILDDIR ?= $(RIOTBASE)/pkg/openthread/source +ifneq (,$(filter openthread-cli-ftd,$(USEMODULE))) + $(info Compile OpenThread for FTD device) + OPENTHREAD_ARGS += --enable-cli-app=ftd +endif +ifneq (,$(filter openthread-cli-mtd,$(USEMODULE))) + $(info Compile OpenThread for MTD device) + OPENTHREAD_ARGS += --enable-cli-app=mtd --enable-joiner +endif +ifneq (,$(filter openthread-ncp-ftd,$(USEMODULE))) + $(info Compile OpenThread with NCP) + OPENTHREAD_ARGS += --enable-ncp-app=ftd --with-ncp-bus=uart --enable-commissioner --enable-border-router +endif +OPENTHREAD_ARGS += --enable-application-coap +CONFIG_FILE = OPENTHREAD_PROJECT_CORE_CONFIG_FILE='\"platform_config.h\"' $(info $$OPENTHREAD_ARGS is [${OPENTHREAD_ARGS}]) .PHONY: all OPENTHREAD_COMMON_FLAGS=-fdata-sections -ffunction-sections -Os -all: git-download +all: cd $(PKG_BUILDDIR) && PREFIX="/" ./bootstrap cd $(PKG_BUILDDIR) && CPP="$(CPP)" CC="$(CC)" CXX="$(CXX)"\ OBJC="" OBJCXX="" AR="$(AR)" RANLIB="$(RANLIB)" NM="$(NM)" \ STRIP="$(STRIP)" \ - CPPFLAGS="$(OPENTHREAD_COMMON_FLAGS) $(CFLAGS_CPU) " \ + CPPFLAGS="$(OPENTHREAD_COMMON_FLAGS) $(CFLAGS_CPU) -D$(CONFIG_FILE)" \ CFLAGS="$(OPENTHREAD_COMMON_FLAGS) $(CFLAGS_CPU) " \ CXXFLAGS="$(OPENTHREAD_COMMON_FLAGS) $(CFLAGS_CPU) -fno-exceptions -fno-rtti " \ LDFLAGS="$(OPENTHREAD_COMMON_FLAGS) $(CFLAGS_CPU) -nostartfiles -specs=nano.specs \ @@ -24,9 +33,18 @@ all: git-download ./configure --disable-docs --host=$(TARGET_ARCH) --target=$(TARGET_ARCH) \ --prefix=/ --enable-default-logging ${OPENTHREAD_ARGS} cd $(PKG_BUILDDIR) && DESTDIR=$(PKG_BUILDDIR)/output PREFIX=/ make -j4 --no-print-directory install - - cp $(PKG_BUILDDIR)/output/lib/libmbedcrypto.a ${BINDIR}/libmbedcrypto.a - cp $(PKG_BUILDDIR)/output/lib/libopenthread-ftd.a ${BINDIR}/libopenthread.a - cp $(PKG_BUILDDIR)/output/lib/libopenthread-cli-ftd.a ${BINDIR}/libopenthread-cli.a + cp $(PKG_BUILDDIR)/output/lib/libmbedcrypto.a ${BINDIR}/mbedcrypto.a +ifneq (,$(filter openthread-cli-ftd,$(USEMODULE))) + cp $(PKG_BUILDDIR)/output/lib/libopenthread-ftd.a ${BINDIR}/openthread-ftd.a + cp $(PKG_BUILDDIR)/output/lib/libopenthread-cli-ftd.a ${BINDIR}/openthread-cli-ftd.a +endif +ifneq (,$(filter openthread-cli-mtd,$(USEMODULE))) + cp $(PKG_BUILDDIR)/output/lib/libopenthread-mtd.a ${BINDIR}/openthread-mtd.a + cp $(PKG_BUILDDIR)/output/lib/libopenthread-cli-mtd.a ${BINDIR}/openthread-cli-mtd.a +endif +ifneq (,$(filter openthread-ncp-ftd,$(USEMODULE))) + cp $(PKG_BUILDDIR)/output/lib/libopenthread-ftd.a ${BINDIR}/openthread-ftd.a + cp $(PKG_BUILDDIR)/output/lib/libopenthread-ncp-ftd.a ${BINDIR}/openthread-ncp-ftd.a +endif sed -ie 's/BASE/_BASE/g' $(PKG_BUILDDIR)/output/include/openthread/types.h -include $(RIOTBASE)/pkg/pkg.mk + diff --git a/pkg/openthread/Makefile.include b/pkg/openthread/Makefile.include index b4eebf43654d..07ec36a8a31c 100644 --- a/pkg/openthread/Makefile.include +++ b/pkg/openthread/Makefile.include @@ -1,11 +1,13 @@ OPENTHREAD_DIR = $(RIOTBASE)/pkg/openthread +OPENTHREAD_SOURCEDIR = $(RIOTBASE)/pkg/openthread/source INCLUDES += -I$(OPENTHREAD_DIR)/include \ -I$(OPENTHREAD_DIR)/include/openthread \ - -I$(BINDIRBASE)/pkg/$(BOARD)/openthread/output/include \ - -I$(BINDIRBASE)/pkg/$(BOARD)/openthread/include/openthread \ + -I$(OPENTHREAD_SOURCEDIR)/output/include \ + -I$(OPENTHREAD_SOURCEDIR)/include \ + -I$(OPENTHREAD_SOURCEDIR)/include/openthread \ + -I$(OPENTHREAD_SOURCEDIR)/include/openthread/platform \ ifneq (,$(filter openthread_contrib,$(USEMODULE))) DIRS += $(OPENTHREAD_DIR)/contrib - DIRS += $(OPENTHREAD_DIR)/contrib/netdev endif diff --git a/pkg/openthread/contrib/netdev/Makefile b/pkg/openthread/contrib/netdev/Makefile deleted file mode 100644 index 7f8ff815f523..000000000000 --- a/pkg/openthread/contrib/netdev/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -MODULE := openthread_contrib_netdev - -include $(RIOTBASE)/Makefile.base diff --git a/pkg/openthread/contrib/netdev/openthread_netdev.c b/pkg/openthread/contrib/netdev/openthread_netdev.c deleted file mode 100644 index 6c294cd207d9..000000000000 --- a/pkg/openthread/contrib/netdev/openthread_netdev.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (C) 2017 Fundacion Inria Chile - * - * 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 net - * @file - * @brief Netdev adoption for OpenThread - * - * @author Jose Ignacio Alamos - * @} - */ - -#include -#include -#include -#include "msg.h" -#include "openthread/cli.h" -#include "openthread/instance.h" -#include "openthread/ip6.h" -#include "openthread/platform/alarm.h" -#include "openthread/platform/uart.h" -#include "openthread/tasklet.h" -#include "openthread/thread.h" -#include "random.h" -#include "ot.h" - -#define ENABLE_DEBUG (0) -#include "debug.h" - -#define OPENTHREAD_QUEUE_LEN (8) -static msg_t _queue[OPENTHREAD_QUEUE_LEN]; - -static kernel_pid_t _pid; -static otInstance *sInstance; - -/** - * @name Default configuration for OpenThread network - * @{ - */ -#ifndef OPENTHREAD_PANID -#define OPENTHREAD_PANID 0x1234 -#endif -#ifndef OPENTHREAD_CHANNEL -#define OPENTHREAD_CHANNEL (26U) -#endif -/** @} */ - -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; -} - -/* OpenThread will call this when switching state from empty tasklet to non-empty tasklet. */ -void otTaskletsSignalPending(otInstance *aInstance) { - otTaskletsProcess(aInstance); -} - -static void *_openthread_event_loop(void *arg) { - _pid = thread_getpid(); - - /* enable OpenThread UART */ - otPlatUartEnable(); - - /* init OpenThread */ - sInstance = otInstanceInit(); - - msg_init_queue(_queue, OPENTHREAD_QUEUE_LEN); - netdev_t *dev; - msg_t msg, reply; - - otCliUartInit(sInstance); - -#if OPENTHREAD_ENABLE_DIAG - diagInit(sInstance); -#endif - - /* Init default parameters */ - otPanId panid = OPENTHREAD_PANID; - uint8_t channel = OPENTHREAD_CHANNEL; - otLinkSetPanId(sInstance, panid); - otLinkSetChannel(sInstance, channel); - /* Bring up the IPv6 interface */ - otIp6SetEnabled(sInstance, true); - /* Start Thread protocol operation */ - otThreadSetEnabled(sInstance, true); - - uint8_t *buf; - ot_job_t *job; - while (1) { - msg_receive(&msg); - switch (msg.type) { - case OPENTHREAD_XTIMER_MSG_TYPE_EVENT: - /* Tell OpenThread a time event was received */ - otPlatAlarmFired(sInstance); - break; - case OPENTHREAD_NETDEV_MSG_TYPE_EVENT: - /* Received an event from driver */ - dev = msg.content.ptr; - dev->driver->isr(dev); - break; - case OPENTHREAD_SERIAL_MSG_TYPE_EVENT: - /* Tell OpenThread about the reception of a CLI command */ - buf = msg.content.ptr; - otPlatUartReceived(buf, strlen((char *) buf)); - break; - 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; -} - -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)); - - _pid = thread_create(stack, stacksize, - priority, THREAD_CREATE_STACKTEST, - _openthread_event_loop, NULL, name); - - if (_pid <= 0) { - return -EINVAL; - } - - return _pid; -} diff --git a/pkg/openthread/contrib/openthread.c b/pkg/openthread/contrib/openthread.c deleted file mode 100644 index 882bb9bd7ae6..000000000000 --- a/pkg/openthread/contrib/openthread.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2017 Fundacion Inria Chile - * - * 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 net - * @file - * @brief Implementation of OpenThread main functions - * - * @author Jose Ignacio Alamos - * @} - */ - -#include - -#include "openthread/platform/alarm.h" -#include "openthread/platform/uart.h" -#include "ot.h" -#include "random.h" -#include "thread.h" -#include "xtimer.h" - -#ifdef MODULE_AT86RF2XX -#include "at86rf2xx.h" -#include "at86rf2xx_params.h" -#endif - -#define ENABLE_DEBUG (0) -#include "debug.h" - -#ifdef MODULE_AT86RF2XX /* is mutual exclusive with above ifdef */ -#define OPENTHREAD_NETIF_NUMOF (sizeof(at86rf2xx_params) / sizeof(at86rf2xx_params[0])) -#endif - -#ifdef MODULE_AT86RF2XX -static at86rf2xx_t at86rf2xx_dev; -#endif - -#define OPENTHREAD_NETDEV_BUFLEN (ETHERNET_MAX_LEN) - -static uint8_t rx_buf[OPENTHREAD_NETDEV_BUFLEN]; -static uint8_t tx_buf[OPENTHREAD_NETDEV_BUFLEN]; -static char ot_thread_stack[2 * THREAD_STACKSIZE_MAIN]; - -/* init and run OpeanThread's UART simulation (stdio) */ -void openthread_uart_run(void) -{ - char buf[256]; - msg_t msg; - - msg.type = OPENTHREAD_SERIAL_MSG_TYPE_EVENT; - msg.content.ptr = buf; - - buf[1] = 0; - while (1) { - char c = getchar(); - buf[0] = c; - msg_send(&msg, openthread_get_pid()); - } -} - -void openthread_bootstrap(void) -{ - /* init random */ - ot_random_init(); - - /* setup netdev modules */ -#ifdef MODULE_AT86RF2XX - at86rf2xx_setup(&at86rf2xx_dev, &at86rf2xx_params[0]); - netdev_t *netdev = (netdev_t *) &at86rf2xx_dev; -#endif - - openthread_radio_init(netdev, tx_buf, rx_buf); - openthread_netdev_init(ot_thread_stack, sizeof(ot_thread_stack), THREAD_PRIORITY_MAIN - 5, "openthread", netdev); -} diff --git a/pkg/openthread/contrib/openthread_event_thread.c b/pkg/openthread/contrib/openthread_event_thread.c new file mode 100644 index 000000000000..337031f8f9aa --- /dev/null +++ b/pkg/openthread/contrib/openthread_event_thread.c @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2017 UC Berkeley + * + * 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 BETS + * @file + * @brief Implementation of OpenThread critical event thread + * + * @author Hyung-Sin Kim + * @} + */ + +#include "thread.h" +#include "ot.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +#define OPENTHREAD_EVENT_QUEUE_LEN (3) +static msg_t _queue[OPENTHREAD_EVENT_QUEUE_LEN]; +static kernel_pid_t _pid; + +/* OpenThread critical event Thread */ +static void *_openthread_event_thread(void *arg) { + _pid = thread_getpid(); + + msg_init_queue(_queue, OPENTHREAD_EVENT_QUEUE_LEN); + msg_t msg; + + while (1) { + msg_receive(&msg); + switch (msg.type) { + case OPENTHREAD_XTIMER_MSG_TYPE_EVENT: + /* Tell OpenThread a time event was received */ + DEBUG("\not_event: OPENTHREAD_XTIMER_MSG_TYPE_EVENT received\n"); + msg.type = OPENTHREAD_XTIMER_MSG_TYPE_EVENT; + msg_send(&msg, openthread_get_main_pid()); + break; + case OPENTHREAD_NETDEV_MSG_TYPE_EVENT: + /* Received an event from driver */ + DEBUG("\not_event: OPENTHREAD_NETDEV_MSG_TYPE_EVENT received\n"); + msg.type = OPENTHREAD_NETDEV_MSG_TYPE_EVENT; + msg_send(&msg, openthread_get_main_pid()); + break; + } + if (openthread_event_stack_overflow_check()) { + DEBUG("\n\n\n\n\n\n\n\n\n\n\n\nevent thread stack overflow\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); + NVIC_SystemReset(); + } + } + + return NULL; +} + +/* starts OpenThread critical event thread */ +int openthread_event_init(char *stack, int stacksize, char priority, const char *name) { + + _pid = thread_create(stack, stacksize, priority, THREAD_CREATE_STACKTEST, + _openthread_event_thread, NULL, name); + + if (_pid <= 0) { + return -EINVAL; + } + + return _pid; +} diff --git a/pkg/openthread/contrib/openthread_main_thread.c b/pkg/openthread/contrib/openthread_main_thread.c new file mode 100644 index 000000000000..c4bb8f89171a --- /dev/null +++ b/pkg/openthread/contrib/openthread_main_thread.c @@ -0,0 +1,301 @@ +/* + * Copyright (C) 2017 Fundacion Inria Chile + * Copyright (C) 2017 UC Berkeley + * + * 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 net + * @file + * @brief Implementation of OpenThread main functions + * + * @author Jose Ignacio Alamos + * @author Hyung-Sin Kim + * @} + */ + +#include + +#include "openthread/platform/uart.h" +#include "openthread/cli.h" +#include "openthread/ip6.h" +#include "openthread/instance.h" +#include "openthread/thread.h" +#include "openthread/platform/alarm-milli.h" +#include "openthread/tasklet.h" +#include "ot.h" +#include "random.h" +#include "thread.h" +#include "xtimer.h" + +#ifdef MODULE_OPENTHREAD_NCP_FTD +#include "openthread/ncp.h" +#endif + +#ifdef MODULE_AT86RF2XX +#include "at86rf2xx.h" +#include "at86rf2xx_params.h" +#endif + +#define ENABLE_DEBUG (0) +#include "debug.h" + +#ifdef MODULE_AT86RF2XX /* is mutual exclusive with above ifdef */ +#define OPENTHREAD_NETIF_NUMOF (sizeof(at86rf2xx_params) / sizeof(at86rf2xx_params[0])) +#endif + +static otInstance *sInstance; + +static xtimer_t ot_timer; + +#ifdef MODULE_AT86RF2XX +static at86rf2xx_t at86rf2xx_dev; +#endif + +#define OPENTHREAD_QUEUE_LEN (8) +static msg_t _queue[OPENTHREAD_QUEUE_LEN]; +static char ot_main_thread_stack[THREAD_STACKSIZE_MAIN+1004]; +static kernel_pid_t main_pid; + +static uint8_t rx_buf[OPENTHREAD_NETDEV_BUFLEN]; +static uint8_t tx_buf[OPENTHREAD_NETDEV_BUFLEN]; + +static char ot_event_thread_stack[THREAD_STACKSIZE_MAIN+4]; +static kernel_pid_t event_pid; + + +/* get OpenThread instance */ +otInstance* openthread_get_instance(void) { + return sInstance; +} + +/* get OpenThread thread main pid */ +kernel_pid_t openthread_get_main_pid(void) { + return main_pid; +} + +/* get OpenThread thread event pid */ +kernel_pid_t openthread_get_event_pid(void) { + return event_pid; +} + +netdev_t* openthread_get_netdev(void) { + return (netdev_t*) &at86rf2xx_dev; +} + +xtimer_t* openthread_get_timer(void) { + return &ot_timer; +} + +bool openthread_main_stack_overflow_check(void) { + if (ot_main_thread_stack[0] == 0xA9 && ot_main_thread_stack[1] == 0x3C && + ot_main_thread_stack[2] == 0x08 && ot_main_thread_stack[3] == 0x29) { + return false; + } + return true; +} + +bool openthread_event_stack_overflow_check(void) { + if (ot_event_thread_stack[0] == 0x82 && ot_event_thread_stack[1] == 0xAE && + ot_event_thread_stack[2] == 0xCA && ot_event_thread_stack[3] == 0x11) { + return false; + } + return true; +} + +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_main_pid()); + return (uint8_t)reply.content.value; +} + +/* OpenThread will call this when switching state from empty tasklet to non-empty tasklet. */ +void otTaskletsSignalPending(otInstance *aInstance) { + (void) aInstance; +} + +/* Interupt handler for OpenThread timer event */ +void _timer_cb(void* arg) { + msg_t msg; + msg.type = OPENTHREAD_XTIMER_MSG_TYPE_EVENT; + msg_send(&msg, event_pid); +} + +/* Interupt handler for OpenThread netdev thread */ +static void _event_cb(netdev_t *dev, netdev_event_t event) { + switch (event) { + case NETDEV_EVENT_ISR: + { + msg_t msg; + msg.type = OPENTHREAD_NETDEV_MSG_TYPE_EVENT; + msg.content.ptr = dev; + + if (msg_send(&msg,main_pid) <= 0) { + DEBUG("ot_main: possibly lost interrupt.\n"); + } + break; + } + case NETDEV_EVENT_ISR2: + { + msg_t msg; + msg.type = OPENTHREAD_NETDEV_MSG_TYPE_EVENT; + msg.content.ptr = dev; + + if (msg_send(&msg, openthread_get_event_pid()) <= 0) { + DEBUG("ot_event: possibly lost interrupt.\n"); + } + break; + } + case NETDEV_EVENT_RX_COMPLETE: + recv_pkt(sInstance, dev); + break; + case NETDEV_EVENT_TX_COMPLETE: + case NETDEV_EVENT_TX_COMPLETE_DATA_PENDING: + case NETDEV_EVENT_TX_NOACK: + case NETDEV_EVENT_TX_MEDIUM_BUSY: + sent_pkt(sInstance, event); + break; + default: + break; + } +} + +static void *_openthread_main_thread(void *arg) { + main_pid = thread_getpid(); + + msg_init_queue(_queue, OPENTHREAD_QUEUE_LEN); + msg_t msg, reply; + + netdev_t* netdev = (netdev_t *) &at86rf2xx_dev; + + ot_job_t *job; + serial_msg_t* serialBuffer; + + /* enable OpenThread UART */ + otPlatUartEnable(); + DEBUG("ot_main: UART setting is OK\n"); + + /* init OpenThread */ + sInstance = otInstanceInitSingle(); + DEBUG("ot_main: OT-instance setting is OK\n"); + +#if defined(MODULE_OPENTHREAD_CLI_FTD) || defined(MODULE_OPENTHREAD_CLI_MTD) + otCliUartInit(sInstance); + DEBUG("ot-main: OT-UART initialization is OK\n"); + /* Init default parameters */ + otPanId panid = OPENTHREAD_PANID; + uint8_t channel = OPENTHREAD_CHANNEL; + otLinkSetPanId(sInstance, panid); + otLinkSetChannel(sInstance, channel); + /* Bring up the IPv6 interface */ + otIp6SetEnabled(sInstance, true); + DEBUG("ot_main: OT-IPv6 setting is OK\n"); + /* Start Thread protocol operation */ + otThreadSetEnabled(sInstance, true); + DEBUG("ot_main: OT-initialization is OK\n"); +#endif + +#ifdef MODULE_OPENTHREAD_NCP_FTD + otNcpInit(sInstance); + DEBUG("ot_main: OT-NCP setting is OK\n"); +#endif + +#if OPENTHREAD_ENABLE_DIAG + diagInit(sInstance); +#endif + + DEBUG("ot_main: START!\n"); + + while (1) { + otTaskletsProcess(sInstance); + if (otTaskletsArePending(sInstance) == false) { + //DEBUG("****** ot_main sleep ******\n"); + if (openthread_main_stack_overflow_check()) { + DEBUG("\n\n\n\n\n\n\n\n\n\n\n\nstack overflow\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); + NVIC_SystemReset(); + } + msg_receive(&msg); + DEBUG("\n****** ot_main wakeup\n"); + switch (msg.type) { + case OPENTHREAD_NETDEV_MSG_TYPE_EVENT: + /* Received an event from driver */ + //DEBUG("ot_main: OPENTHREAD_NETDEV_MSG_TYPE_EVENT received\n"); + netdev->driver->isr(netdev); + break; + case OPENTHREAD_XTIMER_MSG_TYPE_EVENT: + /* Tell OpenThread a time event was received */ + DEBUG("ot_main: timer fired\n");//OPENTHREAD_XTIMER_MSG_TYPE_EVENT received\n"); + otPlatAlarmMilliFired(sInstance); + break; + case OPENTHREAD_SERIAL_MSG_TYPE_EVENT: + /* Tell OpenThread about the reception of a CLI command */ + DEBUG("ot_main: serial\n");//OPENTHREAD_SERIAL_MSG_TYPE_SEND received\n"); + serialBuffer = (serial_msg_t*)msg.content.ptr; + DEBUG("%s", serialBuffer->buf); + otPlatUartReceived((uint8_t*) serialBuffer->buf,serialBuffer->length); + serialBuffer->serial_buffer_status = OPENTHREAD_SERIAL_BUFFER_STATUS_FREE; + break; + case OPENTHREAD_JOB_MSG_TYPE_EVENT: + DEBUG("ot_main: OPENTHREAD_JOB_MSG_TYPE_EVENT received\n"); + job = msg.content.ptr; + reply.content.value = ot_exec_command(sInstance, job->command, job->arg, job->answer); + msg_reply(&msg, &reply); + break; + } + } + } + + return NULL; +} + +void openthread_bootstrap(void) +{ + /* init random */ + ot_random_init(); + + /* set openthread timer callback */ + ot_timer.callback = _timer_cb; + + /* setup netdev modules */ +#ifdef MODULE_AT86RF2XX + at86rf2xx_setup(&at86rf2xx_dev, &at86rf2xx_params[0]); + netdev_t *netdev = (netdev_t *) &at86rf2xx_dev; +#endif + + netdev->driver->init(netdev); + netdev->event_callback = _event_cb; + netopt_enable_t enable = NETOPT_ENABLE; + netdev->driver->set(netdev, NETOPT_RX_END_IRQ, &enable, sizeof(enable)); + netdev->driver->set(netdev, NETOPT_TX_END_IRQ, &enable, sizeof(enable)); + openthread_radio_init(netdev, tx_buf, rx_buf); + DEBUG("RADIO setting is OK\n"); + + ot_main_thread_stack[0] = 0xA9; + ot_main_thread_stack[1] = 0x3C; + ot_main_thread_stack[2] = 0x08; + ot_main_thread_stack[3] = 0x29; + + ot_event_thread_stack[0] = 0x82; + ot_event_thread_stack[1] = 0xAE; + ot_event_thread_stack[2] = 0xCA; + ot_event_thread_stack[3] = 0x11; + + /* init two threads for openthread */ + event_pid = openthread_event_init(ot_event_thread_stack, sizeof(ot_event_thread_stack), + THREAD_PRIORITY_MAIN + 1, "openthread_event"); + main_pid = thread_create(ot_main_thread_stack, sizeof(ot_main_thread_stack), + THREAD_PRIORITY_MAIN + 2, THREAD_CREATE_STACKTEST, + _openthread_main_thread, NULL, "openthread_main"); +} diff --git a/pkg/openthread/contrib/platform_alarm.c b/pkg/openthread/contrib/platform_alarm.c index 6a6f3d6f3225..80dac68c6d19 100644 --- a/pkg/openthread/contrib/platform_alarm.c +++ b/pkg/openthread/contrib/platform_alarm.c @@ -19,17 +19,16 @@ #include #include "msg.h" -#include "openthread/platform/alarm.h" +#include "openthread/platform/alarm-milli.h" #include "ot.h" -#include "thread.h" #include "xtimer.h" #include "timex.h" #define ENABLE_DEBUG (0) #include "debug.h" -static xtimer_t ot_timer; -static msg_t ot_alarm_msg; +uint32_t prev = 0; +uint32_t long_cnt = 0; /** * Set the alarm to fire at @p aDt milliseconds after @p aT0. @@ -38,31 +37,40 @@ static msg_t ot_alarm_msg; * @param[in] aT0 The reference time. * @param[in] aDt The time delay in milliseconds from @p aT0. */ -void otPlatAlarmStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt) +void otPlatAlarmMilliStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt) { - DEBUG("openthread: otPlatAlarmStartAt: aT0: %" PRIu32 ", aDT: %" PRIu32 "\n", aT0, aDt); - ot_alarm_msg.type = OPENTHREAD_XTIMER_MSG_TYPE_EVENT; + //DEBUG("ot_main->otPlatAlarmMilliStartAt: aT0: %" PRIu32 ", aDT: %" PRIu32 "\n", aT0, aDt); + DEBUG("[timer set] %lu ms\n", aDt); - if (aDt == 0) { - msg_send(&ot_alarm_msg, thread_getpid()); + xtimer_remove(openthread_get_timer()); + if (aDt <= 1) { + msg_t msg; + msg.type = OPENTHREAD_XTIMER_MSG_TYPE_EVENT; + msg_send(&msg, openthread_get_event_pid()); } else { - int dt = aDt * US_PER_MS; - xtimer_set_msg(&ot_timer, dt, &ot_alarm_msg, thread_getpid()); + uint32_t dt = aDt * US_PER_MS; + xtimer_set(openthread_get_timer(), dt); } } /* OpenThread will call this to stop alarms */ -void otPlatAlarmStop(otInstance *aInstance) +void otPlatAlarmMilliStop(otInstance *aInstance) { - DEBUG("openthread: otPlatAlarmStop\n"); - xtimer_remove(&ot_timer); + //DEBUG("ot_main->otPlatAlarmMilliStop\n"); + xtimer_remove(openthread_get_timer()); } /* OpenThread will call this for getting running time in millisecs */ -uint32_t otPlatAlarmGetNow(void) +uint32_t otPlatAlarmMilliGetNow(void) { uint32_t now = xtimer_now_usec() / US_PER_MS; - DEBUG("openthread: otPlatAlarmGetNow: %" PRIu32 "\n", now); + if (prev > now) { + long_cnt++; + DEBUG("[timer renew]\n"); + } + prev = now; + now += long_cnt * (0xFFFFFFFF / US_PER_MS); + //DEBUG("ot_main->otPlatAlarmMilliGetNow: %" PRIu32 "\n", now); return now; } diff --git a/pkg/openthread/contrib/platform_functions_wrapper.c b/pkg/openthread/contrib/platform_functions_wrapper.c index e3eb45650bad..c234f5a5577b 100644 --- a/pkg/openthread/contrib/platform_functions_wrapper.c +++ b/pkg/openthread/contrib/platform_functions_wrapper.c @@ -79,7 +79,7 @@ const ot_command_t otCommands[] = uint8_t ot_exec_command(otInstance *ot_instance, const char* command, void *arg, void* answer) { uint8_t res = 0xFF; /* Check running thread */ - if (openthread_get_pid() == thread_getpid()) { + if (openthread_get_main_pid() == thread_getpid()) { for (uint8_t i = 0; i < sizeof(otCommands) / sizeof(otCommands[0]); i++) { if (strcmp(command, otCommands[i].name) == 0) { res = (*otCommands[i].function)(ot_instance, arg, answer); @@ -247,26 +247,23 @@ OT_COMMAND ot_parent(otInstance* ot_instance, void* arg, void* answer) { OT_COMMAND ot_state(otInstance* ot_instance, void* arg, void* answer) { if (answer != NULL) { - uint8_t state = otThreadGetDeviceRole(ot_instance); - *((uint8_t *) answer) = state; + otDeviceRole state = otThreadGetDeviceRole(ot_instance); + *((otDeviceRole *) answer) = state; DEBUG("state: "); switch (state) { - case kDeviceRoleOffline: - puts("offline"); - break; - case kDeviceRoleDisabled: + case OT_DEVICE_ROLE_DISABLED: puts("disabled"); break; - case kDeviceRoleDetached: + case OT_DEVICE_ROLE_DETACHED: puts("detached"); break; - case kDeviceRoleChild: + case OT_DEVICE_ROLE_CHILD: puts("child"); break; - case kDeviceRoleRouter: + case OT_DEVICE_ROLE_ROUTER: puts("router"); break; - case kDeviceRoleLeader: + case OT_DEVICE_ROLE_LEADER: puts("leader"); break; default: diff --git a/pkg/openthread/contrib/platform_logging.c b/pkg/openthread/contrib/platform_logging.c index a3aed1db7d04..829dc01bdb45 100644 --- a/pkg/openthread/contrib/platform_logging.c +++ b/pkg/openthread/contrib/platform_logging.c @@ -13,85 +13,39 @@ * @brief Implementation of OpenThread logging platform abstraction * * @author Jose Ignacio Alamos + * @author Baptiste Clenet * @} */ +#include "openthread/config.h" +#include "openthread/platform/logging.h" +#if OPENTHREAD_ENABLE_CLI_LOGGING #include #include #include #include -#include #include -#include -#include "openthread/platform/logging.h" +#include "utils/code_utils.h" +#include "cli/cli-uart.h" +#endif + +#define ENABLE_DEBUG (0) +#include -/* adapted from OpenThread posix example: - * See: https://github.com/openthread/openthread/blob/master/examples/platforms/posix/logging.c */ void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...) { +#if OPENTHREAD_ENABLE_CLI_LOGGING + va_list args; + va_start(args, aFormat); + otCliLog(aLogLevel, aLogRegion, aFormat, args); + va_end(args); +#else + (void)aLogLevel; + (void)aLogRegion; va_list args; - - switch (aLogLevel) { - case kLogLevelNone: - fprintf(stderr, "NONE "); - break; - - case kLogLevelCrit: - fprintf(stderr, "CRIT "); - break; - - case kLogLevelWarn: - fprintf(stderr, "WARN "); - break; - - case kLogLevelInfo: - fprintf(stderr, "INFO "); - break; - - case kLogLevelDebg: - fprintf(stderr, "DEBG "); - break; - } - - switch (aLogRegion) { - case kLogRegionApi: - fprintf(stderr, "API "); - break; - - case kLogRegionMle: - fprintf(stderr, "MLE "); - break; - - case kLogRegionArp: - fprintf(stderr, "ARP "); - break; - - case kLogRegionNetData: - fprintf(stderr, "NETD "); - break; - - case kLogRegionIp6: - fprintf(stderr, "IPV6 "); - break; - - case kLogRegionIcmp: - fprintf(stderr, "ICMP "); - break; - - case kLogRegionMac: - fprintf(stderr, "MAC "); - break; - - case kLogRegionMem: - fprintf(stderr, "MEM "); - break; - default: - break; - } - va_start(args, aFormat); - vfprintf(stderr, aFormat, args); - fprintf(stderr, "\r"); + DEBUG_V(aFormat, args); va_end(args); +#endif /* OPENTHREAD_ENABLE_CLI_LOGGING */ } diff --git a/pkg/openthread/contrib/platform_misc.c b/pkg/openthread/contrib/platform_misc.c index d8bc9af2b3c6..2d6e97a56bb4 100644 --- a/pkg/openthread/contrib/platform_misc.c +++ b/pkg/openthread/contrib/platform_misc.c @@ -21,10 +21,13 @@ #include "openthread/platform/misc.h" #include "periph/pm.h" +#define ENABLE_DEBUG (0) +#include "debug.h" + void otPlatReset(otInstance *aInstance) { (void)aInstance; - printf("reboot...\n"); + DEBUG("reboot...\n"); pm_reboot(); } @@ -32,5 +35,10 @@ otPlatResetReason otPlatGetResetReason(otInstance *aInstance) { (void)aInstance; /* TODO: Write me! */ - return kPlatResetReason_PowerOn; + return OT_PLAT_RESET_REASON_POWER_ON; +} + +void otPlatWakeHost(void) +{ + /* TODO: implement an operation to wake the host from sleep state. */ } diff --git a/pkg/openthread/contrib/platform_radio.c b/pkg/openthread/contrib/platform_radio.c old mode 100644 new mode 100755 index 6c4e8ba92319..07dd47bb4288 --- a/pkg/openthread/contrib/platform_radio.c +++ b/pkg/openthread/contrib/platform_radio.c @@ -26,6 +26,10 @@ #include "net/ethertype.h" #include "net/ieee802154.h" #include "net/netdev/ieee802154.h" +#include "openthread/config.h" +#include "openthread/openthread.h" +#include "openthread/platform/diag.h" +#include "openthread/platform/platform.h" #include "openthread/platform/radio.h" #include "ot.h" @@ -33,30 +37,26 @@ #include "debug.h" #define RADIO_IEEE802154_FCS_LEN (2U) +#define IEEE802154_ACK_LENGTH (5) +#define IEEE802154_DSN_OFFSET (2) -static RadioPacket sTransmitFrame; -static RadioPacket sReceiveFrame; +static otRadioFrame sTransmitFrame; +static otRadioFrame sReceiveFrame; static int8_t Rssi; static netdev_t *_dev; static bool sDisabled; +uint8_t short_address_list = 0; +uint8_t ext_address_list = 0; + /* set 15.4 channel */ static int _set_channel(uint16_t channel) { return _dev->driver->set(_dev, NETOPT_CHANNEL, &channel, sizeof(uint16_t)); } -/*get transmission power from driver */ -static int16_t _get_power(void) -{ - int16_t power; - - _dev->driver->get(_dev, NETOPT_TX_POWER, &power, sizeof(int16_t)); - return power; -} - /* set transmission power */ static int _set_power(int16_t power) { @@ -132,81 +132,21 @@ void openthread_radio_init(netdev_t *dev, uint8_t *tb, uint8_t *rb) _dev = dev; } -/* Called upon NETDEV_EVENT_RX_COMPLETE event */ -void recv_pkt(otInstance *aInstance, netdev_t *dev) -{ - DEBUG("Openthread: Received pkt\n"); - netdev_ieee802154_rx_info_t rx_info; - /* Read frame length from driver */ - int len = dev->driver->recv(dev, NULL, 0, &rx_info); - Rssi = rx_info.rssi; - - /* very unlikely */ - if ((len > (unsigned) UINT16_MAX)) { - DEBUG("Len too high: %d\n", len); - otPlatRadioReceiveDone(aInstance, NULL, kThreadError_Abort); - return; - } - - /* Fill OpenThread receive frame */ - /* Openthread needs a packet length with FCS included, - * OpenThread do not use the data so we don't need to calculate FCS */ - sReceiveFrame.mLength = len + RADIO_IEEE802154_FCS_LEN; - sReceiveFrame.mPower = _get_power(); - - /* Read received frame */ - int res = dev->driver->recv(dev, (char *) sReceiveFrame.mPsdu, len, NULL); - - DEBUG("Received message: len %d\n", (int) sReceiveFrame.mLength); - for (int i = 0; i < sReceiveFrame.mLength; ++i) { - DEBUG("%x ", sReceiveFrame.mPsdu[i]); - } - DEBUG("\n"); - - /* Tell OpenThread that receive has finished */ - otPlatRadioReceiveDone(aInstance, res > 0 ? &sReceiveFrame : NULL, res > 0 ? kThreadError_None : kThreadError_Abort); -} - -/* Called upon TX event */ -void send_pkt(otInstance *aInstance, netdev_t *dev, netdev_event_t event) -{ - /* Tell OpenThread transmission is done depending on the NETDEV event */ - switch (event) { - case NETDEV_EVENT_TX_COMPLETE: - DEBUG("openthread: NETDEV_EVENT_TX_COMPLETE\n"); - otPlatRadioTransmitDone(aInstance, &sTransmitFrame, false, kThreadError_None); - break; - case NETDEV_EVENT_TX_COMPLETE_DATA_PENDING: - DEBUG("openthread: NETDEV_EVENT_TX_COMPLETE_DATA_PENDING\n"); - otPlatRadioTransmitDone(aInstance, &sTransmitFrame, true, kThreadError_None); - break; - case NETDEV_EVENT_TX_NOACK: - DEBUG("openthread: NETDEV_EVENT_TX_NOACK\n"); - otPlatRadioTransmitDone(aInstance, &sTransmitFrame, false, kThreadError_NoAck); - break; - case NETDEV_EVENT_TX_MEDIUM_BUSY: - DEBUG("openthread: NETDEV_EVENT_TX_MEDIUM_BUSY\n"); - otPlatRadioTransmitDone(aInstance, &sTransmitFrame, false, kThreadError_ChannelAccessFailure); - break; - default: - break; - } -} /* OpenThread will call this for setting PAN ID */ void otPlatRadioSetPanId(otInstance *aInstance, uint16_t panid) { - DEBUG("openthread: otPlatRadioSetPanId: setting PAN ID to %04x\n", panid); + DEBUG("otPlatRadioSetPanId: setting PAN ID to %04x\n", panid); _set_panid(panid); } /* OpenThread will call this for setting extended address */ -void otPlatRadioSetExtendedAddress(otInstance *aInstance, uint8_t *aExtendedAddress) +void otPlatRadioSetExtendedAddress(otInstance *aInstance, const otExtAddress *aExtendedAddress) { - DEBUG("openthread: otPlatRadioSetExtendedAddress\n"); + DEBUG("otPlatRadioSetExtendedAddr\n"); uint8_t reversed_addr[IEEE802154_LONG_ADDRESS_LEN]; for (int i = 0; i < IEEE802154_LONG_ADDRESS_LEN; i++) { - reversed_addr[i] = aExtendedAddress[IEEE802154_LONG_ADDRESS_LEN - 1 - i]; + reversed_addr[i] = aExtendedAddress->m8[IEEE802154_LONG_ADDRESS_LEN - 1 - i]; } _set_long_addr(reversed_addr); } @@ -214,14 +154,14 @@ void otPlatRadioSetExtendedAddress(otInstance *aInstance, uint8_t *aExtendedAddr /* OpenThread will call this for setting short address */ void otPlatRadioSetShortAddress(otInstance *aInstance, uint16_t aShortAddress) { - DEBUG("openthread: otPlatRadioSetShortAddress: setting address to %04x\n", aShortAddress); + DEBUG("otPlatRadioSetShortAddr: %04x\n", aShortAddress); _set_addr(((aShortAddress & 0xff) << 8) | ((aShortAddress >> 8) & 0xff)); } /* OpenThread will call this for enabling the radio */ -ThreadError otPlatRadioEnable(otInstance *aInstance) +otError otPlatRadioEnable(otInstance *aInstance) { - DEBUG("openthread: otPlatRadioEnable\n"); + DEBUG("otPlatRadioEnable\n"); (void) aInstance; if (sDisabled) { @@ -229,21 +169,20 @@ ThreadError otPlatRadioEnable(otInstance *aInstance) _set_idle(); } - return kThreadError_None; + return OT_ERROR_NONE; } /* OpenThread will call this for disabling the radio */ -ThreadError otPlatRadioDisable(otInstance *aInstance) +otError otPlatRadioDisable(otInstance *aInstance) { - DEBUG("openthread: otPlatRadioDisable\n"); + DEBUG("otPlatRadioDisable\n"); (void) aInstance; if (!sDisabled) { sDisabled = true; _set_sleep(); } - - return kThreadError_None; + return OT_ERROR_NONE; } bool otPlatRadioIsEnabled(otInstance *aInstance) @@ -259,30 +198,31 @@ bool otPlatRadioIsEnabled(otInstance *aInstance) } /* OpenThread will call this for setting device state to SLEEP */ -ThreadError otPlatRadioSleep(otInstance *aInstance) +otError otPlatRadioSleep(otInstance *aInstance) { DEBUG("otPlatRadioSleep\n"); (void) aInstance; _set_sleep(); - return kThreadError_None; + return OT_ERROR_NONE; } /*OpenThread will call this for waiting the reception of a packet */ -ThreadError otPlatRadioReceive(otInstance *aInstance, uint8_t aChannel) +otError otPlatRadioReceive(otInstance *aInstance, uint8_t aChannel) { - DEBUG("openthread: otPlatRadioReceive. Channel: %i\n", aChannel); + //DEBUG("openthread: otPlatRadioReceive. Channel: %i\n", aChannel); (void) aInstance; _set_idle(); _set_channel(aChannel); - return kThreadError_None; + + return OT_ERROR_NONE; } /* OpenThread will call this function to get the transmit buffer */ -RadioPacket *otPlatRadioGetTransmitBuffer(otInstance *aInstance) +otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *aInstance) { - DEBUG("openthread: otPlatRadioGetTransmitBuffer\n"); + DEBUG("otPlatRadioGetTransmitBuffer\n"); return &sTransmitFrame; } @@ -295,7 +235,7 @@ void otPlatRadioSetDefaultTxPower(otInstance *aInstance, int8_t aPower) } /* OpenThread will call this for transmitting a packet*/ -ThreadError otPlatRadioTransmit(otInstance *aInstance, RadioPacket *aPacket) +otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aPacket) { (void) aInstance; struct iovec pkt; @@ -308,39 +248,43 @@ ThreadError otPlatRadioTransmit(otInstance *aInstance, RadioPacket *aPacket) pkt.iov_len = aPacket->mLength - RADIO_IEEE802154_FCS_LEN; /*Set channel and power based on transmit frame */ - DEBUG("otPlatRadioTransmit->channel: %i, length %d\n", (int) aPacket->mChannel, (int)aPacket->mLength); - for (int i = 0; i < aPacket->mLength; ++i) { + DEBUG("otTx->channel: %i, length %d, power %d\n", (int) aPacket->mChannel, (int)aPacket->mLength, aPacket->mPower); + /*for (int i = 0; i < aPacket->mLength; ++i) { DEBUG("%x ", aPacket->mPsdu[i]); } - DEBUG("\n"); + DEBUG("\n");*/ _set_channel(aPacket->mChannel); _set_power(aPacket->mPower); /* send packet though netdev */ _dev->driver->send(_dev, &pkt, 1); - return kThreadError_None; + return OT_ERROR_NONE; } /* OpenThread will call this for getting the radio caps */ otRadioCaps otPlatRadioGetCaps(otInstance *aInstance) { - DEBUG("openthread: otPlatRadioGetCaps\n"); - /* all drivers should handle ACK, including call of NETDEV_EVENT_TX_NOACK */ - return kRadioCapsNone; + //DEBUG("openthread: otPlatRadioGetCaps\n"); + /* radio drivers should handle retransmission and CSMA */ +#if MODULE_AT86RF231 | MODULE_AT86RF233 + return OT_RADIO_CAPS_ACK_TIMEOUT | OT_RADIO_CAPS_TRANSMIT_RETRIES | OT_RADIO_CAPS_CSMA_BACKOFF; +#else + return OT_RADIO_CAPS_NONE; +#endif } /* OpenThread will call this for getting the state of promiscuous mode */ bool otPlatRadioGetPromiscuous(otInstance *aInstance) { - DEBUG("openthread: otPlatRadioGetPromiscuous\n"); + //DEBUG("openthread: otPlatRadioGetPromiscuous\n"); return _is_promiscuous(); } /* OpenThread will call this for setting the state of promiscuous mode */ void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnable) { - DEBUG("openthread: otPlatRadioSetPromiscuous\n"); + //DEBUG("openthread: otPlatRadioSetPromiscuous\n"); _set_promiscuous((aEnable) ? NETOPT_ENABLE : NETOPT_DISABLE); } @@ -358,57 +302,89 @@ void otPlatRadioEnableSrcMatch(otInstance *aInstance, bool aEnable) (void)aEnable; } -ThreadError otPlatRadioAddSrcMatchShortEntry(otInstance *aInstance, const uint16_t aShortAddress) +/* OpenThread will call this for indirect transmission to a child node */ +otError otPlatRadioAddSrcMatchShortEntry(otInstance *aInstance, const uint16_t aShortAddress) { - DEBUG("otPlatRadioAddSrcMatchShortEntry\n"); + DEBUG("otPlatRadioAddSrcMatchShortEntry %u\n", short_address_list+1); (void)aInstance; (void)aShortAddress; - return kThreadError_None; + short_address_list++; + bool pending = true; + _dev->driver->set(_dev, NETOPT_ACK_PENDING, &pending, sizeof(bool)); + return OT_ERROR_NONE; } -ThreadError otPlatRadioAddSrcMatchExtEntry(otInstance *aInstance, const uint8_t *aExtAddress) +/* OpenThread will call this for indirect transmission to a child node */ +otError otPlatRadioAddSrcMatchExtEntry(otInstance *aInstance, const otExtAddress *aExtAddress) { - DEBUG("otPlatRadioAddSrcMatchExtEntry\n"); + DEBUG("otPlatRadioAddSrcMatchExtEntry %u\n", ext_address_list+1); (void)aInstance; (void)aExtAddress; - return kThreadError_None; + ext_address_list++; + bool pending = true; + _dev->driver->set(_dev, NETOPT_ACK_PENDING, &pending, sizeof(bool)); + return OT_ERROR_NONE; } -ThreadError otPlatRadioClearSrcMatchShortEntry(otInstance *aInstance, const uint16_t aShortAddress) +/* OpenThread will call this to remove an indirect transmission entry */ +otError otPlatRadioClearSrcMatchShortEntry(otInstance *aInstance, const uint16_t aShortAddress) { - DEBUG("otPlatRadioClearSrcMatchShortEntry\n"); + DEBUG("otPlatRadioClearSrcMatchShortEntry %u\n", short_address_list-1); (void)aInstance; (void)aShortAddress; - return kThreadError_None; + short_address_list--; + if (ext_address_list == 0 && short_address_list == 0) { + bool pending = false; + _dev->driver->set(_dev, NETOPT_ACK_PENDING, &pending, sizeof(bool)); + } + return OT_ERROR_NONE; } -ThreadError otPlatRadioClearSrcMatchExtEntry(otInstance *aInstance, const uint8_t *aExtAddress) +/* OpenThread will call this to remove an indirect transmission entry */ +otError otPlatRadioClearSrcMatchExtEntry(otInstance *aInstance, const otExtAddress *aExtAddress) { - DEBUG("otPlatRadioClearSrcMatchExtEntry\n"); + DEBUG("otPlatRadioClearSrcMatchExtEntry %u\n", ext_address_list-1); (void)aInstance; (void)aExtAddress; - return kThreadError_None; + ext_address_list--; + if (ext_address_list == 0 && short_address_list == 0) { + bool pending = false; + _dev->driver->set(_dev, NETOPT_ACK_PENDING, &pending, sizeof(bool)); + } + return OT_ERROR_NONE; } +/* OpenThread will call this to clear indirect transmission list */ void otPlatRadioClearSrcMatchShortEntries(otInstance *aInstance) { - DEBUG("otPlatRadioClearSrcMatchShortEntries\n"); + DEBUG("otPlatRadioClearSrcMatchShortEntries\n"); (void)aInstance; + short_address_list = 0; + if (ext_address_list == 0 && short_address_list == 0) { + bool pending = false; + _dev->driver->set(_dev, NETOPT_ACK_PENDING, &pending, sizeof(bool)); + } } +/* OpenThread will call this to clear indirect transmission list */ void otPlatRadioClearSrcMatchExtEntries(otInstance *aInstance) { DEBUG("otPlatRadioClearSrcMatchExtEntries\n"); (void)aInstance; + ext_address_list = 0; + if (ext_address_list == 0 && short_address_list == 0) { + bool pending = false; + _dev->driver->set(_dev, NETOPT_ACK_PENDING, &pending, sizeof(bool)); + } } -ThreadError otPlatRadioEnergyScan(otInstance *aInstance, uint8_t aScanChannel, uint16_t aScanDuration) +otError otPlatRadioEnergyScan(otInstance *aInstance, uint8_t aScanChannel, uint16_t aScanDuration) { DEBUG("otPlatRadioEnergyScan\n"); (void)aInstance; (void)aScanChannel; (void)aScanDuration; - return kThreadError_NotImplemented; + return OT_ERROR_NOT_IMPLEMENTED; } void otPlatRadioGetIeeeEui64(otInstance *aInstance, uint8_t *aIeee64Eui64) @@ -418,5 +394,104 @@ void otPlatRadioGetIeeeEui64(otInstance *aInstance, uint8_t *aIeee64Eui64) int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance) { +#if MODULE_AT86RF231 | MODULE_AT86RF233 + return -94; +#else return -100; +#endif +} + + +/* create a fake ACK frame */ +// TODO: pass received ACK frame instead of generating one. +static inline otRadioFrame _create_fake_ack_frame(bool ackPending) +{ + otRadioFrame ackFrame; + uint8_t psdu[IEEE802154_ACK_LENGTH]; + + ackFrame.mPsdu = psdu; + ackFrame.mLength = IEEE802154_ACK_LENGTH; + ackFrame.mPsdu[0] = IEEE802154_FCF_TYPE_ACK; + + if (ackPending) + { + ackFrame.mPsdu[0] |= IEEE802154_FCF_FRAME_PEND; + } + + ackFrame.mPsdu[1] = 0; + ackFrame.mPsdu[2] = sTransmitFrame.mPsdu[IEEE802154_DSN_OFFSET]; + + ackFrame.mPower = OT_RADIO_RSSI_INVALID; + + return ackFrame; +} + +/* Called upon TX event */ +void sent_pkt(otInstance *aInstance, netdev_event_t event) +{ + otRadioFrame ackFrame; + /* Tell OpenThread transmission is done depending on the NETDEV event */ + switch (event) { + case NETDEV_EVENT_TX_COMPLETE: + DEBUG("ot: TX_COMPLETE\n"); + ackFrame = _create_fake_ack_frame(false); + otPlatRadioTxDone(aInstance, &sTransmitFrame, &ackFrame, OT_ERROR_NONE); + break; + case NETDEV_EVENT_TX_COMPLETE_DATA_PENDING: + DEBUG("ot: TX_COMPLETE_DATA_PENDING\n"); + ackFrame = _create_fake_ack_frame(true); + otPlatRadioTxDone(aInstance, &sTransmitFrame, &ackFrame, OT_ERROR_NONE); + break; + case NETDEV_EVENT_TX_NOACK: + DEBUG("ot: TX_NOACK\n"); + otPlatRadioTxDone(aInstance, &sTransmitFrame, NULL, OT_ERROR_NO_ACK); + break; + case NETDEV_EVENT_TX_MEDIUM_BUSY: + DEBUG("ot: TX_MEDIUM_BUSY\n"); + otPlatRadioTxDone(aInstance, &sTransmitFrame, NULL, OT_ERROR_CHANNEL_ACCESS_FAILURE); + break; + default: + break; + } +} + + +/* Called upon NETDEV_EVENT_RX_COMPLETE event */ +void recv_pkt(otInstance *aInstance, netdev_t *dev) +{ + netdev_ieee802154_rx_info_t rx_info; + int res; + + /* Read frame length from driver */ + int len = dev->driver->recv(dev, NULL, 0, NULL); + + /* very unlikely */ + if ((len > (unsigned) UINT16_MAX)) { + DEBUG("Len too high: %d\n", len); + res = -1; + goto exit; + } + + /* Fill OpenThread receive frame */ + /* Openthread needs a packet length with FCS included, + * OpenThread do not use the data so we don't need to calculate FCS */ + sReceiveFrame.mLength = len + RADIO_IEEE802154_FCS_LEN; + + /* Read received frame */ + res = dev->driver->recv(dev, (char *) sReceiveFrame.mPsdu, len, &rx_info); +#if MODULE_AT86RF231 | MODULE_AT86RF233 + Rssi = (int8_t)rx_info.rssi - 94; +#else + Rssi = (int8_t)rx_info.rssi; +#endif + sReceiveFrame.mPower = Rssi; + + DEBUG("ot: RX_COMPLETE, len %d, rssi %d\n", (int) sReceiveFrame.mLength, sReceiveFrame.mPower); + /*for (int i = 0; i < sReceiveFrame.mLength; ++i) { + DEBUG("%x ", sReceiveFrame.mPsdu[i]); + } + DEBUG("\n");*/ +exit: + otPlatRadioReceiveDone(aInstance, res > 0 ? &sReceiveFrame : NULL, + res > 0 ? OT_ERROR_NONE : OT_ERROR_ABORT); } diff --git a/pkg/openthread/contrib/platform_random.c b/pkg/openthread/contrib/platform_random.c index c82bb43ebc74..ae8eb27023ac 100644 --- a/pkg/openthread/contrib/platform_random.c +++ b/pkg/openthread/contrib/platform_random.c @@ -49,3 +49,13 @@ uint32_t otPlatRandomGet(void) DEBUG("otPlatRandomGet: %i\n", (int) rand_val); return rand_val; } + +otError otPlatRandomGetTrue(uint8_t *aOutput, uint16_t aOutputLength) +{ + for (uint16_t index = 0; index < aOutputLength; index++) { + aOutput[index] = 0; + uint32_t rand_val = random_uint32(); + aOutput[index] = (uint8_t) rand_val; + } + return OT_ERROR_NONE; +} diff --git a/pkg/openthread/contrib/platform_settings.c b/pkg/openthread/contrib/platform_settings.c index 0e324c5406ec..8607b7bf87a7 100644 --- a/pkg/openthread/contrib/platform_settings.c +++ b/pkg/openthread/contrib/platform_settings.c @@ -26,45 +26,45 @@ void otPlatSettingsInit(otInstance *aInstance) { } -ThreadError otPlatSettingsBeginChange(otInstance *aInstance) +otError otPlatSettingsBeginChange(otInstance *aInstance) { (void)aInstance; - return kThreadError_None; + return OT_ERROR_NONE; } -ThreadError otPlatSettingsCommitChange(otInstance *aInstance) +otError otPlatSettingsCommitChange(otInstance *aInstance) { DEBUG("openthread: otPlatSettingsCommitChange\n"); (void)aInstance; - return kThreadError_None; + return OT_ERROR_NONE; } -ThreadError otPlatSettingsAbandonChange(otInstance *aInstance) +otError otPlatSettingsAbandonChange(otInstance *aInstance) { (void)aInstance; - return kThreadError_None; + return OT_ERROR_NONE; } -ThreadError otPlatSettingsGet(otInstance *aInstance, uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength) +otError otPlatSettingsGet(otInstance *aInstance, uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength) { DEBUG("openthread: otPlatSettingsGet\n"); *aValueLength = 0; - return kThreadError_NotImplemented; + return OT_ERROR_NOT_IMPLEMENTED; } -ThreadError otPlatSettingsSet(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength) +otError otPlatSettingsSet(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength) { - return kThreadError_None; + return OT_ERROR_NONE; } -ThreadError otPlatSettingsAdd(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength) +otError otPlatSettingsAdd(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength) { - return kThreadError_None; + return OT_ERROR_NONE; } -ThreadError otPlatSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex) +otError otPlatSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex) { - return kThreadError_None; + return OT_ERROR_NONE; } void otPlatSettingsWipe(otInstance *aInstance) diff --git a/pkg/openthread/contrib/platform_uart.c b/pkg/openthread/contrib/platform_uart.c old mode 100644 new mode 100755 index d3aff67af3fc..e925472a9103 --- a/pkg/openthread/contrib/platform_uart.c +++ b/pkg/openthread/contrib/platform_uart.c @@ -13,6 +13,7 @@ * @brief Implementation of OpenThread UART platform abstraction * * @author Jose Ignacio Alamos + * @author Baptiste Clenet * @} */ @@ -20,27 +21,157 @@ #include #include "periph/uart.h" +#include "openthread/types.h" #include "openthread/platform/uart.h" +#include "ot.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +#define OPENTHREAD_UART_DEV UART_DEV(0) +#define OPENTHREAD_SPINEL_FRAME_MARKER (0x7e) + +serial_msg_t * gSerialMessage[OPENTHREAD_NUMBER_OF_SERIAL_BUFFER]; +uint8_t gSerialBuff[OPENTHREAD_NUMBER_OF_SERIAL_BUFFER][OPENTHREAD_SERIAL_BUFFER_SIZE]; + +#ifdef MODULE_OPENTHREAD_NCP_FTD +int8_t getFirstEmptySerialBuffer(void) { + uint8_t i = 0; + for (i = 0; i < OPENTHREAD_NUMBER_OF_SERIAL_BUFFER; i++) { + if ( OPENTHREAD_SERIAL_BUFFER_STATUS_FREE == gSerialMessage[i]->serial_buffer_status ) { + break; + } + } + + if ( i >= OPENTHREAD_NUMBER_OF_SERIAL_BUFFER ) { + return OPENTHREAD_ERROR_NO_EMPTY_SERIAL_BUFFER; + } else { + return i; + } +} + +/* OpenThread will call this for enabling UART (required for OpenThread's NCP)*/ +void uart_handler(void* arg, char c) { + + static int16_t currentSerialBufferNumber = 0; + static uint8_t frameLength = 0; + static uint8_t gOnGoingSpinelReception = 0; + + msg_t msg; + msg.type = OPENTHREAD_SERIAL_MSG_TYPE_EVENT; + + if ((c == OPENTHREAD_SPINEL_FRAME_MARKER) && (gOnGoingSpinelReception == false)) { /* Start of Spinel Frame */ + currentSerialBufferNumber = getFirstEmptySerialBuffer(); + if (OPENTHREAD_ERROR_NO_EMPTY_SERIAL_BUFFER == currentSerialBufferNumber) { + DEBUG("SERIAL: ERROR => OPENTHREAD_ERROR_NO_EMPTY_SERIAL_BUFFER found\n"); + return; + } + frameLength = 0; + + gSerialMessage[currentSerialBufferNumber]->buf[frameLength] = c; + + gOnGoingSpinelReception = true; + } + else if ((c == OPENTHREAD_SPINEL_FRAME_MARKER) && (gOnGoingSpinelReception == true)) { /* End of Spinel Frame */ + if ( OPENTHREAD_ERROR_NO_EMPTY_SERIAL_BUFFER == currentSerialBufferNumber ) { + return; + } + if (frameLength == 1) { /* It means that we handle the Start of a Spinel frame instead of the end */ + + frameLength--; + return; + } + if( OPENTHREAD_SERIAL_BUFFER_STATUS_FULL != gSerialMessage[currentSerialBufferNumber]->serial_buffer_status) { + gSerialMessage[currentSerialBufferNumber]->buf[frameLength] = (uint8_t) c; + gSerialMessage[currentSerialBufferNumber]->serial_buffer_status = OPENTHREAD_SERIAL_BUFFER_STATUS_READY_TO_PROCESS; + gSerialMessage[currentSerialBufferNumber]->length = frameLength + 1; + msg.content.ptr = gSerialMessage[currentSerialBufferNumber]; + msg_send_int(&msg, openthread_get_main_pid()); + } + else { + gSerialMessage[currentSerialBufferNumber]->serial_buffer_status = OPENTHREAD_SERIAL_BUFFER_STATUS_FREE; + } + gOnGoingSpinelReception = false; + frameLength = 0; + } + else if (gOnGoingSpinelReception == true) { /* Payload of Spinel Frame */ + if ( OPENTHREAD_ERROR_NO_EMPTY_SERIAL_BUFFER == currentSerialBufferNumber ) { + return; + } + if ( OPENTHREAD_SERIAL_BUFFER_STATUS_FULL != gSerialMessage[currentSerialBufferNumber]->serial_buffer_status) { + gSerialMessage[currentSerialBufferNumber]->buf[frameLength] = (uint8_t) c; + } + } + + if (gOnGoingSpinelReception == true) { + frameLength++; + if ( frameLength >= OPENTHREAD_SERIAL_BUFFER__PAYLOAD_SIZE) { + DEBUG("SERIAL: ERROR => OPENTHREAD_SERIAL_BUFFER__PAYLOAD_SIZE overflowed\n"); + gSerialMessage[currentSerialBufferNumber]->serial_buffer_status = OPENTHREAD_SERIAL_BUFFER_STATUS_FULL; + } + } +} + +#else + +void uart_handler(void* arg, char c) { + static uint16_t frameLength = 0; + if (frameLength == 0 && gSerialMessage != NULL) { + memset(gSerialMessage[0], 0, sizeof(serial_msg_t)); + } + switch (c) { + case '\r': + case '\n': + if (frameLength > 0) { + 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_main_pid()); + frameLength = 0; + } + break; + default: + if (frameLength < OPENTHREAD_SERIAL_BUFFER_SIZE) { + gSerialMessage[0]->buf[frameLength] = c; + frameLength++; + } + break; + } +} + +#endif /* MODULE_OPENTHREAD_NCP_FTD */ /* OpenThread will call this for enabling UART (required for OpenThread's CLI)*/ -ThreadError otPlatUartEnable(void) +otError otPlatUartEnable(void) { - return kThreadError_None; +#ifdef UART_NUMOF + for (uint8_t i = 0; i < OPENTHREAD_NUMBER_OF_SERIAL_BUFFER; i++) { + gSerialMessage[i] = (serial_msg_t*) &gSerialBuff[i]; + gSerialMessage[i]->serial_buffer_status = OPENTHREAD_SERIAL_BUFFER_STATUS_FREE; + } + uart_init(OPENTHREAD_UART_DEV, OPENTHREAD_UART_BAUDRATE, (uart_rx_cb_t) uart_handler, NULL); +#endif + return OT_ERROR_NONE; } /* OpenThread will call this for disabling UART */ -ThreadError otPlatUartDisable(void) +otError otPlatUartDisable(void) { - return kThreadError_None; + uart_poweroff(OPENTHREAD_UART_DEV); + return OT_ERROR_NONE; } /* OpenThread will call this for sending data through UART */ -ThreadError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength) +otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength) { - uart_write(UART_DEV(0), aBuf, aBufLength); +#ifdef UART_NUMOF + uart_write(OPENTHREAD_UART_DEV, aBuf, aBufLength); /* Tell OpenThread the sending of UART is done */ otPlatUartSendDone(); - - return kThreadError_None; +#endif + return OT_ERROR_NONE; } diff --git a/pkg/openthread/include/ot.h b/pkg/openthread/include/ot.h old mode 100644 new mode 100755 index 196ab7c85827..6b2d71ae5c1e --- a/pkg/openthread/include/ot.h +++ b/pkg/openthread/include/ot.h @@ -17,7 +17,8 @@ * * @file * - * @author José Ignacio Alamos + * @author Jose Ignacio Alamos + * @author Baptiste Clenet */ #ifndef OT_H @@ -33,19 +34,50 @@ extern "C" { #include "net/gnrc/netdev.h" #include "thread.h" #include "openthread/types.h" +#include "openthread/platform/radio.h" + +/**< xtimer message receiver event */ +#define OPENTHREAD_XTIMER_MSG_TYPE_EVENT (0x2235) +/**< event indicating a serial (UART) message was sent to OpenThread */ +#define OPENTHREAD_SERIAL_MSG_TYPE_EVENT (0x2236) +/**< event for frame reception */ +#define OPENTHREAD_NETDEV_MSG_TYPE_EVENT (0x2239) +/**< event indicating an OT_JOB message */ +#define OPENTHREAD_JOB_MSG_TYPE_EVENT (0x2241) +/**< number of serial reception buffer */ +#define OPENTHREAD_NUMBER_OF_SERIAL_BUFFER (1U) +/**< sizeof in bytes the two first members of she serial structure */ +#define OPENTHREAD_SIZEOF_LENGTH_AND_FREEBUFF (4U) +#ifdef MODULE_OPENTHREAD_NCP_FTD +/**< sizeof the serial buffer */ +#define OPENTHREAD_SERIAL_BUFFER_SIZE OPENTHREAD_SIZEOF_LENGTH_AND_FREEBUFF + 200 +#else +/**< sizeof the serial buffer */ +#define OPENTHREAD_SERIAL_BUFFER_SIZE OPENTHREAD_SIZEOF_LENGTH_AND_FREEBUFF + 100 +#endif +/**< sizeof the spinel payload data */ +#define OPENTHREAD_SERIAL_BUFFER__PAYLOAD_SIZE OPENTHREAD_SERIAL_BUFFER_SIZE - OPENTHREAD_SIZEOF_LENGTH_AND_FREEBUFF +/**< error when no more buffer available */ +#define OPENTHREAD_ERROR_NO_EMPTY_SERIAL_BUFFER -1 +/**< serial buffer ready to use */ +#define OPENTHREAD_SERIAL_BUFFER_STATUS_FREE (0x0001) +/**< serial buffer ready for processsing */ +#define OPENTHREAD_SERIAL_BUFFER_STATUS_READY_TO_PROCESS (0x0002) +/**< serial buffer payload full */ +#define OPENTHREAD_SERIAL_BUFFER_STATUS_FULL (0x0004) +/**< Max length for IEEE802154 frame */ +#define IEEE802154_MAX_LENGTH (127U) +/**< Max length for a netdev buffer */ +#define OPENTHREAD_NETDEV_BUFLEN (IEEE802154_MAX_LENGTH) -#define OPENTHREAD_XTIMER_MSG_TYPE_EVENT (0x2235) /**< xtimer message receiver event*/ -#define OPENTHREAD_NETDEV_MSG_TYPE_EVENT (0x2236) /**< message received from driver */ -#define OPENTHREAD_SERIAL_MSG_TYPE_EVENT (0x2237) /**< event indicating a serial (UART) message was sent to OpenThread */ -#define OPENTHREAD_MSG_TYPE_RECV (0x2238) /**< event for frame reception */ -#define OPENTHREAD_JOB_MSG_TYPE_EVENT (0x2240) /**< event indicating an OT_JOB message */ /** * @brief Struct containing a serial message */ typedef struct { - void *buf; /**< buffer containing the message */ - size_t len; /**< length of the message */ + uint16_t length; /**< length of the message */ + uint16_t serial_buffer_status; /**< status of the buffer */ + uint8_t buf[OPENTHREAD_SERIAL_BUFFER__PAYLOAD_SIZE]; /**< buffer containing the message */ } serial_msg_t; /** @@ -71,7 +103,7 @@ void recv_pkt(otInstance *aInstance, netdev_t *dev); * @param[in] dev pointer to a netdev interface * @param[in] event just occurred netdev event */ -void send_pkt(otInstance *aInstance, netdev_t *dev, netdev_event_t event); +void sent_pkt(otInstance *aInstance, netdev_event_t event); /** * @brief Bootstrap OpenThread @@ -87,7 +119,6 @@ void openthread_bootstrap(void); */ void openthread_radio_init(netdev_t *dev, uint8_t *tb, uint8_t *rb); - /** * @brief Starts OpenThread thread. * @@ -100,24 +131,56 @@ void openthread_radio_init(netdev_t *dev, uint8_t *tb, uint8_t *rb); * @return PID of OpenThread thread * @return -EINVAL if there was an error creating the thread */ -int openthread_netdev_init(char *stack, int stacksize, char priority, const char *name, netdev_t *netdev); +//int openthread_rx_init(char *stack, int stacksize, char priority, const char *name, netdev_t *netdev); /** - * @brief get PID of OpenThread thread. + * @brief Starts OpenThread thread. * - * @return PID of OpenThread thread + * @param[in] stack pointer to the stack designed for OpenThread timer + * @param[in] stacksize size of the stack + * @param[in] priority priority of the OpenThread timer stack + * @param[in] name name of the OpenThread timer stack + * + * @return PID of OpenThread event thread + * @return -EINVAL if there was an error creating the thread */ -kernel_pid_t openthread_get_pid(void); +int openthread_event_init(char *stack, int stacksize, char priority, const char *name); /** - * @brief Init OpenThread random + * @brief get PID of OpenThread main thread. + * + * @return PID of OpenThread main thread */ -void ot_random_init(void); +kernel_pid_t openthread_get_main_pid(void); -/* - * @brief Run OpenThread UART simulator (stdio) +/** + * @brief get PID of OpenThread Critical Event thread. + * + * @return PID of OpenThread Critical Event thread */ -void openthread_uart_run(void); +kernel_pid_t openthread_get_event_pid(void); + +/** + * @brief get instance of OpenThread. + * + * @return instance of OpenThread thread + */ +otInstance* openthread_get_instance(void); + +/** + * @brief get timer of OpenThread. + * + * @return timer of OpenThread thread + */ +xtimer_t* openthread_get_timer(void); + +bool openthread_main_stack_overflow_check(void); +bool openthread_event_stack_overflow_check(void); + +/** + * @brief Init OpenThread random + */ +void ot_random_init(void); /** * @brief Execute OpenThread command. Call this function only in OpenThread thread diff --git a/pkg/openthread/include/platform_config.h b/pkg/openthread/include/platform_config.h new file mode 100644 index 000000000000..f563e61eb6e5 --- /dev/null +++ b/pkg/openthread/include/platform_config.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) Baptiste Clenet + * + * 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 net + * @file + * @brief Implementation of OpenThread platform config + * + * @author Baptiste Clenet + * @} + */ + +#ifndef PLATFORM_CONFIG_H +#define PLATFORM_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @def OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS + * + * The number of message buffers in buffer pool + */ +#if OPENTHREAD_ENABLE_NCP_UART +#define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS 20 +#elif OPENTHREAD_MTD +#define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS 20 +#elif OPENTHREAD_FTD +#define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS 20 +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* PLATFORM_CONFIG_H */ diff --git a/pkg/openthread/source b/pkg/openthread/source new file mode 160000 index 000000000000..207000130d06 --- /dev/null +++ b/pkg/openthread/source @@ -0,0 +1 @@ +Subproject commit 207000130d0658189b615ee5ccc6459311577e54