From 0452e168d709cae4ec4aa16a2689a7818c5db05a Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Thu, 25 Jun 2020 22:34:54 +0200 Subject: [PATCH 1/7] sys/ccm: define max MAC length --- sys/include/crypto/modes/ccm.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sys/include/crypto/modes/ccm.h b/sys/include/crypto/modes/ccm.h index 9900b8407ea3..12912132cb79 100644 --- a/sys/include/crypto/modes/ccm.h +++ b/sys/include/crypto/modes/ccm.h @@ -42,6 +42,10 @@ extern "C" { */ #define CCM_BLOCK_SIZE 16 +/** + * @brief Maximum length for the appended MAC + */ +#define CCM_MAC_MAX_LEN 16 /** * @brief Encrypt and authenticate data of arbitrary length in ccm mode. From 6b7640c87b10032a1893f2b38507b7153d001976 Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Thu, 25 Jun 2020 22:35:10 +0200 Subject: [PATCH 2/7] sys/include/net/ieee802154.h: add ACK frame length define --- sys/include/net/ieee802154.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/include/net/ieee802154.h b/sys/include/net/ieee802154.h index 43b392a0a1e1..9c60fd7b716b 100644 --- a/sys/include/net/ieee802154.h +++ b/sys/include/net/ieee802154.h @@ -96,6 +96,7 @@ extern "C" { #define IEEE802154_FRAME_LEN_MAX (127U) /**< maximum 802.15.4 frame length */ #define IEEE802154G_FRAME_LEN_MAX (2047U) /**< maximum 802.15.4g-2012 frame length */ +#define IEEE802154_ACK_FRAME_LEN (5U) /**< ACK frame length */ /** * For the SUN PHYs, the value is 1 ms expressed in symbol periods, rounded From 844ccfbeb3c4eed49fdd94a84f90db3e712e9cfe Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Thu, 25 Jun 2020 22:35:50 +0200 Subject: [PATCH 3/7] pkg/OpenWSN: initial import Co-authored-by: Peter Kietzmann Co-authored-by: Jose Alamos Co-authored-by: Michel Rottleuthner --- pkg/openwsn/Makefile | 51 +++ pkg/openwsn/Makefile.dep | 71 +++ pkg/openwsn/Makefile.include | 40 ++ pkg/openwsn/contrib/Makefile | 13 + pkg/openwsn/contrib/board.c | 88 ++++ pkg/openwsn/contrib/cryptoengine.c | 104 +++++ pkg/openwsn/contrib/debugpins.c | 195 ++++++++ pkg/openwsn/contrib/eui64.c | 44 ++ pkg/openwsn/contrib/leds.c | 236 ++++++++++ pkg/openwsn/contrib/openwsn.c | 122 +++++ pkg/openwsn/contrib/radio.c | 268 +++++++++++ pkg/openwsn/contrib/sctimer_rtt.c | 169 +++++++ pkg/openwsn/contrib/sctimer_ztimer.c | 163 +++++++ pkg/openwsn/contrib/uart.c | 184 ++++++++ pkg/openwsn/doc.txt | 420 ++++++++++++++++++ pkg/openwsn/include/board_info.h | 143 ++++++ pkg/openwsn/include/openwsn.h | 56 +++ pkg/openwsn/include/openwsn_board.h | 71 +++ pkg/openwsn/include/openwsn_debugpins.h | 56 +++ .../include/openwsn_debugpins_params.h | 80 ++++ pkg/openwsn/include/openwsn_leds.h | 66 +++ pkg/openwsn/include/openwsn_leds_params.h | 88 ++++ pkg/openwsn/include/openwsn_radio.h | 84 ++++ pkg/openwsn/include/openwsn_uart.h | 141 ++++++ ...clude-RIOT-OpenWSN-board-definitions.patch | 53 +++ ...penserial-rename-include-for-RIOT-Op.patch | 26 ++ ...-out-unused-COAP-UDP-applications-in.patch | 60 +++ ...Chigh-neighbors.c-expose-neighbors_v.patch | 26 ++ ...heduler-use-thread-flags-restore-irq.patch | 77 ++++ ...hain_defs.h-comment-out-conflict-ISR.patch | 43 ++ ...nstack-openstack-dont-init-idmanager.patch | 27 ++ ...008-openstack-openapps-add-debugging.patch | 175 ++++++++ ...penserial-add-flag-to-echo-badcrc-fr.patch | 32 ++ ...-opentimers-enable-ISR-before-return.patch | 32 ++ ...w-to-set-EB_PORTION-SLOTFRAME_LENGTH.patch | 42 ++ sys/auto_init/auto_init.c | 5 + 36 files changed, 3551 insertions(+) create mode 100644 pkg/openwsn/Makefile create mode 100644 pkg/openwsn/Makefile.dep create mode 100644 pkg/openwsn/Makefile.include create mode 100644 pkg/openwsn/contrib/Makefile create mode 100644 pkg/openwsn/contrib/board.c create mode 100644 pkg/openwsn/contrib/cryptoengine.c create mode 100644 pkg/openwsn/contrib/debugpins.c create mode 100644 pkg/openwsn/contrib/eui64.c create mode 100644 pkg/openwsn/contrib/leds.c create mode 100644 pkg/openwsn/contrib/openwsn.c create mode 100644 pkg/openwsn/contrib/radio.c create mode 100644 pkg/openwsn/contrib/sctimer_rtt.c create mode 100644 pkg/openwsn/contrib/sctimer_ztimer.c create mode 100644 pkg/openwsn/contrib/uart.c create mode 100644 pkg/openwsn/doc.txt create mode 100644 pkg/openwsn/include/board_info.h create mode 100644 pkg/openwsn/include/openwsn.h create mode 100644 pkg/openwsn/include/openwsn_board.h create mode 100644 pkg/openwsn/include/openwsn_debugpins.h create mode 100644 pkg/openwsn/include/openwsn_debugpins_params.h create mode 100644 pkg/openwsn/include/openwsn_leds.h create mode 100644 pkg/openwsn/include/openwsn_leds_params.h create mode 100644 pkg/openwsn/include/openwsn_radio.h create mode 100644 pkg/openwsn/include/openwsn_uart.h create mode 100644 pkg/openwsn/patches/0001-bsp-kernel-include-RIOT-OpenWSN-board-definitions.patch create mode 100644 pkg/openwsn/patches/0002-drivers-common-openserial-rename-include-for-RIOT-Op.patch create mode 100644 pkg/openwsn/patches/0003-openapps-comment-out-unused-COAP-UDP-applications-in.patch create mode 100644 pkg/openwsn/patches/0004-openstack-02b-MAChigh-neighbors.c-expose-neighbors_v.patch create mode 100644 pkg/openwsn/patches/0005-kernel-openos-scheduler-use-thread-flags-restore-irq.patch create mode 100644 pkg/openwsn/patches/0006-bsp-boards-toolchain_defs.h-comment-out-conflict-ISR.patch create mode 100644 pkg/openwsn/patches/0007-openstack-openstack-dont-init-idmanager.patch create mode 100644 pkg/openwsn/patches/0008-openstack-openapps-add-debugging.patch create mode 100644 pkg/openwsn/patches/0009-drivers-common-openserial-add-flag-to-echo-badcrc-fr.patch create mode 100644 pkg/openwsn/patches/0010-drivers-common-opentimers-enable-ISR-before-return.patch create mode 100644 pkg/openwsn/patches/0011-openstack-allow-to-set-EB_PORTION-SLOTFRAME_LENGTH.patch diff --git a/pkg/openwsn/Makefile b/pkg/openwsn/Makefile new file mode 100644 index 000000000000..944bf419bd9b --- /dev/null +++ b/pkg/openwsn/Makefile @@ -0,0 +1,51 @@ +PKG_NAME=openwsn +PKG_URL=https://github.com/openwsn-berkeley/openwsn-fw.git +PKG_VERSION=cbcf622bd9369fcfc8455a5fb9349de2ed3c3a46 +PKG_LICENSE=BSD-3-Clause + +include $(RIOTBASE)/pkg/pkg.mk + +# openwsn_% RIOT Modules or PSEUDOMODULES that don't have custom rules +IGNORE_MODULES := openwsn_leds \ + openwsn_debugpins \ + openwsn_radio \ + openwsn_serial \ + openwsn_sctimer% \ + openwsn_cryptoengine \ + # + +OPENWSN_MODULES := $(filter-out $(IGNORE_MODULES),$(filter openwsn_%,$(USEMODULE))) + +.PHONY: openwsn_% + +OPENWSN_LOG_LEVEL ?= LOG_NONE + +CFLAGS += -Wno-array-bounds +CFLAGS += -Wno-implicit-fallthrough +CFLAGS += -Wno-implicit-function-declaration +CFLAGS += -Wno-incompatible-pointer-types +CFLAGS += -Wno-maybe-uninitialized +CFLAGS += -Wno-old-style-definition +CFLAGS += -Wno-return-type +CFLAGS += -Wno-sign-compare +CFLAGS += -Wno-unused-parameter +CFLAGS += -Wno-strict-prototypes +CFLAGS += -DLOG_LEVEL=$(OPENWSN_LOG_LEVEL) + +OPENWSN_PATH_openstack = openstack +OPENWSN_PATH_openapps = openapps +OPENWSN_PATH_drivers = drivers/common +OPENWSN_PATH_scheduler = kernel/openos +OPENWSN_PATH_cjoin = openapps/cjoin +OPENWSN_PATH_opencoap = openapps/opencoap +OPENWSN_PATH_mac_low = openstack/02a-MAClow +OPENWSN_PATH_mac_high = openstack/02b-MAChigh +OPENWSN_PATH_iphc = openstack/03a-IPHC +OPENWSN_PATH_ipv6 = openstack/03b-IPv6 +OPENWSN_PATH_transport = openstack/04-TRAN +OPENWSN_PATH_crosslayers = openstack/cross-layers + +all: $(OPENWSN_MODULES) + +openwsn_%: + "$(MAKE)" -C $(PKG_SOURCE_DIR)/$(OPENWSN_PATH_$*) -f $(RIOTBASE)/Makefile.base MODULE=$@ diff --git a/pkg/openwsn/Makefile.dep b/pkg/openwsn/Makefile.dep new file mode 100644 index 000000000000..9511b68e166b --- /dev/null +++ b/pkg/openwsn/Makefile.dep @@ -0,0 +1,71 @@ +ifneq (,$(filter openwsn_openstack,$(USEMODULE))) + USEMODULE += openwsn_cjoin + USEMODULE += openwsn_iphc + USEMODULE += openwsn_ipv6 + USEMODULE += openwsn_mac_low + USEMODULE += openwsn_mac_high + USEMODULE += openwsn_transport + USEMODULE += openwsn_crosslayers + + USEMODULE += openwsn_drivers + USEMODULE += openwsn_sctimer + USEMODULE += openwsn_radio + + DEFAULT_MODULE += auto_init_openwsn + + USEMODULE += luid + USEMODULE += netdev_default +endif + +ifneq (,$(filter openwsn_scheduler,$(USEMODULE))) + USEMODULE += core_thread_flags +endif + +ifneq (,$(filter openwsn_cjoin,$(USEMODULE))) + USEMODULE += openwsn_openapps + USEMODULE += openwsn_opencoap + + USEMODULE += openwsn_cryptoengine +endif + +ifneq (,$(filter openwsn_cryptoengine,$(USEMODULE))) + USEMODULE += crypto_3des + USEMODULE += cipher_modes +endif + +ifneq (,$(filter openwsn_sctimer,$(USEMODULE))) + ifeq (,$(filter openwsn_sctimer_ztimer,$(USEMODULE))) + USEMODULE += openwsn_sctimer_rtt + endif +endif + +ifneq (,$(filter openwsn_sctimer_ztimer,$(USEMODULE))) + USEMODULE += ztimer_usec + USEMODULE += ztimer_msec + FEATURES_OPTIONAL += periph_rtt + ifneq (,$(filter periph_rtt,$(FEATURES_USED))) + USEMODULE += ztimer_periph_rtt + endif +endif + +ifneq (,$(filter openwsn_sctimer_rtt,$(USEMODULE))) + FEATURES_REQUIRED += periph_rtt +endif + +ifneq (,$(filter openwsn_serial,$(USEMODULE))) + USEMODULE += openwsn_drivers + USEMODULE += ztimer_usec + FEATURES_REQUIRED += periph_uart + FEATURES_OPTIONAL += periph_uart_nonblocking +endif + +ifneq (,$(filter openwsn_leds openwsn_debugpins,$(USEMODULE))) + FEATURES_REQUIRED += periph_gpio +endif + +ifneq (,$(filter openwsn_debugpins,$(USEMODULE))) + FEATURES_REQUIRED += periph_gpio_irq +endif + +# This port currently requires setting ISR_STACKSIZE +FEATURES_BLACKLIST += arch_esp32 arch_esp8266 arch_riscv arch_avr8 diff --git a/pkg/openwsn/Makefile.include b/pkg/openwsn/Makefile.include new file mode 100644 index 000000000000..b3b66406f901 --- /dev/null +++ b/pkg/openwsn/Makefile.include @@ -0,0 +1,40 @@ +INCLUDES += -I$(PKGDIRBASE)/openwsn \ + -I$(PKGDIRBASE)/openwsn/kernel \ + -I$(PKGDIRBASE)/openwsn/inc \ + -I$(PKGDIRBASE)/openwsn/drivers/common \ + -I$(PKGDIRBASE)/openwsn/bsp/boards/ \ + -I$(PKGDIRBASE)/openwsn/openstack/ \ + -I$(PKGDIRBASE)/openwsn/openstack/02a-MAClow \ + -I$(PKGDIRBASE)/openwsn/openstack/02b-MAChigh \ + -I$(PKGDIRBASE)/openwsn/openstack/03a-IPHC \ + -I$(PKGDIRBASE)/openwsn/openstack/03b-IPv6 \ + -I$(PKGDIRBASE)/openwsn/openstack/04-TRAN \ + -I$(PKGDIRBASE)/openwsn/openstack/cross-layers \ + -I$(PKGDIRBASE)/openwsn/openapps \ + -I$(PKGDIRBASE)/openwsn/openapps/cjoin \ + -I$(PKGDIRBASE)/openwsn/openapps/opencoap \ + -I$(RIOTBASE)/pkg/openwsn/include \ + +DIRS += $(RIOTBASE)/pkg/openwsn/contrib + +PSEUDOMODULES += openwsn_serial +PSEUDOMODULES += openwsn_debugpins +PSEUDOMODULES += openwsn_leds +PSEUDOMODULES += openwsn_sctimer% +PSEUDOMODULES += openwsn_cryptoengine +PSEUDOMODULES += openwsn_radio + +# In OpenWSN the ISR stack is shared with the network stack. OpenWSN stack is +# 2Kb, this means that the ISR stack in OpenWSN might have up to 2Kb available. +# To keep the same marging increase the ISR stack to 2Kb as well. In practice +# 1Kb should be enough. +CFLAGS += -DISR_STACKSIZE=2048 + +# at86rf2xx state machine is in enhanced mode by default, OpenWSN requires +# basic mode. +ifneq (,$(filter at86rf2xx,$(USEMODULE))) + CFLAGS += -DAT86RF2XX_BASIC_MODE +endif + +# LLVM ARM shows issues with missing definitions fot stdatomic +TOOLCHAINS_BLACKLIST += llvm diff --git a/pkg/openwsn/contrib/Makefile b/pkg/openwsn/contrib/Makefile new file mode 100644 index 000000000000..07576b0a8458 --- /dev/null +++ b/pkg/openwsn/contrib/Makefile @@ -0,0 +1,13 @@ +MODULE = openwsn + +SRC := $(filter-out sctimer_% ,$(wildcard *.c)) + +ifneq (,$(filter openwsn_sctimer_rtt,$(USEMODULE))) + SRC += sctimer_rtt.c +endif + +ifneq (,$(filter openwsn_sctimer_ztimer,$(USEMODULE))) + SRC += sctimer_ztimer.c +endif + +include $(RIOTBASE)/Makefile.base diff --git a/pkg/openwsn/contrib/board.c b/pkg/openwsn/contrib/board.c new file mode 100644 index 000000000000..1d57838ac8c1 --- /dev/null +++ b/pkg/openwsn/contrib/board.c @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2018 Hamburg University of Applied Sciences + * 2020 Inria + * + * 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 pkg_openwsn + * @{ + * + * @file + * @brief RIOT adaption of the "board" bsp module + * + * @author Thomas Watteyne , February 2012 + * @author Tengfei Chang , July 2012 + * @author Peter Kietzmann , July 2017 + * @author Francisco Molina + * + * @} + */ + +#include + +#include "sctimer.h" +#include "radio.h" + +#include "thread.h" +#include "periph/pm.h" + +#include "openwsn_board.h" +#include "openwsn_debugpins.h" +#include "openwsn_debugpins_params.h" +#include "openwsn_leds.h" +#include "openwsn_leds_params.h" +#include "openwsn_uart.h" + +#ifdef MODULE_PM_LAYERED +#include "pm_layered.h" +#endif + +#define LOG_LEVEL LOG_NONE +#include "log.h" + +void board_init_openwsn(void) +{ + LOG_DEBUG("[openwsn/board]: init\n"); + +#ifdef MODULE_PM_LAYERED + /* sleeping is currently not supported, block all sleep modes */ + for (uint8_t i = 0; i < PM_NUM_MODES; i++) { + pm_block(i); + } +#endif + + if (IS_USED(MODULE_OPENWSN_LEDS)) { + LOG_DEBUG("[openwsn/board]: leds init\n"); + ledpins_riot_init(openwsn_leds_params); + } + + if (IS_USED(MODULE_OPENWSN_DEBUGPINS)) { + LOG_DEBUG("[openwsn/board]: debugpins init\n"); + openwsn_debugpins_init(openwsn_debugpins_params); + } + + if (IS_USED(MODULE_OPENWSN_SCTIMER)) { + LOG_DEBUG("[openwsn/board]: sctimer init\n"); + sctimer_init(); + } + + if (IS_USED(MODULE_OPENWSN_SERIAL)) { + LOG_DEBUG("[openwsn/board]: uart init\n"); + uart_init_openwsn(); + } +} + +void board_sleep(void) +{ + /* sleep is handled by `pm_layered` */ +} + +void board_reset(void) +{ + LOG_DEBUG("[openwsn/board]: reset\n"); + pm_reboot(); +} diff --git a/pkg/openwsn/contrib/cryptoengine.c b/pkg/openwsn/contrib/cryptoengine.c new file mode 100644 index 000000000000..1ef8ffc6bfa8 --- /dev/null +++ b/pkg/openwsn/contrib/cryptoengine.c @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2020 Inria + * + * 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 pkg_openwsn + * @{ + * + * @file + * @brief RIOT adaption definition of the "cryptoengine" module + * + * @author Francisco Molina + * + * @} + */ + +#include + +#include "opendefs.h" + +#include "crypto/ciphers.h" +#include "crypto/modes/ecb.h" +#include "crypto/modes/ccm.h" + +/* CCM does not restrict the input message size, but these function will + only be called with a message length of at most 125b in OpenWSN */ +#define MAX_MESSAGE_LEN (125U) + +owerror_t cryptoengine_aes_ccms_enc(uint8_t *a, uint8_t len_a, uint8_t *m, + uint8_t *len_m, uint8_t *nonce, uint8_t l, + uint8_t *key, uint8_t len_mac) +{ + cipher_t cipher; + int ret, len; + uint8_t tmp_buff[MAX_MESSAGE_LEN + CCM_MAC_MAX_LEN]; + + ret = cipher_init(&cipher, CIPHER_AES_128, key, CCM_BLOCK_SIZE); + + if (ret != 1) { + return E_FAIL; + } + + len = cipher_encrypt_ccm(&cipher, a, len_a, len_mac, l, + nonce, 15 - l, m, *len_m, tmp_buff); + if (len < 0) { + return E_FAIL; + } + + *len_m = len; + memcpy(m, tmp_buff, *len_m); + + return E_SUCCESS; +} + +owerror_t cryptoengine_aes_ccms_dec(uint8_t *a, uint8_t len_a, uint8_t *m, + uint8_t *len_m, uint8_t *nonce, uint8_t l, + uint8_t *key, uint8_t len_mac) +{ + cipher_t cipher; + int ret, len; + uint8_t tmp_buff[MAX_MESSAGE_LEN]; + + ret = cipher_init(&cipher, CIPHER_AES_128, key, CCM_BLOCK_SIZE); + + if (ret != 1) { + return E_FAIL; + } + + len = cipher_decrypt_ccm(&cipher, a, len_a, len_mac, l, nonce, 15 - l, m, + *len_m, tmp_buff); + + if (len < 0) { + return E_FAIL; + } + + *len_m = len; + memcpy(m, tmp_buff, *len_m); + + return E_SUCCESS; +} + +owerror_t cryptoengine_aes_ecb_enc(uint8_t *buffer, uint8_t *key) +{ + cipher_t cipher; + int ret, len; + + ret = cipher_init(&cipher, CIPHER_AES_128, key, CCM_BLOCK_SIZE); + + if (ret != 1) { + return E_FAIL; + } + + len = cipher_encrypt_ecb(&cipher, buffer, CCM_BLOCK_SIZE, buffer); + + if (len < 0) { + return E_FAIL; + } + + return E_SUCCESS; +} diff --git a/pkg/openwsn/contrib/debugpins.c b/pkg/openwsn/contrib/debugpins.c new file mode 100644 index 000000000000..b2f22f5cad39 --- /dev/null +++ b/pkg/openwsn/contrib/debugpins.c @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2017 Hamburg University of Applied Sciences + * + * 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 pkg_openwsn + * @{ + * + * @file + * @brief RIOT adaption of the "debugpins" bsp module + * + * @author Michael Frey + * @author Peter Kietzmann + * @author Francisco Molina + * + * @} + */ + +#include "debugpins.h" +#include "openwsn_debugpins.h" + +#include +#include + +/* holds the internal configuration for debugpins */ +static debugpins_config_t _configuration = { + GPIO_UNDEF, + GPIO_UNDEF, + GPIO_UNDEF, + GPIO_UNDEF, + GPIO_UNDEF, + GPIO_UNDEF +}; + +static void _set_checked(gpio_t pin) +{ + if (IS_USED(MODULE_OPENWSN_DEBUGPINS)) { + if (pin != GPIO_UNDEF){ + gpio_set(pin); + } + } +} + +static void _clear_checked(gpio_t pin) +{ + if (IS_USED(MODULE_OPENWSN_DEBUGPINS)) { + if (pin != GPIO_UNDEF){ + gpio_clear(pin); + } + } +} + +static void _toggle_checked(gpio_t pin) +{ + if (IS_USED(MODULE_OPENWSN_DEBUGPINS)) { + if (pin != GPIO_UNDEF){ + gpio_toggle(pin); + } + } +} + +static void _init_checked(gpio_t pin) +{ + if (IS_USED(MODULE_OPENWSN_DEBUGPINS)) { + if (pin != GPIO_UNDEF){ + gpio_init(pin, GPIO_OUT); + } + } +} + +void openwsn_debugpins_init(const debugpins_config_t *user_config) +{ + if (IS_USED(MODULE_OPENWSN_DEBUGPINS)) { + memset(&_configuration, GPIO_UNDEF, sizeof(debugpins_config_t)); + + if (user_config != NULL) { + memcpy(&_configuration, user_config, sizeof(debugpins_config_t)); + debugpins_init(); + } + } + else { + (void) user_config; + } +} + +void debugpins_init(void) +{ + _init_checked(_configuration.frame); + _init_checked(_configuration.slot); + _init_checked(_configuration.fsm); + _init_checked(_configuration.task); + _init_checked(_configuration.isr); + _init_checked(_configuration.radio); + + debugpins_frame_clr(); + debugpins_slot_clr(); + debugpins_fsm_clr(); + debugpins_task_clr(); + debugpins_isr_clr(); + debugpins_radio_clr(); +} + +void debugpins_frame_toggle(void) +{ + _toggle_checked(_configuration.frame); +} + +void debugpins_frame_clr(void) +{ + _clear_checked(_configuration.frame); +} + +void debugpins_frame_set(void) +{ + _set_checked(_configuration.frame); +} + +void debugpins_slot_toggle(void) +{ + _toggle_checked(_configuration.slot); +} + +void debugpins_slot_clr(void) +{ + _clear_checked(_configuration.slot); +} + +void debugpins_slot_set(void) +{ + _set_checked(_configuration.slot); +} + +void debugpins_fsm_toggle(void) +{ + _toggle_checked(_configuration.fsm); +} + +void debugpins_fsm_clr(void) +{ + _clear_checked(_configuration.fsm); +} + +void debugpins_fsm_set(void) +{ + _set_checked(_configuration.fsm); +} + +void debugpins_task_toggle(void) +{ + _toggle_checked(_configuration.task); +} + +void debugpins_task_clr(void) +{ + _clear_checked(_configuration.task); +} + +void debugpins_task_set(void) +{ + _set_checked(_configuration.task); +} + +void debugpins_isr_toggle(void) +{ + _toggle_checked(_configuration.isr); +} + +void debugpins_isr_clr(void) +{ + _clear_checked(_configuration.isr); +} + +void debugpins_isr_set(void) +{ + _set_checked(_configuration.isr); +} + +void debugpins_radio_toggle(void) +{ + _toggle_checked(_configuration.radio); +} + +void debugpins_radio_clr(void) +{ + _clear_checked(_configuration.radio); +} + +void debugpins_radio_set(void) +{ + _set_checked(_configuration.radio); +} diff --git a/pkg/openwsn/contrib/eui64.c b/pkg/openwsn/contrib/eui64.c new file mode 100644 index 000000000000..1b7221d7809a --- /dev/null +++ b/pkg/openwsn/contrib/eui64.c @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2017 Hamburg University of Applied Sciences + * + * 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 pkg_openwsn + * @{ + * + * @file + * @brief RIOT adaption definition of the "eui64" bsp module + * + * @author Peter Kietzmann + * + * @} + */ + +#include "string.h" +#include "eui64.h" +#include "openwsn_radio.h" + +#include "luid.h" +#include "net/netdev.h" +#include "net/netopt.h" +#include "net/ieee802154.h" + +extern openwsn_radio_t openwsn_radio; + +void eui64_get(uint8_t *addressToWrite) +{ + eui64_t eui64; + + if (openwsn_radio.dev->driver->get(openwsn_radio.dev, NETOPT_ADDRESS_LONG, + &eui64, + sizeof(eui64_t)) == sizeof(eui64_t)) { + memcpy(addressToWrite, eui64.uint8, sizeof(eui64.uint8)); + } + else { + luid_get_eui64((eui64_t *) addressToWrite); + } +} diff --git a/pkg/openwsn/contrib/leds.c b/pkg/openwsn/contrib/leds.c new file mode 100644 index 000000000000..dc944be7cee3 --- /dev/null +++ b/pkg/openwsn/contrib/leds.c @@ -0,0 +1,236 @@ +/* + * Copyright (C) 2017 Hamburg University of Applied Sciences + * 2020 Inria + * + * 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 pkg_openwsn + * @{ + * + * @file + * + * @author Michael Frey + * @author Peter Kietzmann + * @author Francisco Molina + * + * @} + */ + +#include "leds.h" +#include "openwsn_leds.h" + +#include "board.h" +#include "periph/gpio.h" + +#include +#include + +/** holds the internal configuration for debug pins */ +static leds_config_t _configuration = { + GPIO_UNDEF, + GPIO_UNDEF, + GPIO_UNDEF, + GPIO_UNDEF, + GPIO_LED_HIGH, +}; + +static void _toggle_checked(gpio_t pin) +{ + if (IS_USED(MODULE_OPENWSN_LEDS)) { + if (pin != GPIO_UNDEF) { + gpio_toggle(pin); + } + } +} + +static void _init_checked(gpio_t pin) +{ + if (IS_USED(MODULE_OPENWSN_LEDS)) { + if (pin != GPIO_UNDEF) { + gpio_init(pin, GPIO_OUT); + } + } +} + +static void _write_checked(gpio_t pin, uint8_t on_state) +{ + if (IS_USED(MODULE_OPENWSN_LEDS)) { + if (pin != GPIO_UNDEF) { + gpio_write(pin, on_state); + } + } +} + +static uint8_t _is_on_checked(gpio_t pin) +{ + if (IS_USED(MODULE_OPENWSN_LEDS)) { + uint8_t ret = 0; + + if (pin != GPIO_UNDEF) { + ret = gpio_read(pin); + } + return ret; + } + else { + return 0; + } +} + +static void _blink_checked(gpio_t pin) +{ + if (IS_USED(MODULE_OPENWSN_LEDS)) { + /* toggle for ~10s if ztimer is used */ + for (uint8_t i = 0; i < 100; i++) { + _toggle_checked(pin); + for (uint32_t i = 0; i < (CLOCK_CORECLOCK / 50); i++) { + /* Make sure for loop is not optimized out */ + __asm__ (""); + } + } + } +} + +void ledpins_riot_init(const leds_config_t *user_config) +{ + if (IS_USED(MODULE_OPENWSN_LEDS)) { + if (user_config != NULL) { + memcpy(&_configuration, user_config, sizeof(leds_config_t)); + leds_init(); + } + } + else { + (void)user_config; + } +} + +void leds_init(void) +{ + _init_checked(_configuration.error); + _init_checked(_configuration.sync); + _init_checked(_configuration.radio); + _init_checked(_configuration.debug); + leds_all_off(); +} + +void leds_error_on(void) +{ + _write_checked(_configuration.error, _configuration.led_on); +} + +void leds_error_off(void) +{ + _write_checked(_configuration.error, ~_configuration.led_on); +} + +void leds_error_toggle(void) +{ + _toggle_checked(_configuration.error); +} + +uint8_t leds_error_isOn(void) +{ + return _is_on_checked(_configuration.error); +} + +void leds_error_blink(void) +{ + _blink_checked(_configuration.error); +} + +void leds_radio_on(void) +{ + _write_checked(_configuration.radio, _configuration.led_on); +} + +void leds_radio_off(void) +{ + _write_checked(_configuration.radio, ~_configuration.led_on); +} + +void leds_radio_toggle(void) +{ + _toggle_checked(_configuration.radio); +} + +uint8_t leds_radio_isOn(void) +{ + return _is_on_checked(_configuration.radio); +} + +void leds_sync_on(void) +{ + _write_checked(_configuration.sync, _configuration.led_on); +} + +void leds_sync_off(void) +{ + _write_checked(_configuration.sync, ~_configuration.led_on); +} + +void leds_sync_toggle(void) +{ + _toggle_checked(_configuration.sync); +} + +uint8_t leds_sync_isOn(void) +{ + return _is_on_checked(_configuration.sync); +} + +void leds_debug_on(void) +{ + _write_checked(_configuration.debug, _configuration.led_on); +} + +void leds_debug_off(void) +{ + _write_checked(_configuration.debug, ~_configuration.led_on); +} + +void leds_debug_toggle(void) +{ + _toggle_checked(_configuration.debug); +} + +uint8_t leds_debug_isOn(void) +{ + return _is_on_checked(_configuration.debug); +} + +void leds_all_on(void) +{ + leds_error_on(); + leds_radio_on(); + leds_sync_on(); + leds_debug_on(); +} + +void leds_all_off(void) +{ + leds_error_off(); + leds_radio_off(); + leds_sync_off(); + leds_debug_off(); +} + +void leds_all_toggle(void) +{ + leds_error_toggle(); + leds_radio_toggle(); + leds_sync_toggle(); + leds_debug_toggle(); +} + +void leds_circular_shift(void) +{ + /** not implemented */ +} + +void leds_increment(void) +{ + /** not implemented */ +} diff --git a/pkg/openwsn/contrib/openwsn.c b/pkg/openwsn/contrib/openwsn.c new file mode 100644 index 000000000000..4f9c578b413c --- /dev/null +++ b/pkg/openwsn/contrib/openwsn.c @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2018 Hamburg University of Applied Sciences + * 2020 Inria + * + * 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. + */ + +/** + * @{ + * @file + * @brief OpenWSN bootstraping functions implementation + * + * @author Peter Kietzmann + * @author Francisco Molina + */ + +#include "scheduler.h" +#include "openstack.h" +#include "radio.h" +#include "idmanager.h" + +#include "openwsn.h" +#include "openwsn_board.h" +#include "openwsn_radio.h" + +#ifdef MODULE_AT86RF2XX +#include "at86rf2xx.h" +#include "at86rf2xx_params.h" +#endif + +#define LOG_LEVEL LOG_NONE +#include "log.h" + +#define OPENWSN_SCHED_NAME "openwsn" +#define OPENWSN_SCHED_PRIO (THREAD_PRIORITY_MAIN - 4) +#define OPENWSN_SCHED_STACKSIZE (2048) + +#ifdef MODULE_AT86RF2XX +static at86rf2xx_t at86rf2xx_dev; +#endif + +static char _stack[OPENWSN_SCHED_STACKSIZE]; + +static kernel_pid_t _pid = KERNEL_PID_UNDEF; + +static void *_event_loop(void *arg); + +kernel_pid_t openwsn_get_pid(void) +{ + return _pid; +} + +#ifdef MODULE_OPENWSN_RADIO +void openwsn_set_addr_16b(netdev_t* dev) +{ + uint8_t addr[IEEE802154_SHORT_ADDRESS_LEN]; + dev->driver->get(dev, NETOPT_ADDRESS, addr, IEEE802154_SHORT_ADDRESS_LEN); + open_addr_t id; + id.type = ADDR_16B; + memcpy(&id.addr_16b, addr, IEEE802154_SHORT_ADDRESS_LEN); + idmanager_setMyID(&id); +} +#endif + +int openwsn_bootstrap(void) +{ + LOG_DEBUG("[openwsn]: init RIOT board\n"); + board_init_openwsn(); + +#ifdef MODULE_AT86RF2XX + netdev_t *netdev = (netdev_t *)&at86rf2xx_dev.netdev.netdev; + at86rf2xx_setup(&at86rf2xx_dev, &at86rf2xx_params[0]); + (void) netdev; +#endif + +#ifdef MODULE_OPENWSN_RADIO + LOG_DEBUG("[openwsn]: init radio\n"); + if (openwsn_radio_init(netdev)) { + LOG_ERROR("[openwsn]: failed to init radio\n"); + return -1; + } +#endif + + /* Initiate Id manager here and not in `openstack_init` function to allow + overriding the short id address before additional stack components are + initiated */ + idmanager_init(); + +#ifdef MODULE_OPENWSN_RADIO + /* override 16b address to avoid short address collision */ + openwsn_set_addr_16b(netdev); +#endif + + LOG_DEBUG("[openwsn]: network thread\n"); + _pid = thread_create(_stack, OPENWSN_SCHED_STACKSIZE, OPENWSN_SCHED_PRIO, + THREAD_CREATE_STACKTEST, _event_loop, NULL, + OPENWSN_SCHED_NAME); + if (_pid <= 0) { + LOG_ERROR("[openwsn]: couldn't create thread\n"); + return -1; + } + + return _pid; +} + +static void *_event_loop(void *arg) +{ + (void)arg; + + LOG_DEBUG("[openwsn]: init scheduler\n"); + scheduler_init(); + LOG_DEBUG("[openwsn]: init openstack\n"); + /* Disable IRQ while scheduler is not ready to start */ + unsigned irq_state = irq_disable(); + openstack_init(); + LOG_DEBUG("[openwsn]: start scheduler loop\n"); + scheduler_start(irq_state); + + return NULL; +} diff --git a/pkg/openwsn/contrib/radio.c b/pkg/openwsn/contrib/radio.c new file mode 100644 index 000000000000..fad125de3a9d --- /dev/null +++ b/pkg/openwsn/contrib/radio.c @@ -0,0 +1,268 @@ +/* + * Copyright (C) 2018 Hamburg University of Applied Sciences + * 2020 Inria + * + * 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 pkg_openwsn + * @{ + * + * @file + * @brief RIOT adaption of the "radio" bsp module + * + * @author Peter Kietzmann + * @author Oliver Hahm + * @author Francisco Molina + * @} + */ +#include + +#include "leds.h" +#include "debugpins.h" +#include "sctimer.h" + +#include "net/netopt.h" +#include "net/ieee802154.h" +#include "net/netdev/ieee802154.h" + +#include "openwsn.h" +#include "openwsn_radio.h" + +#define LOG_LEVEL LOG_NONE +#include "log.h" + +openwsn_radio_t openwsn_radio; + +static void _event_cb(netdev_t *dev, netdev_event_t event); + +/* stores the NETDEV_EVENT_ISR capture time to tag the following NETDEV_EVENT */ +static PORT_TIMER_WIDTH _txrx_event_capture_time = 0; + +int openwsn_radio_init(netdev_t *netdev) +{ + assert(netdev); + + LOG_DEBUG("[openwsn/radio]: initialize riot-adaptation\n"); + openwsn_radio.dev = netdev; + + if (netdev->driver->init(netdev)) { + LOG_ERROR("[openwsn/radio]: unable to initialize device\n"); + return -1; + } + netdev->event_callback = _event_cb; + + LOG_DEBUG("[openwsn/radio]: put radio in standby\n"); + netopt_state_t state = NETOPT_STATE_STANDBY; + netdev->driver->set(netdev, NETOPT_STATE, &(state), sizeof(state)); + + LOG_DEBUG("[openwsn/radio]: set needed netdev options\n"); + netopt_enable_t enable; + /* Enable needed IRQs */ + enable = NETOPT_ENABLE; + netdev->driver->set(netdev, NETOPT_TX_START_IRQ, &(enable), sizeof(enable)); + enable = NETOPT_ENABLE; + netdev->driver->set(netdev, NETOPT_RX_START_IRQ, &(enable), sizeof(enable)); + enable = NETOPT_ENABLE; + netdev->driver->set(netdev, NETOPT_RX_END_IRQ, &(enable), sizeof(enable)); + enable = NETOPT_ENABLE; + netdev->driver->set(netdev, NETOPT_TX_END_IRQ, &(enable), sizeof(enable)); + enable = NETOPT_DISABLE; + /* Enable basic mode, no AUTOACK. no CSMA , no frame filtering */ + netdev->driver->set(netdev, NETOPT_AUTOACK, &(enable), sizeof(enable)); + enable = NETOPT_DISABLE; + netdev->driver->set(netdev, NETOPT_CSMA, &(enable), sizeof(enable)); + enable = NETOPT_ENABLE; + netdev->driver->set(netdev, NETOPT_RAWMODE, &(enable), sizeof(enable)); + uint8_t retrans = 0; + /* MAC layer will handle retransmissions */ + netdev->driver->set(netdev, NETOPT_RETRANS, &(retrans), sizeof(uint8_t)); + /* Enable TX with preloading */ + enable = NETOPT_ENABLE; + netdev->driver->set(netdev, NETOPT_PRELOADING, &(enable), sizeof(enable)); + /* Set default PANID */ + uint16_t panid = OPENWSN_PANID; + netdev->driver->set(netdev, NETOPT_NID, &(panid), sizeof(uint16_t)); + + return 0; +} + +void radio_setStartFrameCb(radio_capture_cbt cb) +{ + openwsn_radio.startFrame_cb = cb; +} + +void radio_setEndFrameCb(radio_capture_cbt cb) +{ + openwsn_radio.endFrame_cb = cb; +} + +void radio_reset(void) +{ + netopt_state_t state = NETOPT_STATE_RESET; + + openwsn_radio.dev->driver->set(openwsn_radio.dev, NETOPT_STATE, &(state), + sizeof(netopt_state_t)); + + state = NETOPT_STATE_STANDBY; + openwsn_radio.dev->driver->set(openwsn_radio.dev, NETOPT_STATE, &(state), + sizeof(netopt_state_t)); +} + +void radio_setFrequency(uint8_t frequency, radio_freq_t tx_or_rx) +{ + (void)tx_or_rx; + + uint16_t chan = frequency; + openwsn_radio.dev->driver->set(openwsn_radio.dev, NETOPT_CHANNEL, &(chan), + sizeof(chan)); +} + +void radio_rfOn(void) +{ + netopt_state_t state = NETOPT_STATE_IDLE; + + openwsn_radio.dev->driver->set(openwsn_radio.dev, NETOPT_STATE, &(state), + sizeof(netopt_state_t)); +} + +void radio_rfOff(void) +{ + netopt_state_t state = NETOPT_STATE_STANDBY; + + openwsn_radio.dev->driver->set(openwsn_radio.dev, NETOPT_STATE, &(state), + sizeof(netopt_state_t)); + + debugpins_radio_clr(); + leds_radio_off(); +} + +void radio_loadPacket(uint8_t *packet, uint16_t len) +{ + /* NETOPT_PRELOADING is enabled in radio_init so this will only load the + packet */ + /* OpenWSN `len` accounts for the FCS field which is set by default by + netdev, so remove from the actual packet `len` */ + iolist_t pkt = { + .iol_base = (void *)packet, + .iol_len = (size_t)(len - IEEE802154_FCS_LEN), + }; + + if (openwsn_radio.dev->driver->send(openwsn_radio.dev, &pkt) < 0) { + LOG_DEBUG("[openwsn/radio]: couldn't load pkt\n"); + } + LOG_DEBUG("[openwsn/radio]: loaded radio packet\n"); +} + +void radio_txEnable(void) +{ + debugpins_radio_set(); + leds_radio_on(); +} + +void radio_txNow(void) +{ + netopt_state_t state = NETOPT_STATE_TX; + + openwsn_radio.dev->driver->set(openwsn_radio.dev, NETOPT_STATE, &state, + sizeof(netopt_state_t)); +} + +void radio_rxEnable(void) +{ + debugpins_radio_set(); + leds_radio_on(); + netopt_state_t state = NETOPT_STATE_IDLE; + openwsn_radio.dev->driver->set(openwsn_radio.dev, NETOPT_STATE, &(state), + sizeof(state)); +} + +void radio_rxNow(void) +{ + /* nothing to do */ +} + +void radio_getReceivedFrame(uint8_t *bufRead, + uint8_t *lenRead, + uint8_t maxBufLen, + int8_t *rssi, + uint8_t *lqi, + bool *crc) +{ + /* OpenWSN packets are 130 bytes to hold all required data for an SPI + transaction since in some implementations it's used directly in the SPI + shift register: + - 1B spi address, 1B length, 125B data, 2B CRC, 1B LQI + In RIOT we don't do this so maxBufLen is irrelevant, packet size will + always be enough to hold IEEE802154_FRAME_LEN_MAX, but in practice only + 125B of data are copied into bufRead. + */ + (void)maxBufLen; + netdev_ieee802154_rx_info_t rx_info; + + int bytes_expected = openwsn_radio.dev->driver->recv(openwsn_radio.dev, + NULL, 0, + NULL); + + if (bytes_expected < (int)(IEEE802154_ACK_FRAME_LEN - IEEE802154_FCS_LEN)) { + /* drop invalid packet */ + openwsn_radio.dev->driver->recv(openwsn_radio.dev, NULL, bytes_expected, + NULL); + radio_rxEnable(); + return; + } + + int nread = openwsn_radio.dev->driver->recv(openwsn_radio.dev, bufRead, + bytes_expected, &rx_info); + + /* FCS is skipped by netdev in the returned length, but OpenWSN includes + IEEE802154_FCS_LEN in its length value */ + *lenRead = nread + IEEE802154_FCS_LEN; + + /* get rssi, lqi & crc */ + *rssi = rx_info.rssi; + *lqi = rx_info.lqi; + /* only valid crc frames are currently accepted */ + *crc = 1; + + radio_rxEnable(); +} + +static void _event_cb(netdev_t *dev, netdev_event_t event) +{ + (void)dev; + + if (event == NETDEV_EVENT_ISR) { + /* capture the time */ + debugpins_isr_set(); + _txrx_event_capture_time = sctimer_readCounter(); + openwsn_radio.dev->driver->isr(openwsn_radio.dev); + debugpins_isr_clr(); + } + else { + LOG_DEBUG("[openwsn/radio]: event triggered -> %i\n", event); + switch (event) { + case NETDEV_EVENT_RX_STARTED: + openwsn_radio.startFrame_cb(_txrx_event_capture_time); + LOG_DEBUG("[openwsn/radio]: NETDEV_EVENT_RX_STARTED\n"); + break; + case NETDEV_EVENT_TX_STARTED: + openwsn_radio.startFrame_cb(_txrx_event_capture_time); + LOG_DEBUG("[openwsn/radio]: NETDEV_EVENT_TX_STARTED\n"); + break; + case NETDEV_EVENT_RX_COMPLETE: + openwsn_radio.endFrame_cb(_txrx_event_capture_time); + LOG_DEBUG("[openwsn/radio]: NETDEV_EVENT_RX_COMPLETE\n"); + break; + case NETDEV_EVENT_TX_COMPLETE: + openwsn_radio.endFrame_cb(_txrx_event_capture_time); + LOG_DEBUG("[openwsn/radio]: NETDEV_EVENT_TX_COMPLETE\n"); + break; + default: + break; + } + } +} diff --git a/pkg/openwsn/contrib/sctimer_rtt.c b/pkg/openwsn/contrib/sctimer_rtt.c new file mode 100644 index 000000000000..1efdcd97812a --- /dev/null +++ b/pkg/openwsn/contrib/sctimer_rtt.c @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2017 Hamburg University of Applied Sciences + * 2020 Inria + * + * 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 pkg_openwsn + * @{ + * + * For details on the implementation check pkg/openwsn/doc.txt + * + * @file + * @brief RTT based adaptation of "sctimer" bsp module + * + * @author Tengfei Chang , July 2012 + * @author Peter Kietzmann , July 2017 + * @author Michel Rottleuthner , April 2019 + * @author Francisco Molina + * + * @} + */ +#include + +#include "sctimer.h" +#include "debugpins.h" + +#include "board.h" +#include "periph/rtt.h" + +#define LOG_LEVEL LOG_NONE +#include "log.h" + +/** + * @brief Maximum counter difference to not consider an ISR late, this + * should account for the largest timer interval OpenWSN + * scheduler might work with. When running only the stack this + * should not be more than SLOT_DURATION, but when using cjoin + * it is 65535ms + */ +#ifndef SCTIMER_LOOP_THRESHOLD +#define SCTIMER_LOOP_THRESHOLD (2 * PORT_TICS_PER_MS * 65535) +#endif + +/* OpenWSN needs at least 32 tics per ms,use time division to reach that + if needed */ +#ifdef RTT_FREQUENCY +#if RTT_FREQUENCY < 32768U +#define SCTIMER_TIME_DIVISION (1) +#if (SCTIMER_FREQUENCY % RTT_FREQUENCY) != 0 +#error "RTT_FREQUENCY not supported" +#endif +#endif +#endif + +#ifdef SCTIMER_TIME_DIVISION +#define SCTIMER_PRESCALER __builtin_ctz( \ + SCTIMER_FREQUENCY / RTT_FREQUENCY) +#define SCTIMER_TIME_DIVISION_MASK (RTT_MAX_VALUE >> SCTIMER_PRESCALER) +#define SCTIMER_PRESCALER_MASK (~SCTIMER_TIME_DIVISION_MASK) +#define SCTIMER_PRESCALER_SHIFT __builtin_ctz(SCTIMER_TIME_DIVISION_MASK) + +static uint32_t _prescaler; +static atomic_bool _enable; +#endif + +static sctimer_cbt sctimer_cb; + +static void sctimer_isr_internal(void *arg) +{ + (void)arg; + + if (sctimer_cb != NULL) { + debugpins_isr_set(); + sctimer_cb(); + debugpins_isr_clr(); + } +} + +void sctimer_init(void) +{ + rtt_init(); + sctimer_cb = NULL; +#ifdef SCTIMER_TIME_DIVISION + _prescaler = 0; + _enable = false; +#endif +} + +void sctimer_set_callback(sctimer_cbt cb) +{ + sctimer_cb = cb; +} + +#ifdef SCTIMER_TIME_DIVISION +uint32_t _update_val(uint32_t val, uint32_t now) +{ + now = now & SCTIMER_PRESCALER_MASK; + val = val >> SCTIMER_PRESCALER; + /* Check if next value would cause an overflow */ + if ((now - val) > SCTIMER_LOOP_THRESHOLD && _enable && now > val) { + _prescaler += (1 << SCTIMER_PRESCALER_SHIFT); + _enable = false; + } + /* Make sure it only updates the _prescaler once per overflow cycle */ + if (val > SCTIMER_LOOP_THRESHOLD && val < 2 * SCTIMER_LOOP_THRESHOLD) { + _enable = true; + } + val |= _prescaler; + + return val; +} +#endif + +void sctimer_setCompare(uint32_t val) +{ + unsigned state = irq_disable(); + + uint32_t now = rtt_get_counter(); + +#ifdef SCTIMER_TIME_DIVISION + val = _update_val(val, now); +#endif + + if ((int32_t)now - val < SCTIMER_LOOP_THRESHOLD && now > val) { + rtt_set_alarm((now + RTT_MIN_OFFSET) & RTT_MAX_VALUE, + sctimer_isr_internal, NULL); + } + else { + if ((int32_t)val - now < RTT_MIN_OFFSET) { + rtt_set_alarm((now + RTT_MIN_OFFSET) & RTT_MAX_VALUE, + sctimer_isr_internal, NULL); + } + else { + rtt_set_alarm(val & RTT_MAX_VALUE, sctimer_isr_internal, + NULL); + } + } + + irq_restore(state); + + LOG_DEBUG("[sctimer]: set cb to %" PRIu32 " at %" PRIu32 "\n", + (uint32_t) val, now); +} + +uint32_t sctimer_readCounter(void) +{ + uint32_t now = rtt_get_counter(); + +#ifdef SCTIMER_TIME_DIVISION + now &= SCTIMER_TIME_DIVISION_MASK; + now = (now << SCTIMER_PRESCALER); +#endif + LOG_DEBUG("[sctimer]: now %" PRIu32 "\n", now); + return now; +} + +void sctimer_enable(void) +{ + rtt_poweron(); +} + +void sctimer_disable(void) +{ + rtt_poweroff(); +} diff --git a/pkg/openwsn/contrib/sctimer_ztimer.c b/pkg/openwsn/contrib/sctimer_ztimer.c new file mode 100644 index 000000000000..e1ab32a63213 --- /dev/null +++ b/pkg/openwsn/contrib/sctimer_ztimer.c @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2020 Inria + * + * 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 pkg_openwsn + * @{ + * + * @file + * @brief Ztimer based adaptation of "sctimer" bsp module + * + * For details on the implementation check pkg/openwsn/doc.txt + * + * @author Francisco Molina + * + * @} + */ +#include "sctimer.h" +#include "debugpins.h" + +#include "ztimer.h" +#include "ztimer/convert.h" +#include "ztimer/convert_frac.h" +#include "ztimer/convert_shift.h" +#include "ztimer/config.h" + +#include "periph_conf.h" + +#define LOG_LEVEL LOG_NONE +#include "log.h" + +/** + * @brief Maximum counter difference to not consider an ISR late, this + * should account for the largest timer interval OpenWSN + * scheduler might work with. When running only the stack this + * should not be more than SLOT_DURATION, but when using cjoin + * it is 65535ms + */ +#ifndef SCTIMER_LOOP_THRESHOLD +#define SCTIMER_LOOP_THRESHOLD (2 * PORT_TICS_PER_MS * 65535) +#endif + +#if CONFIG_ZTIMER_MSEC_BASE_FREQ > 32768U +static ztimer_convert_frac_t _ztimer_convert_frac_32768; +#define ZTIMER_32768_CONVERT_LOWER_FREQ CONFIG_ZTIMER_MSEC_BASE_FREQ +#define ZTIMER_32768_CONVERT_LOWER (ZTIMER_MSEC_BASE) +/* cppcheck-suppress preprocessorErrorDirective + * (reason: cppcheck fails to see that CONFIG_ZTIMER_MSEC_BASE_FREQ + * is set in ztimer/config.h to a non zero value */ +#elif (CONFIG_ZTIMER_MSEC_BASE_FREQ < 32768U) && \ + ((32768U % CONFIG_ZTIMER_MSEC_BASE_FREQ) == 0) +static ztimer_convert_shift_t _ztimer_convert_shift_32768; +#define ZTIMER_32768_CONVERT_HIGHER_FREQ CONFIG_ZTIMER_MSEC_BASE_FREQ +#define ZTIMER_32768_CONVERT_HIGHER (ZTIMER_MSEC_BASE) +#elif (CONFIG_ZTIMER_MSEC_BASE_FREQ < 32768U) && \ + ((32768U % CONFIG_ZTIMER_MSEC_BASE_FREQ) != 0) +#error No suitable ZTIMER_MSEC_BASE config. Maybe add USEMODULE += ztimer_usec? +#endif + +static sctimer_cbt _sctimer_cb; +static ztimer_t _ztimer_sctimer; +static ztimer_clock_t *ZTIMER_32768 = NULL; + +static void sctimer_isr_internal(void *arg) +{ + (void)arg; + + if (_sctimer_cb != NULL) { + debugpins_isr_set(); + _sctimer_cb(); + debugpins_isr_clr(); + } +} + +void sctimer_init(void) +{ +#if CONFIG_ZTIMER_MSEC_BASE_FREQ > 32768U + ZTIMER_32768 = &_ztimer_convert_frac_32768.super.super; +/* cppcheck-suppress preprocessorErrorDirective + * (reason: cppcheck fails to see that CONFIG_ZTIMER_MSEC_BASE_FREQ + * is set in ztimer/config.h to a non zero value */ +#elif (CONFIG_ZTIMER_MSEC_BASE_FREQ < 32768U) && \ + (32768U % CONFIG_ZTIMER_MSEC_BASE_FREQ == 0) + ZTIMER_32768 = &_ztimer_convert_shift_32768.super.super; +#elif CONFIG_ZTIMER_MSEC_BASE_FREQ == 32768U + ZTIMER_32768 = ZTIMER_MSEC_BASE; +#else +#error Invalid ZTIMER_MSEC_BASE_FREQ config. Maybe add USEMODULE += ztimer_usec? +#endif + +#if defined(ZTIMER_32768_CONVERT_LOWER) + LOG_DEBUG("[sctimer]: ZTIMER_32768 convert_frac from %lu to 32768\n", + (long unsigned)ZTIMER_32768_CONVERT_LOWER_FREQ); + ztimer_convert_frac_init(&_ztimer_convert_frac_32768, + ZTIMER_32768_CONVERT_LOWER, + SCTIMER_FREQUENCY, + ZTIMER_32768_CONVERT_LOWER_FREQ); +#elif defined(ZTIMER_32768_CONVERT_HIGHER) + LOG_DEBUG("[sctimer]: ZTIMER_32768 convert_shift %lu to 32768\n", + (long unsigned)ZTIMER_32768_CONVERT_HIGHER_FREQ); + ztimer_convert_shift_up_init(&_ztimer_convert_shift_32768, + ZTIMER_32768_CONVERT_HIGHER, + __builtin_ctz(SCTIMER_FREQUENCY / + CONFIG_ZTIMER_MSEC_BASE_FREQ)); +#endif + + _ztimer_sctimer.callback = sctimer_isr_internal; +} + +void sctimer_set_callback(sctimer_cbt cb) +{ + _sctimer_cb = cb; +} + +void sctimer_setCompare(uint32_t val) +{ + unsigned state = irq_disable(); + + uint32_t now = ztimer_now(ZTIMER_32768); + + /* if the next compare value (isr) to schedule is already later than + the required value, but close enough to think we have been slow + in scheduling it, trigger the ISR right away */ + if (now > val) { + if (now - val < SCTIMER_LOOP_THRESHOLD) { + ztimer_set(ZTIMER_32768, &_ztimer_sctimer, 0); + } + else { + ztimer_set(ZTIMER_32768, &_ztimer_sctimer, + UINT32_MAX - now + val); + } + } + else { + ztimer_set(ZTIMER_32768, &_ztimer_sctimer, val - now); + } + + irq_restore(state); + + LOG_DEBUG("[sctimer]: set cb to %" PRIu32 " at %" PRIu32 "\n", + val, now); +} + +uint32_t sctimer_readCounter(void) +{ + uint32_t now = ztimer_now(ZTIMER_32768); + + LOG_DEBUG("[sctimer]: now %" PRIu32 "\n", now); + return now; +} + +void sctimer_enable(void) +{ + /* not supported, sctimer does not control RTT or ztimer */ +} + +void sctimer_disable(void) +{ + /* not supported, sctimer does not control RTT or ztimer */ +} diff --git a/pkg/openwsn/contrib/uart.c b/pkg/openwsn/contrib/uart.c new file mode 100644 index 000000000000..83f22c363047 --- /dev/null +++ b/pkg/openwsn/contrib/uart.c @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2018 Hamburg University of Applied Sciences + * 2020 Inria + * + * 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 pkg_openwsn + * @{ + * + * @file + * @brief RIOT adaption of the OpenWSN "uart" bsp module. + * + * @author Peter Kietzmann + * @author Francisco Molina + * + * @} + */ + +#include + +#include "board.h" +#include "periph/uart.h" + +#ifdef MODULE_ZTIMER_USEC +#include "ztimer.h" +#endif + +#include "openwsn_uart.h" + +#define XOFF 0x13 +#define XON 0x11 +#define XONXOFF_ESCAPE 0x12 +#define XONXOFF_MASK 0x10 + +typedef struct { + uart_tx_cbt txCb; + uart_rx_cbt rxCb; + atomic_bool fXonXoffEscaping; + atomic_char xonXoffEscapedByte; +} uart_vars_t; + +static uart_vars_t _uart_vars; +static atomic_char _uart_rx_byte; + +#ifdef MODULE_ZTIMER_USEC +static ztimer_t _ztimer_tx_uart; +#endif + +static void _openwsn_uart_write(const uint8_t *data) +{ + if (IS_USED(MODULE_OPENWSN_SERIAL)) { + uart_write(OPENWSN_UART_DEV, data, 1); +#ifdef MODULE_ZTIMER_USEC + ztimer_set(ZTIMER_USEC, &_ztimer_tx_uart, 0); +#endif + } +} + +static void _riot_rx_cb(void *arg, uint8_t data) +{ + (void)arg; + if (IS_USED(MODULE_OPENWSN_SERIAL)) { + _uart_rx_byte = data; + if (_uart_vars.rxCb) { + _uart_vars.rxCb(); + } + } + else { + (void)data; + } +} + +static void _riot_tx_cb(void *arg) +{ + (void)arg; + + if (IS_USED(MODULE_OPENWSN_SERIAL)) { + if (_uart_vars.fXonXoffEscaping == 0x01) { + _uart_vars.fXonXoffEscaping = 0x00; + _uart_vars.xonXoffEscapedByte ^= XONXOFF_MASK; + _openwsn_uart_write((uint8_t *)&(_uart_vars.xonXoffEscapedByte)); + } + else { + if (_uart_vars.txCb) { + _uart_vars.txCb(); + } + } + } +} + +void uart_enableInterrupts(void) +{ + /* unused in RIOT */ +} + +void uart_disableInterrupts(void) +{ + /* unused in RIOT */ +} + +void uart_clearRxInterrupts(void) +{ + /* unused in RIOT */ +} + +void uart_clearTxInterrupts(void) +{ + /* unused in RIOT */ +} + +void uart_init_openwsn(void) +{ + if (IS_USED(MODULE_OPENWSN_SERIAL)) { + uart_init(OPENWSN_UART_DEV, OPENWSN_UART_BAUDRATE, \ + (uart_rx_cb_t)_riot_rx_cb, NULL); +#ifdef MODULE_ZTIMER_USEC + _ztimer_tx_uart.callback = &_riot_tx_cb; +#else + (void) _riot_tx_cb; +#endif + } +} + +void uart_setCallbacks(uart_tx_cbt txCb, uart_rx_cbt rxCb) +{ + if (IS_USED(MODULE_OPENWSN_SERIAL)) { + _uart_vars.txCb = txCb; + _uart_vars.rxCb = rxCb; + } + else { + (void)rxCb; + (void)txCb; + } +} + +void uart_setCTS(bool state) +{ + if (IS_USED(MODULE_OPENWSN_SERIAL)) { + uint8_t byte; + if (state == true) { + byte = XON; + } + else { + byte = XOFF; + } + _openwsn_uart_write(&byte); + } + else { + (void)state; + } +} + +void uart_writeByte(uint8_t byteToWrite) +{ + if (IS_USED(MODULE_OPENWSN_SERIAL)) { + if (byteToWrite == XON || byteToWrite == XOFF || \ + byteToWrite == XONXOFF_ESCAPE) { + uint8_t byte = XONXOFF_ESCAPE; + _uart_vars.fXonXoffEscaping = 0x01; + _uart_vars.xonXoffEscapedByte = byteToWrite; + _openwsn_uart_write(&byte); + } + else { + _openwsn_uart_write(&byteToWrite); + } + } + else { + (void)byteToWrite; + } +} + +inline uint8_t uart_readByte(void) +{ + if (IS_USED(MODULE_OPENWSN_SERIAL)) { + return _uart_rx_byte; + } + else { + return 0x00; + } +} diff --git a/pkg/openwsn/doc.txt b/pkg/openwsn/doc.txt new file mode 100644 index 000000000000..94d97326cbca --- /dev/null +++ b/pkg/openwsn/doc.txt @@ -0,0 +1,420 @@ +/** + @defgroup pkg_openwsn OpenWSN network stack + @ingroup pkg + @ingroup net + @brief Provides a RIOT adaption of the OpenWSN network stack + @see https://github.com/openwsn-berkeley/openwsn-fw + @experimental + + # OpenWSN RIOT Port + + This implementation integrates the [OpenWSN](https://github.com/openwsn-berkeley/openwsn-fw) + full network stack (UDP, IPv6 (6LoWPAN), RPL, 6TiSCH) into RIOT. + + It can be used instead of GNRC on supported 802.15.4 radios, and compared to + GNRC, provides a full 6TiSCH implementation. It does not yet support RIOT's + sock API, so applications will have to be written against OpenWSN's API. + + This port provides a new RIOT "board" to the OpenWSN software. In this way + RIOT's hardware abstraction connects to OpenWSN's interfaces. + + The simple scheduling mechanism in OpenWSN is run in a RIOT thread with + second highest priority after the radio thread (THREAD_PRIORITY_MAIN - 4). + + The current port of OpenWSN currently needs a root node that works along an + external tool that performs routing and handles join procedure: + [Openvisualizer](https://github.com/openwsn-berkeley/openvisualizer) + + + ## Joining a network + + The first thing a new mote will need to do is to find a network. On boot it + will actively be listening for enhanced beacons. Once a beacon is received it + will adjust its timers drift and synchronize with the network. Re-synchronization + will be happening constantly to compensate for oscillator and timer drifts. + + Once synchronized the node will need to join the network. OpenWSN uses CoJP + [constrained join protocol](https://datatracker.ietf.org/doc/draft-ietf-6tisch-minimal-security/) + an the stack itself only handles Join Requests. The JRC (join registrar/coordinator, + a central entity) is not running on the root node, but alongside it, in the + `OpenVisualizer` external tool. + + Once joined the device has the required keys to start listening to DIS (DODAG + Information Solicitation) messages and to send DIO (DODAG Information Object) + requests. Once it knows about the topology of the network it is able to + send packets. + + OpenWSN uses source routing. This means that unless the recipient of a packet + is one of the parents in the RPL tree the packet will have to go up the tree + to the root node. But in OpenWSN RPL implementation the node does not know + how to route, instead it is `OpenVisualizer` which generates an SRH (Source + Routing Header), attaches to the incoming packet and sends it down the tree. + + ## Hardware abstraction implementation + + Following, details about the implementation of selected hardware modules. + + ### sctimer + + The `sctimer` ("single compare timer") in OpenWSN is the lowest timer + abstraction which is used by the higher layer timer module `opentimers`. In + the end it is responsible for scheduling on the MAC layer. To enable low power + energy modes, this timer usually uses the RTC (real time clock) or RTT (real + time timer) module. + + This port has two possible implementations or sctimer, one on top of + periph_rtt and another on top of ztimer, `sctimer_rtt` and `sctimer_ztimer` + respectively. If possible `ztimer` should be preferred, being a virtual + timer it will allow RIOT applications/modules to use the low level RTT timer. + But ztimer (any virtual timer) has some overhead which can be costly + depending on the different platforms used, specially when `openserial` + is required. More on this in openserial and Known Issues. + + #### sctimer_ztimer + + In order to get the most portable code, this implementation uses + ztimer and defines a new `ztimer_clock` (`ZTIMER_32768`) that operates + at 32768Khz to have a resolution of ~30usec/tick (same as OpenWSN). + + When available `ZTIMER_32768` will be built on top of `periph_rtt` to + get low power capabilities. If not it will be built on top of a + regular timer. In either case it will be shifted up if the base + frequency is lower than 32768Hz or frac if higher. + + When next interrupt to schedule is already late, current time, + implementations in OpenWSN directly trigger a hardware interrupt. + Until able to trigger sw isr directly a callback is set 0 ticks in + the future, which internally will be set to `now + RTT_MIN_OFFSET`. + + #### sctimer_rtt + + In order to reduce overhead this implementation uses bare RTT. It + expects a RTT running at 32768Hz to have a resolution of ~30usec/tick + (same as OpenWSN). If `RTT_FREQUENCY` is lower than 32768Hz then a + simple time-division mechanism will be used to speed up the clock. + This only works if `RTT_FREQUENCY` is 32768Hz/2. + + When next interrupt to schedule is already late, current time, + Implementations in OpenWSN directly trigger a hardware interrupt. + Until able to trigger sw isr directly a callback is set + `RTT_MIN_OFFSET` ticks in the future. + + ### radio + + The radio adaptation runs in its own thread with the highest priority + (`THREAD_PRIORITY_MAIN - 4`) and maps to RIOT's @ref netdev API. + + Hardware MAC layer features such as CSMA/CA, ACK handling and retransmissions + are handled by OpenWSN, so the radio driver must support disabling AUTOACK + and CSMA handling by the hardware. Frame filtering must as well be disabled. + + The radio adaptation preloads the buffer so `NETOPT_PRELOADING` must be + supported. + + OpenWSN needs to be notified when a frame reception/transmission starts and + when it ends. Therefore radio drivers need to support the following netdev + events: + + - `NETDEV_EVENT_RX_STARTED` + - `NETDEV_EVENT_TX_STARTED` + - `NETDEV_EVENT_RX_COMPLETE` + - `NETDEV_EVENT_TX_COMPLETE` + + OpenWSN expects to recover crc information on every received frame even if it + will simply drop frames with invalid crc. The stack can function correctly if + radio drivers automatically drop frames with an invalid crc (i.e. the stack + doesn't get notified about these frames). + + ### uart + + In RIOT, the first configured uart device is mapped to STDIO in most cases. + In OpenWSN however, the `openserial` tool uses uart to feed external software + running on a host computer such as + [Openvisualizer](https://github.com/openwsn-berkeley/openvisualizer). + To enable use of these tools, an uart adaptation is provided. + + This is provided through the `openwsn_serial` (`openserial`) module. It + will use the next available uart that is not used by STDIO + (checking STDIO_UART_DEV). When multiple uart are available STDIO and + `openserial` can be used in parallel. If `stdio_null` is used then `openserial` + will use `STDIO_UART_DEV`, otherwise it will use the next available uart. + e.g. If `STDIO_UART_DEV = UART_DEV(1)` `OPENWSN_UART_DEV = UART_DEV(0)` if + there are uarts. + + OpenWSN uart abstraction makes use of tx hardware interrupts to execute a + previously registered callback after every byte is sent out. These interrupts + are currently not defined in RIOT in a generic way, so instead a timer is set + to fire shortly after a byte is written. + + It uses `ztimer` to set the timer since it's already pulled in as a dependency. + + ### Openserial + + As was mentioned before any OpenWSN network will require a root node which is + connected to an `OpenVisualizer` instance running on a host computer. + Interaction between `OpenVisualizer` and the root-node is done over serial. As + OpenWSN uses source routing, this means that ultimately all network traffic + must go from the root node to `OpenVisualizer` and back. + + OpenSerial uses software flow control (XonXoff) to turn off serial activity + while time critical TSCH operation are ongoing. But software flow control + can cause issues since delays in the serial pipe (either because of a remote + connection, buffers, etc..) can lead to bytes being transmitted when one side + is not yet ready. + + Serial data is transmitted as High-Level Data Link Control (HDLC) frames. + Since network traffic is tunneled through the serial pipe, in order to + to have a stable connection these packets must not be lost. Packets can be + lost in multiple ways but at the end it reduces to bytes being overridden in + the uart reception buffer. + + 1. The last byte in an HDCL frame is received + 2. Serial pipe delays hindering XonXoff operation + 3. Interrupts are masked or higher/equal ISR are running + + 1. When the last byte of a frame is received some parsing and handling of the + frame occur. This takes some time and during that time OpenSerial can't + handle more incoming bytes. This in practice limits the baudrate depending + on the CPU's speed. + + 2. This can occur when a debugger/virtual-port might act as a + buffer between the mote and the host, or when there is a latency in the + connection (for example tcp connection to iotlab). + + 3. Since uart reception is interrupted based if the uart ISR is not serviced + for too long then bytes start overriding each other in the reception + buffer. In an application where only OpenWSN is running then there are 3 + functions/operations that run in ISR or with disabled ISR. + + (a) `opentimers_timer_callback` (OpenWSN timer abstraction callback) + (b) `sctimer_setCompare` and `sctimer_readCounter` + (c) `ztimer_handler` + + (a) and (b) are closely related since `opentimers_timer_callback` will + itself call `sctimer_setCompare` and `sctimer_readCounter`. And this itself + will depend on `ztimer_set` and `ztimer_now` or `rtt_get_counter` or + `rtt_set_alarm` execution time. + + (c) is also related to (a) (b) since `ztimer_handler` will also call + `opentimers_timer_callback` as well as the underlying `rtt` functions. + + Since a 115200 baudrate means ~1byte every 10us, none of the above can take + longer than that or bytes could be lost at that baudrate. + + Because of the above mentioned reasons, it is preferable to use `sctimer_rtt` + for the root node or "border router" on an OpenWSN network, since this reduces + the likeliness of packets being lost. For non root nodes, OpenSerial only + provides debugging information so no special care needs to be taken. + + It is also recommended that the root node should act as a border router + running only the OpenWSN stack to avoid other threads/ISR disrupting serial + reception. + + ## Tested Platforms and Pin configurations + + So far, this has been successfully tested on `iotlab-m3`,`nucleo-f103` and + `samr21-xpro`, all based on at86rf23x radios. + + ### Synchronization + + To join a network a node must first receive EB (enhanced beacons). Once an EB + is received the node will be synchronized with the network. Synchronization + times are not deterministic, they depend on the following: + + `SLOTFRAME_LENGTH*SLOTDURATION*P_CHANNEL*P_EB` + + `SLOTFRAME_LENGTH` in OpenWSN is 101, and this port uses 20ms as the slotOffset + duration. `P_EB` specifies the a probability for a node to transmit an EB. + By default it's 10%, that means that on average it will take 10 tries before an + EB is transmitted. `P_CHANNEL` is the probability for the transmitter's and + receiver channel to match. If channel hopping is disabled this means that the + average worst case scenario is `101*20ms*10 ~= 20s`, so 20s for synchronization + to take place. `EB_PORTION` can be changed to increase the likelihood of EB to be + sent. This can also be achieved by reducing `SLOTFRAME_LENGTH`, but the later can + have an impact on the MSF (Minimal Scheduling Function). If too few cells are + available this could increase the likelihood of collisions. + + On the other hand if channel hopping is enabled then the joining node picks a + random channel to start listening on. The transmitter also picks a random + channel to start transmitting on and then follows a channel hopping template. + This would take on average ~8 tries for it to hit the correct channel for the + first time, and then it would hit it every 16 hops, on average this could lead + synchronization times of around `320s`. + + If nodes are having trouble in staying synchronized increasing `P_EB` by + reducing the value of `EB_PORTION` can also be done. Note that `EB_PORTION` + and `SLOTFRAME_LENGTH` are not configurable by default so need to be overridden + with `CFLAGS`. + + ### Timing + + Timing is essential for OpenWSN to work properly. For optimal results most + parameters in `board_info.h` should be measured for the specific hardware used. + OpenWSN has done that for most of their boards. These values can not be taken + directly from OpenWSN since they do not necessarily use the same TIMER's or + clock speeds. + + For more details on those parameters refer to: + https://openwsn.atlassian.net/wiki/spaces/OW/pages/688251/State+Machine + + Since all these parameters are HW dependent, it also means that hybrid + networks (different type of underlying hardware) might desynchronize often, + or not manage to keep in sync at all. + + Print messages during TSCH operation should be avoided since these can disrupt + TSCH timings. + + ### ledpins & debugpins + + The OpenWSN software provides different hooks all over the stack to toggle + different LEDs as well as debug pins to examine state and scheduling of a node. + Default configuration files are provided for both. The LED configuration maps to + RIOTs `LEDX_PIN` definitions, if available. On Nucleo boards LED0 line is + shared SPI, so is not used. + + The default configuration can be overwritten by setting `OPENWSN_LEDS_DEFAULT` + in the form of `leds_config_t`. The debugpins work similarly by setting + `OPENWSN_DEBUGPINS_BOARD` in the form of `debugpins_config_t`. + + The default configuration maps to OpenWSN reference hardware `openmote-b`. + + ## Testing and debugging + + List of some items which are helpful to explore the functionality of OpenWSN: + + - LED pins and debug pins as mentioned above in combination with a logic analyzer. + The expected behavior is described in: + [OpenWSN wiki](https://openwsn.atlassian.net/wiki/spaces/OW/pages/688257/Schedules). + + - The provided test application provides a UDP client and server. If the UDP + server is able to receive packets, the mechanism is considered to work correctly. + You should also be able to ping the device from your host. See + `tests/pkg_openwsn/README.md` for more details. + + - To speed up synchronization and make sniffing easier you can disable channel + hopping by setting (`CFLAGS=-DIEEE802154E_SINGLE_CHANNEL=26`). + + - To sniff the packets either use a 802.15.4 capable board and follow at: + https://github.com/RIOT-OS/applications/blob/master/sniffer/tools/README.md. + Alternatively use a Raspberry Pi with an external radio such as Openlabs and + incorporate Linux WPAN tools. In addition to that, there's also other + hardware such as the ATUSB IEEE 802.15.4 USB Adapter which can directly be + used on your Linux computer with WPAN tools installed. If you conduct your + experiments on the IoT-LAB testbed you might want to use a: + [sniffer profile](https://www.iot-lab.info/tutorials/radio-sniffer). + + - To explore the channel hopping mechanism there are rather expensive + multi-channel sniffers such as the BeamLogic 802.15.4 Site Analyzer that can + sniff all channels simultaneously. Alternatively you can set up multiple + separate sniffer devices locally or make use of the `sniffer_aggregator` on + the IoT-LAB testbed. + + - To test Openserial on a given platform the target `make openv-serial` can + be used on a BOARD flashed with `tests/pkg_openwsn` (`USEMODULE=openwsn_serial`) + must be included as well. The following output should appear: + + ``` + Test Setup: + ------------------ + Iterations: 100 + Packet length: 100 + Echo timeout: 2 + + Test Progress: + + [####################################] 100% + + Test Statistics: + ------------------ + Pkts send: 100 + Echo success: 100 + Echo timeout: 0 + Echo corrupted: 0 + ``` + + The test should be considered passing if success rate is > 98%. + + ## Known Issues + + The following errors might be visible when using `openwsn_serial`: + + - `[OPENSERIAL] wrong CRC in input Buffer` + + Since a timer is set to simulate a uart transmit interrupt, it can happen that + the interrupt is missed if another interrupt occurs during that time, this + seems to lead to the input buffer missing a byte and so CRC fails. More details + where given in the `openserial` section. + + - `[IEEE802154E] wdDataDuration overflows while at state 19 in slotOffset 0` + + This error can show up when the radio starts receiving (receives the SFD) and + therefore triggers a `NETDEV_RX_STARTED` but then no `NETDEV_TX_STARTED` + event follows. This happens when packets with invalid CRC are received. + netdev currently silently drops these packets without notifying upper layers. + But this does not affect the stack operation, so they can be ignored. + + - `[IEEE802154E] large timeCorr.: -18 ticks (code loc. 0)` + + Most crystals used to clock the RTT will drift even those with a very similarly + drift (10-30ppm). It's is normal then for motes adjust their timerCorr as long + as it stays within the above mentioned margins and if motes are able to stay + synchronized over the long run. If there aren't then maybe board_info.h + parameters require tuning for the specific platform. + +- `[JRC:ERROR] Type-error in conversion of 5N=ex` + +This errors happen when a node tries to rejoin the network. This error is only +associated to a log print, so can be ignored. + +- `[coap:WARNING] coapRcBadRequest(reason=OSCOAP unprotect failed: oscoapError(reason=Replay protection failed))` + +The join procedure uses a replay window. If a node had already joined the network +and for some reason attempts to rejoin again, then the replay windows will need +to expire for it's join request to be accepted. + +The following errors are platform specific. + + - samr21-xpro issues: + - The serial debugger hinders Openserial operation, an ftdi device must + be used. + + - sam0 issues: + - sam0 requires 180us busy loops every time an alarm is set or the + counter is read. Because of the later only `sctimer_rtt` can be used + and the max. tested baudrate for openserial is of 19200 bauds. + + - iotlab-m3 issues: + - openserial does not work reliably over 57600 bauds or when using + sctimer_ztimer. + +Other errors: + +- missed characters over stdio + +TSCH state machine disable occurs in IRQ context and disables IRQ during time +critical sections. This can cause bytes sent over stdio to be missed. + + ## Todos + + - `sctimer` to trigger an ISR immediately using software interrupts. + - `RTT_FREQUENCY` is not configurable for most platforms, implementations + should be adapted to make this configurable to be able to set `RTT_FREQUENCY` + to 32768Hz or the closer possible value. + - The UART wrapper uses ztimer to fake an interrupt after one byte + has been sent. This should also be done with software interrupts. + + ## Future Steps + + The OpenWSN community is working on refactoring their code base. As + one of the outputs of this modules like `cjoin`, `udp`, `coap` will become + optional. Once this is upstream the support for this pkg should be adapted. + + With above mentioned re-works the extraction of the MAC layer might be favored. + + As more immediate future steps: + + - Follow up PR to add OpenWSN sock + - Complete support of OpenWSN default HW (`openmote-b`) + - Add support for other 802.15.4 network drivers + + */ diff --git a/pkg/openwsn/include/board_info.h b/pkg/openwsn/include/board_info.h new file mode 100644 index 000000000000..03a43f0db86f --- /dev/null +++ b/pkg/openwsn/include/board_info.h @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2017 Hamburg University of Applied Sciences + * 2020 Inria + * + * 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 pkg_openwsn + * @{ + * + * @file + * + * @author Thomas Watteyne , February 2012 + * @author Tengfei Chang , July 2012 + * @author Peter Kietzmann , July 2017 + * @author Francisco Molina + * + * @} + */ + +#ifndef BOARD_INFO_H +#define BOARD_INFO_H + +#include +#include + +#include "board.h" +#include "periph_conf.h" +#include "timex.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name OpenWSN interrupt handling wrappers + * @{ + */ +#define INTERRUPT_DECLARATION() unsigned irq_state; +#define DISABLE_INTERRUPTS() irq_state = irq_disable(); +#define ENABLE_INTERRUPTS() irq_restore(irq_state); +#define SCHEDULER_WAKEUP() /* unused by RIOT */ +#define SCHEDULER_ENABLE_INTERRUPT() /* unused by RIOT */ +/** @} */ + + +/** + * @name OpenWSN platform dependent definitions + * @{ + */ +/* Always 32bit when using ztimer */ +#if RTT_MAX_VALUE == UINT32_MAX || !((RTT_MAX_VALUE + 1) & (RTT_MAX_VALUE)) || \ + IS_USED(MODULE_OPENWSN_SCTIMER_ZTIMER) +#define PORT_TIMER_WIDTH uint32_t +#define PORT_RADIOTIMER_WIDTH uint32_t +#else +#error "RTT_MAX_VALUE not supported" +#endif + +#if __SIZEOF_POINTER__ == 2 +#define PORT_SIGNED_INT_WIDTH int16_t +#else +#define PORT_SIGNED_INT_WIDTH int32_t +#endif + +#define SCTIMER_FREQUENCY (32768U) + +/* 32 ticks @32768Hz */ +#define PORT_TICS_PER_MS (SCTIMER_FREQUENCY / MS_PER_SEC) +/* 30 us per tick @32768Hz */ +#define PORT_US_PER_TICK (US_PER_SEC / SCTIMER_FREQUENCY) +/** @} */ + +/** + * @name OpenWSN IEEE802154E timings + * @{ + * + * @note These parameters are BOARD and CPU specific. + Values can't be taken directly from OpenWSN since they do not necessarily use + the same BSP configuration (timers, clock speed, etc.) + For precise synchronization these values should be measured and tuned for + every BOARD. + To understand the relationship between these values and OpenWSN state machine + as well as how they can be measured refer to: + - https://openwsn.atlassian.net/wiki/spaces/OW/pages/688251/State+Machine + - https://openwsn.atlassian.net/wiki/spaces/OW/pages/688255/Timing+Constants + */ +/* standard slot duration is 10ms but code execution time for most OpenWSN + supported BOARDS takes longer than 10ms, so use the default 20ms upstream + slot */ +#ifndef SLOTDURATION +#define SLOTDURATION 20 /* in milliseconds */ +#endif + +#if SLOTDURATION == 20 +#ifndef PORT_TsSlotDuration /* 655 ticks at @32768Hz */ +#define PORT_TsSlotDuration ((SCTIMER_FREQUENCY * SLOTDURATION) / MS_PER_SEC) +#endif + +/* Execution speed related parameters */ +#ifndef PORT_maxTxDataPrepare +#define PORT_maxTxDataPrepare (3355 / PORT_US_PER_TICK ) /* ~110 ticks at @32768Hz */ +#endif +#ifndef PORT_maxRxAckPrepare +#define PORT_maxRxAckPrepare (610 / PORT_US_PER_TICK ) /* ~20 ticks at @32768Hz */ +#endif +#ifndef PORT_maxRxDataPrepare +#define PORT_maxRxDataPrepare (1000 / PORT_US_PER_TICK ) /* ~33 ticks at@32768Hz */ +#endif +#ifndef PORT_maxTxAckPrepare +#define PORT_maxTxAckPrepare (1525 / PORT_US_PER_TICK ) /* ~50 ticks at@32768Hz */ +#endif + +/* Radio speed related parameters */ +#ifndef PORT_delayTx +#define PORT_delayTx (300 / PORT_US_PER_TICK ) /* ~10 ticks at@32768Hz */ +#endif +#ifndef PORT_delayRx +#define PORT_delayRx (0 / PORT_US_PER_TICK ) /* ~0 ticks at@32768Hz */ +#endif +#else +#error "Only 20ms slot duration is currently supported" +#endif +/** @} */ /* SLOTDURATION == 20 */ + +/** + * @name Adaptive sync accuracy + * + * Used for synchronization in heterogeneous networks (different BOARDs) + * Not supported yet, dummy value needs to be provided. + * @{ + */ +#define SYNC_ACCURACY (1) /* ticks */ +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* BOARD_INFO_H */ diff --git a/pkg/openwsn/include/openwsn.h b/pkg/openwsn/include/openwsn.h new file mode 100644 index 000000000000..dbe18eda63b8 --- /dev/null +++ b/pkg/openwsn/include/openwsn.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2018 Hamburg University of Applied Sciences + * 2020 Inria + * + * 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 pkg_openwsn + * + * @{ + * + * @file + * + * @author Peter Kietzmann + * @author Francisco Molina + */ +#ifndef OPENWSN_H +#define OPENWSN_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "thread.h" + +/** + * @brief Default PANID for OpenWSN network + */ +#ifndef OPENWSN_PANID +#define OPENWSN_PANID (0xCAFE) +#endif + +/** + * @brief Initializes OpenWSN thread + * + * @return PID of OpenWSN thread + * @return -1 on initialization error + */ +int openwsn_bootstrap(void); + +/** + * @brief get PID of OpenWsn thread. + * + * @return PID of OpenWsn thread + */ +kernel_pid_t openwsn_get_pid(void); + +#ifdef __cplusplus +} +#endif + +#endif /* OPENWSN_H */ +/** @} */ diff --git a/pkg/openwsn/include/openwsn_board.h b/pkg/openwsn/include/openwsn_board.h new file mode 100644 index 000000000000..5814662dc7a4 --- /dev/null +++ b/pkg/openwsn/include/openwsn_board.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2017 Hamburg University of Applied Sciences + * 2020 Inria + * + * 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 pkg_openwsn + * @{ + * + * RIOT HAL is provided as a new "board", a "RIOT board" to OpenWSN hardware + * abstraction interfaces. + * + * @file + * @brief RIOT adaption-specific definition of the "uart" bsp module. + * + * @author Thomas Watteyne , February 2012 + * @author Peter Kietzmann , July 2017 + * @author Francisco Molina + * + * @} + */ + +#ifndef OPENWSN_BOARD_H +#define OPENWSN_BOARD_H + +#include "board_info.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief OpenWSN `board.h` enum definitions + */ +typedef enum { + DO_NOT_KICK_SCHEDULER, + KICK_SCHEDULER, +} kick_scheduler_t; + +/** + * @brief Initialize OpenWSN bsp board adaptation + * + * Most initialization functions are not needed since there are initialized by + * RIOT's `auto_init` module. Only OpenWSN specific interfaces will be initialized + * here: `sctimer`, `openwsn_leds`, `openwsn_debugpins` & `uart_ow`. + * + */ +void board_init_openwsn(void); + +/** + * @brief Resets the board + * + */ +void board_reset(void); + +/** + * @brief Function definitions that we do not use in RIOT but that need to be + * defined for OpenWSN. Sleep is handled by `pm_layered` if enabled for + * the platform. + */ +void board_sleep(void); + +#ifdef __cplusplus +} +#endif + +#endif /* OPENWSN_BOARD_H */ diff --git a/pkg/openwsn/include/openwsn_debugpins.h b/pkg/openwsn/include/openwsn_debugpins.h new file mode 100644 index 000000000000..32832a7d1772 --- /dev/null +++ b/pkg/openwsn/include/openwsn_debugpins.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2017 Hamburg University of Applied Sciences + * + * 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 pkg_openwsn + * @{ + * + * @file + * @brief Provides an adaption of OpenWSN debug pin handling + * to RIOTs handling of GPIOs. + * + * @author Michael Frey + * @author Peter Kietzmann + * + * @} + */ + +#ifndef OPENWSN_DEBUGPINS_H +#define OPENWSN_DEBUGPINS_H + +#include "periph/gpio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief struct holding configuration of OpenWSN debug pins + */ +typedef struct debugpins_config { + gpio_t frame; /**< debug pin for frames */ + gpio_t slot; /**< debug pin for slots */ + gpio_t fsm; /**< debug pin for fsm */ + gpio_t task; /**< debug pin for tasks */ + gpio_t isr; /**< debug pin for interrupt service routines */ + gpio_t radio; /**< debug pin for the radio */ +} debugpins_config_t; + +/** + * Sets the debug pins for a specific board for OpenWSN + * + * @param[in] user_config A configuration of GPIO pins used for debugging. + * Unused pins need to be defined as GPIO_UNDEF. + */ +void openwsn_debugpins_init(const debugpins_config_t *user_config); + +#ifdef __cplusplus +} +#endif + +#endif /* OPENWSN_DEBUGPINS_H */ diff --git a/pkg/openwsn/include/openwsn_debugpins_params.h b/pkg/openwsn/include/openwsn_debugpins_params.h new file mode 100644 index 000000000000..5ecc54f5f800 --- /dev/null +++ b/pkg/openwsn/include/openwsn_debugpins_params.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2017 Hamburg University of Applied Sciences + * + * 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 pkg_openwsn + * @{ + * + * @file + * @brief Default configuration for the OpenWSN debugpins + * + * @author Michael Frey + * @author Peter Kietzmann + * + * @} + */ + +#ifndef OPENWSN_DEBUGPINS_PARAMS_H +#define OPENWSN_DEBUGPINS_PARAMS_H + +#include "openwsn_debugpins.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name OpenWSN default debugpins configuration. + * + * Undefined by default. + * @{ + */ +#ifndef OPENWSN_DEBUGPIN_FRAME +#define OPENWSN_DEBUGPIN_FRAME GPIO_UNDEF +#endif +#ifndef OPENWSN_DEBUGPIN_SLOT +#define OPENWSN_DEBUGPIN_SLOT GPIO_UNDEF +#endif +#ifndef OPENWSN_DEBUGPIN_FSM +#define OPENWSN_DEBUGPIN_FSM GPIO_UNDEF +#endif +#ifndef OPENWSN_DEBUGPIN_TASK +#define OPENWSN_DEBUGPIN_TASK GPIO_UNDEF +#endif +#ifndef OPENWSN_DEBUGPIN_ISR +#define OPENWSN_DEBUGPIN_ISR GPIO_UNDEF +#endif +#ifndef OPENWSN_DEBUGPIN_RADIO +#define OPENWSN_DEBUGPIN_RADIO GPIO_UNDEF +#endif + +#define OPENWSN_DEBUGPINS_DEFAULT { .frame = OPENWSN_DEBUGPIN_FRAME, \ + .slot = OPENWSN_DEBUGPIN_SLOT, \ + .fsm = OPENWSN_DEBUGPIN_FSM, \ + .task = OPENWSN_DEBUGPIN_TASK, \ + .isr = OPENWSN_DEBUGPIN_ISR, \ + .radio = OPENWSN_DEBUGPIN_RADIO} +/**@}*/ + +/** + * @brief OpenWSN debugpins configuration + */ +static const debugpins_config_t openwsn_debugpins_params[] = +{ +#ifdef OPENWSN_DEBUGPINS_BOARD + OPENWSN_DEBUGPINS_BOARD, +#else + OPENWSN_DEBUGPINS_DEFAULT, +#endif +}; + +#ifdef __cplusplus +} +#endif + +#endif /* OPENWSN_DEBUGPINS_PARAMS_H */ diff --git a/pkg/openwsn/include/openwsn_leds.h b/pkg/openwsn/include/openwsn_leds.h new file mode 100644 index 000000000000..17774ede2784 --- /dev/null +++ b/pkg/openwsn/include/openwsn_leds.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2017 Hamburg University of Applied Sciences + * 2020 Inria + * + * 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 pkg_openwsn + * @{ + * + * @file + * @brief Provides an adaption of OpenWSN led handling + * to RIOTs handling of LEDs and/or GPIOs + * + * @author Peter Kietzmann + * @author Francisco Molina + * + * @} + */ +#ifndef OPENWSN_LEDS_H +#define OPENWSN_LEDS_H + +#include "periph/gpio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief OpenWSN leds pin configuration + * @{ + */ +typedef struct leds_config { + gpio_t error; /**< error led */ + gpio_t sync; /**< synchronization state led */ + gpio_t radio; /**< radio activity led */ + gpio_t debug; /**< debug led */ + uint8_t led_on; /**< GPIO set to turn led on */ +} leds_config_t; +/** @} */ + +/** + * @brief Led on state values + */ +enum { + GPIO_LED_LOW = 0, + GPIO_LED_HIGH +}; + +/** + * Sets the led pins for a specific board for OpenWSN + * + * @param[in] user_config A configuration of GPIO pins used for debugging. + * + * @note Unused pins need to be defined as GPIO_UNDEF + */ +void ledpins_riot_init(const leds_config_t *user_config); + +#ifdef __cplusplus +} +#endif + +#endif /* OPENWSN_LEDS_H */ diff --git a/pkg/openwsn/include/openwsn_leds_params.h b/pkg/openwsn/include/openwsn_leds_params.h new file mode 100644 index 000000000000..918df88095e3 --- /dev/null +++ b/pkg/openwsn/include/openwsn_leds_params.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2017 Hamburg University of Applied Sciences + * + * 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 pkg_openwsn + * @{ + * + * @file + * @brief Default configuration for the OpenWSN leds + * + * @author Peter Kietzmann + * + * @} + */ +#ifndef OPENWSN_LEDS_PARAMS_H +#define OPENWSN_LEDS_PARAMS_H + +#include "board.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name OpenWSN default leds pins configuration. + * + * Default settings match OpenWSN openmote-b configuration. + * + * @note On Nucleo boards the LED pin is shared with SPI -> don't use it! + * @{ + */ +#if defined (LED0_PIN) && !defined(MODULE_BOARDS_COMMON_NUCLEO) +#define OPENWSN_LEDPIN_ERROR LED0_PIN +#else +#define OPENWSN_LEDPIN_ERROR GPIO_UNDEF +#endif + +#ifdef LED1_PIN +#define OPENWSN_LEDPIN_SYNC LED1_PIN +#else +#define OPENWSN_LEDPIN_SYNC GPIO_UNDEF +#endif + +#ifdef LED2_PIN +#define OPENWSN_LEDPIN_RADIO LED2_PIN +#else +#define OPENWSN_LEDPIN_RADIO GPIO_UNDEF +#endif + +#ifdef LED3_PIN +#define OPENWSN_LEDPIN_DEBUG LED3_PIN +#else +#define OPENWSN_LEDPIN_DEBUG GPIO_UNDEF +#endif + +#ifndef OPENWSN_LED_ON_STATE +#define OPENWSN_LED_ON_STATE GPIO_LED_LOW +#endif + +#define OPENWSN_LEDS_DEFAULT { .error = OPENWSN_LEDPIN_ERROR, \ + .sync = OPENWSN_LEDPIN_SYNC, \ + .radio = OPENWSN_LEDPIN_RADIO, \ + .debug = OPENWSN_LEDPIN_DEBUG, \ + .led_on = OPENWSN_LED_ON_STATE } +/**@}*/ + +/** + * @brief OpenWSN leds configuration + */ +static const leds_config_t openwsn_leds_params[] = +{ +#ifdef OPENWSN_LEDS_BOARD + OPENWSN_LEDS_BOARD, +#else + OPENWSN_LEDS_DEFAULT, +#endif +}; + +#ifdef __cplusplus +} +#endif + +#endif /* OPENWSN_LEDS_PARAMS_H */ diff --git a/pkg/openwsn/include/openwsn_radio.h b/pkg/openwsn/include/openwsn_radio.h new file mode 100644 index 000000000000..a4788b39713d --- /dev/null +++ b/pkg/openwsn/include/openwsn_radio.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2019 Hamburg University of Applied Sciences + * 2020 Inria + * + * 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 pkg_openwsn + * @{ + * + * @file + * @brief RIOT adaption of the "radio" bsp module definitions + * + * The radio adaptation runs in an own thread with the highest priority + * (`THREAD_PRIORITY_MAIN - 4`) and maps to RIOT's `netdev` API. + * + * Hardware MAC layer features such as CSMA/CA, ACK handling and retransmissions + * are handled by OpenWSN, so the radio driver must support disabling AUTOACK + * and CSMA handling by the hardware. Frame filtering must as well be disabled. + * + * The radio adaptation preloads the buffer so `NETOPT_PRELOADING` must be + * supported. + * + * OpenWSN needs to be notified when a frame reception/transmission stats and + * when it ends. Therefore radio drivers need to support the following netdev + * events: + * + * - `NETDEV_EVENT_RX_STARTED` + * - `NETDEV_EVENT_TX_STARTED` + * - `NETDEV_EVENT_RX_COMPLETE` + * - `NETDEV_EVENT_TX_COMPLETE` + * + * OpenWSN expects to recover crc information on every received frame even if it + * will simply drop frames with invalid crc. The stack can function correctly if + * radio drivers automatically drop frames with an invalid crc (i.e. the stack + * doesn't get notified about these frames), but it might print the following + * error if using `openwsn_serial`: + * + * - `[IEEE802154E] wdDataDuration overflows while at state 19 in slotOffset 0` + * + * @author Peter Kietzmann , April 2019 + * @author Francisco Molina + * + * @} + */ + +#ifndef OPENWSN_RADIO_H +#define OPENWSN_RADIO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "net/netdev.h" +#include "radio.h" + +/** + * @brief Initialize OpenWSN radio + * + * @param[in] netdev pointer to a netdev interface + * + * @return PID of OpenWSN thread + * @return -1 on initialization error + */ +int openwsn_radio_init(netdev_t *netdev); + +/** + * @brief OpenWSN radio variables structure + */ +typedef struct { + radio_capture_cbt startFrame_cb; /**< start of frame capture callback */ + radio_capture_cbt endFrame_cb; /**< end of frame capture callback */ + netdev_t *dev; /**< netdev device */ +} openwsn_radio_t; + +#ifdef __cplusplus +} +#endif + +#endif /* OPENWSN_RADIO_H */ +/** @} */ diff --git a/pkg/openwsn/include/openwsn_uart.h b/pkg/openwsn/include/openwsn_uart.h new file mode 100644 index 000000000000..4c4e1cfc4a21 --- /dev/null +++ b/pkg/openwsn/include/openwsn_uart.h @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2018 Hamburg University of Applied Sciences + * 2020 Inria + * + * 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 pkg_openwsn + * @{ + * + * For details on the implementation check pkg/openwsn/doc.txt + * + * @file + * @brief RIOT adaption-specific definition of the "uart" bsp module. + * + * @author Thomas Watteyne , February 2012 + * @author Peter Kietzmann , July 2018 + * @author Francisco Molina + * + * @} + */ + +#ifndef OPENWSN_UART_H +#define OPENWSN_UART_H + +#include "stdint.h" +#include "board.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief UART device to use for STDIO + * + * Dont want to include the stdio header, so redefine the default value + * + */ +#ifndef STDIO_UART_DEV +#define STDIO_UART_DEV (UART_DEV(0)) +#endif +/** + * @brief OpenWSN default uart dev. + * + * @note If only one UART is available that uart might collide with + * STDIO_UART_DEV, otherwise the next available UART will be used. + * + */ +#ifndef OPENWSN_UART_DEV +#ifdef MODULE_STDIO_NULL +#define OPENWSN_UART_DEV (STDIO_UART_DEV) +#else +#define OPENWSN_UART_DEV ((STDIO_UART_DEV + 1) % UART_NUMOF) +#endif +#endif + +/** + * @brief OpenWSN uart baudrate + */ +#ifndef OPENWSN_UART_BAUDRATE +#ifndef STDIO_UART_BAUDRATE +#define OPENWSN_UART_BAUDRATE (115200U) +#else +#define OPENWSN_UART_BAUDRATE (STDIO_UART_BAUDRATE) +#endif +#endif + +/** + * @brief Initialize OpenWSN uart + * + * This will initialize a uart device at STDIO_UART_BAUDRATE/8N1. It will also + * initialize a timer to set sw tx_isr. + * + */ +void uart_init_openwsn(void); + +/** + * @brief OpenWSN uart tx callback type + */ +typedef void (*uart_tx_cbt)(void); + +/** + * @brief OpenWSN uart rx callback type + */ +typedef void (*uart_rx_cbt)(void); + +/** + * @brief OpenWSN uart tx callback type +*/ +void uart_setCallbacks(uart_tx_cbt txCb, uart_rx_cbt rxCb); + +/** + * @brief Sets software flow control CTS + * + * This function sends XON or XOFF bytes to "set" or "unset" CTS by sw. + * + * @param[in] state true sets CTS, false clears CTS + */ +void uart_setCTS(bool state); + +/** + * @brief Write a single byte to the configured OpenWSN uart + */ +void uart_writeByte(uint8_t byteToWrite); + +/** + * @brief Reads a single byte received through uart. + * + * OpenWSN will call this thrpugh uart_rx_cbt. + * + */ +uint8_t uart_readByte(void); + +/** + * @brief Unused in RIOT, needs to be defined for OpenWSN + */ +void uart_enableInterrupts(void); + +/** + * @brief Unused in RIOT, needs to be defined for OpenWSN + */ +void uart_disableInterrupts(void); + +/** + * @brief Unused in RIOT, needs to be defined for OpenWSN + */ +void uart_clearRxInterrupts(void); + +/** + * @brief Unused in RIOT, needs to be defined for OpenWSN + */ +void uart_clearTxInterrupts(void); + +#ifdef __cplusplus +} +#endif + +#endif /* OPENWSN_UART_H */ diff --git a/pkg/openwsn/patches/0001-bsp-kernel-include-RIOT-OpenWSN-board-definitions.patch b/pkg/openwsn/patches/0001-bsp-kernel-include-RIOT-OpenWSN-board-definitions.patch new file mode 100644 index 000000000000..023c6522f61a --- /dev/null +++ b/pkg/openwsn/patches/0001-bsp-kernel-include-RIOT-OpenWSN-board-definitions.patch @@ -0,0 +1,53 @@ +From 6f845cd8b8ea316307fd9ef6ab58127a26772f72 Mon Sep 17 00:00:00 2001 +From: PeterKietzmann +Date: Thu, 8 Feb 2018 10:23:00 +0100 +Subject: [PATCH 01/11] bsp-kernel: include RIOT-OpenWSN board definitions + +--- + bsp/boards/radio.h | 2 +- + bsp/boards/sctimer.h | 2 +- + kernel/openos/scheduler.c | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/bsp/boards/radio.h b/bsp/boards/radio.h +index df4333e8..8435a951 100644 +--- a/bsp/boards/radio.h ++++ b/bsp/boards/radio.h +@@ -12,7 +12,7 @@ + \author Thomas Watteyne , February 2012. + */ + +-#include "board.h" ++#include "openwsn_board.h" + + //=========================== define ========================================== + +diff --git a/bsp/boards/sctimer.h b/bsp/boards/sctimer.h +index 668496cb..90978f89 100644 +--- a/bsp/boards/sctimer.h ++++ b/bsp/boards/sctimer.h +@@ -13,7 +13,7 @@ + */ + + #include "stdint.h" +-#include "board.h" ++#include "openwsn_board.h" + + //=========================== typedef ========================================= + +diff --git a/kernel/openos/scheduler.c b/kernel/openos/scheduler.c +index 35068796..1dad545e 100644 +--- a/kernel/openos/scheduler.c ++++ b/kernel/openos/scheduler.c +@@ -6,7 +6,7 @@ + + #include "opendefs.h" + #include "scheduler.h" +-#include "board.h" ++#include "openwsn_board.h" + #include "debugpins.h" + #include "leds.h" + +-- +2.27.0 + diff --git a/pkg/openwsn/patches/0002-drivers-common-openserial-rename-include-for-RIOT-Op.patch b/pkg/openwsn/patches/0002-drivers-common-openserial-rename-include-for-RIOT-Op.patch new file mode 100644 index 000000000000..007c29dec564 --- /dev/null +++ b/pkg/openwsn/patches/0002-drivers-common-openserial-rename-include-for-RIOT-Op.patch @@ -0,0 +1,26 @@ +From 6fff6e0e31dbed9a603e4e1eab434c45e8b43861 Mon Sep 17 00:00:00 2001 +From: Francisco Molina +Date: Mon, 10 Feb 2020 15:05:07 +0100 +Subject: [PATCH 02/11] drivers/common/openserial: rename include for + RIOT-OpenWSN uart + +--- + drivers/common/openserial.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/common/openserial.c b/drivers/common/openserial.c +index d39634c1..5c3c0003 100644 +--- a/drivers/common/openserial.c ++++ b/drivers/common/openserial.c +@@ -20,7 +20,7 @@ + #include "openbridge.h" + #include "leds.h" + #include "schedule.h" +-#include "uart.h" ++#include "openwsn_uart.h" + #include "opentimers.h" + #include "openhdlc.h" + #include "schedule.h" +-- +2.27.0 + diff --git a/pkg/openwsn/patches/0003-openapps-comment-out-unused-COAP-UDP-applications-in.patch b/pkg/openwsn/patches/0003-openapps-comment-out-unused-COAP-UDP-applications-in.patch new file mode 100644 index 000000000000..74336c62856c --- /dev/null +++ b/pkg/openwsn/patches/0003-openapps-comment-out-unused-COAP-UDP-applications-in.patch @@ -0,0 +1,60 @@ +From 1b9c54459e882a2beb4cedbdbafbb299b95be9e8 Mon Sep 17 00:00:00 2001 +From: Francisco Molina +Date: Fri, 27 Mar 2020 09:59:24 +0100 +Subject: [PATCH 03/11] openapps: comment out unused COAP&UDP applications + includes + +--- + openapps/openapps.c | 26 +++++++++++++------------- + 1 file changed, 13 insertions(+), 13 deletions(-) + +diff --git a/openapps/openapps.c b/openapps/openapps.c +index 3124d0c6..e30dcaec 100644 +--- a/openapps/openapps.c ++++ b/openapps/openapps.c +@@ -8,18 +8,18 @@ + + // CoAP + #include "opencoap.h" +-#include "c6t.h" +-#include "cinfo.h" +-#include "cleds.h" ++// #include "c6t.h" ++// #include "cinfo.h" ++// #include "cleds.h" + #include "cjoin.h" +-#include "cwellknown.h" +-#include "rrt.h" ++// #include "cwellknown.h" ++// #include "rrt.h" + // UDP +-#include "uecho.h" +-#include "uinject.h" +-#include "userialbridge.h" +-#include "uexpiration.h" +-#include "uexpiration_monitor.h" ++// #include "uecho.h" ++// #include "uinject.h" ++// #include "userialbridge.h" ++// #include "uexpiration.h" ++// #include "uexpiration_monitor.h" + + //=========================== variables ======================================= + +@@ -35,10 +35,10 @@ void openapps_init(void) { + + // CoAP + //c6t_init(); +- cinfo_init(); +- cleds__init(); ++ // cinfo_init(); ++ // cleds__init(); + cjoin_init(); +- cwellknown_init(); ++ // cwellknown_init(); + //rrt_init(); + + // UDP +-- +2.27.0 + diff --git a/pkg/openwsn/patches/0004-openstack-02b-MAChigh-neighbors.c-expose-neighbors_v.patch b/pkg/openwsn/patches/0004-openstack-02b-MAChigh-neighbors.c-expose-neighbors_v.patch new file mode 100644 index 000000000000..34b3e2c18e79 --- /dev/null +++ b/pkg/openwsn/patches/0004-openstack-02b-MAChigh-neighbors.c-expose-neighbors_v.patch @@ -0,0 +1,26 @@ +From a4a7bdb3504fe3e0f332170433e1e31f417f64fd Mon Sep 17 00:00:00 2001 +From: Francisco Molina +Date: Fri, 27 Mar 2020 10:15:43 +0100 +Subject: [PATCH 04/11] openstack/02b-MAChigh/neighbors.c: expose + neighbors_vars + +--- + openstack/02b-MAChigh/neighbors.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/openstack/02b-MAChigh/neighbors.c b/openstack/02b-MAChigh/neighbors.c +index a7de3394..4cfcf146 100644 +--- a/openstack/02b-MAChigh/neighbors.c ++++ b/openstack/02b-MAChigh/neighbors.c +@@ -10,7 +10,7 @@ + + //=========================== variables ======================================= + +-static neighbors_vars_t neighbors_vars; ++neighbors_vars_t neighbors_vars; + + //=========================== prototypes ====================================== + +-- +2.27.0 + diff --git a/pkg/openwsn/patches/0005-kernel-openos-scheduler-use-thread-flags-restore-irq.patch b/pkg/openwsn/patches/0005-kernel-openos-scheduler-use-thread-flags-restore-irq.patch new file mode 100644 index 000000000000..3a1d337536af --- /dev/null +++ b/pkg/openwsn/patches/0005-kernel-openos-scheduler-use-thread-flags-restore-irq.patch @@ -0,0 +1,77 @@ +From 626dbbed27b4a66bcf02fe061d5af1bff2d1accd Mon Sep 17 00:00:00 2001 +From: Francisco Molina +Date: Sun, 29 Mar 2020 12:11:53 +0200 +Subject: [PATCH 05/11] kernel/openos/scheduler: use thread flags, restore + irq_state + +Use thread_flags_wait_any to pause the scheduler. Set flag in +scheduler_push_task to trigger new task handling. + +squash! kernel/openos/scheduler: use thread flags +--- + kernel/openos/scheduler.c | 13 ++++++++++++- + kernel/scheduler.h | 2 +- + 2 files changed, 13 insertions(+), 2 deletions(-) + +diff --git a/kernel/openos/scheduler.c b/kernel/openos/scheduler.c +index 1dad545e..28bfe5c2 100644 +--- a/kernel/openos/scheduler.c ++++ b/kernel/openos/scheduler.c +@@ -10,6 +10,11 @@ + #include "debugpins.h" + #include "leds.h" + ++#include "openwsn.h" ++#include "thread.h" ++ ++#define OPENWSN_SCHEDULER_FLAG (1u << 8) ++ + //=========================== variables ======================================= + + scheduler_vars_t scheduler_vars; +@@ -31,8 +36,11 @@ void scheduler_init(void) { + SCHEDULER_ENABLE_INTERRUPT(); + } + +-void scheduler_start(void) { ++void scheduler_start(unsigned state) { + taskList_item_t* pThisTask; ++ ++ irq_restore(state); ++ + while (1) { + while(scheduler_vars.task_list!=NULL) { + // there is still at least one task in the linked-list of tasks +@@ -59,6 +67,7 @@ void scheduler_start(void) { + } + debugpins_task_clr(); + board_sleep(); ++ thread_flags_wait_any(OPENWSN_SCHEDULER_FLAG); + debugpins_task_set(); // IAR should halt here if nothing to do + } + } +@@ -105,6 +114,8 @@ void scheduler_push_task(task_cbt cb, task_prio_t prio) { + } + + ENABLE_INTERRUPTS(); ++ thread_t *thread = (thread_t*) thread_get(openwsn_get_pid()); ++ thread_flags_set(thread, OPENWSN_SCHEDULER_FLAG); + } + + //=========================== private ========================================= +diff --git a/kernel/scheduler.h b/kernel/scheduler.h +index bc49817e..f3f64570 100644 +--- a/kernel/scheduler.h ++++ b/kernel/scheduler.h +@@ -64,7 +64,7 @@ typedef struct { + //=========================== prototypes ====================================== + + void scheduler_init(void); +-void scheduler_start(void); ++void scheduler_start(unsigned state); + void scheduler_push_task(task_cbt task_cb, task_prio_t prio); + + /** +-- +2.27.0 + diff --git a/pkg/openwsn/patches/0006-bsp-boards-toolchain_defs.h-comment-out-conflict-ISR.patch b/pkg/openwsn/patches/0006-bsp-boards-toolchain_defs.h-comment-out-conflict-ISR.patch new file mode 100644 index 000000000000..842fb9a55e47 --- /dev/null +++ b/pkg/openwsn/patches/0006-bsp-boards-toolchain_defs.h-comment-out-conflict-ISR.patch @@ -0,0 +1,43 @@ +From 251802a8050d6b619d2e70c33c6ada5b6e57d549 Mon Sep 17 00:00:00 2001 +From: Francisco Molina +Date: Thu, 2 Apr 2020 16:04:29 +0200 +Subject: [PATCH 06/11] bsp/boards/toolchain_defs.h: comment out conflict ISR + definitions + +The ISR definition conflicts with AVR ISR definitions. +--- + bsp/boards/toolchain_defs.h | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/bsp/boards/toolchain_defs.h b/bsp/boards/toolchain_defs.h +index afcbcbf6..e288e52e 100644 +--- a/bsp/boards/toolchain_defs.h ++++ b/bsp/boards/toolchain_defs.h +@@ -16,15 +16,15 @@ + + //===== ISR and pragma + +-#if defined(__GNUC__) && (__GNUC__==4) && (__GNUC_MINOR__<=5) && defined(__MSP430__) +- // mspgcc <4.5.x +- #include +- #define ISR(v) interrupt (v ## _VECTOR) v ## _ISR(void) +-#else +- // other +- #define __PRAGMA__(x) _Pragma(#x) +- #define ISR(v) __PRAGMA__(vector=v ##_VECTOR) __interrupt void v ##_ISR(void) +-#endif ++// #if defined(__GNUC__) && (__GNUC__==4) && (__GNUC_MINOR__<=5) && defined(__MSP430__) ++// // mspgcc <4.5.x ++// #include ++// #define ISR(v) interrupt (v ## _VECTOR) v ## _ISR(void) ++// #else ++// // other ++// #define __PRAGMA__(x) _Pragma(#x) ++// #define ISR(v) __PRAGMA__(vector=v ##_VECTOR) __interrupt void v ##_ISR(void) ++// #endif + + //===== inline + +-- +2.27.0 + diff --git a/pkg/openwsn/patches/0007-openstack-openstack-dont-init-idmanager.patch b/pkg/openwsn/patches/0007-openstack-openstack-dont-init-idmanager.patch new file mode 100644 index 000000000000..cde78052276f --- /dev/null +++ b/pkg/openwsn/patches/0007-openstack-openstack-dont-init-idmanager.patch @@ -0,0 +1,27 @@ +From 6cf200f4f5fd73c065ac801328497bcfd073b382 Mon Sep 17 00:00:00 2001 +From: Francisco Molina +Date: Fri, 15 May 2020 13:45:02 +0200 +Subject: [PATCH 07/11] openstack/openstack: dont init idmanager + +Dont initiate idmanager in OpenWSN but in RIOT to allow overriding +default short address. +--- + openstack/openstack.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/openstack/openstack.c b/openstack/openstack.c +index 3b10eddb..886e853f 100644 +--- a/openstack/openstack.c ++++ b/openstack/openstack.c +@@ -57,7 +57,7 @@ void openstack_init(void) { + + //===== stack + //-- cross-layer +- idmanager_init(); // call first since initializes EUI64 and isDAGroot ++ // idmanager_init(); // call first since initializes EUI64 and isDAGroot + openqueue_init(); + openrandom_init(); + +-- +2.27.0 + diff --git a/pkg/openwsn/patches/0008-openstack-openapps-add-debugging.patch b/pkg/openwsn/patches/0008-openstack-openapps-add-debugging.patch new file mode 100644 index 000000000000..6a56d7a1da8b --- /dev/null +++ b/pkg/openwsn/patches/0008-openstack-openapps-add-debugging.patch @@ -0,0 +1,175 @@ +From ae6271246adb6fb97a8d23f4b09f78223dbb04f6 Mon Sep 17 00:00:00 2001 +From: Francisco Molina +Date: Fri, 27 Mar 2020 10:18:16 +0100 +Subject: [PATCH 08/11] openstack/openapps: add debugging + +Debugging info that can be also be obtained through ifconfig in +tests/openwsn. +--- + kernel/openos/scheduler.c | 3 ++- + openapps/cjoin/cjoin.c | 10 +++++++++- + openstack/02a-MAClow/IEEE802154E.c | 4 ++++ + openstack/02b-MAChigh/neighbors.c | 4 ++++ + openstack/03b-IPv6/icmpv6rpl.c | 4 ++++ + 5 files changed, 23 insertions(+), 2 deletions(-) + +diff --git a/kernel/openos/scheduler.c b/kernel/openos/scheduler.c +index 28bfe5c2..175d6309 100644 +--- a/kernel/openos/scheduler.c ++++ b/kernel/openos/scheduler.c +@@ -12,6 +12,7 @@ + + #include "openwsn.h" + #include "thread.h" ++#include "log.h" + + #define OPENWSN_SCHEDULER_FLAG (1u << 8) + +@@ -87,7 +88,7 @@ void scheduler_push_task(task_cbt cb, task_prio_t prio) { + } + if (taskContainer>&scheduler_vars.taskBuf[TASK_LIST_DEPTH-1]) { + // task list has overflown. This should never happpen! +- ++ LOG_ERROR("[openos/scheduler]: critical, task list overflow\n"); + // we can not print from within the kernel. Instead: + // blink the error LED + leds_error_blink(); +diff --git a/openapps/cjoin/cjoin.c b/openapps/cjoin/cjoin.c +index 2d87372f..74eca7b3 100644 +--- a/openapps/cjoin/cjoin.c ++++ b/openapps/cjoin/cjoin.c +@@ -18,6 +18,8 @@ + #include "eui64.h" + #include "neighbors.h" + ++#include "log.h" ++ + //=========================== defines ========================================= + + /// inter-packet period (in ms) +@@ -134,14 +136,18 @@ owerror_t cjoin_receive(OpenQueueEntry_t* msg, + owerror_t ret; + + if (coap_header->Code != COAP_CODE_RESP_CHANGED) { ++ LOG_DEBUG("[cjoin]:fail, replay protection\n"); + return E_FAIL; + } + + ret = cojp_cbor_decode_configuration_object(msg->payload, msg->length, &configuration); +- if (ret == E_FAIL) { return E_FAIL; } ++ if (ret == E_FAIL) { ++ LOG_DEBUG("[cjoin]: decode fail\n"); ++ return E_FAIL; } + + if (configuration.keyset.num_keys == 1 && + configuration.keyset.key[0].key_usage == COJP_KEY_USAGE_6TiSCH_K1K2_ENC_MIC32) { ++ LOG_DEBUG("[cjoin]: success\n"); + // set the L2 keys as per the parsed value + IEEE802154_security_setBeaconKey(configuration.keyset.key[0].key_index, configuration.keyset.key[0].key_value); + IEEE802154_security_setDataKey(configuration.keyset.key[0].key_index, configuration.keyset.key[0].key_value); +@@ -152,6 +158,7 @@ owerror_t cjoin_receive(OpenQueueEntry_t* msg, + // TODO not supported for now + } + ++ LOG_DEBUG("[cjoin]: failed\n"); + return E_FAIL; + } + +@@ -300,6 +307,7 @@ owerror_t cjoin_sendJoinRequest(open_addr_t* joinProxy) { + packetfunctions_reserveHeaderSize(pkt, payload_len); + memcpy(pkt->payload, tmp, payload_len); + // send ++ LOG_DEBUG("[cjoin]: send join request\n"); + outcome = opencoap_send( + pkt, + COAP_TYPE_NON, +diff --git a/openstack/02a-MAClow/IEEE802154E.c b/openstack/02a-MAClow/IEEE802154E.c +index 07921ae3..c1b532af 100644 +--- a/openstack/02a-MAClow/IEEE802154E.c ++++ b/openstack/02a-MAClow/IEEE802154E.c +@@ -18,6 +18,8 @@ + #include "openrandom.h" + #include "msf.h" + ++#include "log.h" ++ + //=========================== definition ====================================== + + //=========================== variables ======================================= +@@ -806,6 +808,7 @@ port_INLINE void activity_synchronize_endOfFrame(PORT_TIMER_WIDTH capturedTime) + synchronizePacket(ieee154e_vars.syncCapturedTime); + + // declare synchronized ++ LOG_DEBUG("[IEE20154E]: synchronized\n"); + changeIsSync(TRUE); + // log the info + openserial_printInfo(COMPONENT_IEEE802154E,ERR_SYNCHRONIZED, +@@ -890,6 +893,7 @@ port_INLINE void activity_ti1ORri1(void) { + ieee154e_vars.numOfSleepSlots = 1; + + // declare myself desynchronized ++ LOG_DEBUG("[IEE20154E]: desynchronized\n"); + changeIsSync(FALSE); + + // log the error +diff --git a/openstack/02b-MAChigh/neighbors.c b/openstack/02b-MAChigh/neighbors.c +index 4cfcf146..b5f064e9 100644 +--- a/openstack/02b-MAChigh/neighbors.c ++++ b/openstack/02b-MAChigh/neighbors.c +@@ -8,6 +8,8 @@ + #include "openrandom.h" + #include "msf.h" + ++#include "log.h" ++ + //=========================== variables ======================================= + + neighbors_vars_t neighbors_vars; +@@ -687,6 +689,7 @@ void registerNewNeighbor(open_addr_t* address, + i=0; + while(i +Date: Thu, 4 Jun 2020 15:39:07 +0200 +Subject: [PATCH 09/11] drivers/common/openserial: add flag to echo badcrc + frames + +--- + drivers/common/openserial.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/common/openserial.c b/drivers/common/openserial.c +index 5c3c0003..c6cdddf0 100644 +--- a/drivers/common/openserial.c ++++ b/drivers/common/openserial.c +@@ -981,9 +981,13 @@ port_INLINE void inputHdlcClose(void) { + openserial_vars.inputBufFillLevel -= 2; + } else { + // the CRC is incorrect +- ++#ifdef OPENSERIAL_ECHO_BADCRC ++ // Force echo on invalid crc ++ openserial_vars.inputBuf[0] = SERFRAME_PC2MOTE_TRIGGERSERIALECHO; ++#else + // drop the incoming frame + openserial_vars.inputBufFillLevel = 0; ++#endif + } + } + +-- +2.27.0 + diff --git a/pkg/openwsn/patches/0010-drivers-common-opentimers-enable-ISR-before-return.patch b/pkg/openwsn/patches/0010-drivers-common-opentimers-enable-ISR-before-return.patch new file mode 100644 index 000000000000..fc27caf56050 --- /dev/null +++ b/pkg/openwsn/patches/0010-drivers-common-opentimers-enable-ISR-before-return.patch @@ -0,0 +1,32 @@ +From 02420eb4baf4229c66df5f99254f867d816b5e58 Mon Sep 17 00:00:00 2001 +From: Francisco Molina +Date: Thu, 25 Jun 2020 15:37:44 +0200 +Subject: [PATCH 10/11] drivers/common/opentimers: enable ISR before return + +--- + drivers/common/opentimers.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/common/opentimers.c b/drivers/common/opentimers.c +index 718b39a3..0c7c6683 100644 +--- a/drivers/common/opentimers.c ++++ b/drivers/common/opentimers.c +@@ -60,6 +60,7 @@ opentimers_id_t opentimers_create(uint8_t timer_id, uint8_t task_prio){ + opentimers_vars.timersBuf[timer_id].isUsed = TRUE; + // the TSCH timer and inhibit timer won't push a task, + // hence task_prio is not used ++ ENABLE_INTERRUPTS(); + return timer_id; + } + } +@@ -69,6 +70,7 @@ opentimers_id_t opentimers_create(uint8_t timer_id, uint8_t task_prio){ + if (opentimers_vars.timersBuf[id].isUsed == FALSE){ + opentimers_vars.timersBuf[id].isUsed = TRUE; + opentimers_vars.timersBuf[id].timer_task_prio = task_prio; ++ ENABLE_INTERRUPTS(); + return id; + } + } +-- +2.27.0 + diff --git a/pkg/openwsn/patches/0011-openstack-allow-to-set-EB_PORTION-SLOTFRAME_LENGTH.patch b/pkg/openwsn/patches/0011-openstack-allow-to-set-EB_PORTION-SLOTFRAME_LENGTH.patch new file mode 100644 index 000000000000..36e3fbda10b9 --- /dev/null +++ b/pkg/openwsn/patches/0011-openstack-allow-to-set-EB_PORTION-SLOTFRAME_LENGTH.patch @@ -0,0 +1,42 @@ +From d20020308e0728987dff1190273a7b7322926b64 Mon Sep 17 00:00:00 2001 +From: Francisco Molina +Date: Thu, 25 Jun 2020 17:50:24 +0200 +Subject: [PATCH 11/11] openstack: allow to set EB_PORTION, SLOTFRAME_LENGTH + +--- + openstack/02a-MAClow/IEEE802154E.h | 2 ++ + openstack/02b-MAChigh/schedule.h | 3 +++ + 2 files changed, 5 insertions(+) + +diff --git a/openstack/02a-MAClow/IEEE802154E.h b/openstack/02a-MAClow/IEEE802154E.h +index 117aa7f3..11d7ec10 100644 +--- a/openstack/02a-MAClow/IEEE802154E.h ++++ b/openstack/02a-MAClow/IEEE802154E.h +@@ -41,7 +41,9 @@ static const uint8_t ebIEsBytestream[] = { + #define TXRETRIES 15 // number of MAC retries before declaring failed + #define TX_POWER 31 // 1=-25dBm, 31=0dBm (max value) + #define RESYNCHRONIZATIONGUARD 5 // in 32kHz ticks. min distance to the end of the slot to successfully synchronize ++#ifndef EB_PORTION + #define EB_PORTION 10 // set EB on minimal cell for 1/EB_PORTION portion ++#endif + #define MAXKAPERIOD 1000 // in slots: 1500@20ms per slot -> ~30 seconds. Max value used by adaptive synchronization. + #define DESYNCTIMEOUT 1750 // in slots: 1750@20ms per slot -> ~35 seconds. A larger DESYNCTIMEOUT is needed if using a larger KATIMEOUT. + #define LIMITLARGETIMECORRECTION 5 // threshold number of ticks to declare a timeCorrection "large" +diff --git a/openstack/02b-MAChigh/schedule.h b/openstack/02b-MAChigh/schedule.h +index dc3b9f50..d64d6cf4 100644 +--- a/openstack/02b-MAChigh/schedule.h ++++ b/openstack/02b-MAChigh/schedule.h +@@ -17,7 +17,10 @@ + + The superframe reappears over time and can be arbitrarily long. + */ ++ ++#ifndef SLOTFRAME_LENGTH + #define SLOTFRAME_LENGTH 101 //should be 101 ++#endif + + //draft-ietf-6tisch-minimal-06 + #define SCHEDULE_MINIMAL_6TISCH_ACTIVE_CELLS 1 +-- +2.27.0 + diff --git a/sys/auto_init/auto_init.c b/sys/auto_init/auto_init.c index 628649afbdbc..a2bedb416596 100644 --- a/sys/auto_init/auto_init.c +++ b/sys/auto_init/auto_init.c @@ -108,6 +108,11 @@ void auto_init(void) extern void openthread_bootstrap(void); openthread_bootstrap(); } + if (IS_USED(MODULE_AUTO_INIT_OPENWSN)) { + LOG_DEBUG("Bootstrapping openwsn.\n"); + extern void openwsn_bootstrap(void); + openwsn_bootstrap(); + } if (IS_USED(MODULE_GCOAP) && !IS_ACTIVE(CONFIG_GCOAP_NO_AUTO_INIT)) { LOG_DEBUG("Auto init gcoap.\n"); From 985a7067333c52e3a1e76c9fc043642d16890bb2 Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Thu, 25 Jun 2020 22:36:41 +0200 Subject: [PATCH 4/7] tests/pkg_openwsn: initial import Co-authored-by: Peter Kietzmann --- tests/pkg_openwsn/Makefile | 67 ++++++++ tests/pkg_openwsn/README.md | 316 +++++++++++++++++++++++++++++++++++ tests/pkg_openwsn/main.c | 324 ++++++++++++++++++++++++++++++++++++ tests/pkg_openwsn/udp.c | 195 ++++++++++++++++++++++ 4 files changed, 902 insertions(+) create mode 100644 tests/pkg_openwsn/Makefile create mode 100644 tests/pkg_openwsn/README.md create mode 100644 tests/pkg_openwsn/main.c create mode 100644 tests/pkg_openwsn/udp.c diff --git a/tests/pkg_openwsn/Makefile b/tests/pkg_openwsn/Makefile new file mode 100644 index 000000000000..a4c05a9b6e14 --- /dev/null +++ b/tests/pkg_openwsn/Makefile @@ -0,0 +1,67 @@ +BOARD ?= iotlab-m3 + +include ../Makefile.tests_common + +# list of arm boards that provide at86rf2xx radios, can't require it so +# add whitelist +BOARD_WHITELIST = \ + fox \ + iotlab-m3 \ + iotlab-a8-m3 \ + samr21-xpro \ + samr30-xpro \ + # + +## OpenWSN Modules +USEPKG += openwsn +USEMODULE += openwsn_openstack +USEMODULE += openwsn_scheduler + +# Optional Module required for root nodes +# USEMODULE += openwsn_serial + +# Optional Modules +USEMODULE += openwsn_leds +USEMODULE += openwsn_debugpins + +ifneq (,$(filter openwsn_serial,$(USEMODULE))) +# Uncomment to use STDIO_UART_DEV as the uart for OpenWSN openserial +# USEMODULE += stdio_null + ifneq (,$(filter iotlab-m3 iotlab-a8-m3,$(BOARD))) + USEMODULE += stdio_null + endif + # OpenWSN serial module can't handle data at more than 115200 bauds/s, + # depending on the platform this might be even lower (e.g. 57600 bauds + # for iotlab-m3, 19200 for samr21-xpro). + # NOTE: baudrate can'y be changed when testing over IotLab. + OPENSERIAL_BAUD ?= + ifneq (,$(OPENSERIAL_BAUD)) + CFLAGS += -DOPENWSN_UART_BAUDRATE=$(OPENSERIAL_BAUD) + ifneq (,$(filter stdio_null,$(USEMODULE))) + BAUD ?= $(OPENSERIAL_BAUD) + endif + endif +endif + +# To enable debugging prints on OpenWSN code +# export OPENWSN_LOG_LEVEL ?= LOG_ERROR + +## Test application Modules +USEMODULE += ipv6_addr +USEMODULE += ps +USEMODULE += od_string +USEMODULE += shell +USEMODULE += shell_commands +# ztimer is used instead of xtimer because it's a dependency of some +# OpenWSN modules. +USEMODULE += ztimer_usec + +include $(RIOTBASE)/Makefile.include + +# We want the highest possible frequency set for periph_rtt, but not all +# platforms can configure this value. use highest possible RTT_FREQUENCY +# for platforms that allow it +ifneq (,$(filter stm32,$(CPU))) + RTT_FREQUENCY ?= RTT_MAX_FREQUENCY + CFLAGS += -DRTT_FREQUENCY=$(RTT_FREQUENCY) +endif diff --git a/tests/pkg_openwsn/README.md b/tests/pkg_openwsn/README.md new file mode 100644 index 000000000000..8ea37d9fa7c7 --- /dev/null +++ b/tests/pkg_openwsn/README.md @@ -0,0 +1,316 @@ +# OpenWSN on RIOT + +This test demonstrates the [OpenWSN](https://github.com/openwsn-berkeley/openwsn-fw) full +stack (UDP, IPv6, RPL, 6TiSCH) running on RIOT. When flashed, it will initialize the stack +and provide the user with some minimal shell commands to: + +- print the own IPv6 address `ifconfig` +- change the UDP destination port `udp server start ` +- send a UDP packet `udp send ` + +A tun interface can also be set to allow traffic out of the network. This +allows pinging nodes in the network from the host. + +Please note that this port is still in experimental status. For further information +about the port refer to the [pkg documentation](../../pkg/openwsn/doc.txt). + +## Experimental setups + +The following setup act as a starting point for testing and debugging. Either +build and flash local nodes or incorporate the [FIT IoT-LAB](https://www.iot-lab.info/) +Testbed. Please check the ports [documentation](../../pkg/openwsn/doc.txt) for information +about supported hardware platforms. + +This port currently needs `openvisualizer`, please make sure you follow the +[pre-requisites](../../dist/tools/openvisualizer/makefile.openvisualizer.inc.mk) +to install a patched version of `openvisualizer`. + +An OpenWSN root node acts as a border router, it tunnels IEEE80215.4.E +between `openvisualizer` and the network without looking at the frame content. +This means that a root node will not be reachable when 'pinging' from the host +or if trying to send udp packets to it. + +Two test cases are described with different requirements: + +1. From host [ping](#Communicating-with-host-(IPV6)) nodes in network over ipv6: +``` + - 1 root node + tun interface + - +1 leaf node +``` + +2. Sending [UDP](#Communicating-over-udp) packets between nodes: +``` + - 1 root node + - +2 leaf node +``` + +### Synchronization + +There are 3 things that can be done to speed up and help nodes synchronization, +all related to how often a node will receive an EB (enhanced beacon). + + - disable channel hopping + - increase EB_PORTION + - reduce SLOTFRAME_LENGTH + +If you want to disable channel hopping to speed up synchronization you can set +a fix channel. + + $ export CFLAGS=-DIEEE802154E_SINGLE_CHANNEL=17 + +Enhanced beacon are sent once per slotframe with a likelihood of 1/EB_PORTION. +The default value is EB_PORTION = 10 (10%), reducing the value of EB_PORTION +increases the frequency at which beacons are sent, this will also help nodes +to stay synchronized. + + $ export CFLAGS=-DEB_PORTION=4 + +EB gets an opportunity to be sent (depending on 1/EB_PORTION) once in every +slotframe, reducing the soltframe length will cause EB to be sent more often. +Beware that this could have an impact on the MSF (Minimal Scheduling Function). + + $ export CFLAGS=-DSLOTFRAME_LENGTH=51 + +See [documentation](../../pkg/openwsn/doc.txt#Synchronization) for more on +synchronization. + +## IMPORTANT! + +OpenWSN uses source routing and this means all network traffic must go through +from the root node to OpenVisualizer. If the root node configuration can't +handle the configured baudrate correctly this will lead to packet loss. + +Currently these are the tested configurations: + +(a) samr21-xpro network: + - leaf nodes using `openwsn_sctimer_rtt` + - root node using `openwsn_sctimer_rtt` and 19200 baudrate directly + connected to UART pins (not through the usb debugger) + +(b) iotlab-m3 network: + - leaf nodes using `openwsn_sctimer_rtt` or `sctimer_ztimer` + - root node using `openwsn_sctimer_rtt` and 57600 baudrate + +For more details on this please refer to [pkg documentation](../../pkg/openwsn/doc.txt). + +## Testing configuration (a) (three local samr21-xpro nodes) + +1. figure out each node's serial number (`edbg -l` output might help) +2. hook up the root node to an external USB-serial-converter. For that, connect + the converter's RXD/TXD pins to the node's PA22/PA23. +3. flash the root node: + + $ SERIAL=${ROOT_SERIAL_NODE} OPENSERIAL_BAUD=19200 USEMODULE=openwsn_serial \ + BOARD=samr21-xpro make flash -j4 + +4. flash the leaf nodes: + + $ BOARD=samr21-xpro make all -j4 + $ BOARD=samr21-xpro SERIAL=${LEAF_SERIAL_NODE0} make flash-only + $ BOARD=samr21-xpro SERIAL=${LEAF_SERIAL_NODE1} make flash-only + +5. open a shell to the leaf nodes + so in two shell windows, do (one in each): + + $ BOARD=samr21-xpro SERIAL=${LEAF_SERIAL_NODE0} make term + $ BOARD=samr21-xpro SERIAL=${LEAF_SERIAL_NODE1} make term + +6. in a third shell, launch openvisualizer: + + $ BOARD=samr21-xpro PORT= BAUD=19200 \ + make openv-termroot + +## Testing configuration (b) (iotlab-m3 network on iotlab) + +When using OpenVisualizer over iot-lab an ssh-tunnel is opened to connect to the +IoT-LAB motes' TCP port. For this to work you will need: + +- A valid IoT-LAB [account](https://www.iot-lab.info/testbed/signup) +- Authenticate locally to IoT-LAB `$ iotlab-auth -u ` + +1. Launch an experiment booking 3+ `iotlab-m3` nodes: + + $ iotlab-experiment submit -d 120 -l 3,archi=m3:at86rf231+site=saclay + $ iotlab-experiment wait + $ iotlab-experiment get --nodes + +Since multiple nodes where configured for the experiment `IOTLAB_NODE` needs +to be specified for every node, `IOTLAB_NODE=m3-%.saclay.iot-lab.info` + +2. flash the root node + + $ IOTLAB_NODE=${ROOT_IOTLAB_NODE} USEMODULE=openwsn_serial \ + BOARD=iotlab-m3 make -C tests/pkg_openwsn flash + +3. open a shell to the leaf nodes so in two shell windows, do (one in each): + $ BOARD=iotlab-m3 make -C tests/pkg_openwsn all -j4 + $ BOARD=iotlab-m3 IOTLAB_NODE=${LEAF_IOTLAB_NODE0} make -C tests/pkg_openwsn flash-only + $ BOARD=iotlab-m3 IOTLAB_NODE=${LEAF_IOTLAB_NODE1} make -C tests/pkg_openwsn flash-only + +4. open a shell to the leaf nodes + so in two shell windows, do (one in each): + + $ BOARD=iotlab-m3 IOTLAB_NODE=${LEAF_IOTLAB_NODE0} make -C tests/pkg_openwsn term + $ BOARD=iotlab-m3 IOTLAB_NODE=${LEAF_IOTLAB_NODE1} make -C tests/pkg_openwsn term + +5. in a third shell, launch openvisualizer: + + $ BOARD=iotlab-m3 IOTLAB_NODE=${ROOT_IOTLAB_NODE} make -C tests/pkg_openwsn openv-termroot + +### Network Setup + +If (a) and (b) where followed then on each lead node you should be able +to see the ipv6 address: + + main(): This is RIOT! (Version: 2020.04-devel-1649-g96fa9-pr_openwsn) + OpenWSN UDP test + You are running RIOT on a(n) iotlab-m3 board. + This board features a(n) stm32f1 MCU. + > ifconfig + ifconfig + Iface 3 HWaddr: 07:C2 NID: CA:FE + + Long HWaddr: 96:35:9A:92:4E:3D:65:78 + inet6 addr: fe80::9635:9a92:4e3d:6578 + + IEEE802154E sync: 0 + 6TiSCH joined: 0 + + NO RPL parent + + +On the root node Openvisualizer is launched and the DAGroot is setup. + + [OpenVisualizerServer:INFO] Extracting firmware definitions. + [Utils:VERBOSE] Extracting firmware component names + [Utils:VERBOSE] Extracting firmware log descriptions. + [Utils:VERBOSE] Extracting 6top return codes. + [Utils:VERBOSE] Extracting 6top states. + [OpenVisualizerServer:INFO] Starting RPC server + [OpenVisualizerServer:SUCCESS] Setting mote 43eb as root + [ParserIEC:ERROR] 43eb [IEEE802154E] wrong state 1 in startSlot, at slotOffset 1 + [RPL:INFO] registering DAGroot 82-6b-de-ec-58-34-65-78 + +The root node will now start sending beacons and other nodes will synchronize, and +join. If channel hopping is enabled this can take quite some time (see +[Synchronization](../../pkg/openwsn/doc.txt#Synchronization). Once leaf nodes +have joined the network when issuing `ifconfing` you should see: + + ifconfig + Iface 3 HWaddr: 0F:F4 NID: CA:FE + + Long HWaddr: 06:84:F6:65:10:6B:11:14 + inet6 addr: bbbb::684:f665:106b:1114 + + IEEE802154E sync: 1 + 6TiSCH joined: 1 + + RPL rank: 2816 + RPL parent: 2A:BA:F7:65:10:6B:11:14 + RPL children: + RPL DODAG ID: bbbb::2aba:f765:106b:1114 + + +The root node should start receiving RPL DAOs: + + [RPL:INFO] received RPL DAO from bbbb:0:0:0:ab8:fc65:106b:1114 + - parents: + bbbb:0:0:0:2aba:f765:106b:1114 + - children: + bbbb:0:0:0:684:f665:106b:1114 + + [RPL:INFO] received RPL DAO from bbbb:0:0:0:684:f665:106b:1114 + - parents: + bbbb:0:0:0:2aba:f765:106b:1114 + - children: + bbbb:0:0:0:ab8:fc65:106b:1114 + + [RPL:INFO] received RPL DAO from bbbb:0:0:0:684:f665:106b:1114 + - parents: + bbbb:0:0:0:2aba:f765:106b:1114 + - children: + bbbb:0:0:0:ab8:fc65:106b:1114 + +Once DAOs for all nodes start being received the network is setup and you +should be able to send packets between nodes or ping from the host. + +### Communicating over udp + +On one node setup a udp-server: + + > ifconfig + ifconfig + Iface 3 HWaddr: 0F:F4 NID: CA:FE + + Long HWaddr: 06:84:F6:65:10:6B:11:14 + inet6 addr: bbbb::684:f665:106b:1114 + + IEEE802154E sync: 1 + 6TiSCH joined: 1 + + RPL rank: 2816 + RPL parent: 2A:BA:F7:65:10:6B:11:14 + RPL children: + RPL DODAG ID: bbbb::2aba:f765:106b:1114 + > udp server start 3000 + udp server start 3000 + Set UDP server port to 3000 + +On the other node send udp messages + + > udp send bbbb::684:f665:106b:1114 3000 hello + udp send bbbb::684:f665:106b:1114 3000 hello + Send 5 byte over UDP to [bbbb::684:f665:106b:1114]:3000 + > msg.l2_sendDoneError: 0 + Send success + +The first node should receive the message + + > Received 12 bytes on port 3000 + 00000000 A6 28 00 00 00 02 00 68 65 6C 6C 6F .(.....hello + +### Communicating with host (IPV6) + +OpenVisualizer can set up a tun interface to communicate with the host computer. +This will require starting `OpenVisualizer` with root privileges. The only +difference with the previous setup is that the root node must be setup as +follows: + +on iotlab: + $ IOTLAB_NODE=${ROOT_IOTLAB_NODE} BOARD=iotlab-m3 \ + make -C tests/pkg_openwsn openv-termtun + +on local boards: + $ PORT= BOARD=samr21-xpro \ + make -C tests/pkg_openwsn openv-termtun + +Once DAOs are received you can ping nodes in the network from your host: + +``` +$ ping6 -s 40 -i 5 bbbb:0:0:0:2ab5:fc65:106b:1114 +PING bbbb:0:0:0:2ab5:fc65:106b:1114(bbbb::2ab5:fc65:106b:1114) 40 data bytes +48 bytes from bbbb::2ab5:fc65:106b:1114: icmp_seq=1 ttl=64 time=1064 ms +48 bytes from bbbb::2ab5:fc65:106b:1114: icmp_seq=2 ttl=64 time=2111 ms +48 bytes from bbbb::2ab5:fc65:106b:1114: icmp_seq=3 ttl=64 time=1141 ms +48 bytes from bbbb::2ab5:fc65:106b:1114: icmp_seq=4 ttl=64 time=2197 ms +48 bytes from bbbb::2ab5:fc65:106b:1114: icmp_seq=5 ttl=64 time=1228 ms +48 bytes from bbbb::2ab5:fc65:106b:1114: icmp_seq=6 ttl=64 time=2306 ms +48 bytes from bbbb::2ab5:fc65:106b:1114: icmp_seq=7 ttl=64 time=1324 ms + +``` + +If openserial is used on the leaf node you would get the following output: + +``` +16:02:38 [ParserIEC:INFO] 768f [ICMPv6ECHO] received an echo request +16:02:44 [ParserIEC:INFO] 768f [ICMPv6ECHO] received an echo request +16:02:48 [ParserIEC:INFO] 768f [ICMPv6ECHO] received an echo request +16:02:54 [ParserIEC:INFO] 768f [ICMPv6ECHO] received an echo request +``` + +Some considerations: + - Nodes duty cycle is ~0.5%, so nodes get a chance to transmit roughly every + 2s, so the worst case scenario is ~4s RTT. This is increased for big payloads + since it will lead to fragmentation. + - If incoming packet rate is too fast the internal packet queue can be + be overloaded. diff --git a/tests/pkg_openwsn/main.c b/tests/pkg_openwsn/main.c new file mode 100644 index 000000000000..9f0e425075ed --- /dev/null +++ b/tests/pkg_openwsn/main.c @@ -0,0 +1,324 @@ +/* + * Copyright (C) 2017 Hamburg University of Applied Sciences + * + * 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 tests + * @{ + * + * @file + * @brief OpenWSN test application + * + * @author Peter Kietzmann + * + * @} + */ + +#include +#include + +#include "od.h" +#include "fmt.h" +#include "shell.h" +#include "openwsn.h" +#include "net/ipv6/addr.h" + +#include "opendefs.h" +#include "scheduler.h" +#include "02a-MAClow/IEEE802154E.h" +#include "02b-MAChigh/neighbors.h" +#include "03b-IPv6/icmpv6rpl.h" +#include "04-TRAN/openudp.h" +#include "cjoin.h" +#include "cross-layers/openqueue.h" +#include "cross-layers/idmanager.h" +#include "cross-layers/packetfunctions.h" + +extern idmanager_vars_t idmanager_vars; +extern icmpv6rpl_vars_t icmpv6rpl_vars; +extern neighbors_vars_t neighbors_vars; +extern openqueue_vars_t openqueue_vars; +extern schedule_vars_t schedule_vars; +extern scheduler_dbg_t scheduler_dbg; + +udp_resource_desc_t uinject_vars; +char addr_str[IPV6_ADDR_MAX_STR_LEN]; + +void uinject_sendDone(OpenQueueEntry_t *msg, owerror_t error) +{ + (void)error; + + printf("msg.l2_sendDoneError: %x\n", msg->l2_sendDoneError); + openqueue_freePacketBuffer(msg); + puts("Send success"); +} + +void uinject_receive(OpenQueueEntry_t *pkt) +{ + printf("Received %i bytes on port %i\n", (int)pkt->length, + pkt->l4_destination_port); + od_hex_dump(pkt->payload, pkt->length, OD_WIDTH_DEFAULT); + openqueue_freePacketBuffer(pkt); +} + +void uinject_init(void) +{ + uinject_vars.port = WKP_UDP_INJECT; + uinject_vars.callbackReceive = &uinject_receive; + uinject_vars.callbackSendDone = &uinject_sendDone; + openudp_register(&uinject_vars); +} + +char *_array_2_string(const uint8_t *addr, size_t addr_len, char *out) +{ + char *res = out; + + assert((out != NULL) && ((addr != NULL) || (addr_len == 0U))); + out[0] = '\0'; + for (size_t i = 0; i < addr_len; i++) { + out += fmt_byte_hex((out), *(addr++)); + *(out++) = (i == (addr_len - 1)) ? '\0' : ':'; + } + return res; +} + +static int ifconfig_cmd(int argc, char **argv) +{ + (void)argc; + (void)argv; + + open_addr_t *hwaddr; + open_addr_t temp_my128bID; + + memcpy(&temp_my128bID.addr_128b[0], &idmanager_vars.myPrefix.prefix, 8); + memcpy(&temp_my128bID.addr_128b[8], &idmanager_vars.my64bID.addr_64b, 8); + + printf("Iface %d ", openwsn_get_pid()); + hwaddr = idmanager_getMyID(ADDR_16B); + printf("\tHWaddr: %s ", _array_2_string(hwaddr->addr_16b, 2, addr_str)); + hwaddr = idmanager_getMyID(ADDR_PANID); + printf("NID: %s\n", _array_2_string(hwaddr->panid, 2, addr_str)); + printf("\n"); + + hwaddr = idmanager_getMyID(ADDR_64B); + printf("\t\tLong HWaddr: %s\n", _array_2_string(hwaddr->addr_64b, 8, addr_str)); + + ipv6_addr_to_str(addr_str, (ipv6_addr_t *)temp_my128bID.addr_128b, + sizeof(addr_str)); + printf("\t\tinet6 addr: %s\n", addr_str); + printf("\n"); + + + printf("\t\tIEEE802154E sync: %i\n", ieee154e_isSynch()); + printf("\t\t6TiSCH joined: %i\n", cjoin_getIsJoined()); + printf("\n"); + + if (idmanager_vars.isDAGroot) { + puts("\t\tNode is DAG root"); + } + else { + if (icmpv6rpl_vars.haveParent) { + printf("\t\tRPL rank: %i\n", icmpv6rpl_vars.myDAGrank); + printf("\t\tRPL parent: %s\n", \ + _array_2_string(neighbors_vars.neighbors[icmpv6rpl_vars. + ParentIndex]. + addr_64b.addr_64b, 8, addr_str)); + printf("\t\tRPL children:\n"); + for (uint8_t i = 0; i < MAXNUMNEIGHBORS; i++) { + if ((neighbors_isNeighborWithHigherDAGrank(i)) == true) { + printf("\t\t\t%s\n", \ + _array_2_string(neighbors_vars.neighbors[i]. + addr_64b.addr_64b, 8, addr_str)); + } + } + ipv6_addr_to_str(addr_str, + (ipv6_addr_t *)icmpv6rpl_vars.dao.DODAGID, + sizeof(addr_str)); + printf("\t\tRPL DODAG ID: %16s\n", addr_str); + } + else { + puts("\t\tNO RPL parent"); + } + } + return 0; +} + +static int nc_cmd(int argc, char **argv) +{ + (void)argc; + (void)argv; + + for (int i = 0; i < MAXNUMNEIGHBORS; i++) { + _array_2_string(neighbors_vars.neighbors[i].addr_64b.addr_64b, 8, + addr_str); + if (memcmp(addr_str, "00:00:00:00:00:00:00:00", 8) != 0) { + printf("%02i. %s\n", i, addr_str); + } + } + return 0; +} + +static const struct { + char *name; + int id; +} names[] = { + { "?", COMPONENT_NULL }, + { "owsn", COMPONENT_OPENWSN }, + { "idmanager", COMPONENT_IDMANAGER }, + { "oqueue", COMPONENT_OPENQUEUE }, + { "oserial", COMPONENT_OPENSERIAL }, + { "pktfuncs", COMPONENT_PACKETFUNCTIONS }, + { "random", COMPONENT_RANDOM }, + { "radio", COMPONENT_RADIO }, + { "154", COMPONENT_IEEE802154 }, + { "154e", COMPONENT_IEEE802154E }, + { "6top2154e", COMPONENT_SIXTOP_TO_IEEE802154E }, + { "154e26top", COMPONENT_IEEE802154E_TO_SIXTOP }, + { "6top", COMPONENT_SIXTOP }, + { "neigh", COMPONENT_NEIGHBORS }, + { "sched", COMPONENT_SCHEDULE }, + { "6topres", COMPONENT_SIXTOP_RES }, + { "bridge", COMPONENT_OPENBRIDGE }, + { "iphc", COMPONENT_IPHC }, + { "frag", COMPONENT_FRAG }, + { "fwd", COMPONENT_FORWARDING }, + { "icmpv6", COMPONENT_ICMPv6 }, + { "icmpv6ech", COMPONENT_ICMPv6ECHO }, + { "icmpv6rtr", COMPONENT_ICMPv6ROUTER }, + { "icmpv6rpl", COMPONENT_ICMPv6RPL }, + { "udp", COMPONENT_OPENUDP }, + { "coap", COMPONENT_OPENCOAP }, + { "cjoin", COMPONENT_CJOIN }, + { "openoscoap", COMPONENT_OPENOSCOAP }, + { "c6t", COMPONENT_C6T }, + { "uinject", COMPONENT_UINJECT }, +}; + +char *_get_name(int id) +{ + for (unsigned i = 0; i < ARRAY_SIZE(names); i++) { + if (id == names[i].id) { + return names[i].name; + } + } + return NULL; +} + +static int q_cmd(int argc, char **argv) +{ + (void)argc; + (void)argv; + + bool queue = 1; + + for (uint8_t i = 0; i < QUEUELENGTH; i++) { + if (openqueue_vars.queue[i].creator || openqueue_vars.queue[i].owner) { + queue = 0; + uint8_t creator = openqueue_vars.queue[i].creator; + uint8_t owner = openqueue_vars.queue[i].owner; + printf("Creator: %.9s [%d], ", _get_name(creator), creator); + printf("Owner: %.9s [%d]\n", _get_name(owner), owner); + } + } + if (queue) { + puts("openqueue empty"); + } + return 0; +} + +static int q_rmv(int argc, char **argv) +{ + if (argc < 2) { + printf("usage: %s [creator]\n", argv[0]); + return 1; + } + + uint8_t creator = atoi(argv[1]); + if (creator == 0) { + printf("error: invalid input value\n"); + return 1; + } + else { + printf("Removing entries created by: %.9s [%d]\n", _get_name(creator), creator); + openqueue_removeAllCreatedBy(creator); + } + return 0; +} + +static int as_cmd(int argc, char **argv) +{ + (void)argc; + (void)argv; + + for (int i = 0; i < MAXACTIVESLOTS; i++) { + switch (schedule_vars.scheduleBuf[i].type) { + case CELLTYPE_TX: + printf("neigh: %s, slot: %03i, chan: %02i, type: TX\n", \ + _array_2_string( + schedule_vars.scheduleBuf[i].neighbor.addr_64b, + 8, addr_str), + schedule_vars.scheduleBuf[i].slotOffset, \ + schedule_vars.scheduleBuf[i].channelOffset); + break; + case CELLTYPE_RX: + printf("slot: %03i, chan: %02i, type: RX\n", \ + schedule_vars.scheduleBuf[i].slotOffset, \ + schedule_vars.scheduleBuf[i].channelOffset); + break; + case CELLTYPE_TXRX: + printf("neigh: %s, slot: %03i, chan: %02i, type: RXTX\n", \ + _array_2_string( + schedule_vars.scheduleBuf[i].neighbor.addr_64b, + 8, addr_str), + schedule_vars.scheduleBuf[i].slotOffset, \ + schedule_vars.scheduleBuf[i].channelOffset); + break; + default: + break; + } + } + + return 0; +} + +static int sc_cmd(int argc, char **argv) +{ + (void)argc; + (void)argv; + + /* TODO allow other prefixes via shell ?!? */ + printf("Current tasks:%i\n", scheduler_dbg.numTasksCur); + printf("Max tasks: %i\n", scheduler_dbg.numTasksMax); + + return 0; +} + +extern int udp_cmd(int argc, char **argv); + +static const shell_command_t shell_commands[] = { + { "ifconfig", "Shows assigned IPv6 addresses", ifconfig_cmd }, + { "nc", "Shows neighbor table", nc_cmd }, + { "q", "Shows Openqueue", q_cmd }, + { "q-rmv", "Remove entries from creator in queue", q_rmv }, + { "as", "Shows active cells", as_cmd }, + { "sc", "Shows scheduler (openos) dbg states", sc_cmd }, + { "udp", "Send data over UDP and listen on UDP ports", udp_cmd }, + { NULL, NULL, NULL } +}; + +int main(void) +{ + puts("OpenWSN UDP test"); + + printf("You are running RIOT on a(n) %s board.\n", RIOT_BOARD); + printf("This board features a(n) %s MCU.\n", RIOT_MCU); + + uinject_init(); + + char line_buf[SHELL_DEFAULT_BUFSIZE]; + shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); +} diff --git a/tests/pkg_openwsn/udp.c b/tests/pkg_openwsn/udp.c new file mode 100644 index 000000000000..9afbb2211c5d --- /dev/null +++ b/tests/pkg_openwsn/udp.c @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2015 Freie Universität Berlin + * Copyright (C) 2018 Hamburg University of Applied Sciences + * + * 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 tests + * @{ + * + * @file + * + * @author Martine Lenders + * @author Peter Kietzmann + * @} + */ + +#include +#include +#include +#include + +#include "ztimer.h" +#include "net/ipv6.h" + +#include "opendefs.h" +#include "scheduler.h" +#include "02a-MAClow/IEEE802154E.h" +#include "03b-IPv6/icmpv6rpl.h" +#include "04-TRAN/openudp.h" +#include "cross-layers/openqueue.h" +#include "cross-layers/idmanager.h" +#include "cross-layers/packetfunctions.h" + +extern udp_resource_desc_t uinject_vars; +extern idmanager_vars_t idmanager_vars; +extern openudp_vars_t openudp_vars; + +static uint16_t counter = 0; + +OpenQueueEntry_t *pkt; + +void push_pkt_cb(void){ + owerror_t ret = openudp_send(pkt); + if (ret == E_FAIL) { + puts("could not send"); + openqueue_freePacketBuffer(pkt); + } +} + +static int udp_send(char *addr_str, char *port_str, char *data, + unsigned int num, unsigned int delay) +{ + size_t data_len; + open_addr_t parentNeighbor; + ipv6_addr_t addr; + + data_len = strlen(data); + uint8_t asnArray[data_len]; + + /* parse destination address */ + if (ipv6_addr_from_str(&addr, addr_str) == NULL) { + puts("Error: unable to parse destination address, exit"); + return 1; + } + + for (unsigned int i = 0; i < num; i++) { + + printf("Send %u byte over UDP to [%s]:%s\n", + (unsigned)data_len, addr_str, port_str); + + /* don't run if not in synch */ + if (ieee154e_isSynch() == FALSE) { + puts("Error: Node not in sync, exit"); + return 1; + } + + /* don't run on dagroot */ + if (idmanager_getIsDAGroot()) { + puts("Error: Node is DAGROOT, exit"); + return 1; + } + + bool foundNeighbor = icmpv6rpl_getPreferredParentEui64(&parentNeighbor); + if (foundNeighbor==FALSE) { + puts("Error: No preferred parent EUI64, exit"); + return 1; + } + + /* get a free packet buffer */ + pkt = openqueue_getFreePacketBuffer(COMPONENT_UINJECT); + if (pkt == NULL) { + puts("Error: could not create packet buffer, exit"); + return 1; + } + + pkt->owner = COMPONENT_UINJECT; + pkt->creator = COMPONENT_UINJECT; + pkt->l4_protocol = IANA_UDP; + pkt->l4_destination_port = atoi(port_str); + pkt->l4_sourcePortORicmpv6Type = uinject_vars.port; + pkt->l3_destinationAdd.type = ADDR_128B; + memcpy(&pkt->l3_destinationAdd.addr_128b[0], (void *)&addr, 16); + /* add payload */ + packetfunctions_reserveHeaderSize(pkt, data_len); + memcpy(&pkt->payload[0], data, data_len); + + packetfunctions_reserveHeaderSize(pkt, sizeof(uint16_t)); + pkt->payload[1] = (uint8_t)((counter & 0xff00) >> 8); + pkt->payload[0] = (uint8_t)(counter & 0x00ff); + counter++; + + packetfunctions_reserveHeaderSize(pkt, sizeof(asn_t)); + ieee154e_getAsn(asnArray); + pkt->payload[0] = asnArray[0]; + pkt->payload[1] = asnArray[1]; + pkt->payload[2] = asnArray[2]; + pkt->payload[3] = asnArray[3]; + pkt->payload[4] = asnArray[4]; + + scheduler_push_task(push_pkt_cb, TASKPRIO_COAP); + + ztimer_sleep(ZTIMER_USEC, delay); + } + return 0; +} + +int udp_cmd(int argc, char **argv) +{ + if (argc < 2) { + printf("usage: %s [send|server]\n", argv[0]); + return 1; + } + + if (strcmp(argv[1], "send") == 0) { + uint32_t num = 1; + uint32_t delay = 1000000LU; + /* don't send as root */ + if (idmanager_vars.isDAGroot) { + puts("Error: Node is root, exit"); + return 1; + } + if (argc < 5) { + printf("usage: %s send [ []]\n", + argv[0]); + return 1; + } + if (argc > 5) { + num = atoi(argv[5]); + } + if (argc > 6) { + delay = atoi(argv[6]); + } + return udp_send(argv[2], argv[3], argv[4], num, delay); + } + else if (strcmp(argv[1], "server") == 0) { + if (argc < 3) { + printf("usage: %s server [start|list]\n", argv[0]); + return 1; + } + if (strcmp(argv[2], "start") == 0) { + if (argc < 4) { + printf("usage %s server start \n", argv[0]); + return 1; + } + uint16_t port = atoi(argv[3]); + uinject_vars.port = port; + printf("Set UDP server port to %" PRIu16 "\n", port); + return 0; + } + else if (strcmp(argv[2], "list") == 0) { + udp_resource_desc_t* resource = openudp_vars.resources; + printf("Open UDP Ports: "); + while (NULL != resource) { + printf("%i ", resource->port); + resource = resource->next; + } + puts(""); + } + else { + puts("error: invalid command"); + return 1; + } + } + else { + puts("error: invalid command"); + return 1; + } + + return 1; +} +/** @} */ From d01476a661466bf14eeb5bafdfccfd34687e8075 Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Thu, 25 Jun 2020 22:37:13 +0200 Subject: [PATCH 5/7] dist/tools/openvisualizer: inital support --- Makefile.include | 4 + dist/tools/openvisualizer/logging.conf | 236 ++++++++++++++++++ .../makefile.openvisualizer.inc.mk | 93 +++++++ 3 files changed, 333 insertions(+) create mode 100644 dist/tools/openvisualizer/logging.conf create mode 100644 dist/tools/openvisualizer/makefile.openvisualizer.inc.mk diff --git a/Makefile.include b/Makefile.include index 8056a026f39a..40956332b278 100644 --- a/Makefile.include +++ b/Makefile.include @@ -896,6 +896,10 @@ ifneq (,$(filter iotlab-m3 wsn430-v1_3b wsn430-v1_4,$(BOARD))) endif endif +ifneq (,$(filter openv-%,$(MAKECMDGOALS))) + include $(RIOTBASE)/dist/tools/openvisualizer/makefile.openvisualizer.inc.mk +endif + # Include desvirt Makefile include $(RIOTTOOLS)/desvirt/Makefile.desvirt diff --git a/dist/tools/openvisualizer/logging.conf b/dist/tools/openvisualizer/logging.conf new file mode 100644 index 000000000000..ab17387a049f --- /dev/null +++ b/dist/tools/openvisualizer/logging.conf @@ -0,0 +1,236 @@ +# Note Expects 'logDir' passed in with location for file output. + +#============================ formatters =============================== + +[formatters] +keys=std, console + +[formatter_std] +format=%(asctime)s [%(name)s:%(levelname)s] %(message)s +datefmt=%H:%M:%S + +[formatter_console] +class=openvisualizer.main.ColoredFormatter +format=%(asctime)s [%(name)s:%(levelname)s] %(message)s +datefmt=%H:%M:%S + +#============================ handlers ================================= + +[handlers] +keys=std,console + +[handler_std] +class=handlers.RotatingFileHandler +# args: filename, open mode, max file size, backup file count +args=('LOG_PATH/openv-server.log', 'a', 2000000, 5) +formatter=std + +[handler_console] +class=StreamHandler +args=() +formatter=console + +#============================ loggers ================================== + +[loggers] +keys= + root, + EventBusMonitor, + EventBusClient, + OpenTun, + OpenTunMacOS, + OpenTunWindows, + OpenTunLinux, + MoteConnector, + MoteProbe, + MoteState, + OpenParser, + ParserData, + ParserPrintf, + ParserIEC, + ParserStatus, + Parser, + OpenHdlc, + OpenLbr, + SixLowPanFrag, + RPL, + SourceRoute, + JRC, + Topology, + OpenVisualizerServer, + Utils, + OVWebServer, + OVtracer, + CoAP + +[logger_root] +level=ERROR +handlers=std + +[logger_EventBusMonitor] +level=ERROR +handlers=std +propagate=0 +qualname=EventBusMonitor + +[logger_EventBusClient] +level=ERROR +handlers=std +propagate=0 +qualname=EventBusClient + +[logger_OpenTun] +level=ERROR +handlers=std +propagate=0 +qualname=OpenTun + +[logger_OpenTunWindows] +level=INFO +handlers=std, console +propagate=0 +qualname=OpenTunWindows + +[logger_OpenTunLinux] +level=INFO +handlers=std, console +propagate=0 +qualname=OpenTunLinux + +[logger_OpenTunMacOS] +level=INFO +handlers=std, console +propagate=0 +qualname=OpenTunMacOS + +[logger_MoteConnector] +level=ERROR +handlers=std +propagate=0 +qualname=MoteConnector + +[logger_MoteProbe] +level=INFO +handlers=std, console +propagate=0 +qualname=MoteProbe + +[logger_MoteState] +level=ERROR +handlers=std +propagate=0 +qualname=MoteState + +[logger_OpenParser] +level=ERROR +handlers=std +propagate=0 +qualname=OpenParser + +[logger_Parser] +level=ERROR +handlers=std +propagate=0 +qualname=Parser + +[logger_ParserIEC] +level=VERBOSE +handlers=std, console +propagate=0 +qualname=ParserIEC + +[logger_ParserData] +level=ERROR +handlers=std +propagate=0 +qualname=ParserData + +[logger_ParserPrintf] +level=INFO +handlers=std, console +propagate=0 +qualname=ParserPrintf + +[logger_ParserPacket] +level=ERROR +handlers=std +propagate=0 +qualname=ParserPacket + +[logger_ParserStatus] +level=ERROR +handlers=std +propagate=0 +qualname=ParserStatus + +[logger_OpenHdlc] +level=ERROR +handlers=std +propagate=0 +qualname=OpenHdlc + +[logger_OpenLbr] +level=ERROR +handlers=std +propagate=0 +qualname=OpenLbr + +[logger_SixLowPanFrag] +level=INFO +handlers=std +propagate=0 +qualname=SixLowPanFrag + +[logger_RPL] +level=INFO +handlers=std, console +propagate=0 +qualname=RPL + +[logger_SourceRoute] +level=ERROR +handlers=std +propagate=0 +qualname=SourceRoute + +[logger_JRC] +level=VERBOSE +handlers=std, console +propagate=0 +qualname=JRC + +[logger_Topology] +level=ERROR +handlers=std +propagate=0 +qualname=Topology + +[logger_OpenVisualizerServer] +level=VERBOSE +handlers=std, console +propagate=0 +qualname=OpenVisualizerServer + +[logger_Utils] +level=VERBOSE +handlers=std, console +propagate=0 +qualname=Utils + +[logger_OVWebServer] +level=INFO +handlers=std +propagate=0 +qualname=OVWebServer + +[logger_OVtracer] +level=INFO +handlers=std, console +propagate=0 +qualname=OVtracer + +[logger_CoAP] +level=INFO +handlers=std, console +propagate=0 +qualname=coap diff --git a/dist/tools/openvisualizer/makefile.openvisualizer.inc.mk b/dist/tools/openvisualizer/makefile.openvisualizer.inc.mk new file mode 100644 index 000000000000..43dd8cf06221 --- /dev/null +++ b/dist/tools/openvisualizer/makefile.openvisualizer.inc.mk @@ -0,0 +1,93 @@ +.PHONY: openv-clean openv-setroot openv-term openv-termroot + +# Use a single board with openv +# =================================== +# +# OpenVisualizer runs on port 9000 by default, if that ports conflicts or +# multiple instances are spawned you will need to specify the port, eg. +# * `OPENV_FLAGS='--port=9001` +# +# Not all logs for openvisualizer are piped to the terminal, more detailed logs +# are stored in $(BINDIR)/openv-server.log +# +# More info at https://github.com/fjmolinas/openvisualizer/blob/develop_SW-318-RIOT/README.md +# +# Supported: +# * openv-term +# * openv-termroot +# * openv-termtun +# * openv-setroot +# * openv-clean +# * openv-serial +# +# Prerequisites +# ------------- +# +# * Install openvisualizer: +# * git clone -b develop_SW-318-RIOT https://github.com/fjmolinas/openvisualizer.git +# * cd openvisualizer +# * pip2 install . +# +# * If using iotlab nodes, pre-requisites in makefile.iotlab.single.inc.mk +# +# * For `openv-termtun` it will require root must be able to ssh into iotlab +# + +# Use full path in case it needs to be run with sudo +OPENV_SERVER_PATH := $(shell which openv-server) +OPENV_CLIENT_PATH := $(shell which openv-client) +OPENV_SERIAL_PATH := $(shell which openv-serial) + +# Openvisualizer requires to know where openwsn-fw is located +OPENV_OPENWSN_FW_PATH ?= --fw-path=$(RIOTBASE)/build/pkg/openwsn +OPENV_DEFAULT_FLAGS += $(OPENV_OPENWSN_FW_PATH) + +OPENV_DEFAULT_FLAGS ?= + +ifneq (,$(IOTLAB_NODE)) + OPENV_MOTE ?= $(IOTLAB_NODE) + OPENV_DEFAULT_FLAGS += --iotlab-motes=$(IOTLAB_NODE) +else + OPENV_MOTE += $(PORT) + OPENV_DEFAULT_FLAGS += --port-mask=$(OPENV_MOTE) --baudrate=$(BAUD) +endif + +# Use modified logging configuration +OPENV_LOG_CONFIG = $(BINDIR)/logging.conf +OPENV_LOG_FILE = $(BINDIR)/openv-server.log +OPENV_DEFAULT_FLAGS += --lconf=$(OPENV_LOG_CONFIG) + +$(OPENV_LOG_CONFIG): $(LAST_MAKEFILEDIR)/logging.conf + $(Q)cp $^ $@.tmp + $(Q)sed -i 's#LOG_PATH#'"$(BINDIR)"'#g' $@.tmp + $(Q)mv $@.tmp $@ + +# Start tun interface +ifneq (,$(filter openv-termtun,$(MAKECMDGOALS))) + OPENV_DEFAULT_FLAGS += --opentun +endif + +# Optional flags to pass through command line +OPENV_FLAGS ?= + +openv-term: $(OPENV_LOG_CONFIG) +openv-term: $(TERMDEPS) + $(Q)$(OPENV_SERVER_PATH) $(OPENV_DEFAULT_FLAGS) $(OPENV_FLAGS) + +openv-termroot: $(OPENV_LOG_CONFIG) +openv-termroot: $(TERMDEPS) + $(Q)$(OPENV_SERVER_PATH) $(OPENV_DEFAULT_FLAGS) $(OPENV_FLAGS) --root=$(OPENV_MOTE) + +openv-termtun: $(OPENV_LOG_CONFIG) +openv-termtun: $(TERMDEPS) + sudo $(OPENV_SERVER_PATH) $(OPENV_DEFAULT_FLAGS) $(OPENV_FLAGS) --root=$(OPENV_MOTE) + +openv-setroot: + $(Q)$(OPENV_CLIENT_PATH) $(OPENV_OPENWSN_FW_PATH) $(OPENV_FLAGS) root=$(OPENV_MOTE) + +openv-clean: + $(Q)rm -rf $(OPENV_LOG_CONFIG) + $(Q)rm -rf $(OPENV_LOG_FILE) + +openv-serial: + $(Q)$(OPENV_SERIAL_PATH) --port=$(PORT) --baudrate=$(BAUD) From 7515f1152ab567baa3660a4b6d4fcadd915f65fe Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Thu, 25 Jun 2020 22:37:27 +0200 Subject: [PATCH 6/7] boards/common/iotlab: add OpenWSN timing constants --- boards/common/iotlab/include/board_common.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/boards/common/iotlab/include/board_common.h b/boards/common/iotlab/include/board_common.h index e2b86e4db0ab..ed573fd15609 100644 --- a/boards/common/iotlab/include/board_common.h +++ b/boards/common/iotlab/include/board_common.h @@ -61,6 +61,23 @@ extern "C" { #define CONFIG_ZTIMER_USEC_MIN (2) /** @} */ +/** + * @name OpenWSN timing constants + * + * @{ + */ +/* Measured 440us + ~10% */ +#define PORT_maxTxDataPrepare (500/PORT_US_PER_TICK) +/* Measured 200us + ~10% */ +#define PORT_maxRxAckPrepare (300/PORT_US_PER_TICK) +/* Measured 300us + ~10% */ +#define PORT_maxRxDataPrepare (350/PORT_US_PER_TICK) +/* Measured 316us + ~10% */ +#define PORT_maxTxAckPrepare (350/PORT_US_PER_TICK) +/* Measured 360us with openwsn_sctimer_rtt */ +#define PORT_delayTx (360/PORT_US_PER_TICK) +/** @} */ + /** * @name Define the interface to the AT86RF231 radio * From b0c5c3eacaa5601d55399052ed649f0fc385129e Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Thu, 25 Jun 2020 22:37:43 +0200 Subject: [PATCH 7/7] boards/samr21-xpro: add OpenWSN timing constants --- boards/samr21-xpro/include/board.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/boards/samr21-xpro/include/board.h b/boards/samr21-xpro/include/board.h index 44cc80cf7e7b..649aace5d436 100644 --- a/boards/samr21-xpro/include/board.h +++ b/boards/samr21-xpro/include/board.h @@ -57,6 +57,23 @@ extern "C" { #define AT86RF2XX_PARAM_SLEEP GPIO_PIN(PA, 20) #define AT86RF2XX_PARAM_RESET GPIO_PIN(PB, 15) +/** + * @name OpenWSN timing constants + * + * @{ + */ +/* Measured 800us + ~10% */ +#define PORT_maxTxDataPrepare (900/PORT_US_PER_TICK) +/* Measured 450us + ~10% */ +#define PORT_maxRxAckPrepare (500/PORT_US_PER_TICK) +/* Measured 500us + ~10% */ +#define PORT_maxRxDataPrepare (550/PORT_US_PER_TICK) +/* Measured 660us + ~10% */ +#define PORT_maxTxAckPrepare (750/PORT_US_PER_TICK) +/* Measured 650us with openwsn_sctimer_rtt */ +#define PORT_delayTx (650/PORT_US_PER_TICK) +/** @} */ + /** * @name LED pin definitions and handlers * @{