mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
pkg/OpenWSN: initial import
Co-authored-by: Peter Kietzmann <peter.kietzmann@haw-hamburg.de> Co-authored-by: Jose Alamos <jose.alamos@haw-hamburg.de> Co-authored-by: Michel Rottleuthner <michel.rottleuthner@haw-hamburg.de>
This commit is contained in:
parent
6b7640c87b
commit
844ccfbeb3
51
pkg/openwsn/Makefile
Normal file
51
pkg/openwsn/Makefile
Normal file
@ -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=$@
|
71
pkg/openwsn/Makefile.dep
Normal file
71
pkg/openwsn/Makefile.dep
Normal file
@ -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
|
40
pkg/openwsn/Makefile.include
Normal file
40
pkg/openwsn/Makefile.include
Normal file
@ -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
|
13
pkg/openwsn/contrib/Makefile
Normal file
13
pkg/openwsn/contrib/Makefile
Normal file
@ -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
|
88
pkg/openwsn/contrib/board.c
Normal file
88
pkg/openwsn/contrib/board.c
Normal file
@ -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 <watteyne@eecs.berkeley.edu>, February 2012
|
||||
* @author Tengfei Chang <tengfei.chang@gmail.com>, July 2012
|
||||
* @author Peter Kietzmann <peter.kietzmann@haw-hamburg.de>, July 2017
|
||||
* @author Francisco Molina <francois-xavier.molina@inria.fr>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#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();
|
||||
}
|
104
pkg/openwsn/contrib/cryptoengine.c
Normal file
104
pkg/openwsn/contrib/cryptoengine.c
Normal file
@ -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 <francois-xavier.molina@inria.fr>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#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;
|
||||
}
|
195
pkg/openwsn/contrib/debugpins.c
Normal file
195
pkg/openwsn/contrib/debugpins.c
Normal file
@ -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 <michael.frey@msasafety.com>
|
||||
* @author Peter Kietzmann <peter.kietzmann@haw-hamburg.de>
|
||||
* @author Francisco Molina <francois-xavier.molina@inria.fr>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "debugpins.h"
|
||||
#include "openwsn_debugpins.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
/* 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);
|
||||
}
|
44
pkg/openwsn/contrib/eui64.c
Normal file
44
pkg/openwsn/contrib/eui64.c
Normal file
@ -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 <peter.kietzmann@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
236
pkg/openwsn/contrib/leds.c
Normal file
236
pkg/openwsn/contrib/leds.c
Normal file
@ -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 <michael.frey@msasafety.com>
|
||||
* @author Peter Kietzmann <peter.kietzmann@haw-hamburg.de>
|
||||
* @author Francisco Molina <francois-xavier.molina@inria.fr>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "leds.h"
|
||||
#include "openwsn_leds.h"
|
||||
|
||||
#include "board.h"
|
||||
#include "periph/gpio.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
/** 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 */
|
||||
}
|
122
pkg/openwsn/contrib/openwsn.c
Normal file
122
pkg/openwsn/contrib/openwsn.c
Normal file
@ -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 <peter.kietzmann@haw-hamburg.de>
|
||||
* @author Francisco Molina <francois-xavier.molina@inria.fr>
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
268
pkg/openwsn/contrib/radio.c
Normal file
268
pkg/openwsn/contrib/radio.c
Normal file
@ -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 <peter.kietzmann@haw-hamburg.de>
|
||||
* @author Oliver Hahm <oliver.hahm@inria.fr>
|
||||
* @author Francisco Molina <francois-xavier.molina@inria.fr>
|
||||
* @}
|
||||
*/
|
||||
#include <sys/uio.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
}
|
169
pkg/openwsn/contrib/sctimer_rtt.c
Normal file
169
pkg/openwsn/contrib/sctimer_rtt.c
Normal file
@ -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 <tengfei.chang@gmail.com>, July 2012
|
||||
* @author Peter Kietzmann <peter.kietzmann@haw-hamburg.de>, July 2017
|
||||
* @author Michel Rottleuthner <michel.rottleuthner@haw-hamburg.de>, April 2019
|
||||
* @author Francisco Molina <francois-xavier.molina@inria.fr>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
#include <stdatomic.h>
|
||||
|
||||
#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();
|
||||
}
|
163
pkg/openwsn/contrib/sctimer_ztimer.c
Normal file
163
pkg/openwsn/contrib/sctimer_ztimer.c
Normal file
@ -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 <francois-xavier.molina@inria.fr>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
#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 */
|
||||
}
|
184
pkg/openwsn/contrib/uart.c
Normal file
184
pkg/openwsn/contrib/uart.c
Normal file
@ -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 <peter.kietzmann@haw-hamburg.de>
|
||||
* @author Francisco Molina <francois-xavier.molina@inria.fr>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdatomic.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
420
pkg/openwsn/doc.txt
Normal file
420
pkg/openwsn/doc.txt
Normal file
@ -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
|
||||
|
||||
*/
|
143
pkg/openwsn/include/board_info.h
Normal file
143
pkg/openwsn/include/board_info.h
Normal file
@ -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 <watteyne@eecs.berkeley.edu>, February 2012
|
||||
* @author Tengfei Chang <tengfei.chang@gmail.com>, July 2012
|
||||
* @author Peter Kietzmann <peter.kietzmann@haw-hamburg.de>, July 2017
|
||||
* @author Francisco Molina <francois-xavier.molina@inria.fr>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifndef BOARD_INFO_H
|
||||
#define BOARD_INFO_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#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 */
|
56
pkg/openwsn/include/openwsn.h
Normal file
56
pkg/openwsn/include/openwsn.h
Normal file
@ -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 <peter.kietzmann@haw-hamburg.de>
|
||||
* @author Francisco Molina <francois-xavier.molina@inria.fr>
|
||||
*/
|
||||
#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 */
|
||||
/** @} */
|
71
pkg/openwsn/include/openwsn_board.h
Normal file
71
pkg/openwsn/include/openwsn_board.h
Normal file
@ -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 <watteyne@eecs.berkeley.edu>, February 2012
|
||||
* @author Peter Kietzmann <peter.kietzmann@haw-hamburg.de>, July 2017
|
||||
* @author Francisco Molina <francois-xavier.molina@inria.fr>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#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 */
|
56
pkg/openwsn/include/openwsn_debugpins.h
Normal file
56
pkg/openwsn/include/openwsn_debugpins.h
Normal file
@ -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 <michael.frey@msasafety.com>
|
||||
* @author Peter Kietzmann <peter.kietzmann@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#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 */
|
80
pkg/openwsn/include/openwsn_debugpins_params.h
Normal file
80
pkg/openwsn/include/openwsn_debugpins_params.h
Normal file
@ -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 <michael.frey@msasafety.com>
|
||||
* @author Peter Kietzmann <peter.kietzmann@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#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 */
|
66
pkg/openwsn/include/openwsn_leds.h
Normal file
66
pkg/openwsn/include/openwsn_leds.h
Normal file
@ -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 <peter.kietzmann@haw-hamburg.de>
|
||||
* @author Francisco Molina <francois-xavier.molina@inria.fr>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
#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 */
|
88
pkg/openwsn/include/openwsn_leds_params.h
Normal file
88
pkg/openwsn/include/openwsn_leds_params.h
Normal file
@ -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 <peter.kietzmann@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
#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 */
|
84
pkg/openwsn/include/openwsn_radio.h
Normal file
84
pkg/openwsn/include/openwsn_radio.h
Normal file
@ -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 <peter.kietzmann@haw-hamburg.de>, April 2019
|
||||
* @author Francisco Molina <francois-xavier.molina@inria.fr>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#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 */
|
||||
/** @} */
|
141
pkg/openwsn/include/openwsn_uart.h
Normal file
141
pkg/openwsn/include/openwsn_uart.h
Normal file
@ -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 <watteyne@eecs.berkeley.edu>, February 2012
|
||||
* @author Peter Kietzmann <peter.kietzmann@haw-hamburg.de>, July 2018
|
||||
* @author Francisco Molina <francois-xavier.molina@inria.fr>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#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 */
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
pkg/openwsn/patches/0008-openstack-openapps-add-debugging.patch
Normal file
BIN
pkg/openwsn/patches/0008-openstack-openapps-add-debugging.patch
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user