diff --git a/boards/common/nrf52/Makefile.dep b/boards/common/nrf52/Makefile.dep index b9f6fc79e55878a6e77dab26356150b72af5067b..6f369896e79dc294e8a146a4f6bb982316f4c11c 100644 --- a/boards/common/nrf52/Makefile.dep +++ b/boards/common/nrf52/Makefile.dep @@ -1,3 +1,5 @@ +include $(RIOTCPU)/nrf52/Makefile.dep + ifneq (,$(filter skald,$(USEMODULE))) USEMODULE += nrfble endif diff --git a/boards/common/nrf52/include/cfg_timer_default.h b/boards/common/nrf52/include/cfg_timer_default.h index 43f61d1a6a9837f32d89165f27aba24b4ed4b569..8dd673806f289a211b86bb25f1d4fd2145610d9a 100644 --- a/boards/common/nrf52/include/cfg_timer_default.h +++ b/boards/common/nrf52/include/cfg_timer_default.h @@ -36,10 +36,17 @@ static const timer_conf_t timer_config[] = { .channels = 3, .bitmode = TIMER_BITMODE_BITMODE_32Bit, .irqn = TIMER1_IRQn + }, + { + .dev = NRF_TIMER2, + .channels = 3, + .bitmode = TIMER_BITMODE_BITMODE_08Bit, + .irqn = TIMER2_IRQn } }; #define TIMER_0_ISR isr_timer1 +#define TIMER_1_ISR isr_timer2 #define TIMER_NUMOF (sizeof(timer_config) / sizeof(timer_config[0])) /** @} */ diff --git a/boards/nrf52840dk/Makefile.dep b/boards/nrf52840dk/Makefile.dep index 68628f406a1a5367ae7c1252e6fae6a01d925792..f75b7b047ca5755d92ded1637f5ff55806844627 100644 --- a/boards/nrf52840dk/Makefile.dep +++ b/boards/nrf52840dk/Makefile.dep @@ -1 +1,7 @@ include $(RIOTBOARD)/common/nrf52xxxdk/Makefile.dep + +ifneq (,$(filter gnrc_netdev_default netdev_default,$(USEMODULE))) + ifeq (,$(filter nrfmin,$(USEMODULE))) + USEMODULE += nrf802154 + endif +endif diff --git a/boards/nrf52840dk/Makefile.features b/boards/nrf52840dk/Makefile.features index b99cfa472a13eaf6b79ba38718a4f2fea3563259..4ab48c7cbc2ee092b5a24e524e994f601dbf4736 100644 --- a/boards/nrf52840dk/Makefile.features +++ b/boards/nrf52840dk/Makefile.features @@ -1 +1,5 @@ include $(RIOTBOARD)/common/nrf52xxxdk/Makefile.features + +# Various other features (if any) +FEATURES_PROVIDED += radio_nrf802154 +FEATURES_PROVIDED += periph_pwm diff --git a/cpu/nrf52/Makefile b/cpu/nrf52/Makefile index 7600b58931f0b077fcc2f99e9b59ab2973d42289..59c4f48c9bcb37daea1db3642b7e4ead34e2d924 100644 --- a/cpu/nrf52/Makefile +++ b/cpu/nrf52/Makefile @@ -7,4 +7,9 @@ DIRS = periph $(RIOTCPU)/cortexm_common $(RIOTCPU)/nrf5x_common # (file triggers compiler bug. see #5775) SRC_NOLTO += vectors.c +# build the nrf802154 driver if selected +ifneq (,$(filter nrf802154,$(USEMODULE))) + DIRS += radio/nrf802154 +endif + include $(RIOTBASE)/Makefile.base diff --git a/cpu/nrf52/Makefile.dep b/cpu/nrf52/Makefile.dep new file mode 100644 index 0000000000000000000000000000000000000000..d5e4d42993000d1210d5b354e500154caa9362e7 --- /dev/null +++ b/cpu/nrf52/Makefile.dep @@ -0,0 +1,6 @@ +ifneq (,$(filter nrf802154,$(USEMODULE))) + FEATURES_REQUIRED += periph_timer + FEATURES_REQUIRED += radio_nrf802154 + USEMODULE += luid + USEMODULE += netdev_ieee802154 +endif diff --git a/cpu/nrf52/Makefile.include b/cpu/nrf52/Makefile.include index d6e26d6147b4dc501542b2821c807c663a67986b..03647d823b65cf24efb2574df46bbd3f9029542a 100644 --- a/cpu/nrf52/Makefile.include +++ b/cpu/nrf52/Makefile.include @@ -7,5 +7,9 @@ export MCUBOOT_SLOT0_SIZE = 0x8000 export MCUBOOT_SLOT1_SIZE = 0x3C000 export MCUBOOT_SLOT2_SIZE = 0x3C000 +ifneq (,$(filter nrf802154,$(USEMODULE))) + CFLAGS += -DGNRC_NETIF_MSG_QUEUE_SIZE=16 +endif + include $(RIOTCPU)/nrf5x_common/Makefile.include include $(RIOTMAKE)/arch/cortexm.inc.mk diff --git a/cpu/nrf52/include/nrf802154.h b/cpu/nrf52/include/nrf802154.h new file mode 100644 index 0000000000000000000000000000000000000000..de55018e7795775e25920f54e262cb710168d5cd --- /dev/null +++ b/cpu/nrf52/include/nrf802154.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2019 Freie Universität Berlin + * + * 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. + */ + +/** + * @defgroup drivers_nrf52_802154 IEEE802.15.4 Driver for nRF52840 SoCs + * @ingroup drivers_netdev + * @brief Driver for using the nRF52's radio in IEEE802.15.4 mode + * + * ## Implementation state ## + * Netdev events supported: + * + * - NETDEV_EVENT_RX_COMPLETE + * - NETDEV_EVENT_TX_COMPLETE + * + * Transmission options not yet impemented: + * - Send acknowledgement for packages + * - Request acknowledgement + * - Retransmit unacked packages + * - Carrier Sense Multiple Access (CSMA) and Implementation of Clear Channel + * Assessment Control (CCACTRL) + * + * @{ + * + * @file + * @brief Driver interface for using the nRF52 in IEEE802.15.4 mode + * + * @author Hauke Petersen <hauke.petersen@fu-berlin.de> + * @author Semjon Kerner <semjon.kerner@fu-berlin.de> + */ + +#ifndef NRF802154_H +#define NRF802154_H + +#include "net/netdev/ieee802154.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Export the netdev device descriptor + */ +extern netdev_ieee802154_t nrf802154_dev; + +/** + * @brief IEEE 802.15.4 radio timer configuration + * + * this radio relies on a dedicated hardware timer to maintain IFS + * the default timer may be overwritten in the board configuration + */ +#ifndef NRF802154_TIMER +#define NRF802154_TIMER TIMER_DEV(1) +#endif + +#endif /* NRF802154_H */ +/** @} */ diff --git a/cpu/nrf52/radio/nrf802154/Makefile b/cpu/nrf52/radio/nrf802154/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..b2dbcf3dfe5f1dbd3e269a975280305dde79c239 --- /dev/null +++ b/cpu/nrf52/radio/nrf802154/Makefile @@ -0,0 +1,3 @@ +MODULE = nrf802154 + +include $(RIOTBASE)/Makefile.base diff --git a/cpu/nrf52/radio/nrf802154/nrf802154.c b/cpu/nrf52/radio/nrf802154/nrf802154.c new file mode 100644 index 0000000000000000000000000000000000000000..b69499a84cf29185d8e0c30a2dc1d02d1dac0aeb --- /dev/null +++ b/cpu/nrf52/radio/nrf802154/nrf802154.c @@ -0,0 +1,446 @@ +/* + * Copyright (C) 2019 Freie Universität Berlin + * 2019 HAW Hamburg + * + * 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 drivers_nrf52_802154 + * @{ + * + * @file + * @brief Implementation of the radio driver for nRF52 radios + * + * @author Hauke Petersen <hauke.petersen@fu-berlin.de> + * @author Dimitri Nahm <dimitri.nahm@haw-hamburg.de> + * @author Semjon Kerner <semjon.kerner@fu-berlin.de> + * @} + */ + +#include <string.h> +#include <errno.h> + +#include "cpu.h" +#include "luid.h" +#include "mutex.h" + +#include "net/ieee802154.h" +#include "periph/timer.h" +#include "net/netdev/ieee802154.h" +#include "nrf802154.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +static const netdev_driver_t nrf802154_netdev_driver; + +netdev_ieee802154_t nrf802154_dev = { + { + .driver = &nrf802154_netdev_driver, + .event_callback = NULL, + .context = NULL, + }, +#ifdef MODULE_GNRC +#ifdef MODULE_GNRC_SIXLOWPAN + .proto = GNRC_NETTYPE_SIXLOWPAN, +#else + .proto = GNRC_NETTYPE_UNDEF, +#endif +#endif + .pan = IEEE802154_DEFAULT_PANID, + .short_addr = { 0, 0 }, + .long_addr = { 0, 0, 0, 0, 0, 0, 0, 0 }, + .chan = IEEE802154_DEFAULT_CHANNEL, + .flags = 0 +}; + +static uint8_t rxbuf[IEEE802154_FRAME_LEN_MAX + 3]; /* len PHR + PSDU + LQI */ +static uint8_t txbuf[IEEE802154_FRAME_LEN_MAX + 3]; /* len PHR + PSDU + LQI */ + +#define RX_COMPLETE (0x1) +#define TX_COMPLETE (0x2) +#define LIFS (40U) +#define SIFS (12U) +#define SIFS_MAXPKTSIZE (18U) +#define TIMER_FREQ (250000UL) +static volatile uint8_t _state; +static mutex_t _txlock; + +/** + * @brief Set radio into DISABLED state + */ +static void _disable(void) +{ + /* set device into DISABLED state */ + if (NRF_RADIO->STATE != RADIO_STATE_STATE_Disabled) { + NRF_RADIO->EVENTS_DISABLED = 0; + NRF_RADIO->TASKS_DISABLE = 1; + while (!(NRF_RADIO->EVENTS_DISABLED)) {}; + DEBUG("[nrf802154] Device state: DISABLED\n"); + } +} + +/** + * @brief Set radio into RXIDLE state + */ +static void _enable_rx(void) +{ + DEBUG("[nrf802154] Set device state to RXIDLE\n"); + /* set device into RXIDLE state */ + if (NRF_RADIO->STATE != RADIO_STATE_STATE_RxIdle) { + _disable(); + } + NRF_RADIO->PACKETPTR = (uint32_t)rxbuf; + NRF_RADIO->EVENTS_RXREADY = 0; + NRF_RADIO->TASKS_RXEN = 1; + while (!(NRF_RADIO->EVENTS_RXREADY)) {}; + DEBUG("[nrf802154] Device state: RXIDLE\n"); +} + +/** + * @brief Set radio into TXIDLE state + */ +static void _enable_tx(void) +{ + DEBUG("[nrf802154] Set device state to TXIDLE\n"); + /* set device into TXIDLE state */ + if (NRF_RADIO->STATE != RADIO_STATE_STATE_TxIdle) { + _disable(); + } + NRF_RADIO->PACKETPTR = (uint32_t)txbuf; + NRF_RADIO->EVENTS_TXREADY = 0; + NRF_RADIO->TASKS_TXEN = 1; + while (!(NRF_RADIO->EVENTS_TXREADY)) {}; + DEBUG("[nrf802154] Device state: TXIDLE\n"); +} + +/** + * @brief Reset the RXIDLE state + */ + static void _reset_rx(void) + { + if (NRF_RADIO->STATE != RADIO_STATE_STATE_RxIdle) { + return; + } + + /* reset RX state and listen for new packets */ + _state &= ~RX_COMPLETE; + NRF_RADIO->TASKS_START = 1; + } + +static void _set_chan(uint16_t chan) +{ + assert((chan >= IEEE802154_CHANNEL_MIN) && (chan <= IEEE802154_CHANNEL_MAX)); + /* Channel map between 2400 MHZ ... 2500 MHz + * -> Frequency = 2400 + FREQUENCY (MHz) */ + NRF_RADIO->FREQUENCY = (chan - 10) * 5; + nrf802154_dev.chan = chan; +} + +static int16_t _get_txpower(void) +{ + int8_t txpower = (int8_t)NRF_RADIO->TXPOWER; + if (txpower < 0) { + return (int16_t)(0xff00 | txpower); + } + return (int16_t)txpower; +} + +static void _set_txpower(int16_t txpower) +{ + if (txpower > 8) { + NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_Pos8dBm; + } + if (txpower > 1) { + NRF_RADIO->TXPOWER = (uint32_t)txpower; + } + else if (txpower > -1) { + NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_0dBm; + } + else if (txpower > -5) { + NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_Neg4dBm; + } + else if (txpower > -9) { + NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_Neg8dBm; + } + else if (txpower > -13) { + NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_Neg12dBm; + } + else if (txpower > -17) { + NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_Neg16dBm; + } + else if (txpower > -21) { + NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_Neg20dBm; + } + else { + NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_Neg40dBm; + } +} + +static void _timer_cb(void *arg, int chan) +{ + (void)arg; + (void)chan; + mutex_unlock(&_txlock); + timer_stop(NRF802154_TIMER); + timer_clear(NRF802154_TIMER, 0); +} + +static int _init(netdev_t *dev) +{ + (void)dev; + + int result = timer_init(NRF802154_TIMER, TIMER_FREQ, _timer_cb, NULL); + assert(result >= 0); + (void)result; + + /* initialize local variables */ + mutex_init(&_txlock); + + /* reset buffer */ + rxbuf[0] = 0; + txbuf[0] = 0; + _state = 0; + + /* power on peripheral */ + NRF_RADIO->POWER = 1; + + /* make sure the radio is disabled/stopped */ + _disable(); + + /* we configure it to run in IEEE802.15.4 mode */ + NRF_RADIO->MODE = RADIO_MODE_MODE_Ieee802154_250Kbit; + /* and set some fitting configuration */ + NRF_RADIO->PCNF0 = ((8 << RADIO_PCNF0_LFLEN_Pos) | + (RADIO_PCNF0_PLEN_32bitZero << RADIO_PCNF0_PLEN_Pos) | + (RADIO_PCNF0_CRCINC_Include << RADIO_PCNF0_CRCINC_Pos)); + NRF_RADIO->PCNF1 = IEEE802154_FRAME_LEN_MAX; + /* set start frame delimiter */ + NRF_RADIO->SFD = IEEE802154_SFD; + /* set MHR filters */ + NRF_RADIO->MHRMATCHCONF = 0; /* Search Pattern Configuration */ + NRF_RADIO->MHRMATCHMAS = 0xff0007ff; /* Pattern mask */ + /* configure CRC conform to IEEE802154 */ + NRF_RADIO->CRCCNF = ((RADIO_CRCCNF_LEN_Two << RADIO_CRCCNF_LEN_Pos) | + (RADIO_CRCCNF_SKIPADDR_Ieee802154 << RADIO_CRCCNF_SKIPADDR_Pos)); + NRF_RADIO->CRCPOLY = 0x011021; + NRF_RADIO->CRCINIT = 0; + + /* assign default addresses */ + luid_get(nrf802154_dev.short_addr, IEEE802154_SHORT_ADDRESS_LEN); + luid_get(nrf802154_dev.long_addr, IEEE802154_LONG_ADDRESS_LEN); + + /* set default channel */ + _set_chan(nrf802154_dev.chan); + + /* configure some shortcuts */ + NRF_RADIO->SHORTS = RADIO_SHORTS_RXREADY_START_Msk | RADIO_SHORTS_TXREADY_START_Msk; + + /* enable interrupts */ + NVIC_EnableIRQ(RADIO_IRQn); + NRF_RADIO->INTENSET = RADIO_INTENSET_END_Msk; + + /* switch to RX mode */ + _enable_rx(); + + return 0; +} + +static int _send(netdev_t *dev, const iolist_t *iolist) +{ + (void)dev; + + DEBUG("[nrf802154] Send a packet\n"); + + assert(iolist); + + mutex_lock(&_txlock); + + /* copy packet data into the transmit buffer */ + unsigned int len = 0; + for (; iolist; iolist = iolist->iol_next) { + if ((IEEE802154_FCS_LEN + len + iolist->iol_len) > (IEEE802154_FRAME_LEN_MAX)) { + DEBUG("[nrf802154] send: unable to do so, packet is too large!\n"); + mutex_unlock(&_txlock); + return -EOVERFLOW; + } + memcpy(&txbuf[len + 1], iolist->iol_base, iolist->iol_len); + len += iolist->iol_len; + } + + /* specify the length of the package. */ + txbuf[0] = len + IEEE802154_FCS_LEN; + + /* trigger the actual transmission */ + _enable_tx(); + DEBUG("[nrf802154] send: putting %i byte into the ether\n", len); + + /* set interframe spacing based on packet size */ + unsigned int ifs = (len > SIFS_MAXPKTSIZE) ? LIFS : SIFS; + timer_set_absolute(NRF802154_TIMER, 0, ifs); + + return len; +} + +static int _recv(netdev_t *dev, void *buf, size_t len, void *info) +{ + (void)dev; + (void)info; + + size_t pktlen = (size_t)rxbuf[0] - IEEE802154_FCS_LEN; + + /* check if packet data is readable */ + if (!(_state & RX_COMPLETE)) { + DEBUG("[nrf802154] recv: no packet data available\n"); + return 0; + } + + if (buf == NULL) { + if (len > 0) { + /* drop packet */ + DEBUG("[nrf802154] recv: dropping packet of length %i\n", pktlen); + } + else { + /* return packet length */ + DEBUG("[nrf802154] recv: return packet length: %i\n", pktlen); + return pktlen; + } + } + else if (len < pktlen) { + DEBUG("[nrf802154] recv: buffer is to small\n"); + return -ENOBUFS; + } + else { + DEBUG("[nrf802154] recv: reading packet of length %i\n", pktlen); + memcpy(buf, &rxbuf[1], pktlen); + } + + _reset_rx(); + + return (int)pktlen; +} + +static void _isr(netdev_t *dev) +{ + if (!nrf802154_dev.netdev.event_callback) { + return; + } + if (_state & RX_COMPLETE) { + nrf802154_dev.netdev.event_callback(dev, NETDEV_EVENT_RX_COMPLETE); + } + if (_state & TX_COMPLETE) { + nrf802154_dev.netdev.event_callback(dev, NETDEV_EVENT_TX_COMPLETE); + _state &= ~TX_COMPLETE; + } +} + +static int _get(netdev_t *dev, netopt_t opt, void *value, size_t max_len) +{ + assert(dev); + +#ifdef MODULE_NETOPT + DEBUG("[nrf802154] get: %s\n", netopt2str(opt)); +#else + DEBUG("[nrf802154] get: %d\n", opt); +#endif + + switch (opt) { + case NETOPT_CHANNEL: + assert(max_len >= sizeof(uint16_t)); + *((uint16_t *)value) = nrf802154_dev.chan; + return sizeof(uint16_t); + case NETOPT_TX_POWER: + assert(max_len >= sizeof(int16_t)); + *((int16_t *)value) = _get_txpower(); + return sizeof(int16_t); + + default: + return netdev_ieee802154_get((netdev_ieee802154_t *)dev, + opt, value, max_len); + } +} + +static int _set(netdev_t *dev, netopt_t opt, + const void *value, size_t value_len) +{ + assert(dev); + +#ifdef MODULE_NETOPT + DEBUG("[nrf802154] set: %s\n", netopt2str(opt)); +#else + DEBUG("[nrf802154] set: %d\n", opt); +#endif + + switch (opt) { + case NETOPT_CHANNEL: + assert(value_len == sizeof(uint16_t)); + _set_chan(*((uint16_t *)value)); + return sizeof(uint16_t); + case NETOPT_TX_POWER: + assert(value_len == sizeof(int16_t)); + _set_txpower(*((int16_t *)value)); + return sizeof(int16_t); + + default: + return netdev_ieee802154_set((netdev_ieee802154_t *)dev, + opt, value, value_len); + } +} + +void isr_radio(void) +{ + /* Clear flag */ + if (NRF_RADIO->EVENTS_END) { + NRF_RADIO->EVENTS_END = 0; + + /* did we just send or receive something? */ + uint8_t state = (uint8_t)NRF_RADIO->STATE; + switch(state) { + case RADIO_STATE_STATE_RxIdle: + /* only process packet if event callback is set and CRC is valid */ + if ((nrf802154_dev.netdev.event_callback) && + (NRF_RADIO->CRCSTATUS == 1) && + (netdev_ieee802154_dst_filter(&nrf802154_dev, + &rxbuf[1]) == 0)) { + _state |= RX_COMPLETE; + } + else { + _reset_rx(); + } + break; + case RADIO_STATE_STATE_Tx: + case RADIO_STATE_STATE_TxIdle: + case RADIO_STATE_STATE_TxDisable: + timer_start(NRF802154_TIMER); + DEBUG("[nrf802154] TX state: %x\n", (uint8_t)NRF_RADIO->STATE); + _state |= TX_COMPLETE; + _enable_rx(); + break; + default: + DEBUG("[nrf802154] Unhandled state: %x\n", (uint8_t)NRF_RADIO->STATE); + } + if (_state) { + nrf802154_dev.netdev.event_callback(&nrf802154_dev.netdev, NETDEV_EVENT_ISR); + } + } + else { + DEBUG("[nrf802154] Unknown interrupt triggered\n"); + } + + cortexm_isr_end(); +} + +/** + * @brief Export of the netdev interface + */ +static const netdev_driver_t nrf802154_netdev_driver = { + .send = _send, + .recv = _recv, + .init = _init, + .isr = _isr, + .get = _get, + .set = _set +}; diff --git a/drivers/include/net/netdev/ieee802154.h b/drivers/include/net/netdev/ieee802154.h index d8eb260c185ee4f478d84fd7d3acccbbdf6667cd..70da2a0a5f30f1a43e0f81c115fc9ebf91ffad0e 100644 --- a/drivers/include/net/netdev/ieee802154.h +++ b/drivers/include/net/netdev/ieee802154.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Freie Universität Berlin + * Copyright (C) 2016-2019 Freie Universität Berlin * * 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 @@ -177,6 +177,21 @@ int netdev_ieee802154_get(netdev_ieee802154_t *dev, netopt_t opt, void *value, int netdev_ieee802154_set(netdev_ieee802154_t *dev, netopt_t opt, const void *value, size_t value_len); +/** + * @brief This funtion compares destination address and pan id with addresses + * and pan id of the device + * + * this funciton is meant top be used by drivers that do not support address + * filtering in hw + * + * @param[in] dev network device descriptor + * @param[in] mhr mac header + * + * @return 0 successfull if packet is for the device + * @return 1 fails if packet is not for the device or pan + */ +int netdev_ieee802154_dst_filter(netdev_ieee802154_t *dev, const uint8_t *mhr); + #ifdef __cplusplus } #endif diff --git a/drivers/netdev_ieee802154/netdev_ieee802154.c b/drivers/netdev_ieee802154/netdev_ieee802154.c index d21e798e078079f8532fb9659018261ff74d73ab..623604f39027c0bb0847e7a0b65c214d1e3d9e9e 100644 --- a/drivers/netdev_ieee802154/netdev_ieee802154.c +++ b/drivers/netdev_ieee802154/netdev_ieee802154.c @@ -253,4 +253,30 @@ int netdev_ieee802154_set(netdev_ieee802154_t *dev, netopt_t opt, const void *va return res; } +int netdev_ieee802154_dst_filter(netdev_ieee802154_t *dev, const uint8_t *mhr) +{ + uint8_t dst_addr[IEEE802154_LONG_ADDRESS_LEN]; + le_uint16_t dst_pan; + uint8_t pan_bcast[] = IEEE802154_PANID_BCAST; + + int addr_len = ieee802154_get_dst(mhr, dst_addr, &dst_pan); + + /* filter PAN ID */ + if ((memcmp(pan_bcast, dst_pan.u8, 2) != 0) && + (memcmp(&dev->pan, dst_pan.u8, 2) != 0)) { + return 1; + } + + /* check destination address */ + if (((addr_len == IEEE802154_SHORT_ADDRESS_LEN) && + (memcmp(dev->short_addr, dst_addr, addr_len) == 0 || + memcmp(ieee802154_addr_bcast, dst_addr, addr_len) == 0)) || + ((addr_len == IEEE802154_LONG_ADDRESS_LEN) && + (memcmp(dev->long_addr, dst_addr, addr_len) == 0))) { + return 0; + } + + return 1; +} + /** @} */ diff --git a/examples/default/Makefile b/examples/default/Makefile index a8425efae8244706dd2662ed8f11a045e7445e3f..b9a2f75a02ee5cf4c4c1eab13e392f8607df3396 100644 --- a/examples/default/Makefile +++ b/examples/default/Makefile @@ -37,7 +37,7 @@ USEMODULE += ps USEMODULE += saul_default BOARD_PROVIDES_NETIF := acd52832 airfy-beacon b-l072z-lrwan1 cc2538dk fox iotlab-m3 iotlab-a8-m3 mulle \ - microbit native nrf51dk nrf51dongle nrf52dk nrf6310 openmote-cc2538 pba-d-01-kw2x \ + microbit native nrf51dk nrf51dongle nrf52dk nrf52840dk nrf6310 openmote-cc2538 pba-d-01-kw2x \ remote-pa remote-reva samr21-xpro \ spark-core telosb yunjia-nrf51822 z1 diff --git a/sys/auto_init/auto_init.c b/sys/auto_init/auto_init.c index 11e19163957f35405433379019b61785d6883304..aa66344aefa238aae9e55c5bbcb6964b843a8a9c 100644 --- a/sys/auto_init/auto_init.c +++ b/sys/auto_init/auto_init.c @@ -286,6 +286,11 @@ void auto_init(void) auto_init_sx127x(); #endif +#ifdef MODULE_NRF802154 + extern void auto_init_nrf802154(void); + auto_init_nrf802154(); +#endif + #endif /* MODULE_AUTO_INIT_GNRC_NETIF */ #ifdef MODULE_GNRC_UHCPC diff --git a/sys/auto_init/netif/auto_init_nrf802154.c b/sys/auto_init/netif/auto_init_nrf802154.c new file mode 100644 index 0000000000000000000000000000000000000000..2733c2206c78c65ea5291f7eb9d0243f0d371c0c --- /dev/null +++ b/sys/auto_init/netif/auto_init_nrf802154.c @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2019 Freie Universität Berlin + * + * 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 sys_auto_init_gnrc_netif + * @{ + * + * @file + * @brief Auto initialization the nRF52840 radio in IEEE802.15.4 mode + * + * @author Hauke Petersen <hauke.petersen@fu-berlin.de> + */ + +#ifdef MODULE_NRF802154 + + +#include "log.h" +#include "board.h" +#include "nrf802154.h" +#include "net/gnrc/netif/ieee802154.h" + +/** + * @brief Define stack parameters for the MAC layer thread + * @{ + */ +#ifndef NRF802154_MAC_STACKSIZE +#define NRF802154_MAC_STACKSIZE (THREAD_STACKSIZE_DEFAULT) +#endif +#ifndef NRF802154_MAC_PRIO +#define NRF802154_MAC_PRIO (GNRC_NETIF_PRIO) +#endif +/** @} */ + +static char _stack[NRF802154_MAC_STACKSIZE]; + +void auto_init_nrf802154(void) +{ + LOG_DEBUG("[auto_init_netif] initializing nrf802154\n"); + + gnrc_netif_ieee802154_create(_stack, + NRF802154_MAC_STACKSIZE, + NRF802154_MAC_PRIO, "nrf802154", + (netdev_t *)&nrf802154_dev); +} +#else +typedef int dont_be_pedantic; +#endif /* MODULE_NRF802154 */ + +/** @} */ diff --git a/sys/include/net/ieee802154.h b/sys/include/net/ieee802154.h index 69d4f6c4b2961c85770ea2e8e7d10a3e5d454f96..0f86442b50e8dfee50e473258ba78753dc923be9 100644 --- a/sys/include/net/ieee802154.h +++ b/sys/include/net/ieee802154.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-16 Freie Universität Berlin + * Copyright (C) 2015-2019 Freie Universität Berlin * * 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 @@ -31,6 +31,11 @@ extern "C" { #endif +/** + * @brief Default start frame delimiter + */ +#define IEEE802154_SFD (0xa7) + /** * @brief IEEE 802.15.4 address lengths * @{ @@ -144,6 +149,13 @@ extern const uint8_t ieee802154_addr_bcast[IEEE802154_ADDR_BCAST_LEN]; #define IEEE802154_DEFAULT_PANID (0x0023U) #endif +/** + * @brief IEEE802.15.4 Broadcast PANID + */ +#ifndef IEEE802154_PANID_BCAST +#define IEEE802154_PANID_BCAST { 0xff, 0xff } +#endif + /** * @brief IEEE802.15.4 default TX power (in dBm) */