diff --git a/boards/cc2538dk/Kconfig b/boards/cc2538dk/Kconfig index 47c70726be..0bf24db89f 100644 --- a/boards/cc2538dk/Kconfig +++ b/boards/cc2538dk/Kconfig @@ -13,6 +13,7 @@ config BOARD_CC2538DK select CPU_MODEL_CC2538NF53 select HAS_PERIPH_ADC select HAS_PERIPH_I2C + select HAS_PERIPH_RTT select HAS_PERIPH_SPI select HAS_PERIPH_TIMER select HAS_PERIPH_UART diff --git a/boards/cc2538dk/Makefile.features b/boards/cc2538dk/Makefile.features index 2af2bbc48d..db53ca13e3 100644 --- a/boards/cc2538dk/Makefile.features +++ b/boards/cc2538dk/Makefile.features @@ -4,6 +4,7 @@ CPU_MODEL ?= cc2538nf53 # Put defined MCU peripherals here (in alphabetical order) FEATURES_PROVIDED += periph_adc FEATURES_PROVIDED += periph_i2c +FEATURES_PROVIDED += periph_rtt FEATURES_PROVIDED += periph_spi FEATURES_PROVIDED += periph_timer FEATURES_PROVIDED += periph_uart diff --git a/boards/openmote-b/Makefile.dep b/boards/openmote-b/Makefile.dep index 38c14da37a..23ccf28036 100644 --- a/boards/openmote-b/Makefile.dep +++ b/boards/openmote-b/Makefile.dep @@ -1,3 +1,8 @@ +# ATM openwsn does not support the at86rf215 radio +ifneq (,$(filter openwsn,$(USEPKG))) + USEMODULE += cc2538_rf +endif + ifneq (,$(filter netdev_default,$(USEMODULE))) ifeq (,$(filter cc2538_rf,$(USEMODULE))) USEMODULE += at86rf215 diff --git a/boards/openmote-b/include/board.h b/boards/openmote-b/include/board.h index 29c47f3b71..1863d83b25 100644 --- a/boards/openmote-b/include/board.h +++ b/boards/openmote-b/include/board.h @@ -86,6 +86,30 @@ #define CONFIG_CC2538_RF_OBS_SIG_2_PCX 7 /* PC7 */ /** @} */ +/** + * @name OpenWSN leds configuration + * @{ + */ +#define OPENWSN_LEDPIN_ERROR LED0_PIN +#define OPENWSN_LEDPIN_SYNC LED1_PIN +#define OPENWSN_LEDPIN_RADIO LED3_PIN +#define OPENWSN_LEDPIN_DEBUG LED2_PIN +/** @} */ + +/** + * @name OpenWSN debugpins configuration + * + * @note This configuration mimics the one done in OpenWSN-fw for the + * same platform + * @{ + */ +#define OPENWSN_DEBUGPIN_FRAME GPIO_PIN(0, 7) /* A7 */ +#define OPENWSN_DEBUGPIN_ISR GPIO_PIN(2, 3) /* C3 */ +#define OPENWSN_DEBUGPIN_SLOT GPIO_PIN(1, 3) /* B3 */ +#define OPENWSN_DEBUGPIN_FSM GPIO_PIN(1, 2) /* B2 */ +#define OPENWSN_DEBUGPIN_TASK GPIO_PIN(1, 1) /* B1 */ +#define OPENWSN_DEBUGPIN_RADIO GPIO_PIN(1, 0) /* B0 */ + /** * @name AT86RF215 configuration * @{ diff --git a/cpu/cc2538/include/cc2538_rf.h b/cpu/cc2538/include/cc2538_rf.h index 7803b46016..fc27bf96f8 100644 --- a/cpu/cc2538/include/cc2538_rf.h +++ b/cpu/cc2538/include/cc2538_rf.h @@ -266,7 +266,7 @@ enum { #define CONFIG_CC2538_RF_OBS_2 rssi_valid #endif -/* Default configration for cc2538dk or similar */ +/* Default configuration for cc2538dk or similar */ #ifndef CONFIG_CC2538_RF_OBS_SIG_0_PCX #define CONFIG_CC2538_RF_OBS_SIG_0_PCX 0 /* PC0 = LED_1 (red) */ #endif diff --git a/cpu/cc2538/include/cpu_conf.h b/cpu/cc2538/include/cpu_conf.h index 27eaaf2647..74a927ac42 100644 --- a/cpu/cc2538/include/cpu_conf.h +++ b/cpu/cc2538/include/cpu_conf.h @@ -43,6 +43,19 @@ extern "C" { #define CPU_HAS_BITBAND (1) /** @} */ +/** + * @name OpenWSN timing constants + * + * @{ + */ +/* Taken from openwsn-fw */ +#define PORT_maxTxDataPrepare (460/PORT_US_PER_TICK) +#define PORT_maxRxAckPrepare (300/PORT_US_PER_TICK) +#define PORT_maxRxDataPrepare (300/PORT_US_PER_TICK) +#define PORT_maxTxAckPrepare (460/PORT_US_PER_TICK) +#define PORT_delayTx (400/PORT_US_PER_TICK) +/** @} */ + #ifdef __cplusplus } /* end extern "C" */ #endif diff --git a/cpu/nrf52/include/cpu_conf.h b/cpu/nrf52/include/cpu_conf.h index 2346ac215a..612f05a961 100644 --- a/cpu/nrf52/include/cpu_conf.h +++ b/cpu/nrf52/include/cpu_conf.h @@ -125,6 +125,23 @@ extern "C" { #endif /* SOFTDEVICE_PRESENT */ /** @} */ +#ifdef CPU_MODEL_NRF52840XXAA +/** + * @name OpenWSN timing constants + * + * @{ + */ +/* Taken from OpenWSN @32.768Hz */ +#define PORT_maxTxDataPrepare (400/PORT_US_PER_TICK) +#define PORT_maxRxAckPrepare (400/PORT_US_PER_TICK) +#define PORT_maxRxDataPrepare (400/PORT_US_PER_TICK) +#define PORT_maxTxAckPrepare (400/PORT_US_PER_TICK) +/* Measured 220us */ +#define PORT_delayTx (300/PORT_US_PER_TICK) +#define PORT_delayRx (150/PORT_US_PER_TICK) +/** @} */ +#endif + /** * @brief Put the CPU in the low-power 'wait for event' state */ diff --git a/pkg/openwsn/Makefile.dep b/pkg/openwsn/Makefile.dep index 04bff6eb11..4eadbd0246 100644 --- a/pkg/openwsn/Makefile.dep +++ b/pkg/openwsn/Makefile.dep @@ -16,8 +16,6 @@ ifneq (,$(filter openwsn_openstack,$(USEMODULE))) DEFAULT_MODULE += auto_init_openwsn - USEMODULE += luid - USEMODULE += netdev_default endif ifneq (,$(filter openwsn_scheduler,$(USEMODULE))) @@ -50,6 +48,23 @@ ifneq (,$(filter openwsn_crypto,$(USEMODULE))) USEMODULE += cipher_modes endif +ifneq (,$(filter openwsn_radio,$(USEMODULE))) + USEMODULE += netdev_default + USEMODULE += luid + ifneq (,$(filter cc2538_rf nrf802154,$(USEMODULE))) + USEMODULE += openwsn_radio_hal + endif + ifneq (,$(filter at86rf2xx,$(USEMODULE))) + USEMODULE += openwsn_radio_netdev + endif +endif + +ifneq (,$(filter openwsn_radio_hal,$(USEMODULE))) + USEMODULE += ieee802154_radio_hal + # Used here only for dependency resolution + DISABLE_MODULE += auto_init_gnrc_netif +endif + ifneq (,$(filter openwsn_sctimer,$(USEMODULE))) ifeq (,$(filter openwsn_sctimer_ztimer,$(USEMODULE))) USEMODULE += openwsn_sctimer_rtt diff --git a/pkg/openwsn/Makefile.include b/pkg/openwsn/Makefile.include index 2c2f202a58..471d9bb67b 100644 --- a/pkg/openwsn/Makefile.include +++ b/pkg/openwsn/Makefile.include @@ -84,5 +84,13 @@ ifneq (,$(filter at86rf2xx,$(USEMODULE))) CFLAGS += -DAT86RF2XX_BASIC_MODE endif +# 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 nrf52 sam%,$(CPU))) + RTT_FREQUENCY ?= RTT_MAX_FREQUENCY + CFLAGS += -DRTT_FREQUENCY=$(RTT_FREQUENCY) +endif + # LLVM ARM shows issues with missing definitions for stdatomic TOOLCHAINS_BLACKLIST += llvm diff --git a/pkg/openwsn/contrib/Makefile b/pkg/openwsn/contrib/Makefile index 07576b0a84..cdbd3c2b8d 100644 --- a/pkg/openwsn/contrib/Makefile +++ b/pkg/openwsn/contrib/Makefile @@ -1,6 +1,6 @@ MODULE = openwsn -SRC := $(filter-out sctimer_% ,$(wildcard *.c)) +SRC := $(filter-out sctimer_% radio_%,$(wildcard *.c)) ifneq (,$(filter openwsn_sctimer_rtt,$(USEMODULE))) SRC += sctimer_rtt.c @@ -10,4 +10,12 @@ ifneq (,$(filter openwsn_sctimer_ztimer,$(USEMODULE))) SRC += sctimer_ztimer.c endif +ifneq (,$(filter openwsn_radio_hal,$(USEMODULE))) + SRC += radio_hal.c +endif + +ifneq (,$(filter openwsn_radio_netdev,$(USEMODULE))) + SRC += radio_netdev.c +endif + include $(RIOTBASE)/Makefile.base diff --git a/pkg/openwsn/contrib/eui64.c b/pkg/openwsn/contrib/eui64.c index 1b7221d780..60af85c34c 100644 --- a/pkg/openwsn/contrib/eui64.c +++ b/pkg/openwsn/contrib/eui64.c @@ -29,8 +29,21 @@ extern openwsn_radio_t openwsn_radio; +#ifdef MODULE_OPENWSN_RADIO_HAL +/* HACK: temporary hack while eui_provider still depends on netdev */ +static eui64_t _eui64; +static bool _eui64_is_set = false; +#endif + void eui64_get(uint8_t *addressToWrite) { +#ifdef MODULE_OPENWSN_RADIO_HAL + if (!_eui64_is_set) { + luid_get_eui64(&_eui64); + _eui64_is_set = true; + } + memcpy(addressToWrite, _eui64.uint8, sizeof(_eui64.uint8)); +#else eui64_t eui64; if (openwsn_radio.dev->driver->get(openwsn_radio.dev, NETOPT_ADDRESS_LONG, @@ -41,4 +54,5 @@ void eui64_get(uint8_t *addressToWrite) else { luid_get_eui64((eui64_t *) addressToWrite); } +#endif } diff --git a/pkg/openwsn/contrib/openwsn.c b/pkg/openwsn/contrib/openwsn.c index 5fc7bf1c62..b085fd07ef 100644 --- a/pkg/openwsn/contrib/openwsn.c +++ b/pkg/openwsn/contrib/openwsn.c @@ -19,7 +19,6 @@ #include "scheduler.h" #include "openstack.h" #include "radio.h" -#include "idmanager.h" #include "openwsn.h" #include "openwsn_board.h" @@ -30,6 +29,14 @@ #include "at86rf2xx_params.h" #endif +#ifdef MODULE_CC2538_RF +#include "cc2538_rf.h" +#endif + +#ifdef MODULE_NRF802154 +#include "nrf802154.h" +#endif + #define LOG_LEVEL LOG_NONE #include "log.h" @@ -37,9 +44,11 @@ #define OPENWSN_SCHED_PRIO (THREAD_PRIORITY_MAIN - 4) #define OPENWSN_SCHED_STACKSIZE (2048) +#ifdef MODULE_OPENWSN_RADIO_NETDEV #ifdef MODULE_AT86RF2XX static at86rf2xx_t at86rf2xx_dev; #endif +#endif static char _stack[OPENWSN_SCHED_STACKSIZE]; @@ -52,46 +61,42 @@ kernel_pid_t openwsn_get_pid(void) return _pid; } -#ifdef MODULE_OPENWSN_RADIO -void openwsn_set_addr_16b(netdev_t* dev) +void* _radio_init_dev(void) { - 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); -} + void* dev = NULL; + /* avoid cppcheck style (redundantAssignment)*/ + (void) dev; +#ifdef MODULE_OPENWSN_RADIO_NETDEV + #ifdef MODULE_AT86RF2XX + dev = &at86rf2xx_dev.netdev.netdev; + at86rf2xx_setup(&at86rf2xx_dev, &at86rf2xx_params[0], 0); + #endif +#else + #ifdef MODULE_CC2538_RF + extern ieee802154_dev_t cc2538_rf_dev; + dev = &cc2538_rf_dev; + cc2538_init(); + #endif + #ifdef MODULE_NRF802154 + extern ieee802154_dev_t nrf802154_hal_dev; + dev = &nrf802154_hal_dev; + nrf802154_init(); + #endif #endif + return dev; +} 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], 0); - (void) netdev; -#endif - -#ifdef MODULE_OPENWSN_RADIO LOG_DEBUG("[openwsn]: init radio\n"); - if (openwsn_radio_init(netdev)) { + void* dev = _radio_init_dev(); + if (openwsn_radio_init(dev)) { 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, diff --git a/pkg/openwsn/contrib/radio_hal.c b/pkg/openwsn/contrib/radio_hal.c new file mode 100644 index 0000000000..e2ebec43b5 --- /dev/null +++ b/pkg/openwsn/contrib/radio_hal.c @@ -0,0 +1,317 @@ +/* + * 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 of the "radio" bsp module + * + * @author Francisco Molina + * @} + */ +#include + +#include "leds.h" +#include "debugpins.h" +#include "sctimer.h" +#include "idmanager.h" +#include "eui64.h" + +#include "byteorder.h" + +#include "luid.h" +#include "net/ieee802154.h" +#include "net/ieee802154/radio.h" + +#include "openwsn.h" +#include "openwsn_radio.h" + +#define LOG_LEVEL LOG_NONE +#include "log.h" + +openwsn_radio_t openwsn_radio; + +/* stores the event capture time */ +static PORT_TIMER_WIDTH _txrx_event_capture_time = 0; + +void _idmanager_addr_override(void) +{ + /* 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(); + + /* override 16b address to avoid short address collision */ + network_uint16_t short_addr; + luid_get_short(&short_addr); + open_addr_t id; + id.type = ADDR_16B; + memcpy(&id.addr_16b, short_addr.u8, IEEE802154_SHORT_ADDRESS_LEN); + idmanager_setMyID(&id); + + /* override PANID */ + id.type = ADDR_PANID; + network_uint16_t panid_be = byteorder_htons(OPENWSN_PANID); + memcpy(&id.panid, &panid_be, IEEE802154_SHORT_ADDRESS_LEN); + idmanager_setMyID(&id); + + /* recover ADDR_64B */ + eui64_t eui64; + eui64_get(eui64.uint8); + + /* Set all IEEE addresses */ + uint16_t panid = OPENWSN_PANID; + ieee802154_radio_set_hw_addr_filter(openwsn_radio.dev, &short_addr, + &eui64, &panid); + +} + +static void _hal_radio_cb(ieee802154_dev_t *dev, ieee802154_trx_ev_t status) +{ + (void)dev; + + debugpins_isr_set(); + _txrx_event_capture_time = sctimer_readCounter(); + debugpins_isr_clr(); + + switch (status) { + case IEEE802154_RADIO_CONFIRM_TX_DONE: + ieee802154_radio_confirm_transmit(openwsn_radio.dev, NULL); + ieee802154_radio_request_set_trx_state(openwsn_radio.dev, + IEEE802154_TRX_STATE_TRX_OFF); + while (ieee802154_radio_confirm_set_trx_state(openwsn_radio.dev) == -EAGAIN) {} + openwsn_radio.endFrame_cb(_txrx_event_capture_time); + break; + case IEEE802154_RADIO_INDICATION_RX_DONE: + openwsn_radio.endFrame_cb(_txrx_event_capture_time); + break; + case IEEE802154_RADIO_INDICATION_TX_START: + openwsn_radio.startFrame_cb(_txrx_event_capture_time); + break; + case IEEE802154_RADIO_INDICATION_RX_START: + openwsn_radio.startFrame_cb(_txrx_event_capture_time); + break; + default: + break; + } +} + +int openwsn_radio_init(void *radio_dev) +{ + assert(radio_dev); + ieee802154_dev_t *dev = (ieee802154_dev_t *)radio_dev; + + LOG_DEBUG("[openwsn/radio]: initialize riot-adaptation\n"); + openwsn_radio.dev = dev; + + /* override short_address and panid*/ + _idmanager_addr_override(); + + if (ieee802154_radio_request_on(dev)) { + LOG_ERROR("[openwsn/radio]: unable to initialize device\n"); + return -1; + } + + /* Set the Event Notification */ + dev->cb = _hal_radio_cb; + + /* If the radio is still not in TRX_OFF state, spin */ + while (ieee802154_radio_confirm_on(dev) == -EAGAIN) {} + + /* Enable basic mode, no AUTOACK. no CSMA */ + ieee802154_radio_set_rx_mode(dev, IEEE802154_RX_AACK_DISABLED); + /* MAC layer retransmissions are disabled by _set_csma_params() */ + ieee802154_radio_set_csma_params(dev, NULL, -1); + + if (IS_USED(MODULE_CC2538_RF)) { + /* If frame filtering is enabled cc2538 will not accept beacons + where the destination-address mode is 0 (no destination address). + per rfc8180 4.5.1 the destination address must be set, which means + the destination-address mode can't be 0 */ + ieee802154_radio_set_rx_mode(dev, IEEE802154_RX_PROMISC); + } + + /* Configure PHY settings (channel, TX power) */ + ieee802154_phy_conf_t conf = + { .channel = CONFIG_IEEE802154_DEFAULT_CHANNEL, + .page = CONFIG_IEEE802154_DEFAULT_CHANNEL, + .pow = CONFIG_IEEE802154_DEFAULT_TXPOWER }; + + ieee802154_radio_config_phy(dev, &conf); + + 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) +{ + /* TODO: this is not handled correctly since not all radios implement + this */ + ieee802154_radio_off(openwsn_radio.dev); + ieee802154_radio_request_on(openwsn_radio.dev); + /* If the radio is still not in TRX_OFF state, spin */ + while (ieee802154_radio_confirm_on(openwsn_radio.dev) == -EAGAIN) {} +} + +void radio_setFrequency(uint8_t frequency, radio_freq_t tx_or_rx) +{ + (void)tx_or_rx; + + ieee802154_phy_conf_t conf = + { .channel = frequency, + .page = CONFIG_IEEE802154_DEFAULT_CHANNEL, + .pow = CONFIG_IEEE802154_DEFAULT_TXPOWER }; + + ieee802154_radio_config_phy(openwsn_radio.dev, &conf); +} + +void radio_rfOn(void) +{ + ieee802154_radio_request_on(openwsn_radio.dev); + /* If the radio is still not in TRX_OFF state, spin */ + while (ieee802154_radio_confirm_on(openwsn_radio.dev) == -EAGAIN) {} + /* HACK: cc2538 does not implement on() correctly, remove when it does*/ + ieee802154_radio_request_set_trx_state(openwsn_radio.dev, + IEEE802154_TRX_STATE_TRX_OFF); + while (ieee802154_radio_confirm_set_trx_state(openwsn_radio.dev) == -EAGAIN) {} +} + +void radio_rfOff(void) +{ + /* radio_rfOff is called in the middle of a slot and is not always + followed by an `radio_rfOn`, so don't call `ieee802154_radio_off` + and only send the radio to `TrxOFF` instead */ + int ret = ieee802154_radio_request_set_trx_state(openwsn_radio.dev, + IEEE802154_TRX_STATE_TRX_OFF); + + if (ret) { + LOG_ERROR("[openwsn/radio]: request_set_trx_state failed %s\n", + __FUNCTION__); + } + else { + debugpins_radio_clr(); + leds_radio_off(); + while (ieee802154_radio_confirm_set_trx_state(openwsn_radio.dev) == + -EAGAIN) {} + } + +} + +void radio_loadPacket(uint8_t *packet, uint16_t len) +{ + /* 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 (ieee802154_radio_write(openwsn_radio.dev, &pkt) < 0) { + LOG_ERROR("[openwsn/radio]: couldn't load pkt\n"); + } +} + +void radio_txEnable(void) +{ + int ret = ieee802154_radio_request_set_trx_state(openwsn_radio.dev, + IEEE802154_TRX_STATE_TX_ON); + + if (ret) { + LOG_ERROR("[openwsn/radio]: request_set_trx_state failed %s\n", + __FUNCTION__); + } + else { + while (ieee802154_radio_confirm_set_trx_state(openwsn_radio.dev) == + -EAGAIN) {} + debugpins_radio_set(); + leds_radio_on(); + } +} + +void radio_txNow(void) +{ + int ret = ieee802154_radio_request_transmit(openwsn_radio.dev); + + if (ret) { + LOG_ERROR("[openwsn/radio]: request_set_trx_state failed %s\n", + __FUNCTION__); + } + else { + /* Trigger startFrame manually if no IEEE802154_CAP_IRQ_TX_START */ + if (!ieee802154_radio_has_irq_tx_start(openwsn_radio.dev)) { + debugpins_isr_set(); + _txrx_event_capture_time = sctimer_readCounter(); + debugpins_isr_clr(); + openwsn_radio.startFrame_cb(_txrx_event_capture_time); + } + } +} + +void radio_rxEnable(void) +{ + int ret = ieee802154_radio_request_set_trx_state(openwsn_radio.dev, + IEEE802154_TRX_STATE_TRX_OFF); + + if (ret) { + LOG_ERROR("[openwsn/radio]: request_set_trx_state failed %s\n", + __FUNCTION__); + } + else { + while (ieee802154_radio_confirm_set_trx_state(openwsn_radio.dev) == + -EAGAIN) {} + debugpins_radio_set(); + leds_radio_on(); + } +} + +void radio_rxNow(void) +{ + int ret = ieee802154_radio_request_set_trx_state(openwsn_radio.dev, + IEEE802154_TRX_STATE_RX_ON); + + if (ret) { + LOG_ERROR("[openwsn/radio]: request_set_trx_state failed %s\n", + __FUNCTION__); + } + else { + while (ieee802154_radio_confirm_set_trx_state(openwsn_radio.dev) == + -EAGAIN) {} + } +} + +void radio_getReceivedFrame(uint8_t *bufRead, + uint8_t *lenRead, + uint8_t maxBufLen, + int8_t *rssi, + uint8_t *lqi, + bool *crc) +{ + ieee802154_rx_info_t rx_info; + size_t size = ieee802154_radio_read(openwsn_radio.dev, bufRead, + maxBufLen, &rx_info); + + /* FCS is skipped by the radio-hal in the returned length, but + OpenWSN includes IEEE802154_FCS_LEN in its length value */ + *lenRead = size + IEEE802154_FCS_LEN; + /* get rssi, lqi & crc */ + *rssi = rx_info.rssi; + *lqi = rx_info.lqi; + /* only valid crc frames are currently accepted */ + *crc = 1; +} diff --git a/pkg/openwsn/contrib/radio.c b/pkg/openwsn/contrib/radio_netdev.c similarity index 88% rename from pkg/openwsn/contrib/radio.c rename to pkg/openwsn/contrib/radio_netdev.c index d2dad94171..e09e4581c2 100644 --- a/pkg/openwsn/contrib/radio.c +++ b/pkg/openwsn/contrib/radio_netdev.c @@ -26,6 +26,7 @@ #include "leds.h" #include "debugpins.h" #include "sctimer.h" +#include "idmanager.h" #include "net/netopt.h" #include "net/ieee802154.h" @@ -34,6 +35,15 @@ #include "openwsn.h" #include "openwsn_radio.h" +#ifdef MODULE_AT86RF2XX +#include "at86rf2xx.h" +#include "at86rf2xx_params.h" +#endif + +#ifdef MODULE_CC2538_RF +#include "cc2538_rf.h" +#endif + #define LOG_LEVEL LOG_NONE #include "log.h" @@ -44,9 +54,32 @@ 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) +static void _set_addr(void) { - assert(netdev); + netdev_t* dev = openwsn_radio.dev; + /* 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(); + + /* override 16b address to avoid short address collision */ + 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); + /* override PANID */ + id.type = ADDR_PANID; + uint16_t panid = OPENWSN_PANID; + memcpy(&id.addr_16b, &panid, IEEE802154_SHORT_ADDRESS_LEN); + idmanager_setMyID(&id); +} + +int openwsn_radio_init(void *radio_dev) +{ + assert(radio_dev); + netdev_t *netdev = (netdev_t *)radio_dev; LOG_DEBUG("[openwsn/radio]: initialize riot-adaptation\n"); openwsn_radio.dev = netdev; @@ -89,6 +122,8 @@ int openwsn_radio_init(netdev_t *netdev) uint16_t panid = OPENWSN_PANID; netdev->driver->set(netdev, NETOPT_NID, &(panid), sizeof(uint16_t)); + _set_addr(); + return 0; } diff --git a/pkg/openwsn/contrib/sctimer_rtt.c b/pkg/openwsn/contrib/sctimer_rtt.c index 1efdcd9781..d3c801a025 100644 --- a/pkg/openwsn/contrib/sctimer_rtt.c +++ b/pkg/openwsn/contrib/sctimer_rtt.c @@ -67,6 +67,15 @@ static uint32_t _prescaler; static atomic_bool _enable; #endif +#if RTT_MAX_VALUE < UINT32_MAX +/* If RTT_MAX_VALUE is smaller the UINT32_MAX then handle the remaining + bits here, sctimer is scheduled at least every slot (20ms) so no + overflow will be missed */ +#define SCTIMER_RTT_EXTEND_MSB (1 << (32UL - __builtin_clz(RTT_MAX_VALUE))) +static atomic_uint_fast32_t _counter_msb; +static atomic_uint_fast32_t _now_last; +#endif + static sctimer_cbt sctimer_cb; static void sctimer_isr_internal(void *arg) @@ -84,6 +93,10 @@ void sctimer_init(void) { rtt_init(); sctimer_cb = NULL; +#ifdef SCTIMER_RTT_EXTEND_MSB + atomic_store(&_counter_msb, 0); + atomic_store(&_now_last, 0); +#endif #ifdef SCTIMER_TIME_DIVISION _prescaler = 0; _enable = false; @@ -115,12 +128,34 @@ uint32_t _update_val(uint32_t val, uint32_t now) } #endif +#ifdef SCTIMER_RTT_EXTEND_MSB +uint32_t _sctimer_extend(uint32_t now) +{ + unsigned state = irq_disable(); + uint32_t now_last = atomic_load(&_now_last); + uint32_t counter_msb = atomic_load(&_counter_msb); + if (now < now_last) { + /* account for overflow */ + counter_msb += SCTIMER_RTT_EXTEND_MSB; + atomic_store(&_counter_msb, counter_msb); + } + atomic_store(&_now_last, now); + now += counter_msb; + irq_restore(state); + return now; +} +#endif + void sctimer_setCompare(uint32_t val) { unsigned state = irq_disable(); uint32_t now = rtt_get_counter(); +#ifdef SCTIMER_RTT_EXTEND_MSB + now = _sctimer_extend(now); +#endif + #ifdef SCTIMER_TIME_DIVISION val = _update_val(val, now); #endif @@ -150,6 +185,10 @@ uint32_t sctimer_readCounter(void) { uint32_t now = rtt_get_counter(); +#ifdef SCTIMER_RTT_EXTEND_MSB + now = _sctimer_extend(now); +#endif + #ifdef SCTIMER_TIME_DIVISION now &= SCTIMER_TIME_DIVISION_MASK; now = (now << SCTIMER_PRESCALER); diff --git a/pkg/openwsn/include/openwsn_debugpins_params.h b/pkg/openwsn/include/openwsn_debugpins_params.h index 5ecc54f5f8..e3df46238e 100644 --- a/pkg/openwsn/include/openwsn_debugpins_params.h +++ b/pkg/openwsn/include/openwsn_debugpins_params.h @@ -22,6 +22,7 @@ #ifndef OPENWSN_DEBUGPINS_PARAMS_H #define OPENWSN_DEBUGPINS_PARAMS_H +#include "board.h" #include "openwsn_debugpins.h" #ifdef __cplusplus diff --git a/pkg/openwsn/include/openwsn_leds_params.h b/pkg/openwsn/include/openwsn_leds_params.h index 918df88095..c4f81dfed5 100644 --- a/pkg/openwsn/include/openwsn_leds_params.h +++ b/pkg/openwsn/include/openwsn_leds_params.h @@ -34,29 +34,37 @@ extern "C" { * @note On Nucleo boards the LED pin is shared with SPI -> don't use it! * @{ */ +#ifndef OPENWSN_LEDPIN_ERROR #if defined (LED0_PIN) && !defined(MODULE_BOARDS_COMMON_NUCLEO) #define OPENWSN_LEDPIN_ERROR LED0_PIN #else #define OPENWSN_LEDPIN_ERROR GPIO_UNDEF #endif +#endif +#ifndef OPENWSN_LEDPIN_SYNC #ifdef LED1_PIN #define OPENWSN_LEDPIN_SYNC LED1_PIN #else #define OPENWSN_LEDPIN_SYNC GPIO_UNDEF #endif +#endif +#ifndef OPENWSN_LEDPIN_RADIO #ifdef LED2_PIN #define OPENWSN_LEDPIN_RADIO LED2_PIN #else #define OPENWSN_LEDPIN_RADIO GPIO_UNDEF #endif +#endif +#ifndef OPENWSN_LEDPIN_DEBUG #ifdef LED3_PIN #define OPENWSN_LEDPIN_DEBUG LED3_PIN #else #define OPENWSN_LEDPIN_DEBUG GPIO_UNDEF #endif +#endif #ifndef OPENWSN_LED_ON_STATE #define OPENWSN_LED_ON_STATE GPIO_LED_LOW diff --git a/pkg/openwsn/include/openwsn_radio.h b/pkg/openwsn/include/openwsn_radio.h index a4788b3971..4a80bcf1a4 100644 --- a/pkg/openwsn/include/openwsn_radio.h +++ b/pkg/openwsn/include/openwsn_radio.h @@ -55,25 +55,30 @@ extern "C" { #endif #include "net/netdev.h" +#include "net/ieee802154/radio.h" #include "radio.h" /** * @brief Initialize OpenWSN radio * - * @param[in] netdev pointer to a netdev interface + * @param[in] radio_dev pointer to a dev interface * * @return PID of OpenWSN thread * @return -1 on initialization error */ -int openwsn_radio_init(netdev_t *netdev); +int openwsn_radio_init(void *radio_dev); /** * @brief OpenWSN radio variables structure */ typedef struct { +#if IS_ACTIVE(MODULE_OPENWSN_RADIO_NETDEV) + netdev_t *dev; /**< netdev device */ +#else + ieee802154_dev_t *dev; /**< radio hal */ +#endif 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 diff --git a/pkg/openwsn/scheduler/scheduler.c b/pkg/openwsn/scheduler/scheduler.c index 7fee1702dd..84067b21c7 100644 --- a/pkg/openwsn/scheduler/scheduler.c +++ b/pkg/openwsn/scheduler/scheduler.c @@ -61,14 +61,14 @@ void scheduler_start(unsigned state) /* wait for events */ event_t *event; while ((event = event_wait_multi(_queues, TASKPRIO_MAX))) { - debugpins_task_clr(); + debugpins_task_set(); event->handler(event); /* remove from task list */ memarray_free(&_scheduler_vars.memarray, event); #if SCHEDULER_DEBUG_ENABLE scheduler_dbg.numTasksCur--; #endif - debugpins_task_set(); + debugpins_task_clr(); } } diff --git a/sys/Makefile.dep b/sys/Makefile.dep index f459acccac..e96a15b89b 100644 --- a/sys/Makefile.dep +++ b/sys/Makefile.dep @@ -550,6 +550,9 @@ ifneq (,$(filter shell_commands,$(USEMODULE))) USEMODULE += nimble_scanlist USEMODULE += fmt endif + ifneq (,$(filter openwsn_%,$(USEMODULE))) + USEMODULE += netif + endif endif ifneq (,$(filter posix_semaphore,$(USEMODULE))) diff --git a/tests/pkg_openwsn/Makefile b/tests/pkg_openwsn/Makefile index a34e83c84b..b81ad1463c 100644 --- a/tests/pkg_openwsn/Makefile +++ b/tests/pkg_openwsn/Makefile @@ -2,14 +2,33 @@ BOARD ?= iotlab-m3 include ../Makefile.tests_common -# list of arm boards that provide at86rf2xx radios, can't require it so -# add whitelist +# list of arm boards that provide at86rf2xx radios, cc2538_rf or nrf52840 +# radios BOARD_WHITELIST = \ + adafruit-clue \ + adafruit-itsybitsy-nrf52 \ + arduino-nano-33-ble \ + cc2538dk \ + feather-nrf52840 \ + firefly \ fox \ iotlab-m3 \ iotlab-a8-m3 \ + nrf52840-mdk \ + nrf52840dk \ + nrf52840dongle \ + omote \ + openmote-b \ + openmote-cc2538 \ + particle-argon \ + particle-boron \ + particle-xenon \ samr21-xpro \ samr30-xpro \ + reel \ + remote-pa \ + remote-reva \ + remote-revb \ # # OpenWSN Modules @@ -36,7 +55,7 @@ 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))) + ifneq (,$(filter iotlab-% openmote-b,$(BOARD))) USEMODULE += stdio_null endif # OpenWSN serial module can't handle data at more than 115200 bauds/s, @@ -66,11 +85,3 @@ USEMODULE += shell_commands 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