mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #13824 from fjmolinas/pr_openwsn
pkg/openwsn: re-integrate the network stack as a package
This commit is contained in:
commit
d98ddfad9a
@ -899,6 +899,10 @@ ifneq (,$(filter iotlab-m3 wsn430-v1_3b wsn430-v1_4,$(BOARD)))
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (,$(filter openv-%,$(MAKECMDGOALS)))
|
||||
include $(RIOTBASE)/dist/tools/openvisualizer/makefile.openvisualizer.inc.mk
|
||||
endif
|
||||
|
||||
# Include desvirt Makefile
|
||||
include $(RIOTTOOLS)/desvirt/Makefile.desvirt
|
||||
|
||||
|
@ -61,6 +61,23 @@ extern "C" {
|
||||
#define CONFIG_ZTIMER_USEC_MIN (2)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name OpenWSN timing constants
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
/* Measured 440us + ~10% */
|
||||
#define PORT_maxTxDataPrepare (500/PORT_US_PER_TICK)
|
||||
/* Measured 200us + ~10% */
|
||||
#define PORT_maxRxAckPrepare (300/PORT_US_PER_TICK)
|
||||
/* Measured 300us + ~10% */
|
||||
#define PORT_maxRxDataPrepare (350/PORT_US_PER_TICK)
|
||||
/* Measured 316us + ~10% */
|
||||
#define PORT_maxTxAckPrepare (350/PORT_US_PER_TICK)
|
||||
/* Measured 360us with openwsn_sctimer_rtt */
|
||||
#define PORT_delayTx (360/PORT_US_PER_TICK)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Define the interface to the AT86RF231 radio
|
||||
*
|
||||
|
@ -57,6 +57,23 @@ extern "C" {
|
||||
#define AT86RF2XX_PARAM_SLEEP GPIO_PIN(PA, 20)
|
||||
#define AT86RF2XX_PARAM_RESET GPIO_PIN(PB, 15)
|
||||
|
||||
/**
|
||||
* @name OpenWSN timing constants
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
/* Measured 800us + ~10% */
|
||||
#define PORT_maxTxDataPrepare (900/PORT_US_PER_TICK)
|
||||
/* Measured 450us + ~10% */
|
||||
#define PORT_maxRxAckPrepare (500/PORT_US_PER_TICK)
|
||||
/* Measured 500us + ~10% */
|
||||
#define PORT_maxRxDataPrepare (550/PORT_US_PER_TICK)
|
||||
/* Measured 660us + ~10% */
|
||||
#define PORT_maxTxAckPrepare (750/PORT_US_PER_TICK)
|
||||
/* Measured 650us with openwsn_sctimer_rtt */
|
||||
#define PORT_delayTx (650/PORT_US_PER_TICK)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name LED pin definitions and handlers
|
||||
* @{
|
||||
|
236
dist/tools/openvisualizer/logging.conf
vendored
Normal file
236
dist/tools/openvisualizer/logging.conf
vendored
Normal file
@ -0,0 +1,236 @@
|
||||
# Note Expects 'logDir' passed in with location for file output.
|
||||
|
||||
#============================ formatters ===============================
|
||||
|
||||
[formatters]
|
||||
keys=std, console
|
||||
|
||||
[formatter_std]
|
||||
format=%(asctime)s [%(name)s:%(levelname)s] %(message)s
|
||||
datefmt=%H:%M:%S
|
||||
|
||||
[formatter_console]
|
||||
class=openvisualizer.main.ColoredFormatter
|
||||
format=%(asctime)s [%(name)s:%(levelname)s] %(message)s
|
||||
datefmt=%H:%M:%S
|
||||
|
||||
#============================ handlers =================================
|
||||
|
||||
[handlers]
|
||||
keys=std,console
|
||||
|
||||
[handler_std]
|
||||
class=handlers.RotatingFileHandler
|
||||
# args: filename, open mode, max file size, backup file count
|
||||
args=('LOG_PATH/openv-server.log', 'a', 2000000, 5)
|
||||
formatter=std
|
||||
|
||||
[handler_console]
|
||||
class=StreamHandler
|
||||
args=()
|
||||
formatter=console
|
||||
|
||||
#============================ loggers ==================================
|
||||
|
||||
[loggers]
|
||||
keys=
|
||||
root,
|
||||
EventBusMonitor,
|
||||
EventBusClient,
|
||||
OpenTun,
|
||||
OpenTunMacOS,
|
||||
OpenTunWindows,
|
||||
OpenTunLinux,
|
||||
MoteConnector,
|
||||
MoteProbe,
|
||||
MoteState,
|
||||
OpenParser,
|
||||
ParserData,
|
||||
ParserPrintf,
|
||||
ParserIEC,
|
||||
ParserStatus,
|
||||
Parser,
|
||||
OpenHdlc,
|
||||
OpenLbr,
|
||||
SixLowPanFrag,
|
||||
RPL,
|
||||
SourceRoute,
|
||||
JRC,
|
||||
Topology,
|
||||
OpenVisualizerServer,
|
||||
Utils,
|
||||
OVWebServer,
|
||||
OVtracer,
|
||||
CoAP
|
||||
|
||||
[logger_root]
|
||||
level=ERROR
|
||||
handlers=std
|
||||
|
||||
[logger_EventBusMonitor]
|
||||
level=ERROR
|
||||
handlers=std
|
||||
propagate=0
|
||||
qualname=EventBusMonitor
|
||||
|
||||
[logger_EventBusClient]
|
||||
level=ERROR
|
||||
handlers=std
|
||||
propagate=0
|
||||
qualname=EventBusClient
|
||||
|
||||
[logger_OpenTun]
|
||||
level=ERROR
|
||||
handlers=std
|
||||
propagate=0
|
||||
qualname=OpenTun
|
||||
|
||||
[logger_OpenTunWindows]
|
||||
level=INFO
|
||||
handlers=std, console
|
||||
propagate=0
|
||||
qualname=OpenTunWindows
|
||||
|
||||
[logger_OpenTunLinux]
|
||||
level=INFO
|
||||
handlers=std, console
|
||||
propagate=0
|
||||
qualname=OpenTunLinux
|
||||
|
||||
[logger_OpenTunMacOS]
|
||||
level=INFO
|
||||
handlers=std, console
|
||||
propagate=0
|
||||
qualname=OpenTunMacOS
|
||||
|
||||
[logger_MoteConnector]
|
||||
level=ERROR
|
||||
handlers=std
|
||||
propagate=0
|
||||
qualname=MoteConnector
|
||||
|
||||
[logger_MoteProbe]
|
||||
level=INFO
|
||||
handlers=std, console
|
||||
propagate=0
|
||||
qualname=MoteProbe
|
||||
|
||||
[logger_MoteState]
|
||||
level=ERROR
|
||||
handlers=std
|
||||
propagate=0
|
||||
qualname=MoteState
|
||||
|
||||
[logger_OpenParser]
|
||||
level=ERROR
|
||||
handlers=std
|
||||
propagate=0
|
||||
qualname=OpenParser
|
||||
|
||||
[logger_Parser]
|
||||
level=ERROR
|
||||
handlers=std
|
||||
propagate=0
|
||||
qualname=Parser
|
||||
|
||||
[logger_ParserIEC]
|
||||
level=VERBOSE
|
||||
handlers=std, console
|
||||
propagate=0
|
||||
qualname=ParserIEC
|
||||
|
||||
[logger_ParserData]
|
||||
level=ERROR
|
||||
handlers=std
|
||||
propagate=0
|
||||
qualname=ParserData
|
||||
|
||||
[logger_ParserPrintf]
|
||||
level=INFO
|
||||
handlers=std, console
|
||||
propagate=0
|
||||
qualname=ParserPrintf
|
||||
|
||||
[logger_ParserPacket]
|
||||
level=ERROR
|
||||
handlers=std
|
||||
propagate=0
|
||||
qualname=ParserPacket
|
||||
|
||||
[logger_ParserStatus]
|
||||
level=ERROR
|
||||
handlers=std
|
||||
propagate=0
|
||||
qualname=ParserStatus
|
||||
|
||||
[logger_OpenHdlc]
|
||||
level=ERROR
|
||||
handlers=std
|
||||
propagate=0
|
||||
qualname=OpenHdlc
|
||||
|
||||
[logger_OpenLbr]
|
||||
level=ERROR
|
||||
handlers=std
|
||||
propagate=0
|
||||
qualname=OpenLbr
|
||||
|
||||
[logger_SixLowPanFrag]
|
||||
level=INFO
|
||||
handlers=std
|
||||
propagate=0
|
||||
qualname=SixLowPanFrag
|
||||
|
||||
[logger_RPL]
|
||||
level=INFO
|
||||
handlers=std, console
|
||||
propagate=0
|
||||
qualname=RPL
|
||||
|
||||
[logger_SourceRoute]
|
||||
level=ERROR
|
||||
handlers=std
|
||||
propagate=0
|
||||
qualname=SourceRoute
|
||||
|
||||
[logger_JRC]
|
||||
level=VERBOSE
|
||||
handlers=std, console
|
||||
propagate=0
|
||||
qualname=JRC
|
||||
|
||||
[logger_Topology]
|
||||
level=ERROR
|
||||
handlers=std
|
||||
propagate=0
|
||||
qualname=Topology
|
||||
|
||||
[logger_OpenVisualizerServer]
|
||||
level=VERBOSE
|
||||
handlers=std, console
|
||||
propagate=0
|
||||
qualname=OpenVisualizerServer
|
||||
|
||||
[logger_Utils]
|
||||
level=VERBOSE
|
||||
handlers=std, console
|
||||
propagate=0
|
||||
qualname=Utils
|
||||
|
||||
[logger_OVWebServer]
|
||||
level=INFO
|
||||
handlers=std
|
||||
propagate=0
|
||||
qualname=OVWebServer
|
||||
|
||||
[logger_OVtracer]
|
||||
level=INFO
|
||||
handlers=std, console
|
||||
propagate=0
|
||||
qualname=OVtracer
|
||||
|
||||
[logger_CoAP]
|
||||
level=INFO
|
||||
handlers=std, console
|
||||
propagate=0
|
||||
qualname=coap
|
93
dist/tools/openvisualizer/makefile.openvisualizer.inc.mk
vendored
Normal file
93
dist/tools/openvisualizer/makefile.openvisualizer.inc.mk
vendored
Normal file
@ -0,0 +1,93 @@
|
||||
.PHONY: openv-clean openv-setroot openv-term openv-termroot
|
||||
|
||||
# Use a single board with openv
|
||||
# ===================================
|
||||
#
|
||||
# OpenVisualizer runs on port 9000 by default, if that ports conflicts or
|
||||
# multiple instances are spawned you will need to specify the port, eg.
|
||||
# * `OPENV_FLAGS='--port=9001`
|
||||
#
|
||||
# Not all logs for openvisualizer are piped to the terminal, more detailed logs
|
||||
# are stored in $(BINDIR)/openv-server.log
|
||||
#
|
||||
# More info at https://github.com/fjmolinas/openvisualizer/blob/develop_SW-318-RIOT/README.md
|
||||
#
|
||||
# Supported:
|
||||
# * openv-term
|
||||
# * openv-termroot
|
||||
# * openv-termtun
|
||||
# * openv-setroot
|
||||
# * openv-clean
|
||||
# * openv-serial
|
||||
#
|
||||
# Prerequisites
|
||||
# -------------
|
||||
#
|
||||
# * Install openvisualizer:
|
||||
# * git clone -b develop_SW-318-RIOT https://github.com/fjmolinas/openvisualizer.git
|
||||
# * cd openvisualizer
|
||||
# * pip2 install .
|
||||
#
|
||||
# * If using iotlab nodes, pre-requisites in makefile.iotlab.single.inc.mk
|
||||
#
|
||||
# * For `openv-termtun` it will require root must be able to ssh into iotlab
|
||||
#
|
||||
|
||||
# Use full path in case it needs to be run with sudo
|
||||
OPENV_SERVER_PATH := $(shell which openv-server)
|
||||
OPENV_CLIENT_PATH := $(shell which openv-client)
|
||||
OPENV_SERIAL_PATH := $(shell which openv-serial)
|
||||
|
||||
# Openvisualizer requires to know where openwsn-fw is located
|
||||
OPENV_OPENWSN_FW_PATH ?= --fw-path=$(RIOTBASE)/build/pkg/openwsn
|
||||
OPENV_DEFAULT_FLAGS += $(OPENV_OPENWSN_FW_PATH)
|
||||
|
||||
OPENV_DEFAULT_FLAGS ?=
|
||||
|
||||
ifneq (,$(IOTLAB_NODE))
|
||||
OPENV_MOTE ?= $(IOTLAB_NODE)
|
||||
OPENV_DEFAULT_FLAGS += --iotlab-motes=$(IOTLAB_NODE)
|
||||
else
|
||||
OPENV_MOTE += $(PORT)
|
||||
OPENV_DEFAULT_FLAGS += --port-mask=$(OPENV_MOTE) --baudrate=$(BAUD)
|
||||
endif
|
||||
|
||||
# Use modified logging configuration
|
||||
OPENV_LOG_CONFIG = $(BINDIR)/logging.conf
|
||||
OPENV_LOG_FILE = $(BINDIR)/openv-server.log
|
||||
OPENV_DEFAULT_FLAGS += --lconf=$(OPENV_LOG_CONFIG)
|
||||
|
||||
$(OPENV_LOG_CONFIG): $(LAST_MAKEFILEDIR)/logging.conf
|
||||
$(Q)cp $^ $@.tmp
|
||||
$(Q)sed -i 's#LOG_PATH#'"$(BINDIR)"'#g' $@.tmp
|
||||
$(Q)mv $@.tmp $@
|
||||
|
||||
# Start tun interface
|
||||
ifneq (,$(filter openv-termtun,$(MAKECMDGOALS)))
|
||||
OPENV_DEFAULT_FLAGS += --opentun
|
||||
endif
|
||||
|
||||
# Optional flags to pass through command line
|
||||
OPENV_FLAGS ?=
|
||||
|
||||
openv-term: $(OPENV_LOG_CONFIG)
|
||||
openv-term: $(TERMDEPS)
|
||||
$(Q)$(OPENV_SERVER_PATH) $(OPENV_DEFAULT_FLAGS) $(OPENV_FLAGS)
|
||||
|
||||
openv-termroot: $(OPENV_LOG_CONFIG)
|
||||
openv-termroot: $(TERMDEPS)
|
||||
$(Q)$(OPENV_SERVER_PATH) $(OPENV_DEFAULT_FLAGS) $(OPENV_FLAGS) --root=$(OPENV_MOTE)
|
||||
|
||||
openv-termtun: $(OPENV_LOG_CONFIG)
|
||||
openv-termtun: $(TERMDEPS)
|
||||
sudo $(OPENV_SERVER_PATH) $(OPENV_DEFAULT_FLAGS) $(OPENV_FLAGS) --root=$(OPENV_MOTE)
|
||||
|
||||
openv-setroot:
|
||||
$(Q)$(OPENV_CLIENT_PATH) $(OPENV_OPENWSN_FW_PATH) $(OPENV_FLAGS) root=$(OPENV_MOTE)
|
||||
|
||||
openv-clean:
|
||||
$(Q)rm -rf $(OPENV_LOG_CONFIG)
|
||||
$(Q)rm -rf $(OPENV_LOG_FILE)
|
||||
|
||||
openv-serial:
|
||||
$(Q)$(OPENV_SERIAL_PATH) --port=$(PORT) --baudrate=$(BAUD)
|
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");
|
||||
|
@ -42,6 +42,10 @@ extern "C" {
|
||||
*/
|
||||
#define CCM_BLOCK_SIZE 16
|
||||
|
||||
/**
|
||||
* @brief Maximum length for the appended MAC
|
||||
*/
|
||||
#define CCM_MAC_MAX_LEN 16
|
||||
|
||||
/**
|
||||
* @brief Encrypt and authenticate data of arbitrary length in ccm mode.
|
||||
|
@ -96,6 +96,7 @@ extern "C" {
|
||||
|
||||
#define IEEE802154_FRAME_LEN_MAX (127U) /**< maximum 802.15.4 frame length */
|
||||
#define IEEE802154G_FRAME_LEN_MAX (2047U) /**< maximum 802.15.4g-2012 frame length */
|
||||
#define IEEE802154_ACK_FRAME_LEN (5U) /**< ACK frame length */
|
||||
|
||||
/**
|
||||
* For the SUN PHYs, the value is 1 ms expressed in symbol periods, rounded
|
||||
|
67
tests/pkg_openwsn/Makefile
Normal file
67
tests/pkg_openwsn/Makefile
Normal file
@ -0,0 +1,67 @@
|
||||
BOARD ?= iotlab-m3
|
||||
|
||||
include ../Makefile.tests_common
|
||||
|
||||
# list of arm boards that provide at86rf2xx radios, can't require it so
|
||||
# add whitelist
|
||||
BOARD_WHITELIST = \
|
||||
fox \
|
||||
iotlab-m3 \
|
||||
iotlab-a8-m3 \
|
||||
samr21-xpro \
|
||||
samr30-xpro \
|
||||
#
|
||||
|
||||
## OpenWSN Modules
|
||||
USEPKG += openwsn
|
||||
USEMODULE += openwsn_openstack
|
||||
USEMODULE += openwsn_scheduler
|
||||
|
||||
# Optional Module required for root nodes
|
||||
# USEMODULE += openwsn_serial
|
||||
|
||||
# Optional Modules
|
||||
USEMODULE += openwsn_leds
|
||||
USEMODULE += openwsn_debugpins
|
||||
|
||||
ifneq (,$(filter openwsn_serial,$(USEMODULE)))
|
||||
# Uncomment to use STDIO_UART_DEV as the uart for OpenWSN openserial
|
||||
# USEMODULE += stdio_null
|
||||
ifneq (,$(filter iotlab-m3 iotlab-a8-m3,$(BOARD)))
|
||||
USEMODULE += stdio_null
|
||||
endif
|
||||
# OpenWSN serial module can't handle data at more than 115200 bauds/s,
|
||||
# depending on the platform this might be even lower (e.g. 57600 bauds
|
||||
# for iotlab-m3, 19200 for samr21-xpro).
|
||||
# NOTE: baudrate can'y be changed when testing over IotLab.
|
||||
OPENSERIAL_BAUD ?=
|
||||
ifneq (,$(OPENSERIAL_BAUD))
|
||||
CFLAGS += -DOPENWSN_UART_BAUDRATE=$(OPENSERIAL_BAUD)
|
||||
ifneq (,$(filter stdio_null,$(USEMODULE)))
|
||||
BAUD ?= $(OPENSERIAL_BAUD)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# To enable debugging prints on OpenWSN code
|
||||
# export OPENWSN_LOG_LEVEL ?= LOG_ERROR
|
||||
|
||||
## Test application Modules
|
||||
USEMODULE += ipv6_addr
|
||||
USEMODULE += ps
|
||||
USEMODULE += od_string
|
||||
USEMODULE += shell
|
||||
USEMODULE += shell_commands
|
||||
# ztimer is used instead of xtimer because it's a dependency of some
|
||||
# OpenWSN modules.
|
||||
USEMODULE += ztimer_usec
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
||||
|
||||
# We want the highest possible frequency set for periph_rtt, but not all
|
||||
# platforms can configure this value. use highest possible RTT_FREQUENCY
|
||||
# for platforms that allow it
|
||||
ifneq (,$(filter stm32,$(CPU)))
|
||||
RTT_FREQUENCY ?= RTT_MAX_FREQUENCY
|
||||
CFLAGS += -DRTT_FREQUENCY=$(RTT_FREQUENCY)
|
||||
endif
|
316
tests/pkg_openwsn/README.md
Normal file
316
tests/pkg_openwsn/README.md
Normal file
@ -0,0 +1,316 @@
|
||||
# OpenWSN on RIOT
|
||||
|
||||
This test demonstrates the [OpenWSN](https://github.com/openwsn-berkeley/openwsn-fw) full
|
||||
stack (UDP, IPv6, RPL, 6TiSCH) running on RIOT. When flashed, it will initialize the stack
|
||||
and provide the user with some minimal shell commands to:
|
||||
|
||||
- print the own IPv6 address `ifconfig`
|
||||
- change the UDP destination port `udp server start <port>`
|
||||
- send a UDP packet `udp send <addr> <port> <data>`
|
||||
|
||||
A tun interface can also be set to allow traffic out of the network. This
|
||||
allows pinging nodes in the network from the host.
|
||||
|
||||
Please note that this port is still in experimental status. For further information
|
||||
about the port refer to the [pkg documentation](../../pkg/openwsn/doc.txt).
|
||||
|
||||
## Experimental setups
|
||||
|
||||
The following setup act as a starting point for testing and debugging. Either
|
||||
build and flash local nodes or incorporate the [FIT IoT-LAB](https://www.iot-lab.info/)
|
||||
Testbed. Please check the ports [documentation](../../pkg/openwsn/doc.txt) for information
|
||||
about supported hardware platforms.
|
||||
|
||||
This port currently needs `openvisualizer`, please make sure you follow the
|
||||
[pre-requisites](../../dist/tools/openvisualizer/makefile.openvisualizer.inc.mk)
|
||||
to install a patched version of `openvisualizer`.
|
||||
|
||||
An OpenWSN root node acts as a border router, it tunnels IEEE80215.4.E
|
||||
between `openvisualizer` and the network without looking at the frame content.
|
||||
This means that a root node will not be reachable when 'pinging' from the host
|
||||
or if trying to send udp packets to it.
|
||||
|
||||
Two test cases are described with different requirements:
|
||||
|
||||
1. From host [ping](#Communicating-with-host-(IPV6)) nodes in network over ipv6:
|
||||
```
|
||||
- 1 root node + tun interface
|
||||
- +1 leaf node
|
||||
```
|
||||
|
||||
2. Sending [UDP](#Communicating-over-udp) packets between nodes:
|
||||
```
|
||||
- 1 root node
|
||||
- +2 leaf node
|
||||
```
|
||||
|
||||
### Synchronization
|
||||
|
||||
There are 3 things that can be done to speed up and help nodes synchronization,
|
||||
all related to how often a node will receive an EB (enhanced beacon).
|
||||
|
||||
- disable channel hopping
|
||||
- increase EB_PORTION
|
||||
- reduce SLOTFRAME_LENGTH
|
||||
|
||||
If you want to disable channel hopping to speed up synchronization you can set
|
||||
a fix channel.
|
||||
|
||||
$ export CFLAGS=-DIEEE802154E_SINGLE_CHANNEL=17
|
||||
|
||||
Enhanced beacon are sent once per slotframe with a likelihood of 1/EB_PORTION.
|
||||
The default value is EB_PORTION = 10 (10%), reducing the value of EB_PORTION
|
||||
increases the frequency at which beacons are sent, this will also help nodes
|
||||
to stay synchronized.
|
||||
|
||||
$ export CFLAGS=-DEB_PORTION=4
|
||||
|
||||
EB gets an opportunity to be sent (depending on 1/EB_PORTION) once in every
|
||||
slotframe, reducing the soltframe length will cause EB to be sent more often.
|
||||
Beware that this could have an impact on the MSF (Minimal Scheduling Function).
|
||||
|
||||
$ export CFLAGS=-DSLOTFRAME_LENGTH=51
|
||||
|
||||
See [documentation](../../pkg/openwsn/doc.txt#Synchronization) for more on
|
||||
synchronization.
|
||||
|
||||
## IMPORTANT!
|
||||
|
||||
OpenWSN uses source routing and this means all network traffic must go through
|
||||
from the root node to OpenVisualizer. If the root node configuration can't
|
||||
handle the configured baudrate correctly this will lead to packet loss.
|
||||
|
||||
Currently these are the tested configurations:
|
||||
|
||||
(a) samr21-xpro network:
|
||||
- leaf nodes using `openwsn_sctimer_rtt`
|
||||
- root node using `openwsn_sctimer_rtt` and 19200 baudrate directly
|
||||
connected to UART pins (not through the usb debugger)
|
||||
|
||||
(b) iotlab-m3 network:
|
||||
- leaf nodes using `openwsn_sctimer_rtt` or `sctimer_ztimer`
|
||||
- root node using `openwsn_sctimer_rtt` and 57600 baudrate
|
||||
|
||||
For more details on this please refer to [pkg documentation](../../pkg/openwsn/doc.txt).
|
||||
|
||||
## Testing configuration (a) (three local samr21-xpro nodes)
|
||||
|
||||
1. figure out each node's serial number (`edbg -l` output might help)
|
||||
2. hook up the root node to an external USB-serial-converter. For that, connect
|
||||
the converter's RXD/TXD pins to the node's PA22/PA23.
|
||||
3. flash the root node:
|
||||
|
||||
$ SERIAL=${ROOT_SERIAL_NODE} OPENSERIAL_BAUD=19200 USEMODULE=openwsn_serial \
|
||||
BOARD=samr21-xpro make flash -j4
|
||||
|
||||
4. flash the leaf nodes:
|
||||
|
||||
$ BOARD=samr21-xpro make all -j4
|
||||
$ BOARD=samr21-xpro SERIAL=${LEAF_SERIAL_NODE0} make flash-only
|
||||
$ BOARD=samr21-xpro SERIAL=${LEAF_SERIAL_NODE1} make flash-only
|
||||
|
||||
5. open a shell to the leaf nodes
|
||||
so in two shell windows, do (one in each):
|
||||
|
||||
$ BOARD=samr21-xpro SERIAL=${LEAF_SERIAL_NODE0} make term
|
||||
$ BOARD=samr21-xpro SERIAL=${LEAF_SERIAL_NODE1} make term
|
||||
|
||||
6. in a third shell, launch openvisualizer:
|
||||
|
||||
$ BOARD=samr21-xpro PORT=<USB-serial-port, e.g., /dev/ttyUSB0> BAUD=19200 \
|
||||
make openv-termroot
|
||||
|
||||
## Testing configuration (b) (iotlab-m3 network on iotlab)
|
||||
|
||||
When using OpenVisualizer over iot-lab an ssh-tunnel is opened to connect to the
|
||||
IoT-LAB motes' TCP port. For this to work you will need:
|
||||
|
||||
- A valid IoT-LAB [account](https://www.iot-lab.info/testbed/signup)
|
||||
- Authenticate locally to IoT-LAB `$ iotlab-auth -u <login>`
|
||||
|
||||
1. Launch an experiment booking 3+ `iotlab-m3` nodes:
|
||||
|
||||
$ iotlab-experiment submit -d 120 -l 3,archi=m3:at86rf231+site=saclay
|
||||
$ iotlab-experiment wait
|
||||
$ iotlab-experiment get --nodes
|
||||
|
||||
Since multiple nodes where configured for the experiment `IOTLAB_NODE` needs
|
||||
to be specified for every node, `IOTLAB_NODE=m3-%.saclay.iot-lab.info`
|
||||
|
||||
2. flash the root node
|
||||
|
||||
$ IOTLAB_NODE=${ROOT_IOTLAB_NODE} USEMODULE=openwsn_serial \
|
||||
BOARD=iotlab-m3 make -C tests/pkg_openwsn flash
|
||||
|
||||
3. open a shell to the leaf nodes so in two shell windows, do (one in each):
|
||||
$ BOARD=iotlab-m3 make -C tests/pkg_openwsn all -j4
|
||||
$ BOARD=iotlab-m3 IOTLAB_NODE=${LEAF_IOTLAB_NODE0} make -C tests/pkg_openwsn flash-only
|
||||
$ BOARD=iotlab-m3 IOTLAB_NODE=${LEAF_IOTLAB_NODE1} make -C tests/pkg_openwsn flash-only
|
||||
|
||||
4. open a shell to the leaf nodes
|
||||
so in two shell windows, do (one in each):
|
||||
|
||||
$ BOARD=iotlab-m3 IOTLAB_NODE=${LEAF_IOTLAB_NODE0} make -C tests/pkg_openwsn term
|
||||
$ BOARD=iotlab-m3 IOTLAB_NODE=${LEAF_IOTLAB_NODE1} make -C tests/pkg_openwsn term
|
||||
|
||||
5. in a third shell, launch openvisualizer:
|
||||
|
||||
$ BOARD=iotlab-m3 IOTLAB_NODE=${ROOT_IOTLAB_NODE} make -C tests/pkg_openwsn openv-termroot
|
||||
|
||||
### Network Setup
|
||||
|
||||
If (a) and (b) where followed then on each lead node you should be able
|
||||
to see the ipv6 address:
|
||||
|
||||
main(): This is RIOT! (Version: 2020.04-devel-1649-g96fa9-pr_openwsn)
|
||||
OpenWSN UDP test
|
||||
You are running RIOT on a(n) iotlab-m3 board.
|
||||
This board features a(n) stm32f1 MCU.
|
||||
> ifconfig
|
||||
ifconfig
|
||||
Iface 3 HWaddr: 07:C2 NID: CA:FE
|
||||
|
||||
Long HWaddr: 96:35:9A:92:4E:3D:65:78
|
||||
inet6 addr: fe80::9635:9a92:4e3d:6578
|
||||
|
||||
IEEE802154E sync: 0
|
||||
6TiSCH joined: 0
|
||||
|
||||
NO RPL parent
|
||||
|
||||
|
||||
On the root node Openvisualizer is launched and the DAGroot is setup.
|
||||
|
||||
[OpenVisualizerServer:INFO] Extracting firmware definitions.
|
||||
[Utils:VERBOSE] Extracting firmware component names
|
||||
[Utils:VERBOSE] Extracting firmware log descriptions.
|
||||
[Utils:VERBOSE] Extracting 6top return codes.
|
||||
[Utils:VERBOSE] Extracting 6top states.
|
||||
[OpenVisualizerServer:INFO] Starting RPC server
|
||||
[OpenVisualizerServer:SUCCESS] Setting mote 43eb as root
|
||||
[ParserIEC:ERROR] 43eb [IEEE802154E] wrong state 1 in startSlot, at slotOffset 1
|
||||
[RPL:INFO] registering DAGroot 82-6b-de-ec-58-34-65-78
|
||||
|
||||
The root node will now start sending beacons and other nodes will synchronize, and
|
||||
join. If channel hopping is enabled this can take quite some time (see
|
||||
[Synchronization](../../pkg/openwsn/doc.txt#Synchronization). Once leaf nodes
|
||||
have joined the network when issuing `ifconfing` you should see:
|
||||
|
||||
ifconfig
|
||||
Iface 3 HWaddr: 0F:F4 NID: CA:FE
|
||||
|
||||
Long HWaddr: 06:84:F6:65:10:6B:11:14
|
||||
inet6 addr: bbbb::684:f665:106b:1114
|
||||
|
||||
IEEE802154E sync: 1
|
||||
6TiSCH joined: 1
|
||||
|
||||
RPL rank: 2816
|
||||
RPL parent: 2A:BA:F7:65:10:6B:11:14
|
||||
RPL children:
|
||||
RPL DODAG ID: bbbb::2aba:f765:106b:1114
|
||||
|
||||
|
||||
The root node should start receiving RPL DAOs:
|
||||
|
||||
[RPL:INFO] received RPL DAO from bbbb:0:0:0:ab8:fc65:106b:1114
|
||||
- parents:
|
||||
bbbb:0:0:0:2aba:f765:106b:1114
|
||||
- children:
|
||||
bbbb:0:0:0:684:f665:106b:1114
|
||||
|
||||
[RPL:INFO] received RPL DAO from bbbb:0:0:0:684:f665:106b:1114
|
||||
- parents:
|
||||
bbbb:0:0:0:2aba:f765:106b:1114
|
||||
- children:
|
||||
bbbb:0:0:0:ab8:fc65:106b:1114
|
||||
|
||||
[RPL:INFO] received RPL DAO from bbbb:0:0:0:684:f665:106b:1114
|
||||
- parents:
|
||||
bbbb:0:0:0:2aba:f765:106b:1114
|
||||
- children:
|
||||
bbbb:0:0:0:ab8:fc65:106b:1114
|
||||
|
||||
Once DAOs for all nodes start being received the network is setup and you
|
||||
should be able to send packets between nodes or ping from the host.
|
||||
|
||||
### Communicating over udp
|
||||
|
||||
On one node setup a udp-server:
|
||||
|
||||
> ifconfig
|
||||
ifconfig
|
||||
Iface 3 HWaddr: 0F:F4 NID: CA:FE
|
||||
|
||||
Long HWaddr: 06:84:F6:65:10:6B:11:14
|
||||
inet6 addr: bbbb::684:f665:106b:1114
|
||||
|
||||
IEEE802154E sync: 1
|
||||
6TiSCH joined: 1
|
||||
|
||||
RPL rank: 2816
|
||||
RPL parent: 2A:BA:F7:65:10:6B:11:14
|
||||
RPL children:
|
||||
RPL DODAG ID: bbbb::2aba:f765:106b:1114
|
||||
> udp server start 3000
|
||||
udp server start 3000
|
||||
Set UDP server port to 3000
|
||||
|
||||
On the other node send udp messages
|
||||
|
||||
> udp send bbbb::684:f665:106b:1114 3000 hello
|
||||
udp send bbbb::684:f665:106b:1114 3000 hello
|
||||
Send 5 byte over UDP to [bbbb::684:f665:106b:1114]:3000
|
||||
> msg.l2_sendDoneError: 0
|
||||
Send success
|
||||
|
||||
The first node should receive the message
|
||||
|
||||
> Received 12 bytes on port 3000
|
||||
00000000 A6 28 00 00 00 02 00 68 65 6C 6C 6F .(.....hello
|
||||
|
||||
### Communicating with host (IPV6)
|
||||
|
||||
OpenVisualizer can set up a tun interface to communicate with the host computer.
|
||||
This will require starting `OpenVisualizer` with root privileges. The only
|
||||
difference with the previous setup is that the root node must be setup as
|
||||
follows:
|
||||
|
||||
on iotlab:
|
||||
$ IOTLAB_NODE=${ROOT_IOTLAB_NODE} BOARD=iotlab-m3 \
|
||||
make -C tests/pkg_openwsn openv-termtun
|
||||
|
||||
on local boards:
|
||||
$ PORT=<USB-serial-port, e.g., /dev/ttyUSB0> BOARD=samr21-xpro \
|
||||
make -C tests/pkg_openwsn openv-termtun
|
||||
|
||||
Once DAOs are received you can ping nodes in the network from your host:
|
||||
|
||||
```
|
||||
$ ping6 -s 40 -i 5 bbbb:0:0:0:2ab5:fc65:106b:1114
|
||||
PING bbbb:0:0:0:2ab5:fc65:106b:1114(bbbb::2ab5:fc65:106b:1114) 40 data bytes
|
||||
48 bytes from bbbb::2ab5:fc65:106b:1114: icmp_seq=1 ttl=64 time=1064 ms
|
||||
48 bytes from bbbb::2ab5:fc65:106b:1114: icmp_seq=2 ttl=64 time=2111 ms
|
||||
48 bytes from bbbb::2ab5:fc65:106b:1114: icmp_seq=3 ttl=64 time=1141 ms
|
||||
48 bytes from bbbb::2ab5:fc65:106b:1114: icmp_seq=4 ttl=64 time=2197 ms
|
||||
48 bytes from bbbb::2ab5:fc65:106b:1114: icmp_seq=5 ttl=64 time=1228 ms
|
||||
48 bytes from bbbb::2ab5:fc65:106b:1114: icmp_seq=6 ttl=64 time=2306 ms
|
||||
48 bytes from bbbb::2ab5:fc65:106b:1114: icmp_seq=7 ttl=64 time=1324 ms
|
||||
|
||||
```
|
||||
|
||||
If openserial is used on the leaf node you would get the following output:
|
||||
|
||||
```
|
||||
16:02:38 [ParserIEC:INFO] 768f [ICMPv6ECHO] received an echo request
|
||||
16:02:44 [ParserIEC:INFO] 768f [ICMPv6ECHO] received an echo request
|
||||
16:02:48 [ParserIEC:INFO] 768f [ICMPv6ECHO] received an echo request
|
||||
16:02:54 [ParserIEC:INFO] 768f [ICMPv6ECHO] received an echo request
|
||||
```
|
||||
|
||||
Some considerations:
|
||||
- Nodes duty cycle is ~0.5%, so nodes get a chance to transmit roughly every
|
||||
2s, so the worst case scenario is ~4s RTT. This is increased for big payloads
|
||||
since it will lead to fragmentation.
|
||||
- If incoming packet rate is too fast the internal packet queue can be
|
||||
be overloaded.
|
324
tests/pkg_openwsn/main.c
Normal file
324
tests/pkg_openwsn/main.c
Normal file
@ -0,0 +1,324 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Hamburg University of Applied Sciences
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief OpenWSN test application
|
||||
*
|
||||
* @author Peter Kietzmann <peter.kietzmann@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "od.h"
|
||||
#include "fmt.h"
|
||||
#include "shell.h"
|
||||
#include "openwsn.h"
|
||||
#include "net/ipv6/addr.h"
|
||||
|
||||
#include "opendefs.h"
|
||||
#include "scheduler.h"
|
||||
#include "02a-MAClow/IEEE802154E.h"
|
||||
#include "02b-MAChigh/neighbors.h"
|
||||
#include "03b-IPv6/icmpv6rpl.h"
|
||||
#include "04-TRAN/openudp.h"
|
||||
#include "cjoin.h"
|
||||
#include "cross-layers/openqueue.h"
|
||||
#include "cross-layers/idmanager.h"
|
||||
#include "cross-layers/packetfunctions.h"
|
||||
|
||||
extern idmanager_vars_t idmanager_vars;
|
||||
extern icmpv6rpl_vars_t icmpv6rpl_vars;
|
||||
extern neighbors_vars_t neighbors_vars;
|
||||
extern openqueue_vars_t openqueue_vars;
|
||||
extern schedule_vars_t schedule_vars;
|
||||
extern scheduler_dbg_t scheduler_dbg;
|
||||
|
||||
udp_resource_desc_t uinject_vars;
|
||||
char addr_str[IPV6_ADDR_MAX_STR_LEN];
|
||||
|
||||
void uinject_sendDone(OpenQueueEntry_t *msg, owerror_t error)
|
||||
{
|
||||
(void)error;
|
||||
|
||||
printf("msg.l2_sendDoneError: %x\n", msg->l2_sendDoneError);
|
||||
openqueue_freePacketBuffer(msg);
|
||||
puts("Send success");
|
||||
}
|
||||
|
||||
void uinject_receive(OpenQueueEntry_t *pkt)
|
||||
{
|
||||
printf("Received %i bytes on port %i\n", (int)pkt->length,
|
||||
pkt->l4_destination_port);
|
||||
od_hex_dump(pkt->payload, pkt->length, OD_WIDTH_DEFAULT);
|
||||
openqueue_freePacketBuffer(pkt);
|
||||
}
|
||||
|
||||
void uinject_init(void)
|
||||
{
|
||||
uinject_vars.port = WKP_UDP_INJECT;
|
||||
uinject_vars.callbackReceive = &uinject_receive;
|
||||
uinject_vars.callbackSendDone = &uinject_sendDone;
|
||||
openudp_register(&uinject_vars);
|
||||
}
|
||||
|
||||
char *_array_2_string(const uint8_t *addr, size_t addr_len, char *out)
|
||||
{
|
||||
char *res = out;
|
||||
|
||||
assert((out != NULL) && ((addr != NULL) || (addr_len == 0U)));
|
||||
out[0] = '\0';
|
||||
for (size_t i = 0; i < addr_len; i++) {
|
||||
out += fmt_byte_hex((out), *(addr++));
|
||||
*(out++) = (i == (addr_len - 1)) ? '\0' : ':';
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static int ifconfig_cmd(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
open_addr_t *hwaddr;
|
||||
open_addr_t temp_my128bID;
|
||||
|
||||
memcpy(&temp_my128bID.addr_128b[0], &idmanager_vars.myPrefix.prefix, 8);
|
||||
memcpy(&temp_my128bID.addr_128b[8], &idmanager_vars.my64bID.addr_64b, 8);
|
||||
|
||||
printf("Iface %d ", openwsn_get_pid());
|
||||
hwaddr = idmanager_getMyID(ADDR_16B);
|
||||
printf("\tHWaddr: %s ", _array_2_string(hwaddr->addr_16b, 2, addr_str));
|
||||
hwaddr = idmanager_getMyID(ADDR_PANID);
|
||||
printf("NID: %s\n", _array_2_string(hwaddr->panid, 2, addr_str));
|
||||
printf("\n");
|
||||
|
||||
hwaddr = idmanager_getMyID(ADDR_64B);
|
||||
printf("\t\tLong HWaddr: %s\n", _array_2_string(hwaddr->addr_64b, 8, addr_str));
|
||||
|
||||
ipv6_addr_to_str(addr_str, (ipv6_addr_t *)temp_my128bID.addr_128b,
|
||||
sizeof(addr_str));
|
||||
printf("\t\tinet6 addr: %s\n", addr_str);
|
||||
printf("\n");
|
||||
|
||||
|
||||
printf("\t\tIEEE802154E sync: %i\n", ieee154e_isSynch());
|
||||
printf("\t\t6TiSCH joined: %i\n", cjoin_getIsJoined());
|
||||
printf("\n");
|
||||
|
||||
if (idmanager_vars.isDAGroot) {
|
||||
puts("\t\tNode is DAG root");
|
||||
}
|
||||
else {
|
||||
if (icmpv6rpl_vars.haveParent) {
|
||||
printf("\t\tRPL rank: %i\n", icmpv6rpl_vars.myDAGrank);
|
||||
printf("\t\tRPL parent: %s\n", \
|
||||
_array_2_string(neighbors_vars.neighbors[icmpv6rpl_vars.
|
||||
ParentIndex].
|
||||
addr_64b.addr_64b, 8, addr_str));
|
||||
printf("\t\tRPL children:\n");
|
||||
for (uint8_t i = 0; i < MAXNUMNEIGHBORS; i++) {
|
||||
if ((neighbors_isNeighborWithHigherDAGrank(i)) == true) {
|
||||
printf("\t\t\t%s\n", \
|
||||
_array_2_string(neighbors_vars.neighbors[i].
|
||||
addr_64b.addr_64b, 8, addr_str));
|
||||
}
|
||||
}
|
||||
ipv6_addr_to_str(addr_str,
|
||||
(ipv6_addr_t *)icmpv6rpl_vars.dao.DODAGID,
|
||||
sizeof(addr_str));
|
||||
printf("\t\tRPL DODAG ID: %16s\n", addr_str);
|
||||
}
|
||||
else {
|
||||
puts("\t\tNO RPL parent");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nc_cmd(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
for (int i = 0; i < MAXNUMNEIGHBORS; i++) {
|
||||
_array_2_string(neighbors_vars.neighbors[i].addr_64b.addr_64b, 8,
|
||||
addr_str);
|
||||
if (memcmp(addr_str, "00:00:00:00:00:00:00:00", 8) != 0) {
|
||||
printf("%02i. %s\n", i, addr_str);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct {
|
||||
char *name;
|
||||
int id;
|
||||
} names[] = {
|
||||
{ "?", COMPONENT_NULL },
|
||||
{ "owsn", COMPONENT_OPENWSN },
|
||||
{ "idmanager", COMPONENT_IDMANAGER },
|
||||
{ "oqueue", COMPONENT_OPENQUEUE },
|
||||
{ "oserial", COMPONENT_OPENSERIAL },
|
||||
{ "pktfuncs", COMPONENT_PACKETFUNCTIONS },
|
||||
{ "random", COMPONENT_RANDOM },
|
||||
{ "radio", COMPONENT_RADIO },
|
||||
{ "154", COMPONENT_IEEE802154 },
|
||||
{ "154e", COMPONENT_IEEE802154E },
|
||||
{ "6top2154e", COMPONENT_SIXTOP_TO_IEEE802154E },
|
||||
{ "154e26top", COMPONENT_IEEE802154E_TO_SIXTOP },
|
||||
{ "6top", COMPONENT_SIXTOP },
|
||||
{ "neigh", COMPONENT_NEIGHBORS },
|
||||
{ "sched", COMPONENT_SCHEDULE },
|
||||
{ "6topres", COMPONENT_SIXTOP_RES },
|
||||
{ "bridge", COMPONENT_OPENBRIDGE },
|
||||
{ "iphc", COMPONENT_IPHC },
|
||||
{ "frag", COMPONENT_FRAG },
|
||||
{ "fwd", COMPONENT_FORWARDING },
|
||||
{ "icmpv6", COMPONENT_ICMPv6 },
|
||||
{ "icmpv6ech", COMPONENT_ICMPv6ECHO },
|
||||
{ "icmpv6rtr", COMPONENT_ICMPv6ROUTER },
|
||||
{ "icmpv6rpl", COMPONENT_ICMPv6RPL },
|
||||
{ "udp", COMPONENT_OPENUDP },
|
||||
{ "coap", COMPONENT_OPENCOAP },
|
||||
{ "cjoin", COMPONENT_CJOIN },
|
||||
{ "openoscoap", COMPONENT_OPENOSCOAP },
|
||||
{ "c6t", COMPONENT_C6T },
|
||||
{ "uinject", COMPONENT_UINJECT },
|
||||
};
|
||||
|
||||
char *_get_name(int id)
|
||||
{
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(names); i++) {
|
||||
if (id == names[i].id) {
|
||||
return names[i].name;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int q_cmd(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
bool queue = 1;
|
||||
|
||||
for (uint8_t i = 0; i < QUEUELENGTH; i++) {
|
||||
if (openqueue_vars.queue[i].creator || openqueue_vars.queue[i].owner) {
|
||||
queue = 0;
|
||||
uint8_t creator = openqueue_vars.queue[i].creator;
|
||||
uint8_t owner = openqueue_vars.queue[i].owner;
|
||||
printf("Creator: %.9s [%d], ", _get_name(creator), creator);
|
||||
printf("Owner: %.9s [%d]\n", _get_name(owner), owner);
|
||||
}
|
||||
}
|
||||
if (queue) {
|
||||
puts("openqueue empty");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int q_rmv(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2) {
|
||||
printf("usage: %s [creator]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t creator = atoi(argv[1]);
|
||||
if (creator == 0) {
|
||||
printf("error: invalid input value\n");
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
printf("Removing entries created by: %.9s [%d]\n", _get_name(creator), creator);
|
||||
openqueue_removeAllCreatedBy(creator);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int as_cmd(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
for (int i = 0; i < MAXACTIVESLOTS; i++) {
|
||||
switch (schedule_vars.scheduleBuf[i].type) {
|
||||
case CELLTYPE_TX:
|
||||
printf("neigh: %s, slot: %03i, chan: %02i, type: TX\n", \
|
||||
_array_2_string(
|
||||
schedule_vars.scheduleBuf[i].neighbor.addr_64b,
|
||||
8, addr_str),
|
||||
schedule_vars.scheduleBuf[i].slotOffset, \
|
||||
schedule_vars.scheduleBuf[i].channelOffset);
|
||||
break;
|
||||
case CELLTYPE_RX:
|
||||
printf("slot: %03i, chan: %02i, type: RX\n", \
|
||||
schedule_vars.scheduleBuf[i].slotOffset, \
|
||||
schedule_vars.scheduleBuf[i].channelOffset);
|
||||
break;
|
||||
case CELLTYPE_TXRX:
|
||||
printf("neigh: %s, slot: %03i, chan: %02i, type: RXTX\n", \
|
||||
_array_2_string(
|
||||
schedule_vars.scheduleBuf[i].neighbor.addr_64b,
|
||||
8, addr_str),
|
||||
schedule_vars.scheduleBuf[i].slotOffset, \
|
||||
schedule_vars.scheduleBuf[i].channelOffset);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sc_cmd(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
/* TODO allow other prefixes via shell ?!? */
|
||||
printf("Current tasks:%i\n", scheduler_dbg.numTasksCur);
|
||||
printf("Max tasks: %i\n", scheduler_dbg.numTasksMax);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern int udp_cmd(int argc, char **argv);
|
||||
|
||||
static const shell_command_t shell_commands[] = {
|
||||
{ "ifconfig", "Shows assigned IPv6 addresses", ifconfig_cmd },
|
||||
{ "nc", "Shows neighbor table", nc_cmd },
|
||||
{ "q", "Shows Openqueue", q_cmd },
|
||||
{ "q-rmv", "Remove entries from creator in queue", q_rmv },
|
||||
{ "as", "Shows active cells", as_cmd },
|
||||
{ "sc", "Shows scheduler (openos) dbg states", sc_cmd },
|
||||
{ "udp", "Send data over UDP and listen on UDP ports", udp_cmd },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
puts("OpenWSN UDP test");
|
||||
|
||||
printf("You are running RIOT on a(n) %s board.\n", RIOT_BOARD);
|
||||
printf("This board features a(n) %s MCU.\n", RIOT_MCU);
|
||||
|
||||
uinject_init();
|
||||
|
||||
char line_buf[SHELL_DEFAULT_BUFSIZE];
|
||||
shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE);
|
||||
}
|
195
tests/pkg_openwsn/udp.c
Normal file
195
tests/pkg_openwsn/udp.c
Normal file
@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Freie Universität Berlin
|
||||
* Copyright (C) 2018 Hamburg University of Applied Sciences
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup tests
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
*
|
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
* @author Peter Kietzmann <peter.kietzmann@haw-hamburg.de>
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "ztimer.h"
|
||||
#include "net/ipv6.h"
|
||||
|
||||
#include "opendefs.h"
|
||||
#include "scheduler.h"
|
||||
#include "02a-MAClow/IEEE802154E.h"
|
||||
#include "03b-IPv6/icmpv6rpl.h"
|
||||
#include "04-TRAN/openudp.h"
|
||||
#include "cross-layers/openqueue.h"
|
||||
#include "cross-layers/idmanager.h"
|
||||
#include "cross-layers/packetfunctions.h"
|
||||
|
||||
extern udp_resource_desc_t uinject_vars;
|
||||
extern idmanager_vars_t idmanager_vars;
|
||||
extern openudp_vars_t openudp_vars;
|
||||
|
||||
static uint16_t counter = 0;
|
||||
|
||||
OpenQueueEntry_t *pkt;
|
||||
|
||||
void push_pkt_cb(void){
|
||||
owerror_t ret = openudp_send(pkt);
|
||||
if (ret == E_FAIL) {
|
||||
puts("could not send");
|
||||
openqueue_freePacketBuffer(pkt);
|
||||
}
|
||||
}
|
||||
|
||||
static int udp_send(char *addr_str, char *port_str, char *data,
|
||||
unsigned int num, unsigned int delay)
|
||||
{
|
||||
size_t data_len;
|
||||
open_addr_t parentNeighbor;
|
||||
ipv6_addr_t addr;
|
||||
|
||||
data_len = strlen(data);
|
||||
uint8_t asnArray[data_len];
|
||||
|
||||
/* parse destination address */
|
||||
if (ipv6_addr_from_str(&addr, addr_str) == NULL) {
|
||||
puts("Error: unable to parse destination address, exit");
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < num; i++) {
|
||||
|
||||
printf("Send %u byte over UDP to [%s]:%s\n",
|
||||
(unsigned)data_len, addr_str, port_str);
|
||||
|
||||
/* don't run if not in synch */
|
||||
if (ieee154e_isSynch() == FALSE) {
|
||||
puts("Error: Node not in sync, exit");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* don't run on dagroot */
|
||||
if (idmanager_getIsDAGroot()) {
|
||||
puts("Error: Node is DAGROOT, exit");
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool foundNeighbor = icmpv6rpl_getPreferredParentEui64(&parentNeighbor);
|
||||
if (foundNeighbor==FALSE) {
|
||||
puts("Error: No preferred parent EUI64, exit");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* get a free packet buffer */
|
||||
pkt = openqueue_getFreePacketBuffer(COMPONENT_UINJECT);
|
||||
if (pkt == NULL) {
|
||||
puts("Error: could not create packet buffer, exit");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pkt->owner = COMPONENT_UINJECT;
|
||||
pkt->creator = COMPONENT_UINJECT;
|
||||
pkt->l4_protocol = IANA_UDP;
|
||||
pkt->l4_destination_port = atoi(port_str);
|
||||
pkt->l4_sourcePortORicmpv6Type = uinject_vars.port;
|
||||
pkt->l3_destinationAdd.type = ADDR_128B;
|
||||
memcpy(&pkt->l3_destinationAdd.addr_128b[0], (void *)&addr, 16);
|
||||
/* add payload */
|
||||
packetfunctions_reserveHeaderSize(pkt, data_len);
|
||||
memcpy(&pkt->payload[0], data, data_len);
|
||||
|
||||
packetfunctions_reserveHeaderSize(pkt, sizeof(uint16_t));
|
||||
pkt->payload[1] = (uint8_t)((counter & 0xff00) >> 8);
|
||||
pkt->payload[0] = (uint8_t)(counter & 0x00ff);
|
||||
counter++;
|
||||
|
||||
packetfunctions_reserveHeaderSize(pkt, sizeof(asn_t));
|
||||
ieee154e_getAsn(asnArray);
|
||||
pkt->payload[0] = asnArray[0];
|
||||
pkt->payload[1] = asnArray[1];
|
||||
pkt->payload[2] = asnArray[2];
|
||||
pkt->payload[3] = asnArray[3];
|
||||
pkt->payload[4] = asnArray[4];
|
||||
|
||||
scheduler_push_task(push_pkt_cb, TASKPRIO_COAP);
|
||||
|
||||
ztimer_sleep(ZTIMER_USEC, delay);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int udp_cmd(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2) {
|
||||
printf("usage: %s [send|server]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "send") == 0) {
|
||||
uint32_t num = 1;
|
||||
uint32_t delay = 1000000LU;
|
||||
/* don't send as root */
|
||||
if (idmanager_vars.isDAGroot) {
|
||||
puts("Error: Node is root, exit");
|
||||
return 1;
|
||||
}
|
||||
if (argc < 5) {
|
||||
printf("usage: %s send <addr> <port> <hex data> [<num> [<delay in us>]]\n",
|
||||
argv[0]);
|
||||
return 1;
|
||||
}
|
||||
if (argc > 5) {
|
||||
num = atoi(argv[5]);
|
||||
}
|
||||
if (argc > 6) {
|
||||
delay = atoi(argv[6]);
|
||||
}
|
||||
return udp_send(argv[2], argv[3], argv[4], num, delay);
|
||||
}
|
||||
else if (strcmp(argv[1], "server") == 0) {
|
||||
if (argc < 3) {
|
||||
printf("usage: %s server [start|list]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(argv[2], "start") == 0) {
|
||||
if (argc < 4) {
|
||||
printf("usage %s server start <port>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
uint16_t port = atoi(argv[3]);
|
||||
uinject_vars.port = port;
|
||||
printf("Set UDP server port to %" PRIu16 "\n", port);
|
||||
return 0;
|
||||
}
|
||||
else if (strcmp(argv[2], "list") == 0) {
|
||||
udp_resource_desc_t* resource = openudp_vars.resources;
|
||||
printf("Open UDP Ports: ");
|
||||
while (NULL != resource) {
|
||||
printf("%i ", resource->port);
|
||||
resource = resource->next;
|
||||
}
|
||||
puts("");
|
||||
}
|
||||
else {
|
||||
puts("error: invalid command");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
puts("error: invalid command");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
/** @} */
|
Loading…
Reference in New Issue
Block a user