You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2024/02/18 15:40:50 UTC
(nuttx) 03/04: arch/nrf52: add initial support for IEEE 802.15.4
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit b3b543e093b1ed74431b344cc569429816457e7a
Author: raiden00pl <ra...@railab.me>
AuthorDate: Fri Feb 16 21:17:42 2024 +0100
arch/nrf52: add initial support for IEEE 802.15.4
Supported features:
- frame transmition
- frame reception and filtering
- immediate ACK (incoming and outgoing)
- promiscuous mode
- delayed transmision
- radio events trace
- setting pending bit for all incoming Data Request frames
- un-slotted CSMA-CA
Work in progres features (some logic is present, but they require more work):
- beacon transmision (periodic transmition works, but requires verification)
- slotted CSMA-CA
- GTS
Fetures not implemented:
- enhanced ACK (Enh-ACK)
- enhanced beacon
- low power mode
- advanced features from IEEE 802.15.4e (DSME, TSCH)
Added examples for boards:
- nrf52832-dk: mrf24j40_6lowpan
- nrf52832-dk: mrf24j40_mac
- nrf52840-dk: ieee802154_6lowpan
- nrf52840-dk: ieee802154_mac
- nrf52840-dongle: ieee802154_mac
- nrf9160-dk-nrf52: ieee802154_6lowpan
- nrf9160-dk-nrf52: ieee802154_mac
---
.../arm/nrf52/boards/nrf52840-dk/index.rst | 17 +
Documentation/platforms/arm/nrf52/ieee802154.rst | 44 +
Documentation/platforms/arm/nrf52/index.rst | 14 +-
arch/arm/src/nrf52/CMakeLists.txt | 14 +
arch/arm/src/nrf52/Kconfig | 34 +
arch/arm/src/nrf52/Make.defs | 11 +
arch/arm/src/nrf52/nrf52_ieee802154.c | 999 +++++++++
arch/arm/src/nrf52/nrf52_ieee802154_priv.h | 144 ++
arch/arm/src/nrf52/nrf52_ieee802154_radio.c | 2116 ++++++++++++++++++++
arch/arm/src/nrf52/nrf52_ieee802154_radio.h | 246 +++
arch/arm/src/nrf52/nrf52_ieee802154_rtc.c | 392 ++++
.../arm/src/nrf52/nrf52_ieee802154_rtc.h | 100 +-
arch/arm/src/nrf52/nrf52_ieee802154_tim.c | 347 ++++
.../arm/src/nrf52/nrf52_ieee802154_tim.h | 89 +-
arch/arm/src/nrf52/nrf52_ieee802154_trace.c | 154 ++
.../arm/src/nrf52/nrf52_ieee802154_trace.h | 114 +-
.../arm/src/nrf52/nrf52_radio_ieee802154.h | 35 +-
boards/Kconfig | 9 +
.../include/nrf52_ieee802154.h} | 32 +-
.../include/nrf52_mrf24j40.h} | 45 +-
boards/arm/nrf52/common/src/CMakeLists.txt | 8 +
boards/arm/nrf52/common/src/Make.defs | 8 +
boards/arm/nrf52/common/src/nrf52_ieee802154.c | 106 +
boards/arm/nrf52/common/src/nrf52_mrf24j40.c | 136 ++
.../nrf52832-dk/configs/mrf24j40_6lowpan/defconfig | 81 +
.../nrf52832-dk/configs/mrf24j40_mac/defconfig | 60 +
boards/arm/nrf52/nrf52832-dk/include/board.h | 12 +
boards/arm/nrf52/nrf52832-dk/src/CMakeLists.txt | 8 +
boards/arm/nrf52/nrf52832-dk/src/Make.defs | 8 +
boards/arm/nrf52/nrf52832-dk/src/nrf52832-dk.h | 38 +
boards/arm/nrf52/nrf52832-dk/src/nrf52_boot.c | 6 +
boards/arm/nrf52/nrf52832-dk/src/nrf52_bringup.c | 15 +
.../nrf52832-dk/src/nrf52_ieee802154_mrf24j40.c | 177 ++
boards/arm/nrf52/nrf52832-dk/src/nrf52_spi.c | 177 ++
.../configs/ieee802154_6lowpan/defconfig | 81 +
.../nrf52840-dk/configs/ieee802154_mac/defconfig | 61 +
boards/arm/nrf52/nrf52840-dk/src/nrf52_bringup.c | 15 +-
.../configs/ieee802154_mac/defconfig | 65 +
.../nrf52/nrf52840-dongle/src/nrf52840-dongle.h | 12 +
.../arm/nrf52/nrf52840-dongle/src/nrf52_bringup.c | 24 +
.../configs/ieee802154_6lowpan/defconfig | 81 +
.../configs/ieee802154_mac/defconfig | 56 +
.../arm/nrf52/nrf9160-dk-nrf52/src/nrf52_bringup.c | 28 +
.../nrf52/nrf9160-dk-nrf52/src/nrf9160-dk-nrf52.h | 12 +
include/nuttx/wireless/ieee802154/ieee802154_mac.h | 6 +
45 files changed, 6056 insertions(+), 181 deletions(-)
diff --git a/Documentation/platforms/arm/nrf52/boards/nrf52840-dk/index.rst b/Documentation/platforms/arm/nrf52/boards/nrf52840-dk/index.rst
index 04c565c507..f48585f774 100644
--- a/Documentation/platforms/arm/nrf52/boards/nrf52840-dk/index.rst
+++ b/Documentation/platforms/arm/nrf52/boards/nrf52840-dk/index.rst
@@ -138,3 +138,20 @@ usbnsh
------
Basic NuttShell configuration (CDCACM console enabled in USB Port, at 115200 bps).
+
+ieee802154_6lowpan
+------------------
+
+Cheat Sheet. Here is a concise summary of all all the steps needed to
+run the UDP test (C=Coordinator; E=Endpoint)::
+
+ C: nsh> i8 wpan0 startpan cd:ab
+ C: nsh> i8 set saddr 0A:00
+ C: nsh> i8 set ep_saddr 0B:00
+ C: nsh> i8 acceptassoc
+ E: nsh> i8 wpan0 assoc
+ C: nsh> ifup wpan0
+ C: nsh> ifconfig <-- To get the <server-ip>
+ E: nsh> ifup wpan0
+ C: nsh> udpserver &
+ E: nsh> udpclient <server-ip> &
diff --git a/Documentation/platforms/arm/nrf52/ieee802154.rst b/Documentation/platforms/arm/nrf52/ieee802154.rst
new file mode 100644
index 0000000000..7d2c348ec5
--- /dev/null
+++ b/Documentation/platforms/arm/nrf52/ieee802154.rst
@@ -0,0 +1,44 @@
+==========================
+Nordic nRF52 IEEE 802.15.4
+==========================
+
+.. note::
+
+ This driver is highly experimental.
+ Help with development and testing will be appreciated ;)
+
+Supported features:
+
+* frame transmission
+* frame reception and filtering
+* immediate ACK (incoming and outgoing)
+* promiscuous mode
+* delayed transmision
+* radio events trace
+* setting pending bit for all incoming Data Request frames
+* un-slotted CSMA-CA
+
+Work in progres features (some logic is present, but they require more work):
+
+* beacon transmision (periodic transmition works, but requires verification)
+* slotted CSMA-CA
+* GTS
+
+Fetures not implemented:
+
+* enhanced ACK (Enh-ACK)
+* enhanced beacon
+* low power mode
+* advanced features from IEEE 802.15.4e (DSME, TSCH)
+
+Reserved peripherals
+====================
+
+This implementation reserves the following peripherals:
+
+* ``RADIO`` - used for radio operations
+
+* ``TIMER0`` - used as high resolution timer for ACK, IFS and other radio delays
+
+* ``RTC0`` - if superframe support is enabled, used as low power timer to hande
+ superframe events
diff --git a/Documentation/platforms/arm/nrf52/index.rst b/Documentation/platforms/arm/nrf52/index.rst
index 2bb73de03c..912422ee17 100644
--- a/Documentation/platforms/arm/nrf52/index.rst
+++ b/Documentation/platforms/arm/nrf52/index.rst
@@ -51,9 +51,9 @@ Peripheral Support
The following list indicates peripherals supported in NuttX:
-========== ======= =====
+========== ======= ===============
Peripheral Support Notes
-========== ======= =====
+========== ======= ===============
GPIO Yes
GPIOTE Yes
I2S No
@@ -64,7 +64,7 @@ PPI Yes
PWM Yes
QDEC No
QSPI Yes
-RADIO Yes Basic
+RADIO Yes BLE, IEEE 802.15.4
RNG Yes
RTC Yes
SAADC Yes
@@ -78,7 +78,7 @@ UART Yes
UARTE No
USBD Yes
WDT Yes
-========== ======= =====
+========== ======= ===============
Peripherals such as AAR, ACL, CCM, ECB are not directly used by NuttX since they
are part of BLE controller implementation (link).
@@ -206,6 +206,11 @@ is provided with settings already set.
Note that in this case, some peripherals (mostly those related to BLE) will be unavailable. Some PPI
channels will also be ocuppied (``NRF52_PPI_NUM_CONFIGURABLE_CHANNELS`` will be set accordingly in this case).
+IEEE 802.15.4 Support
+=====================
+
+Details about IEEE 802.15.4 support for nRF52 can be found in :doc:`ieee802154`.
+
Supported Boards
================
@@ -214,3 +219,4 @@ Supported Boards
:maxdepth: 1
boards/*/*
+ ieee802154.rst
diff --git a/arch/arm/src/nrf52/CMakeLists.txt b/arch/arm/src/nrf52/CMakeLists.txt
index 409db39c17..80b8c84408 100644
--- a/arch/arm/src/nrf52/CMakeLists.txt
+++ b/arch/arm/src/nrf52/CMakeLists.txt
@@ -94,6 +94,20 @@ endif()
if(CONFIG_NRF52_RADIO)
list(APPEND SRCS nrf52_radio.c)
+
+ if(CONFIG_NRF52_RADIO_IEEE802154)
+ list(APPEND SRCS nrf52_ieee802154_radio.c)
+ list(APPEND SRCS nrf52_ieee802154_tim.c)
+ list(APPEND SRCS nrf52_ieee802154.c)
+
+ if(CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME)
+ list(APPEND SRCS nrf52_ieee802154_rtc.c)
+ endif()
+
+ if(CONFIG_NRF52_RADIO_IEEE802154_TRACE)
+ list(APPEND SRCS nrf52_ieee802154_trace.c)
+ endif()
+ endif()
endif()
if(CONFIG_NRF52_TIMER)
diff --git a/arch/arm/src/nrf52/Kconfig b/arch/arm/src/nrf52/Kconfig
index 887404af28..5bd0a293bb 100644
--- a/arch/arm/src/nrf52/Kconfig
+++ b/arch/arm/src/nrf52/Kconfig
@@ -629,6 +629,40 @@ config NRF52_RADIO_CUSTOM
bool "RADIO uses custom IRQ handlers"
default n
+config NRF52_RADIO_IEEE802154
+ bool "RADIO IEEE802.15.4 protocol"
+ default n
+ depends on NRF52_HAVE_IEEE802154
+ select ARMV7M_USEBASEPRI
+ select ARCH_RAMVECTORS
+ select ARCH_IRQPRIO
+ select NRF52_RADIO_CUSTOM
+ select NRF52_TIMER0
+
+if NRF52_RADIO_IEEE802154
+
+config NRF52_RADIO_IEEE802154_SUPERFRAME
+ bool "RADIO IEEE802.15.4 superframe support"
+ default n
+ select NRF52_RTC0
+ select NRF52_USE_LFCLK
+
+config NRF52_RADIO_IEEE802154_GTS_SLOTS
+ int "RADIO IEEE802.15.4 GTS slots"
+ default 2
+ depends on NRF52_RADIO_IEEE802154_SUPERFRAME
+
+config NRF52_RADIO_IEEE802154_TRACE
+ bool "RADIO IEEE802.15.4 trace support"
+ default n
+
+config NRF52_RADIO_IEEE802154_TRACE_BUFSIZE
+ int "RADIO IEEE802.15.4 trace buffer size"
+ depends on NRF52_RADIO_IEEE802154_TRACE
+ default 1024
+
+endif
+
endif #NRF52_RADIO
endmenu # "RADIO Configuration"
diff --git a/arch/arm/src/nrf52/Make.defs b/arch/arm/src/nrf52/Make.defs
index c570f66ff4..12650bc976 100644
--- a/arch/arm/src/nrf52/Make.defs
+++ b/arch/arm/src/nrf52/Make.defs
@@ -89,6 +89,17 @@ endif
ifeq ($(CONFIG_NRF52_RADIO),y)
CHIP_CSRCS += nrf52_radio.c
+ifeq ($(CONFIG_NRF52_RADIO_IEEE802154),y)
+CHIP_CSRCS += nrf52_ieee802154_radio.c
+CHIP_CSRCS += nrf52_ieee802154_tim.c
+CHIP_CSRCS += nrf52_ieee802154.c
+ifeq ($(CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME),y)
+CHIP_CSRCS += nrf52_ieee802154_rtc.c
+endif
+ifeq ($(CONFIG_NRF52_RADIO_IEEE802154_TRACE),y)
+CHIP_CSRCS += nrf52_ieee802154_trace.c
+endif
+endif
endif
ifeq ($(CONFIG_NRF52_TIMER),y)
diff --git a/arch/arm/src/nrf52/nrf52_ieee802154.c b/arch/arm/src/nrf52/nrf52_ieee802154.c
new file mode 100644
index 0000000000..28956ce75e
--- /dev/null
+++ b/arch/arm/src/nrf52/nrf52_ieee802154.c
@@ -0,0 +1,999 @@
+/****************************************************************************
+ * arch/arm/src/nrf52/nrf52_ieee802154.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <debug.h>
+#include <string.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/mutex.h>
+#include <nuttx/wqueue.h>
+
+#include <nuttx/mm/iob.h>
+
+#include "nrf52_ieee802154_trace.h"
+
+#include "nrf52_ieee802154_priv.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef CONFIG_NRF52_RADIO_CUSTOM
+# error RADIO custom interrupts must be enabled
+#endif
+
+#ifndef CONFIG_SCHED_HPWORK
+# error High priority work queue required in this driver
+#endif
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* IEEE 802.15.4 radio data */
+
+static struct nrf52_radioi8_dev_s g_nrf52_radioi8;
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* Set/get radio attributes */
+
+static int nrf52_radioi8_setrxmode(struct nrf52_radioi8_dev_s *dev,
+ int mode);
+static int nrf52_radioi8_setpanid(struct nrf52_radioi8_dev_s *dev,
+ const uint8_t *panid);
+static int nrf52_radioi8_setsaddr(struct nrf52_radioi8_dev_s *dev,
+ const uint8_t *saddr);
+static int nrf52_radioi8_seteaddr(struct nrf52_radioi8_dev_s *dev,
+ const uint8_t *eaddr);
+static int nrf52_radioi8_setcoordsaddr(struct nrf52_radioi8_dev_s *dev,
+ const uint8_t *saddr);
+static int nrf52_radioi8_setdevmode(struct nrf52_radioi8_dev_s *dev,
+ uint8_t mode);
+
+/* Radio ops */
+
+static int nrf52_radioi8_bind(struct ieee802154_radio_s *radio,
+ struct ieee802154_radiocb_s *radiocb);
+static int nrf52_radioi8_reset(struct ieee802154_radio_s *radio);
+static int nrf52_radioi8_getattr(struct ieee802154_radio_s *radio,
+ enum ieee802154_attr_e attr,
+ union ieee802154_attr_u *attrval);
+static int nrf52_radioi8_setattr(struct ieee802154_radio_s *radio,
+ enum ieee802154_attr_e attr,
+ const union ieee802154_attr_u *attrval);
+static int nrf52_radioi8_txnotify(struct ieee802154_radio_s *radio,
+ bool gts);
+static int nrf52_radioi8_txdelayed(struct ieee802154_radio_s *radio,
+ struct ieee802154_txdesc_s *txdesc,
+ uint32_t symboldelay);
+static int nrf52_radioi8_rxenable(struct ieee802154_radio_s *radio,
+ bool enable);
+static int nrf52_radioi8_setchannel(struct nrf52_radioi8_dev_s *dev,
+ uint8_t chan);
+static int nrf52_radioi8_setcca(struct nrf52_radioi8_dev_s *dev,
+ struct ieee802154_cca_s *cca);
+static int nrf52_radioi8_energydetect(struct ieee802154_radio_s *radio,
+ uint32_t nsymbols);
+
+static int
+nrf52_radioi8_beaconstart(struct ieee802154_radio_s *radio,
+ const struct ieee802154_superframespec_s *sfspec,
+ struct ieee802154_beaconframe_s *beacon);
+static int
+nrf52_radioi8_beaconupdate(struct ieee802154_radio_s *radio,
+ struct ieee802154_beaconframe_s *beacon);
+static int nrf52_radioi8_beaconstop(struct ieee802154_radio_s *radio);
+static int
+nrf52_radioi8_sfupdate(struct ieee802154_radio_s *radio,
+ const struct ieee802154_superframespec_s *sfspec);
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf52_radioi8_setrxmode
+ *
+ * Description:
+ * Set the RX mode (normal, promiscuous, no CRC).
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_setrxmode(struct nrf52_radioi8_dev_s *dev,
+ int mode)
+{
+ wlinfo("setrxmode %d\n", mode);
+
+ if (mode < NRF52_RXMODE_NORMAL || mode > NRF52_RXMODE_NOCRC)
+ {
+ return -EINVAL;
+ }
+
+ dev->state.rxmode = mode;
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_setpanid
+ *
+ * Description:
+ * Define the PAN ID the device is operating on.
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_setpanid(struct nrf52_radioi8_dev_s *dev,
+ const uint8_t *panid)
+{
+ wlinfo("setpanid: %02X:%02X\n", panid[0], panid[1]);
+ IEEE802154_PANIDCOPY(dev->state.addr.panid, panid);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_setsaddr
+ *
+ * Description:
+ * Define the device short address. The following addresses are special:
+ *
+ * FFFEh : Broadcast
+ * FFFFh : Unspecified
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_setsaddr(struct nrf52_radioi8_dev_s *dev,
+ const uint8_t *saddr)
+{
+ wlinfo("setsaddr: %02X:%02X\n", saddr[0], saddr[1]);
+ IEEE802154_SADDRCOPY(dev->state.addr.saddr, saddr);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_seteaddr
+ *
+ * Description:
+ * Define the device extended address. The following addresses are special:
+ *
+ * ffffffffffffffffh : Unspecified
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_seteaddr(struct nrf52_radioi8_dev_s *dev,
+ const uint8_t *eaddr)
+{
+ int i = 0;
+
+ wlinfo("seteaddr: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
+ eaddr[0], eaddr[1], eaddr[2], eaddr[3], eaddr[4], eaddr[5],
+ eaddr[6], eaddr[7]);
+
+ for (i = 0; i < 8; i++)
+ {
+ dev->state.addr.eaddr[i] = eaddr[i];
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_setcoordsaddr
+ *
+ * Description:
+ * Define the coordinator short address. The following addresses are
+ * special:
+ *
+ * FFFEh : Broadcast
+ * FFFFh : Unspecified
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_setcoordsaddr(struct nrf52_radioi8_dev_s *dev,
+ const uint8_t *saddr)
+{
+ IEEE802154_SADDRCOPY(dev->state.addr.saddr, saddr);
+
+ wlinfo("setcoordsaddr: %02X:%02X\n", saddr[0], saddr[1]);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_setcoordeaddr
+ *
+ * Description:
+ * Define the coordinator extended address. The following addresses are
+ * special:
+ *
+ * FFFFFFFFFFFFFFFFh : Unspecified
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_setcoordeaddr(struct nrf52_radioi8_dev_s *dev,
+ const uint8_t *eaddr)
+{
+ int i = 0;
+
+ wlinfo("setcoordeaddr: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
+ eaddr[0], eaddr[1], eaddr[2], eaddr[3], eaddr[4], eaddr[5],
+ eaddr[6], eaddr[7]);
+
+ for (i = 0; i < 8; i++)
+ {
+ dev->state.addr.eaddr[i] = eaddr[i];
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_setdevmode
+ *
+ * Description:
+ * Define the device behaviour: endpoint, coord or PAN coord.
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_setdevmode(struct nrf52_radioi8_dev_s *dev,
+ uint8_t mode)
+{
+ wlinfo("setdevmode %d\n", mode);
+
+ if (mode < IEEE802154_DEVMODE_ENDPOINT ||
+ mode > IEEE802154_DEVMODE_PANCOORD)
+ {
+ return -EINVAL;
+ }
+
+ dev->state.devmode = mode;
+ return OK;
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_bind
+ *
+ * Description:
+ * Bind radio callbacks.
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_bind(struct ieee802154_radio_s *radio,
+ struct ieee802154_radiocb_s *radiocb)
+{
+ struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)radio;
+
+ DEBUGASSERT(dev != NULL);
+ dev->radiocb = radiocb;
+ return OK;
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_reset
+ *
+ * Description:
+ * Reset radio.
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_reset(struct ieee802154_radio_s *radio)
+{
+ struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)radio;
+ struct ieee802154_cca_s cca;
+ int ret = OK;
+
+#ifdef CONFIG_NRF52_RADIO_IEEE802154_TRACE
+ /* Reset trace */
+
+ nrf52_radioi8_trace_init();
+#endif
+
+ /* Reset radio state */
+
+ memset(&dev->state, 0, sizeof(struct nrf52_radioi8_state_s));
+
+ /* Initialize radio in IEEE 802.15.4 mode */
+
+ ret = dev->radio->ops->reset(dev->radio);
+ if (ret < 0)
+ {
+ goto errout;
+ }
+
+ /* Reset TIMER */
+
+ dev->tim->ops->reset(dev);
+
+#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME
+ /* Reset RTC */
+
+ dev->rtc->ops->reset(dev);
+#endif
+
+ /* Set channel */
+
+ nrf52_radioi8_setchannel(dev, 11);
+
+ /* Configure default CCA:
+ * - CCA mode ED
+ * - no carrier sense
+ * - recommenced ED threshold -69 dBm
+ */
+
+ cca.use_ed = 1;
+ cca.use_cs = 0;
+ cca.edth = 0x60;
+ cca.csth = 0x00;
+ nrf52_radioi8_setcca(dev, &cca);
+
+ /* Configure initial RX mode */
+
+ nrf52_radioi8_setrxmode(dev, NRF52_RXMODE_NORMAL);
+
+errout:
+ return ret;
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_getattr
+ *
+ * Description:
+ * Get radio attribute.
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_getattr(struct ieee802154_radio_s *radio,
+ enum ieee802154_attr_e attr,
+ union ieee802154_attr_u *attrval)
+{
+ struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)radio;
+ int ret = OK;
+
+ switch (attr)
+ {
+ case IEEE802154_ATTR_MAC_EADDR:
+ {
+ memcpy(&attrval->mac.eaddr[0], &dev->state.addr.eaddr[0], 8);
+ ret = IEEE802154_STATUS_SUCCESS;
+ break;
+ }
+
+ case IEEE802154_ATTR_MAC_MAX_FRAME_WAITTIME:
+ {
+ attrval->mac.max_frame_waittime =
+ dev->radio->state.max_frame_waittime;
+ ret = IEEE802154_STATUS_SUCCESS;
+ break;
+ }
+
+ case IEEE802154_ATTR_PHY_SYMBOL_DURATION:
+ {
+ attrval->phy.symdur_picosec = (IEEE802154_SYMBOL_US * 1000000);
+ ret = IEEE802154_STATUS_SUCCESS;
+ break;
+ }
+
+ case IEEE802154_ATTR_PHY_CHAN:
+ {
+ attrval->phy.chan = dev->state.chan;
+ ret = IEEE802154_STATUS_SUCCESS;
+ break;
+ }
+
+ case IEEE802154_ATTR_PHY_FCS_LEN:
+ {
+ attrval->phy.fcslen = 2;
+ ret = IEEE802154_STATUS_SUCCESS;
+ break;
+ }
+
+ case IEEE802154_ATTR_PHY_REGDUMP:
+ {
+ NRF52_RADIO_DUMPREGS(dev->radio->lower);
+ break;
+ }
+
+#ifdef CONFIG_NRF52_RADIO_IEEE802154_TRACE
+ case IEEE802154_ATTR_PHY_TRACEDUMP:
+ {
+ nrf52_radioi8_trace_dump();
+ break;
+ }
+#endif
+
+ default:
+ {
+ ret = IEEE802154_STATUS_UNSUPPORTED_ATTRIBUTE;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_setattr
+ *
+ * Description:
+ * Set radio attribute.
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_setattr(struct ieee802154_radio_s *radio,
+ enum ieee802154_attr_e attr,
+ const union ieee802154_attr_u *attrval)
+{
+ struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)radio;
+ int ret = IEEE802154_STATUS_SUCCESS;
+
+ switch (attr)
+ {
+ case IEEE802154_ATTR_MAC_PANID:
+ {
+ nrf52_radioi8_setpanid(dev, attrval->mac.panid);
+ break;
+ }
+
+ case IEEE802154_ATTR_MAC_SADDR:
+ {
+ nrf52_radioi8_setsaddr(dev, attrval->mac.saddr);
+ break;
+ }
+
+ case IEEE802154_ATTR_MAC_EADDR:
+ {
+ nrf52_radioi8_seteaddr(dev, attrval->mac.eaddr);
+ break;
+ }
+
+ case IEEE802154_ATTR_MAC_COORD_SADDR:
+ {
+ nrf52_radioi8_setcoordsaddr(dev, attrval->mac.coordsaddr);
+ break;
+ }
+
+ case IEEE802154_ATTR_MAC_COORD_EADDR:
+ {
+ nrf52_radioi8_setcoordeaddr(dev, attrval->mac.coordeaddr);
+ break;
+ }
+
+ case IEEE802154_ATTR_MAC_PROMISCUOUS_MODE:
+ {
+ if (attrval->mac.promisc_mode)
+ {
+ nrf52_radioi8_setrxmode(dev, NRF52_RXMODE_PROMISC);
+ }
+ else
+ {
+ nrf52_radioi8_setrxmode(dev, NRF52_RXMODE_NORMAL);
+ }
+ break;
+ }
+
+ case IEEE802154_ATTR_PHY_CHAN:
+ {
+ nrf52_radioi8_setchannel(dev, attrval->phy.chan);
+ break;
+ }
+
+ case IEEE802154_ATTR_MAC_DEVMODE:
+ {
+ nrf52_radioi8_setdevmode(dev, attrval->mac.devmode);
+ break;
+ }
+
+ default:
+ {
+ ret = IEEE802154_STATUS_UNSUPPORTED_ATTRIBUTE;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_txnotify
+ *
+ * Description:
+ * Driver callback invoked when new TX data is available. This is a
+ * stimulus perform an out-of-cycle poll and, thereby, reduce the TX
+ * latency.
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_txnotify(struct ieee802154_radio_s *radio,
+ bool gts)
+{
+ struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)radio;
+ int ret = OK;
+
+ if (gts)
+ {
+ ret = dev->radio->ops->gts_poll(dev);
+ }
+ else
+ {
+ ret = dev->radio->ops->csma_poll(dev);
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_txdelayed
+ *
+ * Description:
+ * Transmit a packet without regard to supeframe structure after a certain
+ * number of symbols. This function is used to send Data Request
+ * responses. It can also be used to send data immediately if the delay
+ * is set to 0.
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_txdelayed(struct ieee802154_radio_s *radio,
+ struct ieee802154_txdesc_s *txdesc,
+ uint32_t symboldelay)
+{
+ struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)radio;
+ int ret = OK;
+
+ /* Get exclusive access to the radio device */
+
+ ret = nxmutex_lock(&dev->lock);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ /* There should never be more than one of these transactions at once. */
+
+ DEBUGASSERT(!dev->state.txdelayed_busy);
+
+ dev->state.txdelayed_desc = txdesc;
+ dev->state.txdelayed_busy = true;
+
+ /* TODO: should we add txdelayed to queue ? */
+
+ if (dev->radio->state.csma_busy)
+ {
+ return -EBUSY;
+ }
+
+ /* Wait for ACKTX done - we start transmition in
+ * nrf52_radioi8_state_acktx()
+ */
+
+ if (dev->radio->state.state == NRF52_RADIO_STATE_ACKTX)
+ {
+ goto out;
+ }
+
+ /* Setup TX */
+
+ dev->radio->ops->norm_setup(dev, txdesc->frame, false);
+
+ if (symboldelay == 0)
+ {
+ /* Send now */
+
+ dev->radio->ops->norm_trigger(dev);
+ }
+ else
+ {
+ /* Run TIMER - TX is handled in timer isr */
+
+ dev->tim->ops->setup(dev, NRF52_TIMER_CHAN_TXDELAY, symboldelay);
+ }
+
+out:
+ nxmutex_unlock(&dev->lock);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_rxenable
+ *
+ * Description:
+ * Enable/Disable receiver.
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_rxenable(struct ieee802154_radio_s *radio,
+ bool enable)
+{
+ struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)radio;
+
+ wlinfo("rxenable %d\n", enable);
+ return dev->radio->ops->rxenable(dev, enable);
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_energydetect
+ *
+ * Description:
+ * Start the energy detect measurement.
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_energydetect(struct ieee802154_radio_s *radio,
+ uint32_t nsymbols)
+{
+ struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)radio;
+
+ return dev->radio->ops->energydetect(dev, nsymbols);
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_setchannel
+ *
+ * Description:
+ * Define the current radio channel the device is operating on.
+ * In the 2.4 GHz, there are 16 channels, each 2 MHz wide, 5 MHz spacing:
+ *
+ * Chan MHz Chan MHz Chan MHz Chan MHz
+ * 11 2405 15 2425 19 2445 23 2465
+ * 12 2410 16 2430 20 2450 24 2470
+ * 13 2415 17 2435 21 2455 25 2475
+ * 14 2420 18 2440 22 2460 26 2480
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_setchannel(struct nrf52_radioi8_dev_s *dev,
+ uint8_t chan)
+{
+ int ret = OK;
+
+ wlinfo("setchannel: %u\n", (unsigned)chan);
+
+ if (dev->state.chan == chan)
+ {
+ return OK;
+ }
+
+ if (chan < 11 || chan > 26)
+ {
+ wlerr("Invalid chan: %d\n", chan);
+ return -EINVAL;
+ }
+
+ ret = dev->radio->ops->setchannel(dev, chan);
+ if (ret < 0)
+ {
+ wlerr("dev->radio->ops->setchannel failed %d\n", ret);
+ return -EINVAL;
+ }
+
+ dev->state.chan = chan;
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_setcca
+ *
+ * Description:
+ * Define the Clear Channel Assessement method.
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_setcca(struct nrf52_radioi8_dev_s *dev,
+ struct ieee802154_cca_s *cca)
+{
+ int ret = OK;
+
+ if (!cca->use_ed && !cca->use_cs)
+ {
+ return -EINVAL;
+ }
+
+ if (cca->use_cs && cca->csth > 0x0f)
+ {
+ return -EINVAL;
+ }
+
+ /* Configure CCA */
+
+ ret = dev->radio->ops->setcca(dev, cca);
+ if (ret < 0)
+ {
+ wlerr("dev->radio->ops->setcca failed %d\n", ret);
+ return -EINVAL;
+ }
+
+ memcpy(&dev->state.cca, cca, sizeof(struct ieee802154_cca_s));
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_beaconstart
+ *
+ * Description:
+ * Start beacon.
+ *
+ ****************************************************************************/
+
+static int
+nrf52_radioi8_beaconstart(struct ieee802154_radio_s *radio,
+ const struct ieee802154_superframespec_s *sfspec,
+ struct ieee802154_beaconframe_s *beacon)
+{
+#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME
+ struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)radio;
+ irqstate_t flags;
+
+ if (sfspec->pancoord)
+ {
+ flags = enter_critical_section();
+
+ /* Local copy */
+
+ memcpy(&dev->state.sf, (void *)sfspec,
+ sizeof(struct ieee802154_superframespec_s));
+
+ /* Setup beacon transmition */
+
+ dev->radio->ops->beacon_setup(dev, beacon->bf_data, beacon->bf_len);
+
+ /* Configure RTC events */
+
+ dev->rtc->ops->setup(dev, &dev->state.sf);
+
+ /* Start RTC */
+
+ dev->rtc->ops->start(dev);
+
+ leave_critical_section(flags);
+ }
+ else
+ {
+ /* TODO: missing logic for non-PAN coord */
+
+ return -ENOTTY;
+ }
+
+ return OK;
+#else
+ return -ENOTSUP;
+#endif
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_beaconupdate
+ *
+ * Description:
+ * Update beacon.
+ *
+ ****************************************************************************/
+
+static int
+nrf52_radioi8_beaconupdate(struct ieee802154_radio_s *radio,
+ struct ieee802154_beaconframe_s *beacon)
+{
+#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME
+ struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)radio;
+ irqstate_t flags;
+
+ flags = enter_critical_section();
+
+ /* Arm the beacon TX buffer */
+
+ memcpy(&dev->radio->beaconbuf[1], beacon->bf_data, beacon->bf_len);
+
+ /* Length = Frame data + CRC */
+
+ dev->radio->beaconbuf[0] = beacon->bf_len + 2;
+
+ leave_critical_section(flags);
+
+ return OK;
+#else
+ return -ENOTSUP;
+#endif
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_beaconstop
+ *
+ * Description:
+ * Stop beacon.
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_beaconstop(struct ieee802154_radio_s *radio)
+{
+#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME
+ struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)radio;
+ irqstate_t flags;
+
+ flags = enter_critical_section();
+
+ /* Stop RTC */
+
+ dev->rtc->ops->stop(dev);
+
+ leave_critical_section(flags);
+
+ return OK;
+#else
+ return -ENOTSUP;
+#endif
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_sfupdate
+ *
+ * Description:
+ * Update super frame.
+ *
+ ****************************************************************************/
+
+static int
+nrf52_radioi8_sfupdate(struct ieee802154_radio_s *radio,
+ const struct ieee802154_superframespec_s *sfspec)
+{
+#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME
+ struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)radio;
+ irqstate_t flags;
+
+ flags = enter_critical_section();
+
+ /* Local copy */
+
+ memcpy(&dev->state.sf, (void *)sfspec,
+ sizeof(struct ieee802154_superframespec_s));
+
+ /* If we are operating on a beacon-enabled network, use slotted CSMA */
+
+ if (sfspec->beaconorder < 15)
+ {
+ /* Need slotted CSMA-CA */
+
+ dev->radio->state.slotted = true;
+
+ /* Configure RTC */
+
+ dev->rtc->ops->setup(dev, &dev->state.sf);
+
+ /* Wait for beacon to sync */
+
+ dev->radio->state.wait_for_beacon = true;
+ }
+ else
+ {
+ /* Need un-slotted CSMA-CA */
+
+ dev->radio->state.slotted = false;
+ }
+
+ leave_critical_section(flags);
+
+ return OK;
+#else
+ return -ENOTSUP;
+#endif
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf52_radioi8_register
+ *
+ * Description:
+ * Register NRF52 radio in IEE802154 mode.
+ *
+ ****************************************************************************/
+
+struct ieee802154_radio_s *
+nrf52_radioi8_register(struct nrf52_radio_board_s *board)
+{
+ struct nrf52_radioi8_dev_s *dev = &g_nrf52_radioi8;
+
+ /* Reset data */
+
+ memset(&g_nrf52_radioi8, 0, sizeof(struct nrf52_radioi8_dev_s));
+
+ /* Allow exclusive access to the privmac struct */
+
+ nxmutex_init(&dev->lock);
+
+ /* Initialize lower-half radio */
+
+ dev->radio = nrf52_radioi8_radio_init(dev, board);
+ if (dev->radio == NULL)
+ {
+ wlerr("nrf52_radioi8_radio_init failed %d\n", -errno);
+ return NULL;
+ }
+
+ DEBUGASSERT(dev->radio->ops->txstart);
+ DEBUGASSERT(dev->radio->ops->notify_noack);
+ DEBUGASSERT(dev->radio->ops->ccastart);
+ DEBUGASSERT(dev->radio->ops->rxenable);
+ DEBUGASSERT(dev->radio->ops->energydetect);
+ DEBUGASSERT(dev->radio->ops->setchannel);
+ DEBUGASSERT(dev->radio->ops->setcca);
+ DEBUGASSERT(dev->radio->ops->norm_setup);
+ DEBUGASSERT(dev->radio->ops->norm_trigger);
+#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME
+ DEBUGASSERT(dev->radio->ops->beacon_setup);
+ DEBUGASSERT(dev->radio->ops->beacon_tx);
+#endif
+ DEBUGASSERT(dev->radio->ops->reset);
+ DEBUGASSERT(dev->radio->ops->csma_poll);
+ DEBUGASSERT(dev->radio->ops->gts_poll);
+
+ /* Initialize TIMER */
+
+ dev->tim = nrf52_radioi8_tim_init(dev);
+ if (dev->tim == NULL)
+ {
+ wlerr("nrf52_radioi8_tim_init failed %d\n", -errno);
+ return NULL;
+ }
+
+ DEBUGASSERT(dev->tim->ops->setup);
+ DEBUGASSERT(dev->tim->ops->stop);
+ DEBUGASSERT(dev->tim->ops->reset);
+
+#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME
+ /* Initialize RTC */
+
+ dev->rtc = nrf52_radioi8_rtc_init(dev);
+ if (dev->rtc == NULL)
+ {
+ wlerr("nrf52_radioi8_rtc_init failed %d\n", -errno);
+ return NULL;
+ }
+
+ DEBUGASSERT(dev->rtc->ops->setup);
+ DEBUGASSERT(dev->rtc->ops->start);
+ DEBUGASSERT(dev->rtc->ops->stop);
+ DEBUGASSERT(dev->rtc->ops->reset);
+#endif
+
+ /* Connect MAC ops */
+
+ dev->macops.bind = nrf52_radioi8_bind;
+ dev->macops.reset = nrf52_radioi8_reset;
+ dev->macops.getattr = nrf52_radioi8_getattr;
+ dev->macops.setattr = nrf52_radioi8_setattr;
+ dev->macops.txnotify = nrf52_radioi8_txnotify;
+ dev->macops.txdelayed = nrf52_radioi8_txdelayed;
+ dev->macops.rxenable = nrf52_radioi8_rxenable;
+ dev->macops.energydetect = nrf52_radioi8_energydetect;
+ dev->macops.beaconstart = nrf52_radioi8_beaconstart;
+ dev->macops.beaconupdate = nrf52_radioi8_beaconupdate;
+ dev->macops.beaconstop = nrf52_radioi8_beaconstop;
+ dev->macops.sfupdate = nrf52_radioi8_sfupdate;
+
+ return &dev->macops;
+}
diff --git a/arch/arm/src/nrf52/nrf52_ieee802154_priv.h b/arch/arm/src/nrf52/nrf52_ieee802154_priv.h
new file mode 100644
index 0000000000..04e542ee3a
--- /dev/null
+++ b/arch/arm/src/nrf52/nrf52_ieee802154_priv.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+ * arch/arm/src/nrf52/nrf52_ieee802154_priv.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_PRIV_H
+#define __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_PRIV_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+
+#include <nuttx/wireless/ieee802154/ieee802154_mac.h>
+#include <nuttx/wireless/ieee802154/ieee802154_radio.h>
+
+#include "nrf52_ieee802154_radio.h"
+#include "nrf52_ieee802154_rtc.h"
+#include "nrf52_ieee802154_tim.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* GTS slots */
+
+#ifndef CONFIG_NRF52_RADIO_IEEE802154_GTS_SLOTS
+# define NRF52_GTS_SLOTS 0
+#else
+# define NRF52_GTS_SLOTS CONFIG_NRF52_RADIO_IEEE802154_GTS_SLOTS
+#endif
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* RX modes */
+
+enum nrf52_ieee802154_rxmode_e
+{
+ NRF52_RXMODE_NORMAL,
+ NRF52_RXMODE_PROMISC,
+ NRF52_RXMODE_NOCRC
+};
+
+/* Device modes */
+
+enum nrf52_ieee802154_devmode_e
+{
+ NRF52_DEVMODE_ENDPOINT,
+ NRF52_DEVMODE_COORD,
+ NRF52_DEVMODE_PANCOORD
+};
+
+/* IEEE 802.15.4 device state */
+
+struct nrf52_radioi8_state_s
+{
+ /* MAC Attributes */
+
+ struct ieee802154_addr_s addr; /* Address */
+ struct ieee802154_cca_s cca; /* Clear channel assessement method */
+
+ /* TX CSMA */
+
+ struct ieee802154_txdesc_s *txdelayed_desc;
+ struct ieee802154_txdesc_s *csma_desc;
+
+ /* Radio state */
+
+ uint8_t chan; /* 11 to 26 for the 2.4 GHz band */
+ uint8_t devmode; /* device mode: endpoint, coord, PAN coord */
+ uint8_t rxmode; /* Reception mode: Normal, no CRC, promiscuous */
+
+ /* TX state */
+
+ bool txdelayed_busy; /* No CSMA transfer */
+
+#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME
+ /* Superframe data */
+
+ struct ieee802154_superframespec_s sf;
+
+ /* TX GTS */
+
+ struct ieee802154_txdesc_s *gts_desc[NRF52_GTS_SLOTS];
+ bool gts_busy[NRF52_GTS_SLOTS];
+#endif
+};
+
+/* IEEE 802.15.4 radio device */
+
+struct nrf52_radioi8_dev_s
+{
+ /* The public device instance - must be first */
+
+ struct ieee802154_radio_s macops;
+
+ /* Registered callbacks */
+
+ struct ieee802154_radiocb_s *radiocb;
+
+ /* Radio interface */
+
+ struct nrf52_radioi8_radio_s *radio;
+
+ /* High resolution timer */
+
+ struct nrf52_radioi8_tim_s *tim;
+
+ /* Low resolution, low power timer */
+
+#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME
+ struct nrf52_radioi8_rtc_s *rtc;
+#endif
+
+ /* Radio state */
+
+ struct nrf52_radioi8_state_s state;
+
+ /* Exclusive access to this struct */
+
+ mutex_t lock;
+};
+
+#endif /* __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_PRIV_H */
diff --git a/arch/arm/src/nrf52/nrf52_ieee802154_radio.c b/arch/arm/src/nrf52/nrf52_ieee802154_radio.c
new file mode 100644
index 0000000000..e4c671504d
--- /dev/null
+++ b/arch/arm/src/nrf52/nrf52_ieee802154_radio.c
@@ -0,0 +1,2116 @@
+/****************************************************************************
+ * arch/arm/src/nrf52/nrf52_ieee802154_radio.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <debug.h>
+#include <errno.h>
+#include <stdio.h>
+#include <sys/param.h>
+
+#include <nuttx/wqueue.h>
+#include <nuttx/mm/iob.h>
+
+#include "nrf52_ieee802154_radio.h"
+#include "nrf52_ieee802154_trace.h"
+
+#include "nrf52_ieee802154_priv.h"
+
+#include "hardware/nrf52_utils.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Constant from NRF52 manual */
+
+#define NRF52_ED_RSSISCALE (4)
+
+/* ED configuration:
+ * - IRQ on EDEND event (sampling of energy detection complete)
+ * - shortcut between READY and EDSTART
+ * - shortcut between EDEND and DISABLE
+ *
+ * Set in nrf52_radioi8_energydetect() reset in nrf52_radioi8_isr_radio().
+ *
+ * EDSTART task set in nrf52_radioi8_energydetect().
+ */
+
+#define IEEE802154_ED_INT (RADIO_INT_EDEND)
+#define IEEE802154_ED_SHORTS (RADIO_SHORTS_READY_EDSTART | \
+ RADIO_SHORTS_EDEND_DISABLE)
+
+/* RX configuration:
+ * - IRQ on END event (packet recveived)
+ * - shortcut between RXREADY and START
+ * - shortcut between END and DISABLE
+ *
+ * Set in nrf52_radioi8_rxenable() reset in nrf52_radioi8_rxenable().
+ *
+ * RXEN task set in nrf52_radioi8_rxenable() and
+ * nrf52_radioi8_isr_radio() after RX handled and no pending ACKTX.
+ */
+
+#define IEEE802154_RX_INT (RADIO_INT_END)
+#define IEEE802154_RX_SHORTS (RADIO_SHORTS_RXREADY_START | \
+ RADIO_SHORTS_END_DISABLE)
+
+/* NOTE: for TX we trigger interrupts on PHYEND event, not END! */
+
+/* TX CCA un-slotted configuration:
+ * - IRQ on PHYEND event
+ * - IRQ on CCABUSY event
+ * - shortcut between TXREADY and START
+ * - shortcut between PHYEND and DISABLE
+ * - shortcut between RXREADY and CCASTART
+ * - shortcut between CCAIDLE and STOP
+ * - shortcut between CCAIDLE and TXEN
+ *
+ * Set in nrf52_radioi8_radio_norm_setup() reset in
+ * nrf52_radioi8_isr_radio().
+ *
+ * CCASTART task set in nrf52_radioi8_isr_tim() when CCA transfer.
+ */
+
+#define IEEE802154_TXCCAUNSLT_INT (RADIO_INT_PHYEND | \
+ RADIO_INT_CCABUSY)
+#define IEEE802154_TXCCAUNSLT_SHORTS (RADIO_SHORTS_TXREADY_START | \
+ RADIO_SHORTS_PHYEND_DISABLE | \
+ RADIO_SHORTS_RXREADY_CCASTART | \
+ RADIO_SHORTS_CCAIDLE_STOP | \
+ RADIO_SHORTS_CCAIDLE_TXEN)
+
+/* TX CCA slotted configuration:
+ * - IRQ on PHYEND event
+ * - IRQ on CCABUSY event
+ * - IRQ on CCAIDLE event
+ * - shortcut between TXREADY and START
+ * - shortcut between PHYEND and DISABLE
+ *
+ * Set in nrf52_radioi8_radio_norm_setup() reset in
+ * nrf52_radioi8_isr_radio().
+ *
+ * CCASTART task set in nrf52_radioi8_isr_tim() when CCA transfer.
+ */
+
+#define IEEE802154_TXCCASLT_INT (RADIO_INT_PHYEND | \
+ RADIO_INT_CCAIDLE | \
+ RADIO_INT_CCABUSY)
+#define IEEE802154_TXCCASLT_SHORTS (RADIO_SHORTS_TXREADY_START | \
+ RADIO_SHORTS_PHYEND_DISABLE | \
+ RADIO_SHORTS_RXREADY_CCASTART)
+
+/* TX no-CCA configuration:
+ * - IRQ on PHYEND event
+ * - shortcut between TXREADY and START
+ * - shortcut between PHYEND and DISABLE
+ *
+ * Set in nrf52_radioi8_radio_norm_setup() reset in
+ * nrf52_radioi8_isr_radio().
+ *
+ * TXEN task set in nrf52_radioi8_radio_norm_trigger() when non-CCA
+ * transfer or in nrf52_radioi8_isr_tim() for TXDELAY.
+ */
+
+#define IEEE802154_TX_INT (RADIO_INT_PHYEND)
+#define IEEE802154_TX_SHORTS (RADIO_SHORTS_TXREADY_START | \
+ RADIO_SHORTS_PHYEND_DISABLE)
+
+/* ACK configuration:
+ * - IRQ on PHYEND event
+ * - shortcut between PHYEND and DISABLE
+ *
+ * Set in nrf52_radioi8_ack_transmit reset in nrf52_radioi8_isr_radio().
+ *
+ * TXEN task set in nrf52_radioi8_ack_transmit().
+ * START task set in nrf52_radioi8_isr_tim().
+ */
+
+#define IEEE802154_ACKTX_INT (RADIO_INT_PHYEND)
+#define IEEE802154_ACKTX_SHORTS (RADIO_SHORTS_PHYEND_DISABLE)
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static void nrf52_radioi8_rx_parse(struct nrf52_radioi8_dev_s *dev,
+ uint8_t *ftype, uint8_t *cmdtype);
+static void nrf52_radioi8_ack_transmit(struct nrf52_radioi8_dev_s *dev);
+static bool nrf52_radioi8_filter(struct nrf52_radioi8_dev_s *dev);
+#if NRF52_GTS_SLOTS > 0
+static void nrf52_radioi8_gts_setup(struct nrf52_radioi8_dev_s *dev,
+ uint8_t fifo, struct iob_s *frame);
+#endif
+
+/* Ops */
+
+static void nrf52_radioi8_txstart(struct nrf52_radioi8_dev_s *dev);
+static void nrf52_radioi8_ccastart(struct nrf52_radioi8_dev_s *dev);
+static void nrf52_radioi8_notify_noack(struct nrf52_radioi8_dev_s *dev);
+static int nrf52_radioi8_rxenable(struct nrf52_radioi8_dev_s *dev,
+ bool enable);
+static int nrf52_radioi8_energydetect(struct nrf52_radioi8_dev_s *dev,
+ uint32_t nsymbols);
+static int nrf52_radioi8_setchannel(struct nrf52_radioi8_dev_s *dev,
+ uint8_t chan);
+static int nrf52_radioi8_setcca(struct nrf52_radioi8_dev_s *dev,
+ struct ieee802154_cca_s *cca);
+static void nrf52_radioi8_norm_setup_buf(struct nrf52_radioi8_dev_s *dev,
+ uint8_t *buf, bool csma);
+static void nrf52_radioi8_norm_setup(struct nrf52_radioi8_dev_s *dev,
+ struct iob_s *frame, bool csma);
+static void nrf52_radioi8_norm_trigger(struct nrf52_radioi8_dev_s *dev);
+#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME
+static void nrf52_radioi8_beacon_setup(struct nrf52_radioi8_dev_s *dev,
+ uint8_t *data, uint8_t len);
+static void nrf52_radioi8_beacon_tx(struct nrf52_radioi8_dev_s *dev);
+#endif
+static int nrf52_radioi8_reset(struct nrf52_radioi8_radio_s *dev);
+static int nrf52_radioi8_csmapoll(struct nrf52_radioi8_dev_s *dev);
+static int nrf52_radioi8_gtspoll(struct nrf52_radioi8_dev_s *dev);
+
+/* Interrupts logic */
+
+static void nrf52_radioi8_work_noack(void *arg);
+static void nrf52_radioi8_work_rx(void *arg);
+static void nrf52_radioi8_work_tx(void *arg);
+static void nrf52_radioi8_work_busy(void *arg);
+static void nrf52_radioi8_work_ed(void *arg);
+static void nrf52_radioi8_state_rx(struct nrf52_radioi8_dev_s *dev);
+static void nrf52_radioi8_state_tx(struct nrf52_radioi8_dev_s *dev);
+static void nrf52_radioi8_state_acktx(struct nrf52_radioi8_dev_s *dev);
+static void nrf52_radioi8_state_ed(struct nrf52_radioi8_dev_s *dev);
+static int nrf52_radioi8_isr_radio(int irq, void *context, void *arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Packet buffers - must be byte aligned in RAM.
+ *
+ * NOTE: The first byte is PHR, the last byte is LQI.
+ */
+
+static uint8_t aligned_data(8)
+ g_nrf52_radioi8_rxbuf[IEEE802154_MAX_PHY_PACKET_SIZE + 2];
+
+static uint8_t aligned_data(8)
+ g_nrf52_radioi8_txbuf[IEEE802154_MAX_PHY_PACKET_SIZE + 2];
+
+static uint8_t aligned_data(8)
+ g_nrf52_radioi8_ackbuf[IEEE802154_ACK_FRAME_SIZE + 1];
+
+#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME
+static uint8_t aligned_data(8)
+ g_nrf52_radioi8_beaconbuf[IEEE802154_MAX_PHY_PACKET_SIZE + 2];
+#endif
+
+/* Radio ops */
+
+static struct nrf52_radioi8_radio_ops_s g_radioi8_radio_ops =
+{
+ .txstart = nrf52_radioi8_txstart,
+ .ccastart = nrf52_radioi8_ccastart,
+ .notify_noack = nrf52_radioi8_notify_noack,
+ .rxenable = nrf52_radioi8_rxenable,
+ .energydetect = nrf52_radioi8_energydetect,
+ .setchannel = nrf52_radioi8_setchannel,
+ .setcca = nrf52_radioi8_setcca,
+ .norm_setup = nrf52_radioi8_norm_setup,
+ .norm_trigger = nrf52_radioi8_norm_trigger,
+#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME
+ .beacon_setup = nrf52_radioi8_beacon_setup,
+ .beacon_tx = nrf52_radioi8_beacon_tx,
+#endif
+ .reset = nrf52_radioi8_reset,
+ .csma_poll = nrf52_radioi8_csmapoll,
+ .gts_poll = nrf52_radioi8_gtspoll
+};
+
+/* Radio interface */
+
+static struct nrf52_radioi8_radio_s g_radioi8_radio;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf52_radioi8_rx_parse
+ *
+ * Description:
+ * Get the RX frame type and command type if present.
+ *
+ ****************************************************************************/
+
+static void nrf52_radioi8_rx_parse(struct nrf52_radioi8_dev_s *dev,
+ uint8_t *ftype, uint8_t *cmdtype)
+{
+ uint16_t *frame_ctrl = NULL;
+ uint8_t smode = 0;
+ uint8_t dmode = 0;
+ uint8_t panid_comp = 0;
+ int i = 0;
+
+ /* Frame starts from offset 1 */
+
+ i = 1;
+
+ /* Frame ctrl */
+
+ frame_ctrl = (uint16_t *)&dev->radio->rxbuf[i];
+ i += sizeof(uint16_t);
+
+ /* Frame seq */
+
+ i += 1;
+
+ /* Return now if a given frame is not a command frame */
+
+ *ftype = ((*frame_ctrl & IEEE802154_FRAMECTRL_FTYPE) >>
+ IEEE802154_FRAMECTRL_SHIFT_FTYPE);
+ if (*ftype != IEEE802154_FRAME_COMMAND)
+ {
+ return;
+ }
+
+ /* Now we have to find the offset for the frame command type */
+
+ smode = ((*frame_ctrl & IEEE802154_FRAMECTRL_SADDR) >>
+ IEEE802154_FRAMECTRL_SHIFT_SADDR);
+
+ dmode = ((*frame_ctrl & IEEE802154_FRAMECTRL_DADDR) >>
+ IEEE802154_FRAMECTRL_SHIFT_DADDR);
+
+ panid_comp = ((*frame_ctrl & IEEE802154_FRAMECTRL_PANIDCOMP) >>
+ IEEE802154_FRAMECTRL_SHIFT_PANIDCOMP);
+
+ if (dmode != IEEE802154_ADDRMODE_NONE)
+ {
+ i += IEEE802154_PANIDSIZE;
+
+ if (dmode == IEEE802154_ADDRMODE_SHORT)
+ {
+ i += IEEE802154_SADDRSIZE;
+ }
+ else if (dmode == IEEE802154_ADDRMODE_EXTENDED)
+ {
+ i += IEEE802154_EADDRSIZE;
+ }
+ }
+
+ if (smode != IEEE802154_ADDRMODE_NONE)
+ {
+ if (!panid_comp)
+ {
+ i += IEEE802154_PANIDSIZE;
+ }
+
+ if (smode == IEEE802154_ADDRMODE_SHORT)
+ {
+ i += IEEE802154_SADDRSIZE;
+ }
+ else if (smode == IEEE802154_ADDRMODE_EXTENDED)
+ {
+ i += IEEE802154_EADDRSIZE;
+ }
+ }
+
+ *cmdtype = dev->radio->rxbuf[i];
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_ack_transmit
+ *
+ * Description:
+ * Transmit ACK.
+ *
+ ****************************************************************************/
+
+static void nrf52_radioi8_ack_transmit(struct nrf52_radioi8_dev_s *dev)
+{
+ struct nrf52_radio_dev_s *lower = NULL;
+ uint8_t *ackbuf = dev->radio->ackbuf;
+ uint32_t regval = 0;
+ uint8_t ftype = 0;
+ uint8_t cmdtype = 0;
+ bool pending = false;
+
+ DEBUGASSERT(dev);
+ lower = dev->radio->lower;
+
+ /* Restore RX after ACK - we already are in DISABLE state so no need to
+ * disable RX
+ */
+
+ if (dev->radio->state.rxenabled)
+ {
+ dev->radio->state.rxrestore = true;
+ }
+
+ /* Clear events */
+
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_READY_OFFSET, 0);
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_TXREADY_OFFSET, 0);
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_RXREADY_OFFSET, 0);
+
+ /* Fill ACK buffer */
+
+ ackbuf[0] = IEEE802154_ACK_FRAME_SIZE;
+ ackbuf[1] = 0x02;
+ ackbuf[2] = 0;
+ ackbuf[3] = dev->radio->rxbuf[3];
+
+ /* Get RX frame type */
+
+ nrf52_radioi8_rx_parse(dev, &ftype, &cmdtype);
+
+ /* If this is ACK for Data Request command - set frame pending flag */
+
+ if (dev->state.devmode != NRF52_DEVMODE_ENDPOINT &&
+ ftype == IEEE802154_FRAME_COMMAND &&
+ cmdtype == IEEE802154_CMD_DATA_REQ)
+ {
+ pending = true;
+ }
+
+ /* Set frame pedning flag for this ACK */
+
+ if (pending)
+ {
+ ackbuf[1] |= 0x10;
+ }
+
+ /* Configure shorts and interrupts */
+
+ NRF52_RADIO_SHRTSET(lower, IEEE802154_ACKTX_SHORTS);
+ NRF52_RADIO_INTEN(lower, IEEE802154_ACKTX_INT);
+
+ /* Set packet pointer - buffer must be aligned */
+
+ regval = (uint32_t)ackbuf;
+ DEBUGASSERT(nrf52_easydma_valid(regval));
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_PACKETPTR_OFFSET, regval);
+
+ /* Set state to ACK */
+
+ dev->radio->state.state = NRF52_RADIO_STATE_ACKTX;
+
+ /* Enable TX - start TX is called from timer interrupt */
+
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_TASKS_TXEN_OFFSET, 1);
+
+ /* Run TIMER - TX is handled in timer isr */
+
+ nrf52_radioi8_trace_put(RADIO_TRACE_ACKTX, pending);
+ dev->tim->ops->setup(dev, NRF52_TIMER_CHAN_ACK, IEEE802154_ACKIFS_SYMBOLS);
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_filter
+ *
+ * Description:
+ * Filter received frames.
+ *
+ ****************************************************************************/
+
+static bool nrf52_radioi8_filter(struct nrf52_radioi8_dev_s *dev)
+{
+ struct ieee802154_addr_s addr;
+ uint8_t *rx = &dev->radio->rxbuf[1];
+ uint16_t *fc = (uint16_t *)&rx[0];
+
+ /* Promiscuous mode */
+
+ if (dev->state.rxmode == NRF52_RXMODE_PROMISC)
+ {
+ return true;
+ }
+
+ /* Beacon frame */
+
+ if (((*fc & IEEE802154_FRAMECTRL_FTYPE) == IEEE802154_FRAME_BEACON) &&
+ IEEE802154_PANIDCMP(IEEE802154_PANID_UNSPEC, &dev->state.addr.panid))
+ {
+ return true;
+ }
+
+ /* Get destination address */
+
+ IEEE802154_PANIDCOPY(addr.panid, &rx[3]);
+ addr.mode = ((*fc & IEEE802154_FRAMECTRL_DADDR) >>
+ IEEE802154_FRAMECTRL_SHIFT_DADDR);
+ if (addr.mode == IEEE802154_ADDRMODE_SHORT)
+ {
+ IEEE802154_SADDRCOPY(addr.saddr, &rx[5]);
+ }
+ else if (addr.mode == IEEE802154_ADDRMODE_EXTENDED)
+ {
+ IEEE802154_EADDRCOPY(addr.eaddr, &rx[5]);
+ }
+
+ /* PAN ID match */
+
+ if (!IEEE802154_PANIDCMP(IEEE802154_PANID_UNSPEC, dev->state.addr.panid) &&
+ !IEEE802154_PANIDCMP(addr.panid, &dev->state.addr.panid))
+ {
+ return false;
+ }
+
+ /* Destination address match */
+
+ if (addr.mode == IEEE802154_ADDRMODE_SHORT)
+ {
+ if (IEEE802154_SADDRCMP(addr.saddr,
+ &dev->state.addr.saddr))
+ {
+ return true;
+ }
+
+ else if (IEEE802154_SADDRCMP(addr.saddr,
+ IEEE802154_SADDR_UNSPEC))
+ {
+ return true;
+ }
+ }
+ else if (addr.mode == IEEE802154_ADDRMODE_EXTENDED)
+ {
+ if (IEEE802154_EADDRCMP(addr.eaddr,
+ &dev->state.addr.eaddr))
+ {
+ return true;
+ }
+
+ else if (IEEE802154_EADDRCMP(addr.eaddr,
+ IEEE802154_EADDR_UNSPEC))
+ {
+ return true;
+ }
+ }
+
+ /* Otherwise drop this frame */
+
+ return false;
+}
+
+#if NRF52_GTS_SLOTS > 0
+/****************************************************************************
+ * Name: nrf52_radioi8_gts_setup
+ *
+ * Description:
+ * Setup a GTS transaction.
+ *
+ ****************************************************************************/
+
+static void nrf52_radioi8_gts_setup(struct nrf52_radioi8_dev_s *dev,
+ uint8_t fifo, struct iob_s *frame)
+{
+ /* Missing logic */
+
+ ASSERT(0);
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_dopoll_gts
+ *
+ * Description:
+ * This function is called in order to perform an out-of-sequence TX poll.
+ *
+ ****************************************************************************/
+
+static void nrf52_radioi8_dopoll_gts(void *arg)
+{
+ struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)arg;
+ int gts = 0;
+ int len = 0;
+
+ /* Get exclusive access to the driver */
+
+ while (nxmutex_lock(&dev->lock) < 0)
+ {
+ }
+
+ for (gts = 0; gts < NRF52_GTS_SLOTS; gts++)
+ {
+ if (!dev->state.gts_busy[gts])
+ {
+ len = dev->radiocb->poll(dev->radiocb, true,
+ &dev->state.gts_desc[gts]);
+
+ if (len > 0)
+ {
+ /* Now the txdesc is in use */
+
+ dev->state.gts_busy[gts] = 1;
+
+ /* Setup the GTS transaction */
+
+ nrf52_radioi8_gts_setup(dev, gts,
+ dev->state.gts_desc[gts]->frame);
+ }
+ }
+ }
+
+ nxmutex_unlock(&dev->lock);
+}
+#endif /* NRF52_GTS_SLOTS > 0 */
+
+/****************************************************************************
+ * Name: nrf52_radioi8_txstart
+ *
+ * Description:
+ * Start transmition, TX must be armed (TXEN must be set).
+ *
+ ****************************************************************************/
+
+static void nrf52_radioi8_txstart(struct nrf52_radioi8_dev_s *dev)
+{
+ struct nrf52_radio_dev_s *lower = NULL;
+
+ DEBUGASSERT(dev);
+ lower = dev->radio->lower;
+
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_TASKS_START_OFFSET, 1);
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_ccastart
+ *
+ * Description:
+ * Start CCA, RX must be armed (RXEN must be set).
+ *
+ ****************************************************************************/
+
+static void nrf52_radioi8_ccastart(struct nrf52_radioi8_dev_s *dev)
+{
+ struct nrf52_radio_dev_s *lower = NULL;
+
+ DEBUGASSERT(dev);
+ lower = dev->radio->lower;
+
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_TASKS_CCASTART_OFFSET, 1);
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_notify_noack
+ *
+ * Description:
+ * Notify Radio layer about noack event.
+ *
+ ****************************************************************************/
+
+static void nrf52_radioi8_notify_noack(struct nrf52_radioi8_dev_s *dev)
+{
+ /* If flag is set - no ACK was received */
+
+ if (dev->radio->state.waitack == true)
+ {
+ /* Notify MAC layer */
+
+ DEBUGASSERT(work_available(&dev->radio->noackwork));
+ work_queue(HPWORK, &dev->radio->noackwork,
+ nrf52_radioi8_work_noack, (void *)dev, 0);
+
+ /* Clear flag */
+
+ dev->radio->state.waitack = false;
+ }
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_rxenable
+ *
+ * Description:
+ * Enable/Disable receiver.
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_rxenable(struct nrf52_radioi8_dev_s *dev,
+ bool enable)
+{
+ struct nrf52_radio_dev_s *lower = NULL;
+ uint32_t regval = 0;
+
+ DEBUGASSERT(dev);
+ lower = dev->radio->lower;
+
+ if (enable)
+ {
+ nrf52_radioi8_trace_put(RADIO_TRACE_RXENABLE, 0);
+
+ /* Clear events */
+
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_END_OFFSET, 0);
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_READY_OFFSET, 0);
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_PHYEND_OFFSET, 0);
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_TXREADY_OFFSET, 0);
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_RXREADY_OFFSET, 0);
+
+ /* Configure shorts and interrupts */
+
+ NRF52_RADIO_SHRTSET(lower, IEEE802154_RX_SHORTS);
+ NRF52_RADIO_INTEN(lower, IEEE802154_RX_INT);
+
+ /* Set packet pointer - buffer must be aligned */
+
+ regval = (uint32_t)dev->radio->rxbuf;
+ DEBUGASSERT(nrf52_easydma_valid(regval));
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_PACKETPTR_OFFSET, regval);
+
+ /* Set state to RX */
+
+ dev->radio->state.state = NRF52_RADIO_STATE_RX;
+
+ /* Start RX */
+
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_TASKS_RXEN_OFFSET, 1);
+ }
+ else
+ {
+ nrf52_radioi8_trace_put(RADIO_TRACE_RXDISABLE, 0);
+
+ /* Disalbe interrups and shorts */
+
+ NRF52_RADIO_INTCLR(lower, IEEE802154_RX_INT);
+ NRF52_RADIO_SHRTSET(lower, 0);
+
+ /* Disable RX */
+
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_TASKS_DISABLE_OFFSET, 1);
+ }
+
+ /* Store state */
+
+ dev->radio->state.rxenabled = enable;
+
+ /* Data returned by callback in ISR */
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_energydetect
+ *
+ * Description:
+ * Start the energy detect measurement.
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_energydetect(struct nrf52_radioi8_dev_s *dev,
+ uint32_t nsymbols)
+{
+ struct nrf52_radio_dev_s *lower = NULL;
+
+ DEBUGASSERT(dev);
+ lower = dev->radio->lower;
+
+ /* Clear events */
+
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_EDEND_OFFSET, 0);
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_READY_OFFSET, 0);
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_RXREADY_OFFSET, 0);
+
+ /* Configure shortucts and interrupts */
+
+ NRF52_RADIO_SHRTSET(lower, IEEE802154_ED_SHORTS);
+ NRF52_RADIO_INTEN(lower, IEEE802154_ED_INT);
+
+ /* Configure ED symbols */
+
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EDCNT_OFFSET, nsymbols);
+
+ /* Set state to ENERGY_DETECT (ED) */
+
+ dev->radio->state.state = NRF52_RADIO_STATE_ED;
+
+ /* Start RX */
+
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_TASKS_RXEN_OFFSET, 1);
+
+ /* Data returned by callback in ISR */
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_setchannel
+ *
+ * Description:
+ * Define the current radio channel the device is operating on.
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_setchannel(struct nrf52_radioi8_dev_s *dev,
+ uint8_t chan)
+{
+ struct nrf52_radio_dev_s *lower = NULL;
+ uint32_t freq = 2405 + 5 * (chan - 11);
+
+ DEBUGASSERT(dev);
+ lower = dev->radio->lower;
+
+ return NRF52_RADIO_FREQSET(lower, freq);
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_setcca
+ *
+ * Description:
+ * Configure the Clear Channel Assessement.
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_setcca(struct nrf52_radioi8_dev_s *dev,
+ struct ieee802154_cca_s *cca)
+{
+ struct nrf52_radio_dev_s *lower = NULL;
+ struct nrf52_radio_cca_s c;
+
+ DEBUGASSERT(dev);
+ lower = dev->radio->lower;
+
+ /* Fill radio sturcture */
+
+ memset(&c, 0, sizeof(struct nrf52_radio_cca_s));
+
+ if (cca->use_ed && !cca->use_cs)
+ {
+ c.mode = NRF52_RADIO_CCA_ED;
+ }
+ else if (~cca->use_ed && cca->use_cs)
+ {
+ c.mode = NRF52_RADIO_CCA_CARRIER;
+ }
+ else if (cca->use_ed && cca->use_cs)
+ {
+ c.mode = NRF52_RADIO_CCA_CARRIER_AND_ED;
+ }
+
+ c.edthres = cca->edth;
+ c.corrthres = cca->csth;
+ c.corrcnt = 5;
+
+ /* Configure radio */
+
+ NRF52_RADIO_CCACFG(lower, &c);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_norm_setup_buf
+ *
+ * Description:
+ * Setup a normal transaction (non GTS) from buffer.
+ *
+ ****************************************************************************/
+
+static void nrf52_radioi8_norm_setup_buf(struct nrf52_radioi8_dev_s *dev,
+ uint8_t *buf, bool csma)
+{
+ struct nrf52_radio_dev_s *lower = NULL;
+ uint32_t regval = 0;
+
+ DEBUGASSERT(dev);
+ lower = dev->radio->lower;
+
+ nrf52_radioi8_trace_put(RADIO_TRACE_CSMASETUP, csma);
+
+ /* If RX is enabled - we have to temporarly disable it */
+
+ if (dev->radio->state.rxenabled)
+ {
+ dev->macops.rxenable((struct ieee802154_radio_s *)dev, false);
+
+ /* Restore RX after TX completed */
+
+ dev->radio->state.rxrestore = true;
+ }
+
+ /* Set packet pointer - buffer must be aligned */
+
+ regval = (uint32_t)buf;
+ DEBUGASSERT(nrf52_easydma_valid(regval));
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_PACKETPTR_OFFSET, regval);
+
+ if (csma)
+ {
+ /* Clear events */
+
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_END_OFFSET, 0);
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_READY_OFFSET, 0);
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_PHYEND_OFFSET, 0);
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_TXREADY_OFFSET, 0);
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_CCABUSY_OFFSET, 0);
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_CCAIDLE_OFFSET, 0);
+
+ /* Configure shorts and interrupts */
+
+ if (dev->radio->state.slotted)
+ {
+#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME
+ NRF52_RADIO_SHRTSET(lower, IEEE802154_TXCCASLT_SHORTS);
+ NRF52_RADIO_INTEN(lower, IEEE802154_TXCCASLT_INT);
+#else
+ ASSERT(0);
+#endif
+ }
+ else
+ {
+ NRF52_RADIO_SHRTSET(lower, IEEE802154_TXCCAUNSLT_SHORTS);
+ NRF52_RADIO_INTEN(lower, IEEE802154_TXCCAUNSLT_INT);
+ }
+
+ dev->radio->state.state = NRF52_RADIO_STATE_TX_CSMA;
+ }
+ else
+ {
+ /* Clear events */
+
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_END_OFFSET, 0);
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_READY_OFFSET, 0);
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_PHYEND_OFFSET, 0);
+
+ /* Configure shorts and interrupts */
+
+ NRF52_RADIO_SHRTSET(lower, IEEE802154_TX_SHORTS);
+ NRF52_RADIO_INTEN(lower, IEEE802154_TX_INT);
+ dev->radio->state.state = NRF52_RADIO_STATE_TX_NOCSMA;
+ }
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_norm_setup
+ *
+ * Description:
+ * Setup a normal transaction (non GTS).
+ *
+ ****************************************************************************/
+
+static void nrf52_radioi8_norm_setup(struct nrf52_radioi8_dev_s *dev,
+ struct iob_s *frame, bool csma)
+{
+ /* The first byte in TX buffer is PHR */
+
+ dev->radio->txbuf[0] = frame->io_len;
+
+ /* Allocate space for CRC */
+
+ dev->radio->txbuf[0] += 2;
+
+ /* Copy frame to RX buffer - we must send from aligned buffer */
+
+ memcpy(&dev->radio->txbuf[1], &frame->io_data[0], frame->io_len);
+
+ /* Setup buffer */
+
+ nrf52_radioi8_norm_setup_buf(dev, dev->radio->txbuf, csma);
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_trg_csma
+ *
+ * Description:
+ * Trigger transaction with CSMA-CA.
+ *
+ ****************************************************************************/
+
+static void nrf52_radioi8_trg_csma(struct nrf52_radioi8_dev_s *dev)
+{
+ uint32_t delay = 0;
+
+ /* Set state to TX */
+
+ dev->radio->state.state = NRF52_RADIO_STATE_TX;
+
+ /* Need slotted CSMA-CA */
+
+ if (dev->radio->state.slotted)
+ {
+#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME
+ if (!dev->radio->state.csma_busy)
+ {
+ /* Initial backoff state */
+
+ dev->radio->state.NB = 0;
+ dev->radio->state.CW = IEEE802154_CW0;
+ }
+
+ /* Battery life extension */
+
+ if (dev->radio->state.ble)
+ {
+ dev->radio->state.BE = MIN(2, dev->radio->state.min_be);
+ }
+ else
+ {
+ dev->radio->state.BE = dev->radio->state.min_be;
+ }
+
+ /* Get random unit backoff period delay */
+
+ delay = rand() % ((1 << dev->radio->state.BE) - 1);
+
+ /* TODO:
+ * - locate backoff period boundary
+ * - perform CCA on backoff period boundary
+ */
+
+ ASSERT(0);
+#else
+ ASSERT(0);
+#endif
+ }
+
+ /* Need un-slotted CSMA-CA */
+
+ else
+ {
+ if (!dev->radio->state.csma_busy)
+ {
+ /* Initial backoff state */
+
+ dev->radio->state.NB = 0;
+ dev->radio->state.BE = dev->radio->state.min_be;
+ }
+
+ /* Get random unit backoff period delay */
+
+ delay = rand() % ((1 << dev->radio->state.BE) - 1);
+ }
+
+ /* CSMA is in use */
+
+ dev->radio->state.csma_busy = true;
+ nrf52_radioi8_trace_put(RADIO_TRACE_CSMATRIGGER, delay);
+
+ dev->tim->ops->setup(dev, NRF52_TIMER_CHAN_CSMADELAY,
+ delay * IEEE802154_UNIT_BACKOFF_PERIOD);
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_trg_nocsma
+ *
+ * Description:
+ * Trigger transaction without CSMA-CA;
+ *
+ ****************************************************************************/
+
+static void nrf52_radioi8_trg_nocsma(struct nrf52_radioi8_dev_s *dev)
+{
+ struct nrf52_radio_dev_s *lower = NULL;
+
+ DEBUGASSERT(dev);
+ lower = dev->radio->lower;
+
+ /* Set state to TX */
+
+ dev->radio->state.state = NRF52_RADIO_STATE_TX;
+
+ /* Start TX - we transmit immediately */
+
+ nrf52_radioi8_trace_put(RADIO_TRACE_NOCSMATRIGGER,
+ dev->radio->state.state);
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_TASKS_TXEN_OFFSET, 1);
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_norm_trigger
+ *
+ * Description:
+ * Trigger normal transaction (non GTS).
+ *
+ ****************************************************************************/
+
+static void nrf52_radioi8_norm_trigger(struct nrf52_radioi8_dev_s *dev)
+{
+ /* Wait for ACK */
+
+ if (dev->radio->txbuf[1] & IEEE802154_FRAMECTRL_ACKREQ)
+ {
+ dev->radio->state.waitack = true;
+ }
+
+ /* CSMA transmition */
+
+ if (dev->radio->state.state == NRF52_RADIO_STATE_TX_CSMA)
+ {
+ nrf52_radioi8_trg_csma(dev);
+ }
+
+ /* No-CSMA transmition */
+
+ else if (dev->radio->state.state == NRF52_RADIO_STATE_TX_NOCSMA)
+ {
+ nrf52_radioi8_trg_nocsma(dev);
+ }
+
+ /* Invalid state */
+
+ else
+ {
+ /* We should not be there */
+
+ DEBUGASSERT(0);
+ }
+}
+
+#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME
+/****************************************************************************
+ * Name: nrf52_radioi8_beacon_setup
+ *
+ * Description:
+ * Setup a beacon frame transfer
+ *
+ ****************************************************************************/
+
+static void nrf52_radioi8_beacon_setup(struct nrf52_radioi8_dev_s *dev,
+ uint8_t *data, uint8_t len)
+{
+ /* Set beacon TX buffer */
+
+ memcpy(&dev->radio->beaconbuf[1], data, len);
+
+ /* Length = Frame data + CRC */
+
+ dev->radio->beaconbuf[0] = len + 2;
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_beacon_tx
+ *
+ * Description:
+ * Transmit a beacon frame (non CSMA-CA transfer).
+ *
+ ****************************************************************************/
+
+static void nrf52_radioi8_beacon_tx(struct nrf52_radioi8_dev_s *dev)
+{
+ /* Beacon buffer is ready to send - transmit as non CSMA-CA */
+
+ nrf52_radioi8_norm_setup_buf(dev, dev->radio->beaconbuf, false);
+
+ /* Send now */
+
+ nrf52_radioi8_norm_trigger(dev);
+}
+#endif
+
+/****************************************************************************
+ * Name: nrf52_radioi8_reset
+ *
+ * Description:
+ * Reset radio state to work with IEEE 802.15.4.
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_reset(struct nrf52_radioi8_radio_s *dev)
+{
+ struct nrf52_radio_dev_s *radio = NULL;
+ struct nrf52_radio_crc_s crc;
+ struct nrf52_radio_pktcfg_s pcfg;
+ int ret = OK;
+
+ DEBUGASSERT(dev);
+ radio = dev->lower;
+
+ /* Reset radio state */
+
+ memset(&dev->state, 0, sizeof(struct nrf52_radioi8_radio_data_s));
+
+ /* Reset radio */
+
+ NRF52_RADIO_RESET(radio);
+
+ /* MAC prameters */
+
+ dev->state.max_frame_waittime = IEEE802154_MAX_FRAME_WAITTIME;
+ dev->state.max_csma_backoffs = IEEE802154_MAX_CSMA_BACKOFFS;
+ dev->state.min_be = IEEE802154_MIN_BE;
+ dev->state.max_be = IEEE802154_MAX_BE;
+
+ /* Set radio IEEE 802.15.4 mode */
+
+ ret = NRF52_RADIO_MODESET(radio, NRF52_RADIO_MODE_IEEE802154);
+ if (ret < 0)
+ {
+ goto errout;
+ }
+
+ /* Configure CRC */
+
+ crc.len = 2;
+ crc.skip = NRF52_RADIO_CRC_SKIPADDR_IEEE802154;
+ crc.poly = 0x011021;
+ crc.init = 0;
+
+ ret = NRF52_RADIO_CRCCFG(radio, &crc);
+ if (ret < 0)
+ {
+ goto errout;
+ }
+
+ /* Configure packet for IEEE 802.15.4 mode */
+
+ pcfg.max_len = IEEE802154_MAX_PHY_PACKET_SIZE;
+ pcfg.stat_len = 0;
+ pcfg.bal_len = 0;
+ pcfg.lf_len = 8;
+ pcfg.s0_len = 0;
+ pcfg.s1_len = 0;
+ pcfg.ci_len = 0;
+ pcfg.pl_len = NRF52_RADIO_PREAMBLE_32BITZERO;
+ pcfg.term_len = 0;
+ pcfg.crcinc = true;
+ pcfg.endian = false;
+ pcfg.whiteen = false;
+
+ ret = NRF52_RADIO_PKTCFG(radio, &pcfg);
+ if (ret < 0)
+ {
+ goto errout;
+ }
+
+ /* Disable hardware TIFS */
+
+ NRF52_RADIO_PUTREG(radio, NRF52_RADIO_MODECNF0_OFFSET,
+ RADIO_MODECNF0_RU);
+
+ /* Set TX power */
+
+ NRF52_RADIO_TXPWRSET(radio, 0);
+
+ /* TODO: Configure LNA/PA */
+
+errout:
+ return ret;
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_dopoll_csma
+ *
+ * Description:
+ * Out-of-sequence TX poll.
+ *
+ ****************************************************************************/
+
+void nrf52_radioi8_dopoll_csma(void *arg)
+{
+ struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)arg;
+ int len = 0;
+
+ /* Get exclusive access to the driver */
+
+ while (nxmutex_lock(&dev->lock) < 0)
+ {
+ }
+
+ /* If this a CSMA transaction and we have room in the CSMA */
+
+ if (!dev->radio->state.csma_busy)
+ {
+ wlinfo("Polling for frame\n");
+ len = dev->radiocb->poll(dev->radiocb, false, &dev->state.csma_desc);
+
+ if (len > 0)
+ {
+ wlinfo("Frame received. Frame length: %d\n", len);
+
+ /* Setup the CSMA transaction */
+
+ dev->radio->ops->norm_setup(dev, dev->state.csma_desc->frame,
+ true);
+ dev->radio->ops->norm_trigger(dev);
+ }
+ }
+
+ nxmutex_unlock(&dev->lock);
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_csmapoll
+ *
+ * Description:
+ * Handle CSMA poll.
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_csmapoll(struct nrf52_radioi8_dev_s *dev)
+{
+ /* Is our single work structure available? It may not be if there are
+ * pending interrupt actions and we will have to ignore the Tx
+ * availability action.
+ */
+
+ if (work_available(&dev->radio->csma_pollwork))
+ {
+ /* Schedule to serialize the poll on the worker thread. */
+
+ work_queue(HPWORK, &dev->radio->csma_pollwork,
+ nrf52_radioi8_dopoll_csma, dev, 0);
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_gtspoll
+ *
+ * Description:
+ * Handle GTS poll.
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_gtspoll(struct nrf52_radioi8_dev_s *dev)
+{
+#if NRF52_GTS_SLOTS > 0
+ /* Is our single work structure available? It may not be if there are
+ * pending interrupt actions and we will have to ignore the Tx
+ * availability action.
+ */
+
+ if (work_available(&dev->radio->gts_pollwork))
+ {
+ /* Schedule to serialize the poll on the worker thread. */
+
+ work_queue(HPWORK, &dev->radio->gts_pollwork,
+ nrf52_radioi8_dopoll_gts, dev, 0);
+ }
+
+ return OK;
+#else
+ /* GTS not supported */
+
+ return -ENOTSUP;
+#endif
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_work_noack
+ *
+ * Description:
+ * Handle no ACK work.
+ *
+ ****************************************************************************/
+
+static void nrf52_radioi8_work_noack(void *arg)
+{
+ struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)arg;
+ struct nrf52_radio_dev_s *lower = NULL;
+ struct ieee802154_txdesc_s *tx = NULL;
+ bool *busy = NULL;
+ bool csma = false;
+
+ DEBUGASSERT(dev);
+ lower = dev->radio->lower;
+
+ nrf52_radioi8_trace_put(RADIO_TRACE_WORK_NOACK, 0);
+
+ /* Get exclusive access to the driver */
+
+ while (nxmutex_lock(&dev->lock) < 0)
+ {
+ }
+
+ if (dev->state.txdelayed_busy)
+ {
+ tx = dev->state.txdelayed_desc;
+ busy = &dev->state.txdelayed_busy;
+ csma = false;
+ }
+ else
+ {
+ tx = dev->state.csma_desc;
+ busy = &dev->radio->state.csma_busy;
+ csma = true;
+ }
+
+ if (tx->retrycount > 0)
+ {
+ /* Disable RX */
+
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_TASKS_DISABLE_OFFSET, 1);
+
+ /* Try again */
+
+ tx->retrycount -= 1;
+ nrf52_radioi8_trace_put(RADIO_TRACE_TXRETRY, tx->retrycount);
+ nrf52_radioi8_norm_setup(dev, tx->frame, csma);
+ nrf52_radioi8_norm_trigger(dev);
+ }
+ else
+ {
+ nrf52_radioi8_trace_put(RADIO_TRACE_NOACK, 0);
+
+ tx->conf->status = IEEE802154_STATUS_NO_ACK;
+ tx->framepending = false;
+ dev->radiocb->txdone(dev->radiocb, tx);
+ *busy = false;
+ }
+
+ /* Unlock the radio device */
+
+ nxmutex_unlock(&dev->lock);
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_work_irq
+ *
+ * Description:
+ * Handle RX work.
+ *
+ ****************************************************************************/
+
+static void nrf52_radioi8_work_rx(void *arg)
+{
+ struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)arg;
+ struct nrf52_radio_dev_s *lower = NULL;
+ struct ieee802154_primitive_s *prim = NULL;
+ struct ieee802154_data_ind_s *ind = NULL;
+ uint8_t index = 0;
+ bool crcok = false;
+
+ DEBUGASSERT(dev);
+ lower = dev->radio->lower;
+
+ nrf52_radioi8_trace_put(RADIO_TRACE_WORK_RX, 0);
+
+ /* Get exclusive access to the driver */
+
+ while (nxmutex_lock(&dev->lock) < 0)
+ {
+ }
+
+ /* Check CRC */
+
+ crcok = NRF52_RADIO_GETREG(lower, NRF52_RADIO_CRCSTATUS_OFFSET);
+ if (dev->state.rxmode != NRF52_RXMODE_NOCRC && crcok == false)
+ {
+ goto out;
+ }
+
+ /* Allocate a data_ind to put the frame in */
+
+ prim = ieee802154_primitive_allocate();
+ ind = (struct ieee802154_data_ind_s *)prim;
+ if (ind == NULL)
+ {
+ wlerr("ERROR: Unable to allocate data_ind. Discarding frame\n");
+ goto out;
+ }
+
+ prim->type = IEEE802154_PRIMITIVE_IND_DATA;
+
+ /* Allocate an IOB to put the frame into */
+
+ ind->frame = iob_alloc(false);
+ DEBUGASSERT(ind->frame != NULL);
+
+ /* First byte is the PHR */
+
+ ind->frame->io_len = dev->radio->rxbuf[0];
+
+ /* Reduce len by 2, we only receive frames with correct crc, no check
+ * required.
+ */
+
+ ind->frame->io_len -= 2;
+
+ for (index = 0; index < ind->frame->io_len; index++)
+ {
+ ind->frame->io_data[index] = dev->radio->rxbuf[index + 1];
+ }
+
+ /* Set CRC fields to 0 */
+
+ ind->frame->io_data[index + 1] = 0;
+ ind->frame->io_data[index + 2] = 0;
+
+ /* LQI is the last byte in RAM */
+
+ ind->lqi = dev->radio->rxbuf[index + 1];
+
+ /* RSSI is non-standard field and is not supported here.
+ * TODO: get RSSI from LQI ?
+ */
+
+ ind->rssi = 0;
+
+ /* Callback the receiver in the next highest layer */
+
+ dev->radiocb->rxframe(dev->radiocb, ind);
+
+out:
+
+ /* Re-Enable RX if not handling ACK TX now */
+
+ if (dev->radio->state.state != NRF52_RADIO_STATE_ACKTX)
+ {
+ /* Enable packet reception */
+
+ dev->macops.rxenable((struct ieee802154_radio_s *)dev, true);
+ }
+
+ /* Unlock the radio device */
+
+ nxmutex_unlock(&dev->lock);
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_work_tx
+ *
+ * Description:
+ * Handle TX work.
+ *
+ ****************************************************************************/
+
+static void nrf52_radioi8_work_tx(void *arg)
+{
+ struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)arg;
+ enum ieee802154_status_e status;
+ bool fpending = false;
+
+ nrf52_radioi8_trace_put(RADIO_TRACE_WORK_TX, 0);
+
+ /* Get exclusive access to the driver */
+
+ while (nxmutex_lock(&dev->lock) < 0)
+ {
+ }
+
+ /* Get frame pending flag from the last TX ACK */
+
+ fpending = dev->radio->state.framepending;
+ dev->radio->state.framepending = false;
+
+ status = IEEE802154_STATUS_SUCCESS;
+
+ if (dev->state.txdelayed_busy)
+ {
+ /* Inform the next layer of the transmission success/failure */
+
+ dev->state.txdelayed_desc->conf->status = status;
+ dev->state.txdelayed_desc->framepending = fpending;
+ dev->radiocb->txdone(dev->radiocb, dev->state.txdelayed_desc);
+ dev->state.txdelayed_desc = NULL;
+ dev->state.txdelayed_busy = false;
+ }
+ else
+ {
+ /* Inform the next layer of the transmission success/failure */
+
+ dev->state.csma_desc->conf->status = status;
+ dev->state.csma_desc->framepending = fpending;
+ dev->radiocb->txdone(dev->radiocb, dev->state.csma_desc);
+ dev->state.csma_desc = NULL;
+
+ /* We are now done with the transaction */
+
+ dev->radio->state.csma_busy = false;
+
+ /* Must unlock the radio before calling poll */
+
+ nxmutex_unlock(&dev->lock);
+ nrf52_radioi8_dopoll_csma(dev);
+ while (nxmutex_lock(&dev->lock) < 0)
+ {
+ }
+ }
+
+ /* Re-Enable RX if not handling ACK TX now */
+
+ if (dev->radio->state.state != NRF52_RADIO_STATE_ACKTX)
+ {
+ /* Enable packet reception */
+
+ dev->macops.rxenable((struct ieee802154_radio_s *)dev, true);
+ }
+
+ /* Unlock the radio device */
+
+ nxmutex_unlock(&dev->lock);
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_work_busy
+ *
+ * Description:
+ * Handle CCABUSY work.
+ *
+ ****************************************************************************/
+
+static void nrf52_radioi8_work_busy(void *arg)
+{
+ struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)arg;
+
+ nrf52_radioi8_trace_put(RADIO_TRACE_WORK_BUSY, 0);
+
+ /* Get exclusive access to the driver */
+
+ while (nxmutex_lock(&dev->lock) < 0)
+ {
+ }
+
+ dev->state.txdelayed_desc->conf->status =
+ IEEE802154_STATUS_CHANNEL_ACCESS_FAILURE;
+
+ dev->radiocb->txdone(dev->radiocb, dev->state.txdelayed_desc);
+
+ /* Unlock the radio device */
+
+ nxmutex_unlock(&dev->lock);
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_work_ed
+ *
+ * Description:
+ * Handle ED work.
+ *
+ ****************************************************************************/
+
+static void nrf52_radioi8_work_ed(void *arg)
+{
+ struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)arg;
+ struct nrf52_radio_dev_s *lower = NULL;
+ int ed = 0;
+
+ DEBUGASSERT(dev);
+ lower = dev->radio->lower;
+
+ nrf52_radioi8_trace_put(RADIO_TRACE_WORK_ED, 0);
+
+ /* Get result */
+
+ ed = NRF52_RADIO_GETREG(lower, NRF52_RADIO_EDSAMPLE_OFFSET);
+
+ /* Convert to IEEE 802.15.4 scale */
+
+ ed = ((ed > 63) ? 255: (ed * NRF52_ED_RSSISCALE));
+
+ /* Callback the receiver in the next highest layer */
+
+ dev->radiocb->edresult(dev->radiocb, ed);
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_state_rx
+ *
+ * Description:
+ * Handle radio interrupt for RX state.
+ *
+ ****************************************************************************/
+
+static void nrf52_radioi8_state_rx(struct nrf52_radioi8_dev_s *dev)
+{
+ uint8_t *rxbuf = dev->radio->rxbuf;
+
+ /* Frame filter */
+
+ if (dev->radio->state.waitack == false)
+ {
+ if (!nrf52_radioi8_filter(dev))
+ {
+ nrf52_radioi8_trace_put(RADIO_TRACE_DROPFRAME, 0);
+
+ /* Enable RX and ignore this frame */
+
+ dev->macops.rxenable((struct ieee802154_radio_s *)dev,
+ true);
+ return;
+ }
+ }
+
+#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME
+ /* TODO: resync with beacon ? */
+
+ if (dev->radio->state.wait_for_beacon == true)
+ {
+ uint16_t *fc = (uint16_t *)&rxbuf[0];
+
+ /* TODO: NOT TESTES, should we check panid here ? */
+
+ if (((*fc & IEEE802154_FRAMECTRL_FTYPE) == IEEE802154_FRAME_BEACON) &&
+ IEEE802154_PANIDCMP(IEEE802154_PANID_UNSPEC,
+ &dev->state.addr.panid))
+ {
+ /* Start RTC */
+
+ dev->rtc->ops->start(dev);
+
+ dev->radio->state.wait_for_beacon = false;
+ }
+ }
+#endif
+
+ /* Start ACK handling now - this must be done in isr */
+
+ if (dev->state.rxmode == NRF52_RXMODE_NORMAL &&
+ rxbuf[1] & IEEE802154_FRAMECTRL_ACKREQ &&
+ rxbuf[0] != IEEE802154_ACK_FRAME_SIZE)
+ {
+ nrf52_radioi8_ack_transmit(dev);
+ }
+
+ /* Store RX frame long flag */
+
+ dev->radio->state.rxlong = rxbuf[0] > 18 ? true : false;
+
+ /* We don't wait for TX ACK - forward this frame to MAC */
+
+ if (dev->radio->state.waitack == false)
+ {
+ nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_RXDONE, 0);
+
+ /* Receive DONE */
+
+ if (work_available(&dev->radio->irqwork))
+ {
+ work_queue(HPWORK, &dev->radio->irqwork,
+ nrf52_radioi8_work_rx, (void *)dev, 0);
+ }
+ }
+
+ /* We wait for TX ACK and this frame is ACK - confirm TX to MAC */
+
+ else if (rxbuf[0] == IEEE802154_ACK_FRAME_SIZE &&
+ dev->radio->state.waitack == true)
+ {
+ nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_RXACKDONE, 0);
+
+ /* ACK frame received */
+
+ dev->radio->state.waitack = false;
+
+ /* Get frame pedning flag */
+
+ dev->radio->state.framepending = rxbuf[1] & 0x10;
+
+ /* Clear timer */
+
+ dev->tim->ops->stop(dev);
+
+ /* This is ACK - notify MAC that TX complete */
+
+ if (work_available(&dev->radio->irqwork))
+ {
+ work_queue(HPWORK, &dev->radio->irqwork,
+ nrf52_radioi8_work_tx, (void *)dev, 0);
+ }
+ }
+
+ /* We wait for TX ACK and this is not ACK - notify TX failure */
+
+ else
+ {
+ /* Clear flag */
+
+ dev->radio->state.waitack = false;
+
+ /* And notify MAC */
+
+ DEBUGASSERT(work_available(&dev->radio->noackwork));
+ work_queue(HPWORK, &dev->radio->noackwork,
+ nrf52_radioi8_work_noack, (void *)dev, 0);
+ }
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_state_tx
+ *
+ * Description:
+ * Handle radio interrupt for TX state.
+ *
+ ****************************************************************************/
+
+static void nrf52_radioi8_state_tx(struct nrf52_radioi8_dev_s *dev)
+{
+ struct nrf52_radio_dev_s *lower = NULL;
+
+ DEBUGASSERT(dev);
+ lower = dev->radio->lower;
+
+ if (dev->radio->state.waitack == true)
+ {
+ nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_WAITACK, 0);
+
+ /* Start timer and wait for ACK */
+
+ dev->tim->ops->setup(dev, NRF52_TIMER_CHAN_WAITACK,
+ IEEE802154_ACK_WAIT);
+ }
+ else
+ {
+ nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_TXDONE, 0);
+
+ /* Transmit DONE */
+
+ if (work_available(&dev->radio->irqwork))
+ {
+ work_queue(HPWORK, &dev->radio->irqwork,
+ nrf52_radioi8_work_tx, (void *)dev, 0);
+ }
+ }
+
+ /* CCABUSY event for TX */
+
+ if (NRF52_RADIO_GETREG(lower, NRF52_RADIO_EVENTS_CCABUSY_OFFSET))
+ {
+ nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_TXCCABUSY, 0);
+
+ /* Clear event */
+
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_CCABUSY_OFFSET, 0);
+
+ /* Slotted CSMA-CA */
+
+ if (dev->radio->state.slotted == true)
+ {
+#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME
+ dev->radio->state.NB += 1;
+ dev->radio->state.CW = IEEE802154_CW0;
+ dev->radio->state.BE = MIN(2, dev->radio->state.min_be);
+
+ if (dev->radio->state.NB > dev->radio->state.max_csma_backoffs)
+ {
+ /* Return fauilure to MAC */
+
+ if (work_available(&dev->radio->irqwork))
+ {
+ work_queue(HPWORK, &dev->radio->irqwork,
+ nrf52_radioi8_work_busy, (void *)dev, 0);
+ }
+ }
+ else
+ {
+ /* Try again */
+
+ dev->radio->state.state = NRF52_RADIO_STATE_TX_CSMA;
+ nrf52_radioi8_norm_trigger(dev);
+
+ /* Do not restore RX */
+
+ return;
+ }
+#else
+ ASSERT(0);
+#endif
+ }
+
+ /* Un-slotted CSMA-CA */
+
+ else
+ {
+ /* Update backoff */
+
+ dev->radio->state.NB -= 1;
+ dev->radio->state.BE = MIN(dev->radio->state.BE + 1,
+ dev->radio->state.max_be);
+
+ if (dev->radio->state.NB > dev->radio->state.max_csma_backoffs)
+ {
+ /* Return fauilure to MAC */
+
+ if (work_available(&dev->radio->irqwork))
+ {
+ work_queue(HPWORK, &dev->radio->irqwork,
+ nrf52_radioi8_work_busy, (void *)dev, 0);
+ }
+ }
+ else
+ {
+ /* Try again */
+
+ dev->radio->state.state = NRF52_RADIO_STATE_TX_CSMA;
+ nrf52_radioi8_norm_trigger(dev);
+
+ /* Do not restore RX */
+
+ return;
+ }
+ }
+ }
+
+ /* CCAIDLE event for TX */
+
+ if (NRF52_RADIO_GETREG(lower, NRF52_RADIO_EVENTS_CCAIDLE_OFFSET))
+ {
+ /* Clear event */
+
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_CCAIDLE_OFFSET, 0);
+
+ /* Slotted CSMA-CA */
+
+ if (dev->radio->state.slotted == true)
+ {
+#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME
+ dev->radio->state.CW -= 1;
+
+ if (dev->radio->state.CW == 0)
+ {
+ /* Enable TX - short TXREADY-START is enabled */
+
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_TASKS_TXEN_OFFSET, 1);
+ }
+ else
+ {
+ /* Do not restore RX */
+
+ return;
+ }
+#else
+ ASSERT(0);
+#endif
+ }
+
+ /* Un-slotted CSMA-CA */
+
+ else
+ {
+ /* Nothing here */
+ }
+ }
+
+ /* Restore RX */
+
+ if (dev->radio->state.rxrestore | dev->radio->state.waitack)
+ {
+ dev->macops.rxenable((struct ieee802154_radio_s *)dev, true);
+ dev->radio->state.rxrestore = false;
+ }
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_state_acktx
+ *
+ * Description:
+ * Handle radio interrupt for ACKTX state.
+ *
+ ****************************************************************************/
+
+static void nrf52_radioi8_state_acktx(struct nrf52_radioi8_dev_s *dev)
+{
+ nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_ACKTX, 0);
+
+ /* Handle pending TX */
+
+ if (dev->state.txdelayed_busy)
+ {
+ nrf52_radioi8_norm_setup(dev,
+ dev->state.txdelayed_desc->frame,
+ false);
+
+ /* Send with timer to keep IFS */
+
+ if (dev->radio->state.rxlong)
+ {
+ dev->tim->ops->setup(dev, NRF52_TIMER_CHAN_TXDELAY,
+ IEEE802154_LIFS_SYMBOLS);
+ }
+ else
+ {
+ dev->tim->ops->setup(dev, NRF52_TIMER_CHAN_TXDELAY,
+ IEEE802154_SIFS_SYMBOLS);
+ }
+ }
+
+ /* Restore RX */
+
+ else if (dev->radio->state.rxrestore)
+ {
+ dev->macops.rxenable((struct ieee802154_radio_s *)dev, true);
+ dev->radio->state.rxrestore = false;
+ }
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_state_ed
+ *
+ * Description:
+ * Handle radio interrupt for ED state.
+ *
+ ****************************************************************************/
+
+static void nrf52_radioi8_state_ed(struct nrf52_radioi8_dev_s *dev)
+{
+ /* Energy detect DONE */
+
+ DEBUGASSERT(work_available(&dev->radio->irqwork));
+ work_queue(HPWORK, &dev->radio->irqwork,
+ nrf52_radioi8_work_ed, (void *)dev, 0);
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_isr_radio
+ *
+ * Description:
+ * Radio IEEE 802.15.4 interrupt handler.
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_isr_radio(int irq, void *context, void *arg)
+{
+ struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)arg;
+ struct nrf52_radio_dev_s *lower = NULL;
+ irqstate_t flags;
+ uint8_t state;
+
+ DEBUGASSERT(dev != NULL);
+ lower = dev->radio->lower;
+
+ flags = enter_critical_section();
+
+ nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_RADIO, 0);
+
+ /* Get state */
+
+ state = dev->radio->state.state;
+ dev->radio->state.state = NRF52_RADIO_STATE_DISABLED;
+
+ /* Always clear END and PHYEND events */
+
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_END_OFFSET, 0);
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_PHYEND_OFFSET, 0);
+
+ /* Clear interrupts and shorts */
+
+ NRF52_RADIO_INTCLR(lower, 0xffffffff);
+ NRF52_RADIO_SHRTSET(lower, 0);
+
+ /* If by chance radio is not disabled - disable it now. This should be
+ * handled by SHORTS, but this not always work...
+ */
+
+ if (NRF52_RADIO_GETREG(lower, NRF52_RADIO_STATE_OFFSET)
+ != RADIO_STATE_DISABLED)
+ {
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_TASKS_DISABLE_OFFSET, 1);
+
+ /* Don't wait for the DISABLED event, hopefully the radio will be
+ * disabled by the time we use it again. Max delay is TX->DSIABLED
+ * and takes 21us.
+ */
+ }
+
+ /* Handle IRQ depending on the current state */
+
+ switch (state)
+ {
+ case NRF52_RADIO_STATE_RX:
+ {
+ nrf52_radioi8_state_rx(dev);
+
+ break;
+ }
+
+ case NRF52_RADIO_STATE_TX:
+ {
+ nrf52_radioi8_state_tx(dev);
+
+ break;
+ }
+
+ case NRF52_RADIO_STATE_ACKTX:
+ {
+ nrf52_radioi8_state_acktx(dev);
+
+ break;
+ }
+
+ case NRF52_RADIO_STATE_ED:
+ {
+ /* Clear event */
+
+ NRF52_RADIO_PUTREG(lower, NRF52_RADIO_EVENTS_EDEND_OFFSET, 0);
+
+ nrf52_radioi8_state_ed(dev);
+
+ break;
+ }
+
+ default:
+ {
+ ASSERT(0);
+ break;
+ }
+ }
+
+ leave_critical_section(flags);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf52_radioi8_radio_init
+ *
+ * Description:
+ * Initialize RADIO for IEEE802154 operations.
+ *
+ ****************************************************************************/
+
+struct nrf52_radioi8_radio_s *
+nrf52_radioi8_radio_init(struct nrf52_radioi8_dev_s *dev,
+ struct nrf52_radio_board_s *board)
+{
+ struct nrf52_radio_dev_s *radio = NULL;
+
+ /* Initialize lower-half radio */
+
+ radio = nrf52_radio_initialize(0, board);
+ if (radio == NULL)
+ {
+ wlerr("nrf52_radio_initialize failed %d\n", -errno);
+ return NULL;
+ }
+
+ /* Attach custom RADIO interrupt */
+
+ irq_attach(radio->irq, nrf52_radioi8_isr_radio, dev);
+ up_enable_irq(radio->irq);
+
+ /* Set interrupts priority */
+
+ up_prioritize_irq(radio->irq, 0);
+
+ /* Connect radioer */
+
+ memset(&g_radioi8_radio, 0, sizeof(struct nrf52_radioi8_radio_s));
+ g_radioi8_radio.ops = &g_radioi8_radio_ops;
+ g_radioi8_radio.lower = radio;
+
+ /* Connect buffers */
+
+ g_radioi8_radio.rxbuf = g_nrf52_radioi8_rxbuf;
+ g_radioi8_radio.txbuf = g_nrf52_radioi8_txbuf;
+ g_radioi8_radio.ackbuf = g_nrf52_radioi8_ackbuf;
+#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME
+ g_radioi8_radio.beaconbuf = g_nrf52_radioi8_beaconbuf;
+#endif
+
+ return &g_radioi8_radio;
+}
diff --git a/arch/arm/src/nrf52/nrf52_ieee802154_radio.h b/arch/arm/src/nrf52/nrf52_ieee802154_radio.h
new file mode 100644
index 0000000000..8dd9146bd0
--- /dev/null
+++ b/arch/arm/src/nrf52/nrf52_ieee802154_radio.h
@@ -0,0 +1,246 @@
+/****************************************************************************
+ * arch/arm/src/nrf52/nrf52_ieee802154_radio.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_RADIO_H
+#define __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_RADIO_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <nuttx/wqueue.h>
+
+#include "hardware/nrf52_radio.h"
+
+#include "nrf52_radio.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* IEEE 802.15.4 constants */
+
+#define IEEE802154_MAX_FRAME_WAITTIME (16 + 32 + 4064)
+#define IEEE802154_MAX_CSMA_BACKOFFS (1)
+#define IEEE802154_MIN_BE (3)
+#define IEEE802154_MAX_BE (5)
+#define IEEE802154_CW0 (2)
+
+/* ACK_SYM + turnaround symbols + backoff */
+
+#define IEEE802154_ACK_WAIT (12+ \
+ IEEE802154_TURN_AROUND_TIME+ \
+ IEEE802154_UNIT_BACKOFF_PERIOD)
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* Radio state */
+
+enum nrf52_radioi8_state_e
+{
+ NRF52_RADIO_STATE_DISABLED = 0, /* Radio disabled */
+ NRF52_RADIO_STATE_TX_CSMA, /* CSMA TX armed */
+ NRF52_RADIO_STATE_TX_NOCSMA, /* Non CSMA TX armed */
+ NRF52_RADIO_STATE_TX, /* TX on the air */
+ NRF52_RADIO_STATE_RX, /* RX active */
+ NRF52_RADIO_STATE_ACKTX, /* Transmiting ACK now */
+ NRF52_RADIO_STATE_ED, /* Energy detection now */
+};
+
+/* Radio data */
+
+struct nrf52_radioi8_radio_data_s
+{
+ /* Radio state */
+
+ uint8_t state;
+
+ /* CSMA-CA */
+
+ uint8_t NB; /* Number of required back offs */
+ uint8_t CW; /* Contention window length */
+ uint8_t BE; /* Backoff exponent */
+
+ /* RX state */
+
+ bool rxenabled; /* RX enabled now */
+ bool rxrestore; /* RX needs to be restored */
+ bool rxlong; /* Last RX frame was long */
+
+ /* TX state */
+
+ bool waitack; /* TX needs ACK */
+ bool framepending; /* Frame pending from the last TX ACK */
+ bool csma_busy; /* Un-slotted CSMA busy */
+ bool slotted; /* Slotted CSMA-CA */
+
+ /* Radio configuration */
+
+ uint32_t max_frame_waittime; /* Max Frame wait time */
+ uint8_t max_csma_backoffs; /* Max CSMA backoffs */
+ uint8_t min_be; /* Min backoff exponent (BE) */
+ uint8_t max_be; /* Max backoff exponent (BE) */
+
+#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME
+ /* Superframe data */
+
+ bool wait_for_beacon; /* Device wait for beacon */
+ bool ble; /* Batter life extension */
+#endif
+};
+
+/* Forward reference */
+
+struct nrf52_radioi8_radio_s;
+struct ieee802154_radio_s;
+struct nrf52_radioi8_dev_s;
+struct ieee802154_cca_s;
+
+/* Radio ops */
+
+struct nrf52_radioi8_radio_ops_s
+{
+ /* Start transmition - TX must be armed (TXEN set) */
+
+ void (*txstart)(struct nrf52_radioi8_dev_s *dev);
+
+ /* Start CCA - RX must be armed (RXEN set) */
+
+ void (*ccastart)(struct nrf52_radioi8_dev_s *dev);
+
+ /* Notify MAC about no ACK */
+
+ void (*notify_noack)(struct nrf52_radioi8_dev_s *dev);
+
+ /* Enable/Disable receiver */
+
+ int (*rxenable)(struct nrf52_radioi8_dev_s *dev, bool enable);
+
+ /* Start the energy detect measurement */
+
+ int (*energydetect)(struct nrf52_radioi8_dev_s *dev, uint32_t nsymbols);
+
+ /* Define the current radio channel the device is operating on */
+
+ int (*setchannel)(struct nrf52_radioi8_dev_s *dev, uint8_t chan);
+
+ /* Configure the Clear Channel Assessement */
+
+ int (*setcca)(struct nrf52_radioi8_dev_s *dev,
+ struct ieee802154_cca_s *cca);
+
+ /* Setup a normal transaction (non GTS) */
+
+ void (*norm_setup)(struct nrf52_radioi8_dev_s *dev,
+ struct iob_s *frame, bool csma);
+
+ /* Trigger normal transaction (non GTS) */
+
+ void (*norm_trigger)(struct nrf52_radioi8_dev_s *dev);
+
+#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME
+ /* Setup a beacon frame transfe */
+
+ void (*beacon_setup)(struct nrf52_radioi8_dev_s *dev,
+ uint8_t *data, uint8_t len);
+
+ /* Transmit a beacon frame (non CSMA-CA transfer) */
+
+ void (*beacon_tx)(struct nrf52_radioi8_dev_s *dev);
+#endif
+
+ /* Reset radio state to work with IEEE 802.15.4 */
+
+ int (*reset)(struct nrf52_radioi8_radio_s *dev);
+
+ /* Handle TX poll (no GTS) */
+
+ int (*csma_poll)(struct nrf52_radioi8_dev_s *dev);
+
+ /* Handle GTS poll */
+
+ int (*gts_poll)(struct nrf52_radioi8_dev_s *dev);
+};
+
+/* Radio interface */
+
+struct nrf52_radioi8_radio_s
+{
+ /* Radio lower-half */
+
+ struct nrf52_radio_dev_s *lower;
+
+ /* IEEE 802.15.4 radio operations */
+
+ struct nrf52_radioi8_radio_ops_s *ops;
+
+ /* Packet buffers */
+
+ uint8_t *rxbuf;
+ uint8_t *txbuf;
+ uint8_t *ackbuf;
+#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME
+ uint8_t *beaconbuf;
+#endif
+
+ /* For deferring interrupts work */
+
+ struct work_s irqwork;
+
+ /* For deferring no ACK work */
+
+ struct work_s noackwork;
+
+ /* For deferring poll work to the work queue */
+
+ struct work_s csma_pollwork;
+
+#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME
+ /* For deferring poll work to the work queue */
+
+ struct work_s gts_pollwork;
+#endif
+
+ /* Radio data */
+
+ struct nrf52_radioi8_radio_data_s state;
+};
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf52_radioi8_radio_init
+ *
+ * Description:
+ * Initialize RADIO for IEEE802154 operations.
+ *
+ ****************************************************************************/
+
+struct nrf52_radioi8_radio_s *
+nrf52_radioi8_radio_init(struct nrf52_radioi8_dev_s *dev,
+ struct nrf52_radio_board_s *board);
+
+#endif /* __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_RADIO_H */
diff --git a/arch/arm/src/nrf52/nrf52_ieee802154_rtc.c b/arch/arm/src/nrf52/nrf52_ieee802154_rtc.c
new file mode 100644
index 0000000000..7d32b3df78
--- /dev/null
+++ b/arch/arm/src/nrf52/nrf52_ieee802154_rtc.c
@@ -0,0 +1,392 @@
+/****************************************************************************
+ * arch/arm/src/nrf52/nrf52_ieee802154_rtc.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <debug.h>
+#include <errno.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/irq.h>
+#include <nuttx/wqueue.h>
+
+#include <nuttx/wireless/ieee802154/ieee802154_mac.h>
+
+#include "nrf52_ieee802154_rtc.h"
+#include "nrf52_ieee802154_trace.h"
+
+#include "nrf52_ieee802154_priv.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME
+# warning Beacon and superframe support work in progress
+#endif
+
+#ifndef CONFIG_NRF52_RTC0
+# error CONFIG_NRF52_RTC0 is needed to handle radio timings
+#endif
+
+/* RTC instance - 0 */
+
+#define NRF52_IEEE802154_RTC0 (0)
+
+/* RTC prescaler set to 0, freq = 32.768kHz, resolution = 30.517 us */
+
+#define NRF52_RTC_PRESCALER (0)
+#define NRF52_RTC_FREQUENCY (32768)
+
+#define NRF52_RTC_RESOLUTION_NS (30517)
+
+/* 31 * 30.517us = 946.027us */
+
+#define NRF52_RTC_TIMESLOT_CC (31)
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* RTC ops */
+
+static int nrf52_radioi8_rtc(struct nrf52_radioi8_dev_s *dev,
+ struct ieee802154_superframespec_s *sfspec);
+static int nrf52_radioi8_rtc_start(struct nrf52_radioi8_dev_s *dev);
+static int nrf52_radioi8_rtc_stop(struct nrf52_radioi8_dev_s *dev);
+static void nrf52_radioi8_rtc_reset(struct nrf52_radioi8_dev_s *dev);
+
+/* Interrupts logic */
+
+static void nrf52_radioi8_work_inactive(void *arg);
+static int nrf52_radioi8_isr_rtc(int irq, void *context, void *arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* RTC ops */
+
+static struct nrf52_radioi8_rtc_ops_s g_radioi8_rtc_ops =
+{
+ .setup = nrf52_radioi8_rtc,
+ .start = nrf52_radioi8_rtc_start,
+ .stop = nrf52_radioi8_rtc_stop,
+ .reset = nrf52_radioi8_rtc_reset
+};
+
+/* RTC instance */
+
+static struct nrf52_radioi8_rtc_s g_radioi8_rtc;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf52_radioi8_rtc
+ *
+ * Description:
+ * Configure RTC events according to superframe spec.
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_rtc(struct nrf52_radioi8_dev_s *dev,
+ struct ieee802154_superframespec_s *sfspec)
+{
+ uint32_t bi = 0;
+ uint32_t sd = 0;
+ uint32_t cap = 0;
+ irqstate_t flags;
+
+ flags = enter_critical_section();
+
+ /* Stop RTC and clear the counter */
+
+ NRF52_RTC_STOP(dev->rtc->rtc);
+ NRF52_RTC_CLEAR(dev->rtc->rtc);
+
+ /* Initialize BI counter */
+
+ bi = ((IEEE802154_BASE_SUPERFRAME_DURATION *
+ (2 << sfspec->beaconorder) *
+ IEEE802154_SYMBOL_US * 1000) /
+ NRF52_RTC_RESOLUTION_NS);
+ NRF52_RTC_SETCC(dev->rtc->rtc, NRF52_RTC_BI, bi);
+
+ /* Initialize SD counter */
+
+ sd = ((IEEE802154_BASE_SUPERFRAME_DURATION *
+ (2 << sfspec->sforder) *
+ IEEE802154_SYMBOL_US * 1000) /
+ NRF52_RTC_RESOLUTION_NS);
+ NRF52_RTC_SETCC(dev->rtc->rtc, NRF52_RTC_SD, sd);
+
+ /* Initialize CAP counter */
+
+ cap = ((sfspec->final_capslot *
+ IEEE802154_TIMESLOT_US * 1000) /
+ NRF52_RTC_RESOLUTION_NS);
+ NRF52_RTC_SETCC(dev->rtc->rtc, NRF52_RTC_CAP, cap);
+
+ /* Initialize timeslot counter */
+
+ dev->rtc->rtc_timeslot = NRF52_RTC_TIMESLOT_CC;
+ NRF52_RTC_SETCC(dev->rtc->rtc, NRF52_RTC_TIMESLOT, dev->rtc->rtc_timeslot);
+
+ /* Configure interupts */
+
+ NRF52_RTC_ENABLEINT(dev->rtc->rtc, NRF52_RTC_BI);
+ NRF52_RTC_ENABLEINT(dev->rtc->rtc, NRF52_RTC_SD);
+ NRF52_RTC_ENABLEINT(dev->rtc->rtc, NRF52_RTC_CAP);
+ NRF52_RTC_ENABLEINT(dev->rtc->rtc, NRF52_RTC_TIMESLOT);
+
+ /* Configure events */
+
+ NRF52_RTC_ENABLEEVT(dev->rtc->rtc, NRF52_RTC_BI);
+ NRF52_RTC_ENABLEEVT(dev->rtc->rtc, NRF52_RTC_SD);
+ NRF52_RTC_ENABLEEVT(dev->rtc->rtc, NRF52_RTC_CAP);
+ NRF52_RTC_ENABLEEVT(dev->rtc->rtc, NRF52_RTC_TIMESLOT);
+
+ leave_critical_section(flags);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_rtc_start
+ *
+ * Description:
+ * Start RTC.
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_rtc_start(struct nrf52_radioi8_dev_s *dev)
+{
+ NRF52_RTC_START(dev->rtc->rtc);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_rtc_stop
+ *
+ * Description:
+ * Stop RTC.
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_rtc_stop(struct nrf52_radioi8_dev_s *dev)
+{
+ NRF52_RTC_STOP(dev->rtc->rtc);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_rtc_reset
+ *
+ * Description:
+ * Reset RTC.
+ *
+ ****************************************************************************/
+
+static void nrf52_radioi8_rtc_reset(struct nrf52_radioi8_dev_s *dev)
+{
+ /* Configure RTC - freq = 32.768 kHz */
+
+ NRF52_RTC_STOP(dev->rtc->rtc);
+ NRF52_RTC_SETPRE(dev->rtc->rtc, NRF52_RTC_PRESCALER);
+
+ /* Reset data */
+
+ dev->rtc->rtc_timeslot = 0;
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_work_inactive
+ *
+ * Description:
+ * Work when we enter inactive state.
+ *
+ ****************************************************************************/
+
+static void nrf52_radioi8_work_inactive(void *arg)
+{
+ struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)arg;
+ enum ieee802154_sfevent_e sfevent;
+
+ /* Notify MAC */
+
+ sfevent = IEEE802154_SFEVENT_ENDOFACTIVE;
+ dev->radiocb->sfevent(dev->radiocb, sfevent);
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_isr_rtc
+ *
+ * Description:
+ * Helper RTC0 interrupt handler.
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_isr_rtc(int irq, void *context, void *arg)
+{
+ struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)arg;
+ struct nrf52_radioi8_rtc_s *rtc = NULL;
+ irqstate_t flags;
+
+ DEBUGASSERT(dev != NULL);
+ rtc = dev->rtc;
+
+ flags = enter_critical_section();
+
+ /* End of CAP */
+
+ if (NRF52_RTC_CHECKINT(rtc->rtc, NRF52_RTC_CAP))
+ {
+ nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_RTCCAP, 0);
+
+ /* TODO */
+
+ /* Clear event */
+
+ NRF52_RTC_ACKINT(rtc->rtc, NRF52_RTC_CAP);
+ }
+
+ /* End of active portion */
+
+ else if (NRF52_RTC_CHECKINT(rtc->rtc, NRF52_RTC_SD))
+ {
+ nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_RTCSD, 0);
+
+ /* Schedule work */
+
+ DEBUGASSERT(work_available(&dev->rtc->inactive_work));
+ work_queue(HPWORK, &dev->rtc->inactive_work,
+ nrf52_radioi8_work_inactive, dev, 0);
+
+ /* Reset timeslot */
+
+ rtc->rtc_timeslot = NRF52_RTC_TIMESLOT_CC;
+
+ /* Clear event */
+
+ NRF52_RTC_ACKINT(rtc->rtc, NRF52_RTC_SD);
+ }
+
+ /* Beacon interval */
+
+ else if (NRF52_RTC_CHECKINT(rtc->rtc, NRF52_RTC_BI))
+ {
+ nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_RTCBI, 0);
+
+ /* Transmit beacon if we are not endpoint */
+
+ if (dev->state.devmode != NRF52_DEVMODE_ENDPOINT)
+ {
+ /* Transmit data from beaconbuf */
+
+ dev->radio->ops->beacon_tx(dev);
+ }
+
+ /* Clear event */
+
+ NRF52_RTC_ACKINT(rtc->rtc, NRF52_RTC_BI);
+
+ /* Next cycle */
+
+ NRF52_RTC_TRGOVRFLW(rtc->rtc);
+
+ /* TODO: resync with beacon ? */
+ }
+
+ /* Timeslot in active portion */
+
+ if (NRF52_RTC_CHECKINT(rtc->rtc, NRF52_RTC_TIMESLOT))
+ {
+ nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_RTCTIMESLOT, 0);
+
+ /* TODO: how to sync transmition with timeslot ?
+ * do we need count every timeslot here ?
+ * or wait for the timeslot we are interested in ?
+ * or just use txdelay ?
+ */
+
+ /* Update timeslot */
+
+ rtc->rtc_timeslot += NRF52_RTC_TIMESLOT_CC;
+ NRF52_RTC_SETCC(rtc->rtc, NRF52_RTC_TIMESLOT, rtc->rtc_timeslot);
+
+ /* Clear event */
+
+ NRF52_RTC_ACKINT(rtc->rtc, NRF52_RTC_TIMESLOT);
+ }
+
+ leave_critical_section(flags);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf52_radioi8_rtc_init
+ *
+ * Description:
+ * Initialize low resoluton, low power timer for IEEE802154 operations.
+ * Used to handle superframe timings.
+ *
+ ****************************************************************************/
+
+struct nrf52_radioi8_rtc_s *
+nrf52_radioi8_rtc_init(struct nrf52_radioi8_dev_s *dev)
+{
+ struct nrf52_rtc_dev_s *rtc = NULL;
+
+ /* Reserve RTC0 */
+
+ rtc = nrf52_rtc_init(NRF52_IEEE802154_RTC0);
+ if (rtc == NULL)
+ {
+ wlerr("nrf52_rtc_init(0) failed %d\n", -errno);
+ return NULL;
+ }
+
+ /* Atach RTC interrupt */
+
+ NRF52_RTC_SETISR(rtc, nrf52_radioi8_isr_rtc, dev);
+
+ /* Set interrupts priority */
+
+ up_prioritize_irq(NRF52_IRQ_RTC0, 0);
+
+ /* Connect RTC */
+
+ memset(&g_radioi8_rtc, 0, sizeof(struct nrf52_radioi8_rtc_s));
+ g_radioi8_rtc.ops = &g_radioi8_rtc_ops;
+ g_radioi8_rtc.rtc = rtc;
+
+ return &g_radioi8_rtc;
+}
diff --git a/boards/arm/nrf52/nrf52840-dongle/src/nrf52840-dongle.h b/arch/arm/src/nrf52/nrf52_ieee802154_rtc.h
similarity index 53%
copy from boards/arm/nrf52/nrf52840-dongle/src/nrf52840-dongle.h
copy to arch/arm/src/nrf52/nrf52_ieee802154_rtc.h
index e2f688fb5a..de6f475ff2 100644
--- a/boards/arm/nrf52/nrf52840-dongle/src/nrf52840-dongle.h
+++ b/arch/arm/src/nrf52/nrf52_ieee802154_rtc.h
@@ -1,5 +1,5 @@
/****************************************************************************
- * boards/arm/nrf52/nrf52840-dongle/src/nrf52840-dongle.h
+ * arch/arm/src/nrf52/nrf52_ieee802154_rtc.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -18,69 +18,99 @@
*
****************************************************************************/
-#ifndef __BOARDS_ARM_NRF52_NRF52840_DONGLE_SRC_NRF52840_DONGLE_H
-#define __BOARDS_ARM_NRF52_NRF52840_DONGLE_SRC_NRF52840_DONGLE_H
+#ifndef __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_RTC_H
+#define __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_RTC_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
-#include <nuttx/compiler.h>
-#include "nrf52_gpio.h"
+#include "nrf52_rtc.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
-/* LED definitions **********************************************************/
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
-/* Definitions to configure LED GPIO as outputs */
+/* RTC events */
-#define GPIO_LED1 (GPIO_OUTPUT | GPIO_VALUE_ONE | GPIO_PORT0 | GPIO_PIN(6))
+enum nrf52_ieee802154_rtc_e
+{
+ NRF52_RTC_BI = 0, /* Beacon Interval interval (BI) */
+ NRF52_RTC_TIMESLOT = 1, /* Time slot */
+ NRF52_RTC_CAP = 2, /* Contention Access Period (CAP) */
+ NRF52_RTC_SD = 3 /* Super Frame Duration (SD) */
+};
-/* RGB LED - LD2:
- * RGB_RED - P0-8
- * RGB_GREEN - P1-9
- * RGB_BLUE - P0-12
- */
+/* Forward reference */
-/* Button definitions *******************************************************/
+struct nrf52_radioi8_rtc_s;
+struct nrf52_radioi8_dev_s;
-/* Board supports four buttons. */
+/* RTC ops */
-#define GPIO_BUTTON1 (GPIO_INPUT | GPIO_PULLUP | GPIO_PORT1 | GPIO_PIN(6))
+struct nrf52_radioi8_rtc_ops_s
+{
+ /* Configure RTC events according to superframe spec */
-/****************************************************************************
- * Public Types
- ****************************************************************************/
+ int (*setup)(struct nrf52_radioi8_dev_s *dev,
+ struct ieee802154_superframespec_s *sfspec);
-/****************************************************************************
- * Public Data
- ****************************************************************************/
+ /* Start RTC */
+
+ int (*start)(struct nrf52_radioi8_dev_s *dev);
+
+ /* Stop RTC */
+
+ int (*stop)(struct nrf52_radioi8_dev_s *dev);
+
+ /* Reset RTC */
-#ifndef __ASSEMBLY__
+ void (*reset)(struct nrf52_radioi8_dev_s *dev);
+};
+
+/* RTC interface */
+
+struct nrf52_radioi8_rtc_s
+{
+ /* RTC lower-half */
+
+ struct nrf52_rtc_dev_s *rtc;
+
+ /* IEEE 802.15.4 RTC operations */
+
+ struct nrf52_radioi8_rtc_ops_s *ops;
+
+#ifdef CONFIG_NRF52_RADIO_IEEE802154_SUPERFRAME
+ /* For deferring inactive state work to the work queue */
+
+ struct work_s inactive_work;
+
+ /* RTC state */
+
+ uint32_t rtc_timeslot;
+#endif
+};
/****************************************************************************
- * Public Functions Prototypes
+ * Public Function Prototypes
****************************************************************************/
/****************************************************************************
- * Name: nrf52_bringup
+ * Name: nrf52_radioi8_rtc_init
*
* Description:
- * Perform architecture-specific initialization
- *
- * CONFIG_BOARD_LATE_INITIALIZE=y :
- * Called from board_late_initialize().
- *
- * CONFIG_BOARD_LATE_INITIALIZE=n && CONFIG_BOARDCTL=y :
- * Called from the NSH library
+ * Initialize low resoluton, low power timer for IEEE802154 operations.
+ * Used to handle superframe timings.
*
****************************************************************************/
-int nrf52_bringup(void);
+struct nrf52_radioi8_rtc_s *
+nrf52_radioi8_rtc_init(struct nrf52_radioi8_dev_s *dev);
-#endif /* __ASSEMBLY__ */
-#endif /* __BOARDS_ARM_NRF52_NRF52840_DONGLE_SRC_NRF52840_DONGLE_H */
+#endif /* __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_RTC_H */
diff --git a/arch/arm/src/nrf52/nrf52_ieee802154_tim.c b/arch/arm/src/nrf52/nrf52_ieee802154_tim.c
new file mode 100644
index 0000000000..7e8dd5749c
--- /dev/null
+++ b/arch/arm/src/nrf52/nrf52_ieee802154_tim.c
@@ -0,0 +1,347 @@
+/****************************************************************************
+ * arch/arm/src/nrf52/nrf52_ieee802154_tim.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <debug.h>
+#include <errno.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/irq.h>
+#include <nuttx/wqueue.h>
+
+#include "nrf52_ieee802154_tim.h"
+#include "nrf52_ieee802154_trace.h"
+
+#include "nrf52_ieee802154_priv.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef CONFIG_NRF52_TIMER0
+# error CONFIG_NRF52_TIMER0 is needed to handle radio timings
+#endif
+
+/* Timer instance - 0 */
+
+#define NRF52_IEEE802154_TIMER0 (0)
+
+/* Timer period set to 16us (symbol duration) */
+
+#define NRF52_TIMER_FREQUENCY (1000000 / 16)
+
+/* 16MHz / (2 ** 8) = 62500 */
+
+#define NRF52_TIMER_PRESCALER (8)
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* RTC ops */
+
+static int nrf52_radioi8_tim(struct nrf52_radioi8_dev_s *dev, uint8_t chan,
+ uint32_t val);
+static void nrf52_radioi8_tim_stop(struct nrf52_radioi8_dev_s *dev);
+static void nrf52_radioi8_tim_reset(struct nrf52_radioi8_dev_s *dev);
+
+/* Interrupts logic */
+
+static int nrf52_radioi8_isr_tim(int irq, void *context, void *arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Timer ops */
+
+static struct nrf52_radioi8_tim_ops_s g_radioi8_tim_ops =
+{
+ .setup = nrf52_radioi8_tim,
+ .stop = nrf52_radioi8_tim_stop,
+ .reset = nrf52_radioi8_tim_reset
+};
+
+/* Timer instance */
+
+static struct nrf52_radioi8_tim_s g_radioi8_tim;
+
+/****************************************************************************
+ * Private Function
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf52_radioi8_tim
+ *
+ * Description:
+ * Configure TIMER event.
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_tim(struct nrf52_radioi8_dev_s *dev, uint8_t chan,
+ uint32_t val)
+{
+ struct nrf52_radioi8_tim_s *tim = NULL;
+ irqstate_t flags;
+
+ DEBUGASSERT(dev != NULL);
+ tim = dev->tim;
+
+ flags = enter_critical_section();
+
+ if (tim->tim_pending == true)
+ {
+ wlerr("TIMER busy! drop %" PRId8 " %" PRId32 " request\n", chan, val);
+ ASSERT(0);
+ return -EBUSY;
+ }
+
+ /* Stop timer and clear the counter */
+
+ NRF52_TIM_STOP(tim->tim);
+ NRF52_TIM_CLEAR(tim->tim);
+
+ /* Clear the previous event */
+
+ NRF52_TIM_ACKINT(tim->tim, chan);
+
+ /* Set compare register */
+
+ NRF52_TIM_SETCC(tim->tim, chan, val);
+
+ /* Configure interupt */
+
+ NRF52_TIM_ENABLEINT(tim->tim, chan);
+
+ /* Set TIMER pending flag and used channel */
+
+ tim->tim_pending = true;
+ tim->tim_now = chan;
+
+ /* Start timer */
+
+ nrf52_radioi8_trace_put(RADIO_TRACE_TIMSTART, chan);
+
+ if (val > 0)
+ {
+ NRF52_TIM_START(tim->tim);
+ }
+ else
+ {
+ /* Call handler now */
+
+ nrf52_radioi8_isr_tim(0, NULL, dev);
+ }
+
+ leave_critical_section(flags);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_tim_stop
+ *
+ * Description:
+ * Stop timer.
+ *
+ ****************************************************************************/
+
+static void nrf52_radioi8_tim_stop(struct nrf52_radioi8_dev_s *dev)
+{
+ NRF52_TIM_STOP(dev->tim->tim);
+ NRF52_TIM_DISABLEINT(dev->tim->tim, dev->tim->tim_now);
+
+ /* Reset state */
+
+ dev->tim->tim_pending = false;
+ dev->tim->tim_now = -1;
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_tim_reset
+ *
+ * Description:
+ * Reset TIMER.
+ *
+ ****************************************************************************/
+
+static void nrf52_radioi8_tim_reset(struct nrf52_radioi8_dev_s *dev)
+{
+ /* Configure TIMER - freq = 62500 */
+
+ NRF52_TIM_STOP(dev->tim->tim);
+ NRF52_TIM_CONFIGURE(dev->tim->tim, NRF52_TIM_MODE_TIMER,
+ NRF52_TIM_WIDTH_32B);
+ NRF52_TIM_SETPRE(dev->tim->tim, NRF52_TIMER_PRESCALER);
+
+ /* Reset state */
+
+ dev->tim->tim_pending = false;
+ dev->tim->tim_now = -1;
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_isr_tim
+ *
+ * Description:
+ * Helper tim interrupt handler.
+ *
+ ****************************************************************************/
+
+static int nrf52_radioi8_isr_tim(int irq, void *context, void *arg)
+{
+ struct nrf52_radioi8_dev_s *dev = (struct nrf52_radioi8_dev_s *)arg;
+ struct nrf52_radioi8_tim_s *tim = NULL;
+ irqstate_t flags;
+
+ DEBUGASSERT(dev != NULL);
+ tim = dev->tim;
+
+ flags = enter_critical_section();
+
+ switch (tim->tim_now)
+ {
+ /* RX ACK handler */
+
+ case NRF52_TIMER_CHAN_ACK:
+ {
+ nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_TIMACKTX, 0);
+
+ /* Start TX */
+
+ dev->radio->ops->txstart(dev);
+
+ break;
+ }
+
+ /* Delayed TX handler */
+
+ case NRF52_TIMER_CHAN_TXDELAY:
+ {
+ nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_TIMTXDELAY, 0);
+
+ /* Trigger TX */
+
+ dev->radio->ops->norm_trigger(dev);
+
+ break;
+ }
+
+ /* ACK wait handler */
+
+ case NRF52_TIMER_CHAN_WAITACK:
+ {
+ nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_TIMWAITACK, 0);
+
+ /* Notify radio layer */
+
+ dev->radio->ops->notify_noack(dev);
+
+ break;
+ }
+
+ case NRF52_TIMER_CHAN_CSMADELAY:
+ {
+ nrf52_radioi8_trace_put(RADIO_TRACE_IRQ_TIMCSMADELAY, 0);
+
+ /* Start CCA - we transmit immediately after the CCA procedure ends
+ * (CCAIDLE_TXEN short), or CCABUSY interrupt happen.
+ */
+
+ dev->radio->ops->ccastart(dev);
+
+ break;
+ }
+
+ default:
+ {
+ ASSERT(0);
+ break;
+ }
+ }
+
+ /* Stop timer */
+
+ NRF52_TIM_STOP(tim->tim);
+
+ /* Disable and clear interrupts */
+
+ NRF52_TIM_DISABLEINT(tim->tim, tim->tim_now);
+ NRF52_TIM_ACKINT(tim->tim, tim->tim_now);
+
+ /* Clear TIMER pending flag and used channel */
+
+ tim->tim_pending = false;
+ tim->tim_now = -1;
+
+ leave_critical_section(flags);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf52_radioi8_tim_init
+ *
+ * Description:
+ * Initialize high resoluton timer for IEEE802154 operations.
+ * Used to handle short radio timeouts like ACK, IFS or delayed
+ * transmitions.
+ *
+ ****************************************************************************/
+
+struct nrf52_radioi8_tim_s *
+nrf52_radioi8_tim_init(struct nrf52_radioi8_dev_s *dev)
+{
+ struct nrf52_tim_dev_s *tim = NULL;
+
+ /* Reserve TIMER0 */
+
+ tim = nrf52_tim_init(NRF52_IEEE802154_TIMER0);
+ if (tim == NULL)
+ {
+ wlerr("nrf52_tim_init(0) failed %d\n", -errno);
+ return NULL;
+ }
+
+ /* Atach TIMER interrupt */
+
+ NRF52_TIM_SETISR(tim, nrf52_radioi8_isr_tim, dev);
+
+ /* Set interrupts priority */
+
+ up_prioritize_irq(NRF52_IRQ_TIMER0, 0);
+
+ /* Connect timer */
+
+ memset(&g_radioi8_tim, 0, sizeof(struct nrf52_radioi8_tim_s));
+ g_radioi8_tim.ops = &g_radioi8_tim_ops;
+ g_radioi8_tim.tim = tim;
+
+ return &g_radioi8_tim;
+}
diff --git a/boards/arm/nrf52/nrf52840-dongle/src/nrf52840-dongle.h b/arch/arm/src/nrf52/nrf52_ieee802154_tim.h
similarity index 56%
copy from boards/arm/nrf52/nrf52840-dongle/src/nrf52840-dongle.h
copy to arch/arm/src/nrf52/nrf52_ieee802154_tim.h
index e2f688fb5a..0821353475 100644
--- a/boards/arm/nrf52/nrf52840-dongle/src/nrf52840-dongle.h
+++ b/arch/arm/src/nrf52/nrf52_ieee802154_tim.h
@@ -1,5 +1,5 @@
/****************************************************************************
- * boards/arm/nrf52/nrf52840-dongle/src/nrf52840-dongle.h
+ * arch/arm/src/nrf52/nrf52_ieee802154_tim.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -18,69 +18,88 @@
*
****************************************************************************/
-#ifndef __BOARDS_ARM_NRF52_NRF52840_DONGLE_SRC_NRF52840_DONGLE_H
-#define __BOARDS_ARM_NRF52_NRF52840_DONGLE_SRC_NRF52840_DONGLE_H
+#ifndef __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_TIM_H
+#define __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_TIM_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
-#include <nuttx/compiler.h>
-#include "nrf52_gpio.h"
+#include "nrf52_tim.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
-/* LED definitions **********************************************************/
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
-/* Definitions to configure LED GPIO as outputs */
+enum nrf52_ieee802154_timer_e
+{
+ NRF52_TIMER_CHAN_ACK = 0, /* Handle ACK time */
+ NRF52_TIMER_CHAN_TXDELAY = 1, /* Handle TX delay */
+ NRF52_TIMER_CHAN_WAITACK = 2, /* Handle ACK wait */
+ NRF52_TIMER_CHAN_CSMADELAY = 3, /* Handle CSMA wait */
+};
-#define GPIO_LED1 (GPIO_OUTPUT | GPIO_VALUE_ONE | GPIO_PORT0 | GPIO_PIN(6))
+/* Forward reference */
-/* RGB LED - LD2:
- * RGB_RED - P0-8
- * RGB_GREEN - P1-9
- * RGB_BLUE - P0-12
- */
+struct nrf52_radioi8_tim_s;
+struct nrf52_radioi8_dev_s;
-/* Button definitions *******************************************************/
+/* Timer ops */
-/* Board supports four buttons. */
+struct nrf52_radioi8_tim_ops_s
+{
+ /* Configure TIMER event */
-#define GPIO_BUTTON1 (GPIO_INPUT | GPIO_PULLUP | GPIO_PORT1 | GPIO_PIN(6))
+ int (*setup)(struct nrf52_radioi8_dev_s *dev, uint8_t chan, uint32_t val);
-/****************************************************************************
- * Public Types
- ****************************************************************************/
+ /* Stop timer */
-/****************************************************************************
- * Public Data
- ****************************************************************************/
+ void (*stop)(struct nrf52_radioi8_dev_s *dev);
+
+ /* Reset timer */
-#ifndef __ASSEMBLY__
+ void (*reset)(struct nrf52_radioi8_dev_s *dev);
+};
+
+/* Timer interface */
+
+struct nrf52_radioi8_tim_s
+{
+ /* Timer lower-half */
+
+ struct nrf52_tim_dev_s *tim;
+
+ /* IEEE 802.15.4 timer operations */
+
+ struct nrf52_radioi8_tim_ops_s *ops;
+
+ /* Timer state */
+
+ int8_t tim_now;
+ bool tim_pending;
+};
/****************************************************************************
- * Public Functions Prototypes
+ * Public Function Prototypes
****************************************************************************/
/****************************************************************************
- * Name: nrf52_bringup
+ * Name: nrf52_radioi8_tim_init
*
* Description:
- * Perform architecture-specific initialization
- *
- * CONFIG_BOARD_LATE_INITIALIZE=y :
- * Called from board_late_initialize().
- *
- * CONFIG_BOARD_LATE_INITIALIZE=n && CONFIG_BOARDCTL=y :
- * Called from the NSH library
+ * Initialize high resoluton timer for IEEE802154 operations.
+ * Used to handle short radio timeouts like ACK, IFS or delayed
+ * transmitions.
*
****************************************************************************/
-int nrf52_bringup(void);
+struct nrf52_radioi8_tim_s *
+nrf52_radioi8_tim_init(struct nrf52_radioi8_dev_s *dev);
-#endif /* __ASSEMBLY__ */
-#endif /* __BOARDS_ARM_NRF52_NRF52840_DONGLE_SRC_NRF52840_DONGLE_H */
+#endif /* __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_TIM_H */
diff --git a/arch/arm/src/nrf52/nrf52_ieee802154_trace.c b/arch/arm/src/nrf52/nrf52_ieee802154_trace.c
new file mode 100644
index 0000000000..69d6f7f668
--- /dev/null
+++ b/arch/arm/src/nrf52/nrf52_ieee802154_trace.c
@@ -0,0 +1,154 @@
+/****************************************************************************
+ * arch/arm/src/nrf52/nrf52_ieee802154_trace.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <string.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include <arch/board/board.h>
+
+#include "nrf52_ieee802154_trace.h"
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* This must match enum radio_trace_type_e */
+
+static const char *g_radio_trace_str[] =
+{
+ "RADIO IRQ",
+ "RADIO IRQ: RX DONE",
+ "RADIO IRQ: TX DONE",
+ "RADIO IRQ: ACK TX",
+ "RADIO IRQ: WAIT ACK",
+ "RADIO IRQ: RX ACK DONE",
+ "RADIO IRQ: TX CCA BUSY",
+
+ "TIM IRQ: TIM ACK TX",
+ "TIM IRQ; TIM TX DELAY",
+ "TIM IRQ: TIM WAIT ACK",
+ "TIM IRQ: TIM CSMA DELAY",
+ "RTC IRQ: RTC SD",
+ "RTC IRQ: RTC CAP",
+ "RTC IRQ: RTC TIMESLOT",
+ "RTC IRQ: RTC BI",
+
+ "WORK: RX",
+ "WORK: TX",
+ "WORK: BUSY",
+ "WORK: ED",
+ "WORK: NO ACK",
+
+ "ACKTX",
+ "TIMSTART",
+ "RXENABLE",
+ "RXDISABLE",
+ "CSMASETUP",
+ "CSMATRIGGER",
+ "NOCSMATRIGGER",
+ "NOACK",
+ "DROPFRAME",
+ "TXTRYAGAIN",
+};
+
+/* Trace data */
+
+static volatile size_t g_radio_trace_cntr = 0;
+static volatile struct radio_trace_s
+g_radio_trace[CONFIG_NRF52_RADIO_IEEE802154_TRACE_BUFSIZE];
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf52_radioi8_trace_init
+ *
+ * Description:
+ * Initialize trace interface.
+ *
+ ****************************************************************************/
+
+void nrf52_radioi8_trace_init(void)
+{
+ g_radio_trace_cntr = 0;
+ memset((void *)g_radio_trace, 0, sizeof(g_radio_trace));
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_trace_put
+ *
+ * Description:
+ * Put trace event.
+ *
+ ****************************************************************************/
+
+void nrf52_radioi8_trace_put(uint8_t type, uint32_t arg)
+{
+ if (g_radio_trace_cntr >= CONFIG_NRF52_RADIO_IEEE802154_TRACE_BUFSIZE)
+ {
+ g_radio_trace_cntr = 0;
+ }
+
+ g_radio_trace[g_radio_trace_cntr].time = perf_gettime();
+ g_radio_trace[g_radio_trace_cntr].str = g_radio_trace_str[type];
+ g_radio_trace[g_radio_trace_cntr].arg = arg;
+ g_radio_trace_cntr += 1;
+}
+
+/****************************************************************************
+ * Name: nrf52_radioi8_trace_dump
+ *
+ * Description:
+ * Dump radio trace.
+ *
+ ****************************************************************************/
+
+void nrf52_radioi8_trace_dump(void)
+{
+ int i = 0;
+
+ printf("NRF52 Radio IEEE 802.15.4 Trace dump:\n");
+ printf("CPU freq: %d\n\n", BOARD_SYSTICK_CLOCK);
+
+ for (i = 0; i < g_radio_trace_cntr; i += 1)
+ {
+ printf("[%lu]: %s %lu\n\n",
+ g_radio_trace[i].time,
+ g_radio_trace[i].str,
+ g_radio_trace[i].arg);
+ }
+
+ /* Reset trace buffer */
+
+ g_radio_trace_cntr = 0;
+ memset((void *)g_radio_trace, 0, sizeof(g_radio_trace));
+}
diff --git a/boards/arm/nrf52/nrf52840-dongle/src/nrf52840-dongle.h b/arch/arm/src/nrf52/nrf52_ieee802154_trace.h
similarity index 51%
copy from boards/arm/nrf52/nrf52840-dongle/src/nrf52840-dongle.h
copy to arch/arm/src/nrf52/nrf52_ieee802154_trace.h
index e2f688fb5a..a43daa8c10 100644
--- a/boards/arm/nrf52/nrf52840-dongle/src/nrf52840-dongle.h
+++ b/arch/arm/src/nrf52/nrf52_ieee802154_trace.h
@@ -1,5 +1,5 @@
/****************************************************************************
- * boards/arm/nrf52/nrf52840-dongle/src/nrf52840-dongle.h
+ * arch/arm/src/nrf52/nrf52_ieee802154_trace.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -18,69 +18,89 @@
*
****************************************************************************/
-#ifndef __BOARDS_ARM_NRF52_NRF52840_DONGLE_SRC_NRF52840_DONGLE_H
-#define __BOARDS_ARM_NRF52_NRF52840_DONGLE_SRC_NRF52840_DONGLE_H
+#ifndef __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_TRACE_H
+#define __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_TRACE_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
-#include <nuttx/compiler.h>
-
-#include "nrf52_gpio.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
-/* LED definitions **********************************************************/
-
-/* Definitions to configure LED GPIO as outputs */
-
-#define GPIO_LED1 (GPIO_OUTPUT | GPIO_VALUE_ONE | GPIO_PORT0 | GPIO_PIN(6))
-
-/* RGB LED - LD2:
- * RGB_RED - P0-8
- * RGB_GREEN - P1-9
- * RGB_BLUE - P0-12
- */
-
-/* Button definitions *******************************************************/
-
-/* Board supports four buttons. */
-
-#define GPIO_BUTTON1 (GPIO_INPUT | GPIO_PULLUP | GPIO_PORT1 | GPIO_PIN(6))
-
/****************************************************************************
* Public Types
****************************************************************************/
-/****************************************************************************
- * Public Data
- ****************************************************************************/
-
-#ifndef __ASSEMBLY__
-
-/****************************************************************************
- * Public Functions Prototypes
- ****************************************************************************/
+/* Trace item */
+
+struct radio_trace_s
+{
+ clock_t time; /* Event timestamp */
+ const char *str; /* Event string */
+ uint32_t arg; /* Optional data */
+};
+
+/* This must match char *g_radio_trace_str[] */
+
+enum radio_trace_type_e
+{
+ /* Radio interupts */
+
+ RADIO_TRACE_IRQ_RADIO,
+ RADIO_TRACE_IRQ_RXDONE,
+ RADIO_TRACE_IRQ_TXDONE,
+ RADIO_TRACE_IRQ_ACKTX,
+ RADIO_TRACE_IRQ_WAITACK,
+ RADIO_TRACE_IRQ_RXACKDONE,
+ RADIO_TRACE_IRQ_TXCCABUSY,
+
+ /* Timer interrupts */
+
+ RADIO_TRACE_IRQ_TIMACKTX,
+ RADIO_TRACE_IRQ_TIMTXDELAY,
+ RADIO_TRACE_IRQ_TIMWAITACK,
+ RADIO_TRACE_IRQ_TIMCSMADELAY,
+ RADIO_TRACE_IRQ_RTCSD,
+ RADIO_TRACE_IRQ_RTCCAP,
+ RADIO_TRACE_IRQ_RTCTIMESLOT,
+ RADIO_TRACE_IRQ_RTCBI,
+
+ /* Works */
+
+ RADIO_TRACE_WORK_RX,
+ RADIO_TRACE_WORK_TX,
+ RADIO_TRACE_WORK_BUSY,
+ RADIO_TRACE_WORK_ED,
+ RADIO_TRACE_WORK_NOACK,
+
+ /* Various events */
+
+ RADIO_TRACE_ACKTX,
+ RADIO_TRACE_TIMSTART,
+ RADIO_TRACE_RXENABLE,
+ RADIO_TRACE_RXDISABLE,
+ RADIO_TRACE_CSMASETUP,
+ RADIO_TRACE_CSMATRIGGER,
+ RADIO_TRACE_NOCSMATRIGGER,
+ RADIO_TRACE_NOACK,
+ RADIO_TRACE_DROPFRAME,
+ RADIO_TRACE_TXRETRY,
+};
/****************************************************************************
- * Name: nrf52_bringup
- *
- * Description:
- * Perform architecture-specific initialization
- *
- * CONFIG_BOARD_LATE_INITIALIZE=y :
- * Called from board_late_initialize().
- *
- * CONFIG_BOARD_LATE_INITIALIZE=n && CONFIG_BOARDCTL=y :
- * Called from the NSH library
- *
+ * Public Function Prototypes
****************************************************************************/
-int nrf52_bringup(void);
+#ifdef CONFIG_NRF52_RADIO_IEEE802154_TRACE
+void nrf52_radioi8_trace_init(void);
+void nrf52_radioi8_trace_put(uint8_t type, uint32_t arg);
+void nrf52_radioi8_trace_dump(void);
+#else
+# define nrf52_radioi8_trace_put(...)
+#endif
-#endif /* __ASSEMBLY__ */
-#endif /* __BOARDS_ARM_NRF52_NRF52840_DONGLE_SRC_NRF52840_DONGLE_H */
+#endif /* __ARCH_ARM_SRC_NRF52_NRF52_IEEE802154_TRACE_H */
diff --git a/boards/arm/nrf52/nrf9160-dk-nrf52/src/nrf52_bringup.c b/arch/arm/src/nrf52/nrf52_radio_ieee802154.h
similarity index 69%
copy from boards/arm/nrf52/nrf9160-dk-nrf52/src/nrf52_bringup.c
copy to arch/arm/src/nrf52/nrf52_radio_ieee802154.h
index d5bb51e644..7160378a50 100644
--- a/boards/arm/nrf52/nrf9160-dk-nrf52/src/nrf52_bringup.c
+++ b/arch/arm/src/nrf52/nrf52_radio_ieee802154.h
@@ -1,5 +1,5 @@
/****************************************************************************
- * boards/arm/nrf52/nrf9160-dk-nrf52/src/nrf52_bringup.c
+ * arch/arm/src/nrf52/nrf52_radio_ieee802154.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -18,37 +18,36 @@
*
****************************************************************************/
+#ifndef __ARCH_ARM_SRC_NRF52_NRF52_RADIO_IEEE802154_H
+#define __ARCH_ARM_SRC_NRF52_NRF52_RADIO_IEEE802154_H
+
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
-#include <sys/types.h>
-#include <syslog.h>
+#include <nuttx/wireless/ieee802154/ieee802154_radio.h>
+
+#include "nrf52_radio.h"
/****************************************************************************
- * Public Functions
+ * Public Types
****************************************************************************/
/****************************************************************************
- * Name: nrf52_bringup
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf52_radioi8_register
*
* Description:
- * Perform architecture-specific initialization
- *
- * CONFIG_BOARD_LATE_INITIALIZE=y :
- * Called from board_late_initialize().
- *
- * CONFIG_BOARD_LATE_INITIALIZE=n && CONFIG_BOARDCTL=y :
- * Called from the NSH library
+ * Register NRF52 radio in IEEE802154 mode
*
****************************************************************************/
-int nrf52_bringup(void)
-{
- int ret;
+struct ieee802154_radio_s *
+nrf52_radioi8_register(struct nrf52_radio_board_s *board);
- UNUSED(ret);
- return OK;
-}
+#endif /* __ARCH_ARM_SRC_NRF52_NRF52_RADIO_IEEE802154_H */
diff --git a/boards/Kconfig b/boards/Kconfig
index 5fed6ec4c0..fe94e4ba1a 100644
--- a/boards/Kconfig
+++ b/boards/Kconfig
@@ -3650,6 +3650,15 @@ endif
if ARCH_BOARD_NRF52840_DK
source "boards/arm/nrf52/nrf52840-dk/Kconfig"
endif
+if ARCH_BOARD_THINGY52
+source "boards/arm/nrf52/thingy52/Kconfig"
+endif
+if ARCH_BOARD_THINGY91_NRF52
+source "boards/arm/nrf52/thingy91-nrf52/Kconfig"
+endif
+if ARCH_BOARD_NRF9160_DK_NRF52
+source "boards/arm/nrf52/nrf9160-dk-nrf52/Kconfig"
+endif
if ARCH_BOARD_NUTINY_NUC120
source "boards/arm/nuc1xx/nutiny-nuc120/Kconfig"
endif
diff --git a/boards/arm/nrf52/nrf9160-dk-nrf52/src/nrf52_bringup.c b/boards/arm/nrf52/common/include/nrf52_ieee802154.h
similarity index 72%
copy from boards/arm/nrf52/nrf9160-dk-nrf52/src/nrf52_bringup.c
copy to boards/arm/nrf52/common/include/nrf52_ieee802154.h
index d5bb51e644..187348bf9e 100644
--- a/boards/arm/nrf52/nrf9160-dk-nrf52/src/nrf52_bringup.c
+++ b/boards/arm/nrf52/common/include/nrf52_ieee802154.h
@@ -1,5 +1,5 @@
/****************************************************************************
- * boards/arm/nrf52/nrf9160-dk-nrf52/src/nrf52_bringup.c
+ * boards/arm/nrf52/common/include/nrf52_ieee802154.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -18,37 +18,33 @@
*
****************************************************************************/
+#ifndef __BOARDS_ARM_NRF52_COMMON_INCLUDE_NRF52_IEEE802154_H
+#define __BOARDS_ARM_NRF52_COMMON_INCLUDE_NRF52_IEEE802154_H
+
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
-#include <sys/types.h>
-#include <syslog.h>
-
/****************************************************************************
- * Public Functions
+ * Public Functions Prototypes
****************************************************************************/
/****************************************************************************
- * Name: nrf52_bringup
+ * Name: nrf52_ieee802154_initialize
*
* Description:
- * Perform architecture-specific initialization
- *
- * CONFIG_BOARD_LATE_INITIALIZE=y :
- * Called from board_late_initialize().
+ * Initialize IEEE802154 network.
*
- * CONFIG_BOARD_LATE_INITIALIZE=n && CONFIG_BOARDCTL=y :
- * Called from the NSH library
+ * Returned Value:
+ * Zero is returned on success. Otherwise, a negated errno value is
+ * returned to indicate the nature of the failure.
*
****************************************************************************/
-int nrf52_bringup(void)
-{
- int ret;
+#ifdef CONFIG_NRF52_RADIO_IEEE802154
+int nrf52_ieee802154_initialize(void);
+#endif
- UNUSED(ret);
- return OK;
-}
+#endif /* __BOARDS_ARM_NRF52_COMMON_INCLUDE_NRF52_IEEE802154_H */
diff --git a/boards/arm/nrf52/nrf9160-dk-nrf52/src/nrf9160-dk-nrf52.h b/boards/arm/nrf52/common/include/nrf52_mrf24j40.h
similarity index 63%
copy from boards/arm/nrf52/nrf9160-dk-nrf52/src/nrf9160-dk-nrf52.h
copy to boards/arm/nrf52/common/include/nrf52_mrf24j40.h
index 82fe34c862..cde0af3688 100644
--- a/boards/arm/nrf52/nrf9160-dk-nrf52/src/nrf9160-dk-nrf52.h
+++ b/boards/arm/nrf52/common/include/nrf52_mrf24j40.h
@@ -1,5 +1,5 @@
/****************************************************************************
- * boards/arm/nrf52/nrf9160-dk-nrf52/src/nrf9160-dk-nrf52.h
+ * boards/arm/nrf52/common/include/nrf52_mrf24j40.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -18,51 +18,50 @@
*
****************************************************************************/
-#ifndef __BOARDS_ARM_NRF52_NRF9160_DK_NRF52_SRC_NRF9160_DK_NRF52_H
-#define __BOARDS_ARM_NRF52_NRF9160_DK_NRF52_SRC_NRF9160_DK_NRF52_H
+#ifndef __BOARDS_ARM_NRF52_COMMON_INCLUDE_NRF52_MRF24J40_H
+#define __BOARDS_ARM_NRF52_COMMON_INCLUDE_NRF52_MRF24J40_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
-#include <nuttx/compiler.h>
-#include "nrf52_gpio.h"
+#include <stdint.h>
-/****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
+#include <nuttx/wireless/ieee802154/mrf24j40.h>
/****************************************************************************
* Public Types
****************************************************************************/
-/****************************************************************************
- * Public Data
- ****************************************************************************/
-
-#ifndef __ASSEMBLY__
+struct nrf52_mrf24j40_s
+{
+ struct mrf24j40_lower_s dev;
+ xcpt_t handler;
+ void *arg;
+ uint32_t intcfg;
+ uint8_t spidev;
+};
/****************************************************************************
* Public Functions Prototypes
****************************************************************************/
/****************************************************************************
- * Name: nrf52_bringup
+ * Name: nrf52_mrf24j40_devsetup
*
* Description:
- * Perform architecture-specific initialization
- *
- * CONFIG_BOARD_LATE_INITIALIZE=y :
- * Called from board_late_initialize().
+ * Initialize one the MRF24J40 device in one mikroBUS slot
*
- * CONFIG_BOARD_LATE_INITIALIZE=n && CONFIG_BOARDCTL=y :
- * Called from the NSH library
+ * Returned Value:
+ * Zero is returned on success. Otherwise, a negated errno value is
+ * returned to indicate the nature of the failure.
*
****************************************************************************/
-int nrf52_bringup(void);
+#ifdef CONFIG_IEEE802154_MRF24J40
+int nrf52_mrf24j40_devsetup(struct nrf52_mrf24j40_s *priv);
+#endif
-#endif /* __ASSEMBLY__ */
-#endif /* __BOARDS_ARM_NRF52_NRF9160_DK_NRF52_SRC_NRF9160_DK_NRF52_H */
+#endif /* __BOARDS_ARM_NRF52_COMMON_INCLUDE_NRF52_MRF24J40_H */
diff --git a/boards/arm/nrf52/common/src/CMakeLists.txt b/boards/arm/nrf52/common/src/CMakeLists.txt
index fa869af2fd..ade42fdd19 100644
--- a/boards/arm/nrf52/common/src/CMakeLists.txt
+++ b/boards/arm/nrf52/common/src/CMakeLists.txt
@@ -40,6 +40,14 @@ if(CONFIG_ARCH_BOARD_COMMON)
list(APPEND SRCS nrf52_reset.c)
endif()
+ if(CONFIG_NRF52_RADIO_IEEE802154)
+ list(APPEND SRCS nrf52_ieee802154.c)
+ endif()
+
+ if(CONFIG_IEEE802154_MRF24J40)
+ list(APPEND SRCS nrf52_mrf24j40.c)
+ endif()
+
target_sources(board PRIVATE ${SRCS})
endif()
diff --git a/boards/arm/nrf52/common/src/Make.defs b/boards/arm/nrf52/common/src/Make.defs
index f7870690a7..90031c5cf2 100644
--- a/boards/arm/nrf52/common/src/Make.defs
+++ b/boards/arm/nrf52/common/src/Make.defs
@@ -40,6 +40,14 @@ ifeq ($(CONFIG_BOARDCTL_RESET),y)
CSRCS += nrf52_reset.c
endif
+ifeq ($(CONFIG_NRF52_RADIO_IEEE802154),y)
+CSRCS += nrf52_ieee802154.c
+endif
+
+ifeq ($(CONFIG_IEEE802154_MRF24J40),y)
+CSRCS += nrf52_mrf24j40.c
+endif
+
DEPPATH += --dep-path src
VPATH += :src
CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)src
diff --git a/boards/arm/nrf52/common/src/nrf52_ieee802154.c b/boards/arm/nrf52/common/src/nrf52_ieee802154.c
new file mode 100644
index 0000000000..d2dcedd086
--- /dev/null
+++ b/boards/arm/nrf52/common/src/nrf52_ieee802154.c
@@ -0,0 +1,106 @@
+/****************************************************************************
+ * boards/arm/nrf52/common/src/nrf52_ieee802154.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <debug.h>
+#include <errno.h>
+
+#include <nuttx/wireless/ieee802154/ieee802154_mac.h>
+
+#include "nrf52_radio_ieee802154.h"
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf52_ieee802154_initialize
+ *
+ * Description:
+ * Initialize the IEEE 802.15.4 network.
+ *
+ * Returned Value:
+ * Zero is returned on success. Otherwise, a negated errno value is
+ * returned to indicate the nature of the failure.
+ *
+ ****************************************************************************/
+
+int nrf52_ieee802154_initialize(void)
+{
+ struct ieee802154_radio_s *radio;
+ MACHANDLE mac;
+ int ret;
+
+ /* Initialize and register the SPI MRF24J40 device */
+
+ radio = nrf52_radioi8_register(NULL);
+ if (radio == NULL)
+ {
+ wlerr("ERROR: Failed to initialize radio\n");
+ return -ENODEV;
+ }
+
+ /* Create a 802.15.4 MAC device from a 802.15.4 compatible radio device. */
+
+ mac = mac802154_create(radio);
+ if (mac == NULL)
+ {
+ wlerr("ERROR: Failed to initialize IEEE802.15.4 MAC\n");
+ return -ENODEV;
+ }
+
+#ifdef CONFIG_IEEE802154_NETDEV
+ /* Use the IEEE802.15.4 MAC interface instance to create a 6LoWPAN
+ * network interface by wrapping the MAC intrface instance in a
+ * network device driver via mac802154dev_register().
+ */
+
+ ret = mac802154netdev_register(mac);
+ if (ret < 0)
+ {
+ wlerr("ERROR: Failed to register the MAC network driver wpan%d: %d\n",
+ 0, ret);
+ return ret;
+ }
+#endif
+
+#ifdef CONFIG_IEEE802154_MACDEV
+ /* If want to call these APIs from userspace, you have to wrap the MAC
+ * interface in a character device viamac802154dev_register().
+ */
+
+ ret = mac802154dev_register(mac, 0);
+ if (ret < 0)
+ {
+ wlerr("ERROR:");
+ wlerr(" Failed to register the MAC character driver /dev/ieee%d: %d\n",
+ 0, ret);
+ return ret;
+ }
+#endif
+
+ UNUSED(ret);
+ return OK;
+}
diff --git a/boards/arm/nrf52/common/src/nrf52_mrf24j40.c b/boards/arm/nrf52/common/src/nrf52_mrf24j40.c
new file mode 100644
index 0000000000..dcfbf40840
--- /dev/null
+++ b/boards/arm/nrf52/common/src/nrf52_mrf24j40.c
@@ -0,0 +1,136 @@
+/****************************************************************************
+ * boards/arm/nrf52/common/src/nrf52_mrf24j40.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdio.h>
+#include <stdint.h>
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/wireless/ieee802154/ieee802154_mac.h>
+#include <nuttx/wireless/ieee802154/mrf24j40.h>
+
+#include "nrf52_gpio.h"
+#include "nrf52_spi.h"
+
+#include "nrf52_mrf24j40.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef CONFIG_DRIVERS_WIRELESS
+# error Wireless support requires CONFIG_DRIVERS_WIRELESS
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf52_mrf24j40_devsetup
+ *
+ * Description:
+ * Initialize one the MRF24J40 device in one mikroBUS slot
+ *
+ * Returned Value:
+ * Zero is returned on success. Otherwise, a negated errno value is
+ * returned to indicate the nature of the failure.
+ *
+ ****************************************************************************/
+
+int nrf52_mrf24j40_devsetup(struct nrf52_mrf24j40_s *priv)
+{
+ struct ieee802154_radio_s *radio;
+ MACHANDLE mac;
+ struct spi_dev_s *spi;
+ int ret;
+
+ /* Configure pins */
+
+ nrf52_gpio_config(priv->intcfg);
+
+ /* Initialize the SPI bus and get an instance of the SPI interface */
+
+ spi = nrf52_spibus_initialize(priv->spidev);
+ if (spi == NULL)
+ {
+ wlerr("Failed to initialize SPI bus %d\n", priv->spidev);
+ return -ENODEV;
+ }
+
+ /* Initialize and register the SPI MRF24J40 device */
+
+ radio = mrf24j40_init(spi, &priv->dev);
+ if (radio == NULL)
+ {
+ wlerr("Failed to initialize SPI bus %d\n", priv->spidev);
+ return -ENODEV;
+ }
+
+ /* Create a 802.15.4 MAC device from a 802.15.4 compatible radio device. */
+
+ mac = mac802154_create(radio);
+ if (mac == NULL)
+ {
+ wlerr("Failed to initialize IEEE802.15.4 MAC\n");
+ return -ENODEV;
+ }
+
+#ifdef CONFIG_IEEE802154_NETDEV
+ /* Use the IEEE802.15.4 MAC interface instance to create a 6LoWPAN
+ * network interface by wrapping the MAC intrface instance in a
+ * network device driver via mac802154dev_register().
+ */
+
+ ret = mac802154netdev_register(mac);
+ if (ret < 0)
+ {
+ wlerr("Failed to register the MAC network driver wpan%d: %d\n",
+ 0, ret);
+ return ret;
+ }
+#endif
+
+#ifdef CONFIG_IEEE802154_MACDEV
+ /* If want to call these APIs from userspace, you have to wrap the MAC
+ * interface in a character device viamac802154dev_register().
+ */
+
+ ret = mac802154dev_register(mac, 0);
+ if (ret < 0)
+ {
+ wlerr("Failed to register the MAC character driver /dev/ieee%d: %d\n",
+ 0, ret);
+ return ret;
+ }
+#endif
+
+ UNUSED(ret);
+ return OK;
+}
diff --git a/boards/arm/nrf52/nrf52832-dk/configs/mrf24j40_6lowpan/defconfig b/boards/arm/nrf52/nrf52832-dk/configs/mrf24j40_6lowpan/defconfig
new file mode 100644
index 0000000000..f0c31e2a45
--- /dev/null
+++ b/boards/arm/nrf52/nrf52832-dk/configs/mrf24j40_6lowpan/defconfig
@@ -0,0 +1,81 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed .config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that includes your
+# modifications.
+#
+# CONFIG_ARCH_FPU is not set
+CONFIG_ARCH="arm"
+CONFIG_ARCH_BOARD="nrf52832-dk"
+CONFIG_ARCH_BOARD_COMMON=y
+CONFIG_ARCH_BOARD_NRF52832_DK=y
+CONFIG_ARCH_CHIP="nrf52"
+CONFIG_ARCH_CHIP_NRF52832=y
+CONFIG_ARCH_CHIP_NRF52=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_ARCH_STDARG_H=y
+CONFIG_BOARDCTL_RESET=y
+CONFIG_BOARD_LOOPSPERMSEC=5500
+CONFIG_BUILTIN=y
+CONFIG_DRIVERS_IEEE802154=y
+CONFIG_DRIVERS_WIRELESS=y
+CONFIG_EXAMPLES_NETTEST=y
+CONFIG_EXAMPLES_NETTEST_DEVNAME="wpan0"
+CONFIG_EXAMPLES_NETTEST_SERVER_PORTNO=61616
+CONFIG_EXAMPLES_NETTEST_TARGET2=y
+CONFIG_EXAMPLES_UDP=y
+CONFIG_EXAMPLES_UDP_CLIENT_PORTNO=61617
+CONFIG_EXAMPLES_UDP_DEVNAME="wpan0"
+CONFIG_EXAMPLES_UDP_IPv6=y
+CONFIG_EXAMPLES_UDP_SERVER_PORTNO=61616
+CONFIG_EXAMPLES_UDP_TARGET2=y
+CONFIG_EXPERIMENTAL=y
+CONFIG_FS_PROCFS=y
+CONFIG_IDLETHREAD_STACKSIZE=2048
+CONFIG_IEEE802154_I8SAK=y
+CONFIG_IEEE802154_MAC=y
+CONFIG_IEEE802154_MACDEV=y
+CONFIG_IEEE802154_MRF24J40=y
+CONFIG_IEEE802154_NETDEV=y
+CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_MAC802154_NTXDESC=36
+CONFIG_MM_REGIONS=2
+CONFIG_NET=y
+CONFIG_NETDEV_HPWORK_THREAD=y
+CONFIG_NETDEV_LATEINIT=y
+CONFIG_NETDEV_STATISTICS=y
+CONFIG_NETDEV_WIRELESS_IOCTL=y
+CONFIG_NETINIT_NETLOCAL=y
+CONFIG_NETINIT_NOMAC=y
+CONFIG_NETUTILS_TELNETD=y
+CONFIG_NET_6LOWPAN=y
+CONFIG_NET_BROADCAST=y
+CONFIG_NET_IPv6=y
+CONFIG_NET_SOCKOPTS=y
+CONFIG_NET_STATISTICS=y
+CONFIG_NET_TCP=y
+CONFIG_NET_TCPBACKLOG=y
+CONFIG_NET_TCP_WRITE_BUFFERS=y
+CONFIG_NET_UDP=y
+CONFIG_NRF52_GPIOTE=y
+CONFIG_NRF52_SPI0_MASTER=y
+CONFIG_NRF52_UART0=y
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_PROMPT_STRING="nsh-mrf> "
+CONFIG_NSH_READLINE=y
+CONFIG_RAM_SIZE=65535
+CONFIG_RAM_START=0x20000000
+CONFIG_RAW_BINARY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_HPWORK=y
+CONFIG_SCHED_LPWORK=y
+CONFIG_SCHED_WAITPID=y
+CONFIG_SPI=y
+CONFIG_SYMTAB_ORDEREDBYNAME=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_SYSTEM_TELNET_CLIENT=y
+CONFIG_UART0_SERIAL_CONSOLE=y
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_IEEE802154=y
diff --git a/boards/arm/nrf52/nrf52832-dk/configs/mrf24j40_mac/defconfig b/boards/arm/nrf52/nrf52832-dk/configs/mrf24j40_mac/defconfig
new file mode 100644
index 0000000000..0b3a93261d
--- /dev/null
+++ b/boards/arm/nrf52/nrf52832-dk/configs/mrf24j40_mac/defconfig
@@ -0,0 +1,60 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed .config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that includes your
+# modifications.
+#
+# CONFIG_ARCH_FPU is not set
+CONFIG_ARCH="arm"
+CONFIG_ARCH_BOARD="nrf52832-dk"
+CONFIG_ARCH_BOARD_COMMON=y
+CONFIG_ARCH_BOARD_NRF52832_DK=y
+CONFIG_ARCH_CHIP="nrf52"
+CONFIG_ARCH_CHIP_NRF52832=y
+CONFIG_ARCH_CHIP_NRF52=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_ARCH_STDARG_H=y
+CONFIG_BOARDCTL_RESET=y
+CONFIG_BOARD_LOOPSPERMSEC=5500
+CONFIG_BUILTIN=y
+CONFIG_DEBUG_FULLOPT=y
+CONFIG_DEBUG_SYMBOLS=y
+CONFIG_DRIVERS_IEEE802154=y
+CONFIG_DRIVERS_WIRELESS=y
+CONFIG_FS_PROCFS=y
+CONFIG_IDLETHREAD_STACKSIZE=2048
+CONFIG_IEEE802154_I8SAK=y
+CONFIG_IEEE802154_MAC=y
+CONFIG_IEEE802154_MACDEV=y
+CONFIG_IEEE802154_MRF24J40=y
+CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_MM_REGIONS=2
+CONFIG_NRF52_GPIOTE=y
+CONFIG_NRF52_SPI0_MASTER=y
+CONFIG_NRF52_UART0=y
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_LINELEN=64
+CONFIG_NSH_PROMPT_STRING="nsh-mrf> "
+CONFIG_NSH_READLINE=y
+CONFIG_PREALLOC_TIMERS=4
+CONFIG_RAM_SIZE=65535
+CONFIG_RAM_START=0x20000000
+CONFIG_RAW_BINARY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_HPWORK=y
+CONFIG_SCHED_LPWORK=y
+CONFIG_SCHED_WAITPID=y
+CONFIG_SPI=y
+CONFIG_STACK_COLORATION=y
+CONFIG_STACK_USAGE=y
+CONFIG_START_DAY=26
+CONFIG_START_MONTH=3
+CONFIG_SYMTAB_ORDEREDBYNAME=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_TASK_NAME_SIZE=0
+CONFIG_UART0_SERIAL_CONSOLE=y
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_IEEE802154=y
diff --git a/boards/arm/nrf52/nrf52832-dk/include/board.h b/boards/arm/nrf52/nrf52832-dk/include/board.h
index b776889582..092a3a0e10 100644
--- a/boards/arm/nrf52/nrf52832-dk/include/board.h
+++ b/boards/arm/nrf52/nrf52832-dk/include/board.h
@@ -107,4 +107,16 @@
#define BOARD_UART0_RX_PIN (GPIO_INPUT | GPIO_PORT0 | GPIO_PIN(8))
#define BOARD_UART0_TX_PIN (GPIO_OUTPUT | GPIO_VALUE_ONE | GPIO_PORT0 | GPIO_PIN(6))
+/* SPI Pins *****************************************************************/
+
+/* SPI0 - Arduino PINs
+ * SPI0_SCK - P0.25 (P13)
+ * SPI0_MISO - P0.24 (D12)
+ * SPI0_MOSI - P0.23 (D11)
+ */
+
+#define BOARD_SPI0_SCK_PIN (GPIO_OUTPUT | GPIO_VALUE_ONE | GPIO_PORT0 | GPIO_PIN(25))
+#define BOARD_SPI0_MISO_PIN (GPIO_INPUT | GPIO_PORT0 | GPIO_PIN(24))
+#define BOARD_SPI0_MOSI_PIN (GPIO_OUTPUT | GPIO_PORT0 | GPIO_PIN(23))
+
#endif /* __BOARDS_ARM_NRF52_NRF52832_DK_INCLUDE_BOARD_H */
diff --git a/boards/arm/nrf52/nrf52832-dk/src/CMakeLists.txt b/boards/arm/nrf52/nrf52832-dk/src/CMakeLists.txt
index 7e61a0d0a9..d09591c71e 100644
--- a/boards/arm/nrf52/nrf52832-dk/src/CMakeLists.txt
+++ b/boards/arm/nrf52/nrf52832-dk/src/CMakeLists.txt
@@ -34,6 +34,14 @@ if(CONFIG_ARCH_BUTTONS)
list(APPEND SRCS nrf52_buttons.c)
endif()
+if(CONFIG_NRF52_SPI_MASTER)
+ list(APPEND SRCS nrf52_spi.c)
+endif()
+
+if(CONFIG_IEEE802154_MRF24J40)
+ list(APPEND SRCS nrf52_ieee802154_mrf24j40.c)
+endif()
+
target_sources(board PRIVATE ${SRCS})
if(CONFIG_ARCH_BOARD_COMMON)
diff --git a/boards/arm/nrf52/nrf52832-dk/src/Make.defs b/boards/arm/nrf52/nrf52832-dk/src/Make.defs
index 7e4e6508fa..7b6364940c 100644
--- a/boards/arm/nrf52/nrf52832-dk/src/Make.defs
+++ b/boards/arm/nrf52/nrf52832-dk/src/Make.defs
@@ -36,6 +36,14 @@ ifeq ($(CONFIG_ARCH_BUTTONS),y)
CSRCS += nrf52_buttons.c
endif
+ifeq ($(CONFIG_NRF52_SPI_MASTER),y)
+CSRCS += nrf52_spi.c
+endif
+
+ifeq ($(CONFIG_IEEE802154_MRF24J40),y)
+CSRCS += nrf52_ieee802154_mrf24j40.c
+endif
+
DEPPATH += --dep-path board
VPATH += :board
CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)board
diff --git a/boards/arm/nrf52/nrf52832-dk/src/nrf52832-dk.h b/boards/arm/nrf52/nrf52832-dk/src/nrf52832-dk.h
index bdf5c8f0ad..c857ac3e5d 100644
--- a/boards/arm/nrf52/nrf52832-dk/src/nrf52832-dk.h
+++ b/boards/arm/nrf52/nrf52832-dk/src/nrf52832-dk.h
@@ -64,6 +64,16 @@
#define GPIO_BUTTON3 (GPIO_INPUT | GPIO_PULLUP | GPIO_PORT0 | GPIO_PIN(15))
#define GPIO_BUTTON4 (GPIO_INPUT | GPIO_PULLUP | GPIO_PORT0 | GPIO_PIN(16))
+/* GPIO definitions *********************************************************/
+
+/* MRF24J40 pins
+ * CS - P0.11
+ * INT - P0.12
+ */
+
+#define GPIO_MRF24J40_CS (GPIO_OUTPUT | GPIO_VALUE_ONE | GPIO_PORT0 | GPIO_PIN(11))
+#define GPIO_MRF24J40_INT (GPIO_INPUT | GPIO_PORT0 | GPIO_PIN(12))
+
/****************************************************************************
* Public Types
****************************************************************************/
@@ -94,5 +104,33 @@
int nrf52_bringup(void);
+/****************************************************************************
+ * Name: nrf52_spidev_initialize
+ *
+ * Description:
+ * Called to configure SPI chip select GPIO pins for the nrf52840-dk board.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NRF52_SPI_MASTER
+void nrf52_spidev_initialize(void);
+#endif
+
+/****************************************************************************
+ * Name: nrf52_mrf24j40_initialize
+ *
+ * Description:
+ * Initialize the MRF24J40 device.
+ *
+ * Returned Value:
+ * Zero is returned on success. Otherwise, a negated errno value is
+ * returned to indicate the nature of the failure.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_IEEE802154_MRF24J40
+int nrf52_mrf24j40_initialize(void);
+#endif
+
#endif /* __ASSEMBLY__ */
#endif /* __BOARDS_ARM_NRF52_NRF52832_DK_SRC_NRF52832_DK_H */
diff --git a/boards/arm/nrf52/nrf52832-dk/src/nrf52_boot.c b/boards/arm/nrf52/nrf52832-dk/src/nrf52_boot.c
index a23cf76ca9..aeaf57d630 100644
--- a/boards/arm/nrf52/nrf52832-dk/src/nrf52_boot.c
+++ b/boards/arm/nrf52/nrf52832-dk/src/nrf52_boot.c
@@ -54,6 +54,12 @@ void nrf52_board_initialize(void)
#ifdef CONFIG_ARCH_LEDS
board_autoled_initialize();
#endif
+
+#ifdef CONFIG_NRF52_SPI_MASTER
+ /* Configure SPI chip selects */
+
+ nrf52_spidev_initialize();
+#endif
}
/****************************************************************************
diff --git a/boards/arm/nrf52/nrf52832-dk/src/nrf52_bringup.c b/boards/arm/nrf52/nrf52832-dk/src/nrf52_bringup.c
index 3526a9f930..aca8f50019 100644
--- a/boards/arm/nrf52/nrf52832-dk/src/nrf52_bringup.c
+++ b/boards/arm/nrf52/nrf52832-dk/src/nrf52_bringup.c
@@ -53,6 +53,10 @@
# include "nrf52_sdc.h"
#endif
+#ifdef CONFIG_IEEE802154_MRF24J40
+# include "nrf52_mrf24j40.h"
+#endif
+
#include "nrf52832-dk.h"
/****************************************************************************
@@ -152,6 +156,17 @@ int nrf52_bringup(void)
}
#endif /* CONFIG_MTD */
+#ifdef CONFIG_IEEE802154_MRF24J40
+ /* Configure MRF24J40 wireless */
+
+ ret = nrf52_mrf24j40_initialize();
+ if (ret < 0)
+ {
+ syslog(LOG_ERR, "ERROR: nrf52_mrf24j40_initialize() failed: %d\n",
+ ret);
+ }
+#endif
+
UNUSED(ret);
return OK;
}
diff --git a/boards/arm/nrf52/nrf52832-dk/src/nrf52_ieee802154_mrf24j40.c b/boards/arm/nrf52/nrf52832-dk/src/nrf52_ieee802154_mrf24j40.c
new file mode 100644
index 0000000000..13986ab94f
--- /dev/null
+++ b/boards/arm/nrf52/nrf52832-dk/src/nrf52_ieee802154_mrf24j40.c
@@ -0,0 +1,177 @@
+/****************************************************************************
+ * boards/arm/nrf52/nrf52832-dk/src/nrf52_ieee802154_mrf24j40.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <debug.h>
+
+#include "nrf52_gpio.h"
+#include "nrf52_gpiote.h"
+#include "nrf52_spi.h"
+
+#include "nrf52_mrf24j40.h"
+
+#include "nrf52832-dk.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef CONFIG_NRF52_SPI0_MASTER
+# error this driver requires CONFIG_NRF52_SPI0_MASTER
+#endif
+
+#define NRF52_MRF24J40_SPI (0)
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* IRQ/GPIO access callbacks. These operations all hidden behind callbacks
+ * to isolate the MRF24J40 driver from differences in GPIO interrupt handling
+ * varying boards and MCUs.
+ *
+ * irq_attach - Attach the MRF24J40 interrupt handler to the GPIO
+ * interrupt
+ * irq_enable - Enable or disable the GPIO interrupt
+ */
+
+static int nrf52_attach_irq(const struct mrf24j40_lower_s *lower,
+ xcpt_t handler, void *arg);
+static void nrf52_enable_irq(const struct mrf24j40_lower_s *lower,
+ bool state);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* A reference to a structure of this type must be passed to the MRF24J40
+ * driver. This structure provides information about the configuration
+ * of the MRF24J40 and provides some board-specific hooks.
+ *
+ * Memory for this structure is provided by the caller. It is not copied
+ * by the driver and is presumed to persist while the driver is active. The
+ * memory must be writable because, under certain circumstances, the driver
+ * may modify frequency or X plate resistance values.
+ */
+
+static struct nrf52_mrf24j40_s g_mrf24j40_priv =
+{
+ .dev.attach = nrf52_attach_irq,
+ .dev.enable = nrf52_enable_irq,
+ .handler = NULL,
+ .arg = NULL,
+ .intcfg = GPIO_MRF24J40_INT,
+ .spidev = NRF52_MRF24J40_SPI,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf52_attach_irq
+ *
+ * Description:
+ * Attach the MRF24J40 interrupt handler to the GPIO interrupt.
+ *
+ ****************************************************************************/
+
+static int nrf52_attach_irq(const struct mrf24j40_lower_s *lower,
+ xcpt_t handler, void *arg)
+{
+ struct nrf52_mrf24j40_s *priv = (struct nrf52_mrf24j40_s *)lower;
+
+ DEBUGASSERT(priv != NULL);
+
+ /* Just save the handler for use when the interrupt is enabled */
+
+ priv->handler = handler;
+ priv->arg = arg;
+ return OK;
+}
+
+/****************************************************************************
+ * Name: nrf52_enable_irq
+ *
+ * Description:
+ * Enable or disable the GPIO interrupt
+ *
+ ****************************************************************************/
+
+static void nrf52_enable_irq(const struct mrf24j40_lower_s *lower,
+ bool state)
+{
+ struct nrf52_mrf24j40_s *priv = (struct nrf52_mrf24j40_s *)lower;
+
+ /* The caller should not attempt to enable interrupts if the handler
+ * has not yet been 'attached'
+ */
+
+ DEBUGASSERT(priv != NULL && (priv->handler != NULL || !state));
+
+ wlinfo("state:%d\n", (int)state);
+
+ /* Attach and enable, or detach and disable */
+
+ if (state)
+ {
+ nrf52_gpiote_set_event(priv->intcfg, false, true,
+ priv->handler, priv->arg);
+ }
+ else
+ {
+ nrf52_gpiote_set_event(priv->intcfg, false, false,
+ priv->handler, priv->arg);
+ }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf52_mrf24j40_initialize
+ *
+ * Description:
+ * Initialize the MRF24J40 device.
+ *
+ * Returned Value:
+ * Zero is returned on success. Otherwise, a negated errno value is
+ * returned to indicate the nature of the failure.
+ *
+ ****************************************************************************/
+
+int nrf52_mrf24j40_initialize(void)
+{
+ int ret;
+
+ ret = nrf52_mrf24j40_devsetup(&g_mrf24j40_priv);
+ if (ret < 0)
+ {
+ wlerr("Failed to initialize mrf24j40: %d\n", ret);
+ }
+
+ return ret;
+}
diff --git a/boards/arm/nrf52/nrf52832-dk/src/nrf52_spi.c b/boards/arm/nrf52/nrf52832-dk/src/nrf52_spi.c
new file mode 100644
index 0000000000..7e8e6d3adf
--- /dev/null
+++ b/boards/arm/nrf52/nrf52832-dk/src/nrf52_spi.c
@@ -0,0 +1,177 @@
+/****************************************************************************
+ * boards/arm/nrf52/nrf52832-dk/src/nrf52_spi.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/spi/spi.h>
+
+#include "arm_internal.h"
+#include "chip.h"
+#include "nrf52_gpio.h"
+#include "nrf52_spi.h"
+
+#include "nrf52832-dk.h"
+#include <arch/board/board.h>
+
+#ifdef CONFIG_NRF52_SPI_MASTER
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf52_spidev_initialize
+ *
+ * Description:
+ * Called to configure SPI chip select GPIO pins for the Nucleo-144 board.
+ *
+ ****************************************************************************/
+
+void nrf52_spidev_initialize(void)
+{
+#ifdef CONFIG_NRF52_SPI0_MASTER
+# ifdef CONFIG_IEEE802154_MRF24J40
+ /* Configure the SPI-based MRF24J40 chip select GPIO */
+
+ spiinfo("Configure GPIO for MRF24J40 SPI1/CS\n");
+
+ nrf52_gpio_config(GPIO_MRF24J40_CS);
+ nrf52_gpio_write(GPIO_MRF24J40_CS, true);
+# endif
+#endif
+}
+
+/****************************************************************************
+ * Name: nrf52_spi0/1/2/3/select and nrf52_spi0/1/2/3/status
+ *
+ * Description:
+ * The external functions, nrf52_spi0/1/2/3select and
+ * nrf52_spi0/1/2/3status must be provided by board-specific logic.
+ * They are implementations of the select and status methods of the SPI
+ * interface defined by struct spi_ops_s (see include/nuttx/spi/spi.h).
+ * All other methods (including nrf52_spibus_initialize()) are provided
+ * by common NRF52 logic. To use this common SPI logic on your board:
+ *
+ * 1. Provide logic in nrf52_boardinitialize() to configure SPI chip select
+ * pins.
+ * 2. Provide nrf52_spi0/1/2/3select() and nrf52_spi0/1/2/3status()
+ * functions in your board-specific logic. These functions will perform
+ * chip selection and status operations using GPIOs in the way your
+ * board is configured.
+ * 3. Add a calls to nrf52_spibus_initialize() in your low level
+ * application initialization logic
+ * 4. The handle returned by nrf52_spibus_initialize() may then be used to
+ * bind the SPI driver to higher level logic (e.g., calling
+ * mmcsd_spislotinitialize(), for example, will bind the SPI driver to
+ * the SPI MMC/SD driver).
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NRF52_SPI0_MASTER
+void nrf52_spi0select(struct spi_dev_s *dev, uint32_t devid,
+ bool selected)
+{
+ spiinfo("devid: %08lx CS: %s\n",
+ (unsigned long)devid, selected ? "assert" : "de-assert");
+
+ switch (devid)
+ {
+#ifdef CONFIG_IEEE802154_MRF24J40
+ case SPIDEV_IEEE802154(0):
+ {
+ spiinfo("MRF24J40 device %s\n",
+ selected ? "asserted" : "de-asserted");
+
+ /* Set the GPIO low to select and high to de-select */
+
+ nrf52_gpio_write(GPIO_MRF24J40_CS, !selected);
+ break;
+ }
+#endif
+
+ default:
+ {
+ break;
+ }
+ }
+}
+
+uint8_t nrf52_spi0status(struct spi_dev_s *dev, uint32_t devid)
+{
+ uint8_t status = 0;
+
+ switch (devid)
+ {
+#ifdef CONFIG_IEEE802154_MRF24J40
+ case SPIDEV_IEEE802154(0):
+ {
+ status |= SPI_STATUS_PRESENT;
+ break;
+ }
+#endif
+
+ default:
+ {
+ break;
+ }
+ }
+
+ return status;
+}
+#endif
+
+#ifdef CONFIG_NRF52_SPI1_MASTER
+void nrf52_spi1select(struct spi_dev_s *dev, uint32_t devid,
+ bool selected)
+{
+ spiinfo("devid: %08lx CS: %s\n",
+ (unsigned long)devid, selected ? "assert" : "de-assert");
+}
+
+uint8_t nrf52_spi1status(struct spi_dev_s *dev, uint32_t devid)
+{
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_nrf52_SPI2_MASTER
+void nrf52_spi2select(struct spi_dev_s *dev, uint32_t devid,
+ bool selected)
+{
+ spiinfo("devid: %08lx CS: %s\n",
+ (unsigned long)devid, selected ? "assert" : "de-assert");
+}
+
+uint8_t nrf52_spi2status(struct spi_dev_s *dev, uint32_t devid)
+{
+ return 0;
+}
+#endif
+
+#endif /* CONFIG_NRF52_SPI_MASTER */
diff --git a/boards/arm/nrf52/nrf52840-dk/configs/ieee802154_6lowpan/defconfig b/boards/arm/nrf52/nrf52840-dk/configs/ieee802154_6lowpan/defconfig
new file mode 100644
index 0000000000..6afe61de12
--- /dev/null
+++ b/boards/arm/nrf52/nrf52840-dk/configs/ieee802154_6lowpan/defconfig
@@ -0,0 +1,81 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed .config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that includes your
+# modifications.
+#
+# CONFIG_ARCH_FPU is not set
+CONFIG_ARCH="arm"
+CONFIG_ARCH_BOARD="nrf52840-dk"
+CONFIG_ARCH_BOARD_COMMON=y
+CONFIG_ARCH_BOARD_NRF52840_DK=y
+CONFIG_ARCH_CHIP="nrf52"
+CONFIG_ARCH_CHIP_NRF52840=y
+CONFIG_ARCH_CHIP_NRF52=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_ARCH_STDARG_H=y
+CONFIG_BOARDCTL_RESET=y
+CONFIG_BOARD_LOOPSPERMSEC=5500
+CONFIG_BUILTIN=y
+CONFIG_DEBUG_FULLOPT=y
+CONFIG_DEBUG_SYMBOLS=y
+CONFIG_DRIVERS_IEEE802154=y
+CONFIG_DRIVERS_WIRELESS=y
+CONFIG_EXAMPLES_NETTEST=y
+CONFIG_EXAMPLES_NETTEST_DEVNAME="wpan0"
+CONFIG_EXAMPLES_NETTEST_SERVER_PORTNO=61616
+CONFIG_EXAMPLES_NETTEST_TARGET2=y
+CONFIG_EXAMPLES_UDP=y
+CONFIG_EXAMPLES_UDP_CLIENT_PORTNO=61617
+CONFIG_EXAMPLES_UDP_DEVNAME="wpan0"
+CONFIG_EXAMPLES_UDP_IPv6=y
+CONFIG_EXAMPLES_UDP_SERVER_PORTNO=61616
+CONFIG_EXAMPLES_UDP_TARGET2=y
+CONFIG_EXPERIMENTAL=y
+CONFIG_FS_PROCFS=y
+CONFIG_IEEE802154_I8SAK=y
+CONFIG_IEEE802154_MAC=y
+CONFIG_IEEE802154_MACDEV=y
+CONFIG_IEEE802154_NETDEV=y
+CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_MAC802154_NTXDESC=36
+CONFIG_MM_REGIONS=2
+CONFIG_NET=y
+CONFIG_NETDEV_HPWORK_THREAD=y
+CONFIG_NETDEV_LATEINIT=y
+CONFIG_NETDEV_STATISTICS=y
+CONFIG_NETDEV_WIRELESS_IOCTL=y
+CONFIG_NETINIT_NETLOCAL=y
+CONFIG_NETINIT_NOMAC=y
+CONFIG_NETUTILS_TELNETD=y
+CONFIG_NET_6LOWPAN=y
+CONFIG_NET_BROADCAST=y
+CONFIG_NET_IPv6=y
+CONFIG_NET_SOCKOPTS=y
+CONFIG_NET_STATISTICS=y
+CONFIG_NET_TCP=y
+CONFIG_NET_TCPBACKLOG=y
+CONFIG_NET_TCP_WRITE_BUFFERS=y
+CONFIG_NET_UDP=y
+CONFIG_NRF52_HFCLK_XTAL=y
+CONFIG_NRF52_RADIO=y
+CONFIG_NRF52_RADIO_IEEE802154=y
+CONFIG_NRF52_UART0=y
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_PROMPT_STRING="nsh-nrf52> "
+CONFIG_NSH_READLINE=y
+CONFIG_RAM_SIZE=262144
+CONFIG_RAM_START=0x20000000
+CONFIG_RAW_BINARY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_HPWORK=y
+CONFIG_SCHED_LPWORK=y
+CONFIG_SCHED_WAITPID=y
+CONFIG_SYMTAB_ORDEREDBYNAME=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_SYSTEM_TELNET_CLIENT=y
+CONFIG_UART0_SERIAL_CONSOLE=y
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_IEEE802154=y
diff --git a/boards/arm/nrf52/nrf52840-dk/configs/ieee802154_mac/defconfig b/boards/arm/nrf52/nrf52840-dk/configs/ieee802154_mac/defconfig
new file mode 100644
index 0000000000..4d9a842623
--- /dev/null
+++ b/boards/arm/nrf52/nrf52840-dk/configs/ieee802154_mac/defconfig
@@ -0,0 +1,61 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed .config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that includes your
+# modifications.
+#
+# CONFIG_ARCH_FPU is not set
+# CONFIG_NSH_DISABLE_IFCONFIG is not set
+# CONFIG_NSH_DISABLE_PS is not set
+CONFIG_ARCH="arm"
+CONFIG_ARCH_BOARD="nrf52840-dk"
+CONFIG_ARCH_BOARD_COMMON=y
+CONFIG_ARCH_BOARD_NRF52840_DK=y
+CONFIG_ARCH_CHIP="nrf52"
+CONFIG_ARCH_CHIP_NRF52840=y
+CONFIG_ARCH_CHIP_NRF52=y
+CONFIG_ARCH_PERF_EVENTS=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_ARCH_STDARG_H=y
+CONFIG_BOARDCTL_RESET=y
+CONFIG_BOARD_LOOPSPERMSEC=5500
+CONFIG_BUILTIN=y
+CONFIG_DEBUG_FULLOPT=y
+CONFIG_DEBUG_SYMBOLS=y
+CONFIG_DRIVERS_IEEE802154=y
+CONFIG_DRIVERS_WIRELESS=y
+CONFIG_EXPERIMENTAL=y
+CONFIG_IDLETHREAD_STACKSIZE=4096
+CONFIG_IEEE802154_I8SAK=y
+CONFIG_IEEE802154_MAC=y
+CONFIG_IEEE802154_MACDEV=y
+CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_MM_REGIONS=2
+CONFIG_NRF52_HFCLK_XTAL=y
+CONFIG_NRF52_RADIO=y
+CONFIG_NRF52_RADIO_IEEE802154=y
+CONFIG_NRF52_TIMER1=y
+CONFIG_NRF52_UART0=y
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_PROMPT_STRING="nsh-nrf52> "
+CONFIG_NSH_READLINE=y
+CONFIG_RAM_SIZE=262144
+CONFIG_RAM_START=0x20000000
+CONFIG_RAW_BINARY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_BACKTRACE=y
+CONFIG_SCHED_HPWORK=y
+CONFIG_SCHED_HPWORKSTACKSIZE=4096
+CONFIG_SCHED_LPWORK=y
+CONFIG_SCHED_LPWORKSTACKSIZE=4096
+CONFIG_SCHED_WAITPID=y
+CONFIG_STACK_CANARIES=y
+CONFIG_STACK_COLORATION=y
+CONFIG_STACK_USAGE=y
+CONFIG_SYMTAB_ORDEREDBYNAME=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_UART0_SERIAL_CONSOLE=y
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_IEEE802154=y
diff --git a/boards/arm/nrf52/nrf52840-dk/src/nrf52_bringup.c b/boards/arm/nrf52/nrf52840-dk/src/nrf52_bringup.c
index 4bc740ff01..26e8ea89ae 100644
--- a/boards/arm/nrf52/nrf52840-dk/src/nrf52_bringup.c
+++ b/boards/arm/nrf52/nrf52840-dk/src/nrf52_bringup.c
@@ -61,13 +61,17 @@
# include "nrf52_lsm9ds1.h"
#endif
+#ifdef CONFIG_NRF52_RADIO_IEEE802154
+# include "nrf52_ieee802154.h"
+#endif
+
#include "nrf52840-dk.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
-#define NRF52_TIMER (1)
+#define NRF52_TIMER (2)
#define LMS9DS1_I2CBUS (0)
/****************************************************************************
@@ -309,6 +313,15 @@ int nrf52_bringup(void)
}
#endif /* CONFIG_SENSORS_LSM6DSL */
+#ifdef CONFIG_NRF52_RADIO_IEEE802154
+ ret = nrf52_ieee802154_initialize();
+ if (ret < 0)
+ {
+ syslog(LOG_ERR, "ERROR: Failed to initialize IEE802154 radio: %d\n",
+ ret);
+ }
+#endif
+
UNUSED(ret);
return OK;
}
diff --git a/boards/arm/nrf52/nrf52840-dongle/configs/ieee802154_mac/defconfig b/boards/arm/nrf52/nrf52840-dongle/configs/ieee802154_mac/defconfig
new file mode 100644
index 0000000000..3e3a0a98d2
--- /dev/null
+++ b/boards/arm/nrf52/nrf52840-dongle/configs/ieee802154_mac/defconfig
@@ -0,0 +1,65 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed .config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that includes your
+# modifications.
+#
+# CONFIG_ARCH_FPU is not set
+# CONFIG_DEV_CONSOLE is not set
+# CONFIG_NSH_DISABLE_IFCONFIG is not set
+# CONFIG_NSH_DISABLE_PS is not set
+# CONFIG_SYSLOG_DEFAULT is not set
+CONFIG_ARCH="arm"
+CONFIG_ARCH_BOARD="nrf52840-dongle"
+CONFIG_ARCH_BOARD_COMMON=y
+CONFIG_ARCH_BOARD_NRF52840_DONGLE=y
+CONFIG_ARCH_CHIP="nrf52"
+CONFIG_ARCH_CHIP_NRF52840=y
+CONFIG_ARCH_CHIP_NRF52=y
+CONFIG_ARCH_PERF_EVENTS=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_ARCH_STDARG_H=y
+CONFIG_BOARDCTL_RESET=y
+CONFIG_BOARDCTL_USBDEVCTRL=y
+CONFIG_BOARD_LOOPSPERMSEC=5500
+CONFIG_BUILTIN=y
+CONFIG_CDCACM=y
+CONFIG_CDCACM_CONSOLE=y
+CONFIG_DEBUG_FULLOPT=y
+CONFIG_DEBUG_SYMBOLS=y
+CONFIG_DRIVERS_IEEE802154=y
+CONFIG_DRIVERS_WIRELESS=y
+CONFIG_EXPERIMENTAL=y
+CONFIG_IDLETHREAD_STACKSIZE=4096
+CONFIG_IEEE802154_I8SAK=y
+CONFIG_IEEE802154_MAC=y
+CONFIG_IEEE802154_MACDEV=y
+CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_MM_REGIONS=2
+CONFIG_NRF52_HFCLK_XTAL=y
+CONFIG_NRF52_RADIO=y
+CONFIG_NRF52_RADIO_IEEE802154=y
+CONFIG_NRF52_TIMER1=y
+CONFIG_NRF52_USBDEV=y
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_PROMPT_STRING="nsh-dongle> "
+CONFIG_NSH_READLINE=y
+CONFIG_RAM_SIZE=262144
+CONFIG_RAM_START=0x20000000
+CONFIG_RAW_BINARY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_BACKTRACE=y
+CONFIG_SCHED_HPWORK=y
+CONFIG_SCHED_HPWORKSTACKSIZE=4096
+CONFIG_SCHED_LPWORK=y
+CONFIG_SCHED_LPWORKSTACKSIZE=4096
+CONFIG_SCHED_WAITPID=y
+CONFIG_STACK_CANARIES=y
+CONFIG_STACK_COLORATION=y
+CONFIG_STACK_USAGE=y
+CONFIG_SYMTAB_ORDEREDBYNAME=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_IEEE802154=y
diff --git a/boards/arm/nrf52/nrf52840-dongle/src/nrf52840-dongle.h b/boards/arm/nrf52/nrf52840-dongle/src/nrf52840-dongle.h
index e2f688fb5a..6c17917383 100644
--- a/boards/arm/nrf52/nrf52840-dongle/src/nrf52840-dongle.h
+++ b/boards/arm/nrf52/nrf52840-dongle/src/nrf52840-dongle.h
@@ -34,6 +34,18 @@
* Pre-processor Definitions
****************************************************************************/
+/* Configuration ************************************************************/
+
+/* procfs File System */
+
+#ifdef CONFIG_FS_PROCFS
+# ifdef CONFIG_NSH_PROC_MOUNTPOINT
+# define NRF52_PROCFS_MOUNTPOINT CONFIG_NSH_PROC_MOUNTPOINT
+# else
+# define NRF52_PROCFS_MOUNTPOINT "/proc"
+# endif
+#endif
+
/* LED definitions **********************************************************/
/* Definitions to configure LED GPIO as outputs */
diff --git a/boards/arm/nrf52/nrf52840-dongle/src/nrf52_bringup.c b/boards/arm/nrf52/nrf52840-dongle/src/nrf52_bringup.c
index 1ad015a417..fbcf6b4475 100644
--- a/boards/arm/nrf52/nrf52840-dongle/src/nrf52_bringup.c
+++ b/boards/arm/nrf52/nrf52840-dongle/src/nrf52_bringup.c
@@ -31,6 +31,10 @@
# include <nuttx/leds/userled.h>
#endif
+#ifdef CONFIG_NRF52_RADIO_IEEE802154
+# include "nrf52_ieee802154.h"
+#endif
+
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -53,6 +57,17 @@ int nrf52_bringup(void)
{
int ret;
+#ifdef CONFIG_FS_PROCFS
+ /* Mount the procfs file system */
+
+ ret = nx_mount(NULL, NRF52_PROCFS_MOUNTPOINT, "procfs", 0, NULL);
+ if (ret < 0)
+ {
+ syslog(LOG_ERR,
+ "ERROR: Failed to mount the PROC filesystem: %d\n", ret);
+ }
+#endif /* CONFIG_FS_PROCFS */
+
#ifdef CONFIG_USERLED
/* Register the LED driver */
@@ -63,6 +78,15 @@ int nrf52_bringup(void)
}
#endif
+#ifdef CONFIG_NRF52_RADIO_IEEE802154
+ ret = nrf52_ieee802154_initialize();
+ if (ret < 0)
+ {
+ syslog(LOG_ERR, "ERROR: Failed to initialize IEE802154 radio: %d\n",
+ ret);
+ }
+#endif
+
UNUSED(ret);
return OK;
}
diff --git a/boards/arm/nrf52/nrf9160-dk-nrf52/configs/ieee802154_6lowpan/defconfig b/boards/arm/nrf52/nrf9160-dk-nrf52/configs/ieee802154_6lowpan/defconfig
new file mode 100644
index 0000000000..473979b070
--- /dev/null
+++ b/boards/arm/nrf52/nrf9160-dk-nrf52/configs/ieee802154_6lowpan/defconfig
@@ -0,0 +1,81 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed .config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that includes your
+# modifications.
+#
+# CONFIG_ARCH_FPU is not set
+CONFIG_ARCH="arm"
+CONFIG_ARCH_BOARD="nrf9160-dk-nrf52"
+CONFIG_ARCH_BOARD_COMMON=y
+CONFIG_ARCH_BOARD_NRF9160_DK_NRF52=y
+CONFIG_ARCH_CHIP="nrf52"
+CONFIG_ARCH_CHIP_NRF52840=y
+CONFIG_ARCH_CHIP_NRF52=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_ARCH_STDARG_H=y
+CONFIG_BOARDCTL_RESET=y
+CONFIG_BOARD_LOOPSPERMSEC=5500
+CONFIG_BUILTIN=y
+CONFIG_DEBUG_FULLOPT=y
+CONFIG_DEBUG_SYMBOLS=y
+CONFIG_DRIVERS_IEEE802154=y
+CONFIG_DRIVERS_WIRELESS=y
+CONFIG_EXAMPLES_NETTEST=y
+CONFIG_EXAMPLES_NETTEST_DEVNAME="wpan0"
+CONFIG_EXAMPLES_NETTEST_SERVER_PORTNO=61616
+CONFIG_EXAMPLES_NETTEST_TARGET2=y
+CONFIG_EXAMPLES_UDP=y
+CONFIG_EXAMPLES_UDP_CLIENT_PORTNO=61617
+CONFIG_EXAMPLES_UDP_DEVNAME="wpan0"
+CONFIG_EXAMPLES_UDP_IPv6=y
+CONFIG_EXAMPLES_UDP_SERVER_PORTNO=61616
+CONFIG_EXAMPLES_UDP_TARGET2=y
+CONFIG_EXPERIMENTAL=y
+CONFIG_FS_PROCFS=y
+CONFIG_IEEE802154_I8SAK=y
+CONFIG_IEEE802154_MAC=y
+CONFIG_IEEE802154_MACDEV=y
+CONFIG_IEEE802154_NETDEV=y
+CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_MAC802154_NTXDESC=36
+CONFIG_MM_REGIONS=2
+CONFIG_NET=y
+CONFIG_NETDEV_HPWORK_THREAD=y
+CONFIG_NETDEV_LATEINIT=y
+CONFIG_NETDEV_STATISTICS=y
+CONFIG_NETDEV_WIRELESS_IOCTL=y
+CONFIG_NETINIT_NETLOCAL=y
+CONFIG_NETINIT_NOMAC=y
+CONFIG_NETUTILS_TELNETD=y
+CONFIG_NET_6LOWPAN=y
+CONFIG_NET_BROADCAST=y
+CONFIG_NET_IPv6=y
+CONFIG_NET_SOCKOPTS=y
+CONFIG_NET_STATISTICS=y
+CONFIG_NET_TCP=y
+CONFIG_NET_TCPBACKLOG=y
+CONFIG_NET_TCP_WRITE_BUFFERS=y
+CONFIG_NET_UDP=y
+CONFIG_NRF52_HFCLK_XTAL=y
+CONFIG_NRF52_RADIO=y
+CONFIG_NRF52_RADIO_IEEE802154=y
+CONFIG_NRF52_UART0=y
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_PROMPT_STRING="nsh-nrf91> "
+CONFIG_NSH_READLINE=y
+CONFIG_RAM_SIZE=262144
+CONFIG_RAM_START=0x20000000
+CONFIG_RAW_BINARY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_HPWORK=y
+CONFIG_SCHED_LPWORK=y
+CONFIG_SCHED_WAITPID=y
+CONFIG_SYMTAB_ORDEREDBYNAME=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_SYSTEM_TELNET_CLIENT=y
+CONFIG_UART0_SERIAL_CONSOLE=y
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_IEEE802154=y
diff --git a/boards/arm/nrf52/nrf9160-dk-nrf52/configs/ieee802154_mac/defconfig b/boards/arm/nrf52/nrf9160-dk-nrf52/configs/ieee802154_mac/defconfig
new file mode 100644
index 0000000000..1725e9d4d4
--- /dev/null
+++ b/boards/arm/nrf52/nrf9160-dk-nrf52/configs/ieee802154_mac/defconfig
@@ -0,0 +1,56 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed .config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that includes your
+# modifications.
+#
+# CONFIG_ARCH_FPU is not set
+# CONFIG_NSH_DISABLE_IFCONFIG is not set
+# CONFIG_NSH_DISABLE_PS is not set
+CONFIG_ARCH="arm"
+CONFIG_ARCH_BOARD="nrf9160-dk-nrf52"
+CONFIG_ARCH_BOARD_COMMON=y
+CONFIG_ARCH_BOARD_NRF9160_DK_NRF52=y
+CONFIG_ARCH_CHIP="nrf52"
+CONFIG_ARCH_CHIP_NRF52840=y
+CONFIG_ARCH_CHIP_NRF52=y
+CONFIG_ARCH_PERF_EVENTS=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_ARCH_STDARG_H=y
+CONFIG_BOARDCTL_RESET=y
+CONFIG_BOARD_LOOPSPERMSEC=5500
+CONFIG_BUILTIN=y
+CONFIG_DEBUG_FULLOPT=y
+CONFIG_DEBUG_SYMBOLS=y
+CONFIG_DRIVERS_IEEE802154=y
+CONFIG_DRIVERS_WIRELESS=y
+CONFIG_EXPERIMENTAL=y
+CONFIG_IDLETHREAD_STACKSIZE=2048
+CONFIG_IEEE802154_I8SAK=y
+CONFIG_IEEE802154_MAC=y
+CONFIG_IEEE802154_MACDEV=y
+CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_MM_REGIONS=2
+CONFIG_NRF52_HFCLK_XTAL=y
+CONFIG_NRF52_RADIO=y
+CONFIG_NRF52_RADIO_IEEE802154=y
+CONFIG_NRF52_UART0=y
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_PROMPT_STRING="nsh-nrf91> "
+CONFIG_NSH_READLINE=y
+CONFIG_RAM_SIZE=262144
+CONFIG_RAM_START=0x20000000
+CONFIG_RAW_BINARY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_HPWORK=y
+CONFIG_SCHED_LPWORK=y
+CONFIG_SCHED_WAITPID=y
+CONFIG_STACK_COLORATION=y
+CONFIG_STACK_USAGE=y
+CONFIG_SYMTAB_ORDEREDBYNAME=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_UART0_SERIAL_CONSOLE=y
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_IEEE802154=y
diff --git a/boards/arm/nrf52/nrf9160-dk-nrf52/src/nrf52_bringup.c b/boards/arm/nrf52/nrf9160-dk-nrf52/src/nrf52_bringup.c
index d5bb51e644..095fb9d496 100644
--- a/boards/arm/nrf52/nrf9160-dk-nrf52/src/nrf52_bringup.c
+++ b/boards/arm/nrf52/nrf9160-dk-nrf52/src/nrf52_bringup.c
@@ -27,6 +27,14 @@
#include <sys/types.h>
#include <syslog.h>
+#include <nuttx/fs/fs.h>
+
+#ifdef CONFIG_NRF52_RADIO_IEEE802154
+# include "nrf52_ieee802154.h"
+#endif
+
+#include "nrf9160-dk-nrf52.h"
+
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -49,6 +57,26 @@ int nrf52_bringup(void)
{
int ret;
+#ifdef CONFIG_FS_PROCFS
+ /* Mount the procfs file system */
+
+ ret = nx_mount(NULL, NRF52_PROCFS_MOUNTPOINT, "procfs", 0, NULL);
+ if (ret < 0)
+ {
+ syslog(LOG_ERR,
+ "ERROR: Failed to mount the PROC filesystem: %d\n", ret);
+ }
+#endif /* CONFIG_FS_PROCFS */
+
+#ifdef CONFIG_NRF52_RADIO_IEEE802154
+ ret = nrf52_ieee802154_initialize();
+ if (ret < 0)
+ {
+ syslog(LOG_ERR, "ERROR: Failed to initialize IEE802154 radio: %d\n",
+ ret);
+ }
+#endif
+
UNUSED(ret);
return OK;
}
diff --git a/boards/arm/nrf52/nrf9160-dk-nrf52/src/nrf9160-dk-nrf52.h b/boards/arm/nrf52/nrf9160-dk-nrf52/src/nrf9160-dk-nrf52.h
index 82fe34c862..95744c9424 100644
--- a/boards/arm/nrf52/nrf9160-dk-nrf52/src/nrf9160-dk-nrf52.h
+++ b/boards/arm/nrf52/nrf9160-dk-nrf52/src/nrf9160-dk-nrf52.h
@@ -34,6 +34,18 @@
* Pre-processor Definitions
****************************************************************************/
+/* Configuration ************************************************************/
+
+/* procfs File System */
+
+#ifdef CONFIG_FS_PROCFS
+# ifdef CONFIG_NSH_PROC_MOUNTPOINT
+# define NRF52_PROCFS_MOUNTPOINT CONFIG_NSH_PROC_MOUNTPOINT
+# else
+# define NRF52_PROCFS_MOUNTPOINT "/proc"
+# endif
+#endif
+
/****************************************************************************
* Public Types
****************************************************************************/
diff --git a/include/nuttx/wireless/ieee802154/ieee802154_mac.h b/include/nuttx/wireless/ieee802154/ieee802154_mac.h
index 2a998d035c..35f345ab23 100644
--- a/include/nuttx/wireless/ieee802154/ieee802154_mac.h
+++ b/include/nuttx/wireless/ieee802154/ieee802154_mac.h
@@ -219,6 +219,7 @@
#define IEEE802154_MAX_PHY_PACKET_SIZE 127
#define IEEE802154_TURN_AROUND_TIME 12 /* symbol periods*/
+#define IEEE802154_SYMBOL_US 16 /* 16us */
/* IEEE 802.15.4 MAC constants */
@@ -251,6 +252,11 @@
#define IEEE802154_MAX_SIFS_FRAME_SIZE 18
#define IEEE802154_MIN_CAP_LENGTH 440
#define IEEE802154_UNIT_BACKOFF_PERIOD 20
+#define IEEE802154_LIFS_SYMBOLS 40
+#define IEEE802154_SIFS_SYMBOLS 12
+#define IEEE802154_ACKIFS_SYMBOLS 12
+#define IEEE802154_TIMESLOT_US (16 * 60)
+#define IEEE802154_ACK_FRAME_SIZE 5 /* ACK length (FCF + Seq + FCS) */
/* IEEE 802.15.4 MAC PIB Attribute Defaults */