You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by gn...@apache.org on 2020/04/04 00:23:02 UTC

[incubator-nuttx] branch master updated: arch/arm/src/nrf52: add initial interface to work with on-chip radio

This is an automated email from the ASF dual-hosted git repository.

gnutt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new df1eeb8  arch/arm/src/nrf52: add initial interface to work with on-chip radio
df1eeb8 is described below

commit df1eeb8e3fe13133c4e243629c8a926342395f76
Author: raiden00pl <ra...@gmail.com>
AuthorDate: Fri Apr 3 17:12:41 2020 +0200

    arch/arm/src/nrf52: add initial interface to work with on-chip radio
---
 arch/arm/src/nrf52/Kconfig                |    1 +
 arch/arm/src/nrf52/Make.defs              |    5 +
 arch/arm/src/nrf52/hardware/nrf52_radio.h |   53 +-
 arch/arm/src/nrf52/nrf52_radio.c          | 1204 +++++++++++++++++++++++++++++
 arch/arm/src/nrf52/nrf52_radio.h          |  281 +++++++
 5 files changed, 1526 insertions(+), 18 deletions(-)

diff --git a/arch/arm/src/nrf52/Kconfig b/arch/arm/src/nrf52/Kconfig
index 2c92c39..e2daee4 100644
--- a/arch/arm/src/nrf52/Kconfig
+++ b/arch/arm/src/nrf52/Kconfig
@@ -160,6 +160,7 @@ config NRF52_WDT
 
 config NRF52_RADIO
 	bool "RADIO"
+	depends on EXPERIMENTAL
 	default n
 
 config NRF52_NFCT
diff --git a/arch/arm/src/nrf52/Make.defs b/arch/arm/src/nrf52/Make.defs
index 5d3b9d7..57fb504 100644
--- a/arch/arm/src/nrf52/Make.defs
+++ b/arch/arm/src/nrf52/Make.defs
@@ -128,3 +128,8 @@ endif
 ifeq ($(CONFIG_NRF52_I2C_MASTER),y)
 CHIP_CSRCS += nrf52_i2c.c
 endif
+
+ifeq ($(CONFIG_NRF52_RADIO),y)
+CHIP_CSRCS += nrf52_radio.c
+
+endif
diff --git a/arch/arm/src/nrf52/hardware/nrf52_radio.h b/arch/arm/src/nrf52/hardware/nrf52_radio.h
index f368bb2..b28d00f 100644
--- a/arch/arm/src/nrf52/hardware/nrf52_radio.h
+++ b/arch/arm/src/nrf52/hardware/nrf52_radio.h
@@ -428,6 +428,7 @@
 
 #define RADIO_TXPOWER_SHIFT               (0)      /* Bits 0-7: RADIO output power */
 #define RADIO_TXPOWER_MASK                (0xff << RADIO_TXPOWER_SHIFT)
+#define RADIO_TXPOWER_MAX                 (0xff)
 
 /* MODE Register */
 
@@ -445,34 +446,47 @@
 
 #define RADIO_PCNF0_LFLEN_SHIFT           (0)       /* Bits 0-3: Length on air of LENGTH field in number of bits */
 #define RADIO_PCNF0_LFLEN_MASK            (0xf << RADIO_PCNF0_LFLEN_SHIFT)
-#define RADIO_PCNF0_S0LEN                 (1 << 8)  /* Bit 8: Length on air of S0 field in number of bytes */
+#define RADIO_PCNF0_LFLEN_MAX             (0xf)
+#define RADIO_PCNF0_S0LEN_SHIFT           (8)      /* Bit 8: Length on air of S0 field in number of bytes */
+#define RADIO_PCNF0_S0LEN_MASK            (1 << RADIO_PCNF0_S0LEN_SHIFT)
+#define RADIO_PCNF0_S0LEN_MAX             (1)
 #define RADIO_PCNF0_S1LEN_SHIFT           (16)      /* Bits 16-19: Length on air of S1 field in number of bits */
 #define RADIO_PCNF0_S1LEN_MASK            (0xf << RADIO_PCNF0_S1LEN_SHIFT)
+#define RADIO_PCNF0_S1LEN_MAX             (0xf)
 #define RADIO_PCNF0_S1INCL                (1 << 20) /* Bit 20: Include or exclude S1 field in RAM */
 #define RADIO_PCNF0_CILEN_SHIFT           (22)      /* Bits 22-23: Length of code indicator - long range */
 #define RADIO_PCNF0_CILEN_MASK            (0x3 << RADIO_PCNF0_CILEN_SHIFT)
+#define RADIO_PCNF0_CILEN_MAX             (0x3)
 #define RADIO_PCNF0_PLEN_SHIFT            (24)      /* Bits 24-25: Length of preamble on air */
 #define RADIO_PCNF0_PLEN_MASK             (0x3 << RADIO_PCNF0_PLEN_SHIFT)
 #  define RADIO_PCNF0_PLEN_8BIT           (0 << RADIO_PCNF0_PLEN_SHIFT)
 #  define RADIO_PCNF0_PLEN_16BIT          (1 << RADIO_PCNF0_PLEN_SHIFT)
 #  define RADIO_PCNF0_PLEN_32BITZ         (2 << RADIO_PCNF0_PLEN_SHIFT)
 #  define RADIO_PCNF0_PLEN_LONGRANGE      (3 << RADIO_PCNF0_PLEN_SHIFT)
-#define RADIO_PCNF0_CRCINC                (1 << 26) /* Bit 26: Indicates if LENGTH field contains CRC */
+#define RADIO_PCNF0_CRCINC_SHIFT          (26)      /* Bit 26: Indicates if LENGTH field contains CRC */
+#define RADIO_PCNF0_CRCINC                (1 << RADIO_PCNF0_CRCINC_SHIFT)
 #define RADIO_PCNF0_TERMLEN_SHIFT         (29)      /* Bits 29-30: Length of TERM field in Long Range operation */
 #define RADIO_PCNF0_TERMLEN_MASK          (0x3 << RADIO_PCNF0_TERMLEN_SHIFT)
+#define RADIO_PCNF0_TERMLEN_MAX           (0x3)
 
 /* PCNF1 Register */
 
 #define RADIO_PCNF1_MAXLEN_SHIFT          (0)       /* Bits 0-7: Maximum length of packet payload */
 #define RADIO_PCNF1_MAXLEN_MASK           (0xff << RADIO_PCNF1_MAXLEN_SHIFT)
+#define RADIO_PCNF1_MAXLEN_MAX            (0xff)
 #define RADIO_PCNF1_STATLEN_SHIFT         (8)       /* Bits 8-15: Static length in number of bytes */
 #define RADIO_PCNF1_STATLEN_MASK          (0xff << RADIO_PCNF1_STATLEN_SHIFT)
+#define RADIO_PCNF1_STATLEN_MAX           (0xff)
 #define RADIO_PCNF1_BALEN_SHIFT           (16)      /* Bits 16-18: Base address length in number of bytes */
 #define RADIO_PCNF1_BALEN_MASK            (0x7 << RADIO_PCNF1_BALEN_SHIFT)
-#define RADIO_PCNF1_ENDIAN                (1 << 24) /* Bit 24: On air endianness of packet */
+#define RADIO_PCNF1_BALEN_MIN             (0x2)
+#define RADIO_PCNF1_BALEN_MAX             (0x4)
+#define RADIO_PCNF1_ENDIAN_SHIFT          (24)      /* Bit 24: On air endianness of packet */
+#define RADIO_PCNF1_ENDIAN                (1 << RADIO_PCNF1_ENDIAN_SHIFT)
 #  define RADIO_PCNF1_ENDIAN_LITTLE       (0 << 24) /* Least significant bit on air first */
 #  define RADIO_PCNF1_ENDIAN_BITG         (1 << 24) /* Most significant bit on air first */
-#define RADIO_PCNF1_WHITEEN               (1 << 25) /* Bit 25: Enable or disable packet whitening */
+#define RADIO_PCNF1_WHITEEN_SHIFT         (25)      /* Bit 25: Enable or disable packet whitening */
+#define RADIO_PCNF1_WHITEEN               (1 << RADIO_PCNF1_WHITEEN_SHIFT)
 
 /* TXADDRESS Register */
 
@@ -492,10 +506,10 @@
 #  define RADIO_CRCCNF_LEN_2              (2 << RADIO_CRCCNF_LEN_SHIFT)
 #  define RADIO_CRCCNF_LEN_3              (3 << RADIO_CRCCNF_LEN_SHIFT)
 #define RADIO_CRCCNF_SKIPADDR_SHIFT       (8)       /* Bit 8-9: Include or exclude packet address field out of CRC calculation */
-#define RADIO_CRCCNF_SKIPADDR_MASK        (0x3 << RADIO_CRCCNF_SKIPADDR_SHIFT)
-#  define RADIO_CRCCNF_SKIPADDR_INCL      (0x3 << RADIO_CRCCNF_SKIPADDR_SHIFT)
-#  define RADIO_CRCCNF_SKIPADDR_SKIP      (0x3 << RADIO_CRCCNF_SKIPADDR_SHIFT)
-#  define RADIO_CRCCNF_SKIPADDR_IEEE      (0x3 << RADIO_CRCCNF_SKIPADDR_SHIFT)
+#define RADIO_CRCCNF_SKIPADDR_MASK        (0 << RADIO_CRCCNF_SKIPADDR_SHIFT)
+#  define RADIO_CRCCNF_SKIPADDR_INCL      (1 << RADIO_CRCCNF_SKIPADDR_SHIFT)
+#  define RADIO_CRCCNF_SKIPADDR_SKIP      (2 << RADIO_CRCCNF_SKIPADDR_SHIFT)
+#  define RADIO_CRCCNF_SKIPADDR_IEEE      (3 << RADIO_CRCCNF_SKIPADDR_SHIFT)
 
 /* CRCPOLY Register */
 
@@ -511,6 +525,7 @@
 
 #define RADIO_TIFS_SHIFT                  (0)      /* Bits 0-9: Interframe spacing in μs */
 #define RADIO_TIFS_MASK                   (0x3ff << RADIO_TIFS_SHIFT)
+#define RADIO_TIFS_MAX                    (0x3ff)
 
 /* RSSISAMPLE Register */
 
@@ -520,21 +535,22 @@
 /* STATE Register */
 
 #define RADIO_STATE_SHIFT                 (0)     /* Bits 0-2: Current radio state */
-#define RADIO_STATE_MASK                  (0xf << RADIO_STATE_STATE_SHIFT)
-#  define RADIO_STATE_DISABLED            (0 << RADIO_STATE_STATE_SHIFT)
-#  define RADIO_STATE_RXRU                (1 << RADIO_STATE_STATE_SHIFT)
-#  define RADIO_STATE_RXIDLE              (2 << RADIO_STATE_STATE_SHIFT)
-#  define RADIO_STATE_RX                  (3 << RADIO_STATE_STATE_SHIFT)
-#  define RADIO_STATE_RXDISABLE           (4 << RADIO_STATE_STATE_SHIFT)
-#  define RADIO_STATE_TXRU                (9 << RADIO_STATE_STATE_SHIFT)
-#  define RADIO_STATE_TXIDLE              10 << RADIO_STATE_STATE_SHIFT)
-#  define RADIO_STATE_TX                  (11 << RADIO_STATE_STATE_SHIFT)
-#  define RADIO_STATE_TXDISABLE           (12 << RADIO_STATE_STATE_SHIFT)
+#define RADIO_STATE_MASK                  (0xf << RADIO_STATE_SHIFT)
+#  define RADIO_STATE_DISABLED            (0 << RADIO_STATE_SHIFT)
+#  define RADIO_STATE_RXRU                (1 << RADIO_STATE_SHIFT)
+#  define RADIO_STATE_RXIDLE              (2 << RADIO_STATE_SHIFT)
+#  define RADIO_STATE_RX                  (3 << RADIO_STATE_SHIFT)
+#  define RADIO_STATE_RXDISABLE           (4 << RADIO_STATE_SHIFT)
+#  define RADIO_STATE_TXRU                (9 << RADIO_STATE_SHIFT)
+#  define RADIO_STATE_TXIDLE              (10 << RADIO_STATE_SHIFT)
+#  define RADIO_STATE_TX                  (11 << RADIO_STATE_SHIFT)
+#  define RADIO_STATE_TXDISABLE           (12 << RADIO_STATE_SHIFT)
 
 /* DATAWHITEIV Register */
 
 #define RADIO_DATAWHITEIV_SHIFT           (0)     /* Bits 0-6: Data whitening initial value */
 #define RADIO_DATAWHITEIV_MASK            (0x3f << RADIO_DATAWHITEIV_SHIFT)
+#define RADIO_DATAWHITEIV_MAX             (0x3f)
 
 /* DAP Register */
 
@@ -583,5 +599,6 @@
 /* POWER Register */
 
 #define RADIO_POWER_ENABLE                (1 << 0) /* Bit 0: Peripheral power control */
+#define RADIO_POWER_DISABLE               (0 << 0) /* Bit 0: Peripheral power control */
 
 #endif /* __ARCH_ARM_SRC_NRF52_HARDWARE_NRF52_RADIO_H */
diff --git a/arch/arm/src/nrf52/nrf52_radio.c b/arch/arm/src/nrf52/nrf52_radio.c
new file mode 100644
index 0000000..5431c70
--- /dev/null
+++ b/arch/arm/src/nrf52/nrf52_radio.c
@@ -0,0 +1,1204 @@
+/****************************************************************************
+ * arch/arm/src/nrf52/nrf52_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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <errno.h>
+#include <debug.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <arch/board/board.h>
+
+#include "up_arch.h"
+
+#include "nrf52_gpio.h"
+#include "nrf52_radio.h"
+
+#include "hardware/nrf52_radio.h"
+
+#warning NRF52 RADIO support is EXPERIMENTAL!
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define NRF52_RADIO_RXBUFFER (255)
+#define NRF52_RADIO_TXBUFFER (255)
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* Radio registers access ***************************************************/
+
+static void nrf52_radio_putreg(FAR struct nrf52_radio_dev_s *dev,
+                               uint32_t offset,
+                               uint32_t value);
+static uint32_t nrf52_radio_getreg(FAR struct nrf52_radio_dev_s *dev,
+                                   uint32_t offset);
+
+/* Radio operations *********************************************************/
+
+static int nrf52_radio_power(FAR struct nrf52_radio_dev_s *dev, bool state);
+static int nrf52_radio_mode_set(FAR struct nrf52_radio_dev_s *dev,
+                                uint8_t mode);
+static int nrf52_radio_freq_set(FAR struct nrf52_radio_dev_s *dev,
+                                uint32_t freq);
+static int nrf52_radio_rssi_get(FAR struct nrf52_radio_dev_s *dev,
+                                FAR int *rssi);
+static int nrf52_radio_txpower_set(FAR struct nrf52_radio_dev_s *dev,
+                                   uint8_t txpower);
+static int nrf52_radio_tifs_set(FAR struct nrf52_radio_dev_s *dev,
+                                uint16_t us);
+static int nrf52_radio_pkt_cfg(FAR struct nrf52_radio_dev_s *dev,
+                               FAR struct nrf52_radio_pktcfg_s *cfg);
+static int nrf52_radio_crc_cfg(FAR struct nrf52_radio_dev_s *dev,
+                               FAR struct nrf52_radio_crc_s *cfg);
+static int nrf52_radio_white_set(FAR struct nrf52_radio_dev_s *dev,
+                                 uint8_t init);
+static int nrf52_radio_addr_set(FAR struct nrf52_radio_dev_s *dev, uint8_t i,
+                                FAR struct nrf52_radio_addr_s *addr);
+static int nrf52_radio_write(FAR struct nrf52_radio_dev_s *dev,
+                             FAR uint8_t *buf, int len);
+static int nrf52_radio_read(FAR struct nrf52_radio_dev_s *dev,
+                            FAR uint8_t *buf, int len);
+static void nrf52_radio_dumpregs(FAR struct nrf52_radio_dev_s *dev);
+
+/* Radio interrupts *********************************************************/
+
+static int nrf52_radio_isr(int irq, FAR void *context, FAR void *arg);
+static int nrf52_radio_isr_rx(FAR struct nrf52_radio_dev_s *dev);
+static int nrf52_radio_isr_tx(FAR struct nrf52_radio_dev_s *dev);
+
+/* Radio configuration ******************************************************/
+
+static int nrf52_radio_setup(FAR struct nrf52_radio_dev_s *dev);
+static int nrf52_radio_reset(FAR struct nrf52_radio_dev_s *dev);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* NRF52 radio operations */
+
+struct nrf52_radio_dev_s;
+struct nrf52_radio_ops_s g_nrf52_radio_ops =
+{
+  .power        = nrf52_radio_power,
+  .mode_set     = nrf52_radio_mode_set,
+  .freq_set     = nrf52_radio_freq_set,
+  .rssi_get     = nrf52_radio_rssi_get,
+  .txpower_set  = nrf52_radio_txpower_set,
+  .tifs_set     = nrf52_radio_tifs_set,
+  .pkt_cfg      = nrf52_radio_pkt_cfg,
+  .white_set    = nrf52_radio_white_set,
+  .crc_cfg      = nrf52_radio_crc_cfg,
+  .addr_set     = nrf52_radio_addr_set,
+  .read         = nrf52_radio_read,
+  .write        = nrf52_radio_write,
+  .dumpregs     = nrf52_radio_dumpregs
+};
+
+/* RX buffer 1 */
+
+uint8_t g_nrf52_radio_dev_rx1[NRF52_RADIO_RXBUFFER];
+
+/* TX buffer 1 */
+
+uint8_t g_nrf52_radio_dev_tx1[NRF52_RADIO_TXBUFFER];
+
+/* Radio device 1 */
+
+struct nrf52_radio_dev_s g_nrf52_radio_dev_1 =
+{
+  .ops       = &g_nrf52_radio_ops,
+  .irq       = NRF52_IRQ_RADIO,
+  .base      = NRF52_RADIO_BASE,
+  .mode      = 0,
+  .rxbuf_len = NRF52_RADIO_RXBUFFER,
+  .txbuf_len = NRF52_RADIO_TXBUFFER,
+  .rxbuf     = g_nrf52_radio_dev_rx1,
+  .txbuf     = g_nrf52_radio_dev_tx1,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf52_radio_putreg
+ *
+ * Description:
+ *   Put register value
+ *
+ ****************************************************************************/
+
+static void nrf52_radio_putreg(FAR struct nrf52_radio_dev_s *dev,
+                               uint32_t offset,
+                               uint32_t value)
+{
+  putreg32(value, dev->base + offset);
+}
+
+/****************************************************************************
+ * Name: nrf52_radio_getreg
+ *
+ * Description:
+ *   Get register value
+ *
+ ****************************************************************************/
+
+static uint32_t nrf52_radio_getreg(FAR struct nrf52_radio_dev_s *dev,
+                                   uint32_t offset)
+{
+  return getreg32(dev->base + offset);
+}
+
+/****************************************************************************
+ * Name: nrf52_radio_power
+ *
+ * Description:
+ *   Power on/off radio
+ *
+ ****************************************************************************/
+
+static int nrf52_radio_power(FAR struct nrf52_radio_dev_s *dev, bool state)
+{
+  DEBUGASSERT(dev);
+
+  if (state == true)
+    {
+      /* Turn on radio */
+
+      nrf52_radio_putreg(dev, NRF52_RADIO_POWER_OFFSET, RADIO_POWER_ENABLE);
+    }
+  else
+    {
+      /* Turn off radio */
+
+      nrf52_radio_putreg(dev, NRF52_RADIO_POWER_OFFSET, RADIO_POWER_DISABLE);
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: nrf52_radio_mode_set
+ *
+ * Description:
+ *   Set radio mode
+ *
+ ****************************************************************************/
+
+static int nrf52_radio_mode_set(FAR struct nrf52_radio_dev_s *dev,
+                                uint8_t mode)
+{
+  uint32_t regval = 0;
+  int ret = OK;
+
+  DEBUGASSERT(dev);
+
+  /* Change mode if needed */
+
+  if (dev->mode == mode)
+    {
+      goto errout;
+    }
+
+  /* Check if mode is valid */
+
+  if (mode > NRF52_RADIO_MODE_IEEE802154)
+    {
+      wlerr("ERROR: unsupported RADIO mode %d\n", mode);
+      ret = -EINVAL;
+      goto errout;
+    }
+
+  regval = (mode << RADIO_MODE_SHIFT);
+  nrf52_radio_putreg(dev, NRF52_RADIO_MODE_OFFSET, regval);
+
+  /* Store mode */
+
+  dev->mode = mode;
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf52_radio_freq_set
+ *
+ * Description:
+ *   Set radio frequency (in MHz)
+ *
+ ****************************************************************************/
+
+static int nrf52_radio_freq_set(FAR struct nrf52_radio_dev_s *dev,
+                                uint32_t freq)
+{
+  uint32_t regval = 0;
+  int      ret    = OK;
+
+  DEBUGASSERT(dev);
+
+  /* Check input */
+
+  if (freq < 2360 || freq > 2500)
+    {
+      wlerr("ERROR: unsupported radio frequency %d MHz\n", freq);
+      ret = -EINVAL;
+      goto errout;
+    }
+
+  /* Map frequency to lower band */
+
+  if (freq < 2400)
+    {
+      regval |= RADIO_FREQUENCY_MAP_2360MHZ;
+    }
+
+  regval |= freq;
+  nrf52_radio_putreg(dev, NRF52_RADIO_FREQUENCY_OFFSET, regval);
+
+errout:
+  return ret;
+};
+
+/****************************************************************************
+ * Name: nrf52_radio_rssi_get
+ *
+ * Description:
+ *   Get RSSI sample
+ *
+ ****************************************************************************/
+
+static int nrf52_radio_rssi_get(FAR struct nrf52_radio_dev_s *dev,
+                                FAR int *rssi)
+{
+  uint32_t regval = 0;
+
+  /* Start the RSSI meassurement */
+
+  nrf52_radio_putreg(dev, NRF52_RADIO_TASKS_RSSISTART_OFFSET,
+                     RADIO_TASKS_RSSISTART);
+
+  /* Wait for the RSSI sample */
+
+  while (nrf52_radio_getreg(dev, NRF52_RADIO_EVENTS_RSSIEND_OFFSET));
+
+  /* Get the RSSI sample */
+
+  regval = nrf52_radio_getreg(dev, NRF52_RADIO_RSSISAMPLE_OFFSET);
+  *rssi = -(int)regval;
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: nrf52_radio_addr_set
+ *
+ * Description:
+ *   Set radio logical adress
+ *
+ ****************************************************************************/
+
+static int nrf52_radio_addr_set(FAR struct nrf52_radio_dev_s *dev, uint8_t i,
+                                FAR struct nrf52_radio_addr_s *addr)
+{
+  uint32_t basereg      = 0;
+  uint32_t prefixreg    = 0;
+  uint32_t base_now     = 0;
+  uint32_t prefix_now   = 0;
+  uint32_t base_new     = 0;
+  uint32_t prefix_new   = 0;
+  uint32_t prefix_shift = 0;
+  int      ret          = OK;
+
+  /* Assert input */
+
+  if (i > NRF52_RADIO_LOGICAL_ADDRESS_MAX - 1)
+    {
+      ret = -EINVAL;
+      goto errout;
+    }
+
+  /* Get data specific for given logical adress */
+
+  if (i == 0)
+    {
+      /* Logical address 0 - BASE0 and PREFIX0.AP0 */
+
+      basereg   = NRF52_RADIO_BASE0_OFFSET;
+      prefixreg = NRF52_RADIO_PREFIX0_OFFSET;
+
+      prefix_shift = 0;
+    }
+  else if (i < 4)
+    {
+      /* Logical addres 1-3 - BASE1 and PREFIX0 */
+
+      basereg   = NRF52_RADIO_BASE1_OFFSET;
+      prefixreg = NRF52_RADIO_PREFIX0_OFFSET;
+
+      prefix_shift = (i * 8);
+    }
+  else
+    {
+      /* Logical addres 1-3 - BASE1 and PREFIX1 */
+
+      basereg   = NRF52_RADIO_BASE1_OFFSET;
+      prefixreg = NRF52_RADIO_PREFIX1_OFFSET;
+
+      prefix_shift = (i - 4) * 8;
+    }
+
+  /* Get current BASE and PREFIX registers */
+
+  base_now = nrf52_radio_getreg(dev, basereg);
+  prefix_now = nrf52_radio_getreg(dev, prefixreg);
+
+  /* TODO: check if new address match to old BASE1 */
+
+  if (basereg == NRF52_RADIO_BASE1_OFFSET)
+    {
+#warning missing logic!
+    }
+
+  /* Get new BASE */
+
+  base_new = (addr->a1 | addr->a2 << 8 | addr->a3 << 16 | addr->a4 << 24);
+
+  /* Write new base */
+
+  nrf52_radio_putreg(dev, basereg, base_new);
+
+  /* Write new PREFIX */
+
+  prefix_new = prefix_now;
+  prefix_new &= ~(0xff << prefix_shift);
+  prefix_new |= (addr->a0 << prefix_shift);
+
+  nrf52_radio_putreg(dev, prefixreg, prefix_new);
+
+  /* Copy address */
+
+  memcpy(&dev->addr[i], addr, sizeof(struct nrf52_radio_addr_s));
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf52_radio_txpower_set
+ *
+ * Description:
+ *  Set TX power
+ *
+ ****************************************************************************/
+
+static int nrf52_radio_txpower_set(FAR struct nrf52_radio_dev_s *dev,
+                                   uint8_t txpower)
+{
+  int ret = OK;
+
+  /* Do nothing if already configured */
+
+  if (dev->txpower == txpower)
+    {
+      goto errout;
+    }
+
+  /* Verify input */
+
+  if (txpower > RADIO_TXPOWER_MAX)
+    {
+      ret = -EINVAL;
+      goto errout;
+    }
+
+  nrf52_radio_putreg(dev, NRF52_RADIO_TXPOWER_OFFSET, txpower);
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf52_radio_tifs_set
+ *
+ * Description:
+ *   Set interframe spacing in us
+ *
+ ****************************************************************************/
+
+static int nrf52_radio_tifs_set(FAR struct nrf52_radio_dev_s *dev,
+                                uint16_t us)
+{
+  int ret = OK;
+
+  /* Do nothing if already configured */
+
+  if (dev->tifs == us)
+    {
+      goto errout;
+    }
+
+  /* Verify input */
+
+  if (us > RADIO_TIFS_MAX)
+    {
+      ret = -EINVAL;
+      goto errout;
+    }
+
+  nrf52_radio_putreg(dev, NRF52_RADIO_TIFS_OFFSET, us);
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf52_radio_pkt_cfg
+ *
+ * Description:
+ *   Configure radio packet
+ *
+ ****************************************************************************/
+
+static int nrf52_radio_pkt_cfg(FAR struct nrf52_radio_dev_s *dev,
+                               FAR struct nrf52_radio_pktcfg_s *cfg)
+{
+  uint32_t pcnf0 = 0;
+  uint32_t pcnf1 = 0;
+  int ret       = OK;
+
+  /* LENGTH field length */
+
+  if (cfg->lf_len > RADIO_PCNF0_LFLEN_MAX)
+    {
+      ret = -EINVAL;
+      goto errout;
+    }
+
+  pcnf0 |= (cfg->lf_len << RADIO_PCNF0_LFLEN_SHIFT);
+
+  /* Configure S0 field */
+
+  if (cfg->s0_len > RADIO_PCNF0_S0LEN_MAX)
+    {
+      ret = -EINVAL;
+      goto errout;
+    }
+
+  pcnf0 |= (cfg->s0_len << RADIO_PCNF0_S0LEN_SHIFT);
+
+  /* Configure S1 field */
+
+  if (cfg->s1_len > RADIO_PCNF0_S1LEN_MAX)
+    {
+      ret = -EINVAL;
+      goto errout;
+    }
+
+  pcnf0 |= (cfg->s1_len << RADIO_PCNF0_S1LEN_SHIFT);
+
+  /* S1 in RAM only if S1LEN > 0 */
+
+  pcnf0 &= (~RADIO_PCNF0_S1INCL);
+
+  /* Configure code indicator length */
+
+  if (cfg->ci_len > RADIO_PCNF0_CILEN_MAX)
+    {
+      ret = -EINVAL;
+      goto errout;
+    }
+
+  pcnf0 |= (cfg->ci_len << RADIO_PCNF0_CILEN_SHIFT);
+
+  /* Configure preamble length */
+
+  if (cfg->pl_len > NRF52_RADIO_PREAMBLE_LONGRANGE)
+    {
+      ret = -EINVAL;
+      goto errout;
+    }
+
+  pcnf0 |= (cfg->pl_len << RADIO_PCNF0_PLEN_SHIFT);
+
+  /* Configure TERM length */
+
+  if (cfg->term_len > RADIO_PCNF0_TERMLEN_MAX)
+    {
+      ret = -EINVAL;
+      goto errout;
+    }
+
+  pcnf0 |= (cfg->term_len << RADIO_PCNF0_TERMLEN_SHIFT);
+
+  /* Include CRC in LENGTH or not */
+
+  pcnf0 |= (cfg->crcinc << RADIO_PCNF0_CRCINC_SHIFT);
+
+  /* Configure maximum payload length */
+
+  if (cfg->max_len > RADIO_PCNF1_MAXLEN_MAX)
+    {
+      ret = -EINVAL;
+      goto errout;
+    }
+
+  pcnf1 |= (cfg->max_len << RADIO_PCNF1_MAXLEN_SHIFT);
+
+  /* Configure static payload length */
+
+  if (cfg->stat_len > RADIO_PCNF1_STATLEN_MAX)
+    {
+      ret = -EINVAL;
+      goto errout;
+    }
+
+  pcnf1 |= (cfg->stat_len << RADIO_PCNF1_STATLEN_SHIFT);
+
+  /* Configure base address length */
+
+  if (cfg->bal_len < RADIO_PCNF1_BALEN_MIN ||
+      cfg->bal_len > RADIO_PCNF1_BALEN_MAX)
+    {
+      ret = -EINVAL;
+      goto errout;
+    }
+
+  pcnf1 |= (cfg->bal_len << RADIO_PCNF1_BALEN_SHIFT);
+
+  /* Configure on-air endianess of packet */
+
+  pcnf1 |= (cfg->endian << RADIO_PCNF1_ENDIAN_SHIFT);
+
+  /* Enable whitening */
+
+  pcnf1 |= (cfg->whiteen << RADIO_PCNF1_WHITEEN_SHIFT);
+
+  /* Write registers */
+
+  nrf52_radio_putreg(dev, NRF52_RADIO_PCNF0_OFFSET, pcnf0);
+  nrf52_radio_putreg(dev, NRF52_RADIO_PCNF1_OFFSET, pcnf1);
+
+  /* Copy packet configuration */
+
+  memcpy(&dev->pktcfg, cfg, sizeof(struct nrf52_radio_pktcfg_s));
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf52_radio_white_set
+ *
+ * Description:
+ *   Configure data whitening initial value
+ *
+ ****************************************************************************/
+
+static int nrf52_radio_white_set(FAR struct nrf52_radio_dev_s *dev,
+                                 uint8_t init)
+{
+  uint32_t regval = 0;
+  int      ret    = OK;
+
+  /* Return error if whitening is disabled */
+
+  if (dev->pktcfg.whiteen == false)
+    {
+      ret = -EACCES;
+      goto errout;
+    }
+
+  /* Configure whitening initial value */
+
+  if (init > RADIO_DATAWHITEIV_MAX)
+    {
+      ret = -EINVAL;
+      goto errout;
+    }
+
+  regval |= (init << RADIO_DATAWHITEIV_SHIFT);
+  nrf52_radio_putreg(dev, NRF52_RADIO_DATAWHITEIV_OFFSET, init);
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf52_radio_crc_cfg
+ *
+ * Description:
+ *   Configure packet CRC
+ *
+ ****************************************************************************/
+
+static int nrf52_radio_crc_cfg(FAR struct nrf52_radio_dev_s *dev,
+                               FAR struct nrf52_radio_crc_s *cfg)
+{
+  uint32_t regval = 0;
+  int      ret    = OK;
+
+  /* Configure CRC length */
+
+  if (cfg->len > NRF52_RADIO_CRC_LEN_3B)
+    {
+      ret = -EINVAL;
+      goto errout;
+    }
+
+  regval |= (cfg->len << RADIO_CRCCNF_LEN_SHIFT);
+
+  /* Configure CRC SKIPADDR */
+
+  if (cfg->skip > NRF52_RADIO_CRC_SKIPADDR_IEEE802154)
+    {
+      ret = -EINVAL;
+      goto errout;
+    }
+
+  regval |= (cfg->skip << RADIO_CRCCNF_SKIPADDR_SHIFT);
+  nrf52_radio_putreg(dev, NRF52_RADIO_CRCCNF_OFFSET, regval);
+
+  /* Configure CRC POLY */
+
+  if (cfg->poly > RADIO_CRCPOLY_MASK)
+    {
+      ret = -EINVAL;
+      goto errout;
+    }
+
+  nrf52_radio_putreg(dev, NRF52_RADIO_CRCPOLY_OFFSET, cfg->poly);
+
+  /* Configure CRC INIT */
+
+  if (cfg->init > RADIO_CRCINIT_MASK)
+    {
+      ret = -EINVAL;
+      goto errout;
+    }
+
+  nrf52_radio_putreg(dev, NRF52_RADIO_CRCINIT_OFFSET, cfg->init);
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf52_radio_write
+ *
+ * Description:
+ *   Write radio packet
+ *
+ ****************************************************************************/
+
+static int nrf52_radio_write(FAR struct nrf52_radio_dev_s *dev,
+                             FAR uint8_t *buf, int len)
+{
+  int ret = OK;
+
+  /* Lock device */
+
+  ret = nxsem_wait(&dev->sem_excl);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  /*  */
+
+  if (len > dev->txbuf_len)
+    {
+      ret = -ENOMEM;
+      goto errout;
+    }
+
+  /* Copy packet */
+
+  memcpy(dev->txbuf, buf, len);
+
+  /* Set packet pointer */
+
+  nrf52_radio_putreg(dev, NRF52_RADIO_PACKETPTR_OFFSET, &dev->txbuf);
+
+  /* Set state to TX */
+
+  dev->state = NRF52_RADIO_STATE_TX;
+
+  /* Start TX.
+   * NOTE: shortcut between READ and START is enabled.
+   */
+
+  nrf52_radio_putreg(dev, NRF52_RADIO_TASKS_TXEN_OFFSET, RADIO_TASKS_TXEN);
+
+  /* Wait for IRQ */
+
+  ret = nxsem_wait(&dev->sem_isr);
+
+errout:
+
+  /* Unlock device */
+
+  nxsem_post(&dev->sem_excl);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf52_radio_read
+ *
+ * Description:
+ *   Read radio packet
+ *
+ ****************************************************************************/
+
+static int nrf52_radio_read(FAR struct nrf52_radio_dev_s *dev,
+                            FAR uint8_t *buf, int len)
+{
+  int ret = OK;
+
+  /* Lock radio */
+
+  ret = nxsem_wait(&dev->sem_excl);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  /*  */
+
+  if (len > dev->rxbuf_len)
+    {
+      ret = -ENOMEM;
+      goto errout;
+    }
+
+  /* Set packet pointer */
+
+  nrf52_radio_putreg(dev, NRF52_RADIO_PACKETPTR_OFFSET, &dev->rxbuf);
+
+  /* Set state to RX */
+
+  dev->state = NRF52_RADIO_STATE_RX;
+
+  /* Start RX.
+   * NOTE: shortcut between READ and START is enabled.
+   */
+
+  nrf52_radio_putreg(dev, NRF52_RADIO_TASKS_RXEN_OFFSET, RADIO_TASKS_RXEN);
+
+  /* Wait for IRQ */
+
+  ret = nxsem_wait(&dev->sem_isr);
+
+  /* Copy packet */
+
+  memcpy(buf, dev->rxbuf, len);
+
+errout:
+
+  /* Unlock radio */
+
+  nxsem_post(&dev->sem_excl);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf52_radio_dumpregs
+ *
+ * Description:
+ *   Dump radio registers
+ *
+ ****************************************************************************/
+
+static void nrf52_radio_dumpregs(FAR struct nrf52_radio_dev_s *dev)
+{
+  printf("\nnrf52_radio_dumpregs:\n");
+
+  printf("SHORTS       0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_SHORTS_OFFSET));
+  printf("INTENSET     0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_INTENSET_OFFSET));
+  printf("CRCSTATUS    0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_CRCSTATUS_OFFSET));
+  printf("RXMATCH      0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_RXMATCH_OFFSET));
+  printf("RXCRC        0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_RXCRC_OFFSET));
+  printf("DAI          0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_DAI_OFFSET));
+  printf("PDUSTAT      0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_PDUSTAT_OFFSET));
+  printf("PACKETPTR    0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_PACKETPTR_OFFSET));
+  printf("FREQUENCY    0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_FREQUENCY_OFFSET));
+  printf("TXPOWER      0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_TXPOWER_OFFSET));
+  printf("MODE         0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_MODE_OFFSET));
+  printf("PCNF0        0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_PCNF0_OFFSET));
+  printf("PCNF1        0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_PCNF1_OFFSET));
+  printf("BASE0        0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_BASE0_OFFSET));
+  printf("BASE1        0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_BASE1_OFFSET));
+  printf("PREFIX0      0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_PREFIX0_OFFSET));
+  printf("PREFIX1      0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_PREFIX1_OFFSET));
+  printf("TXADDRESS    0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_TXADDRESS_OFFSET));
+  printf("RXADDRESS    0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_RXADDRESS_OFFSET));
+  printf("CRCCNF       0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_CRCCNF_OFFSET));
+  printf("CRCPOLY      0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_CRCPOLY_OFFSET));
+  printf("CRCINIT      0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_CRCINIT_OFFSET));
+  printf("TIFS         0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_TIFS_OFFSET));
+  printf("RSSISAMPLE   0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_RSSISAMPLE_OFFSET));
+  printf("STATE        0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_STATE_OFFSET));
+  printf("DATAWHITEIV  0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_DATAWHITEIV_OFFSET));
+  printf("BCC          0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_BCC_OFFSET));
+  printf("DAB0         0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_DAB_OFFSET(0)));
+  printf("DAB1         0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_DAB_OFFSET(1)));
+  printf("DAB2         0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_DAB_OFFSET(2)));
+  printf("DAB3         0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_DAB_OFFSET(3)));
+  printf("DAB4         0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_DAB_OFFSET(4)));
+  printf("DAB5         0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_DAB_OFFSET(5)));
+  printf("DAB6         0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_DAB_OFFSET(6)));
+  printf("DAB7         0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_DAB_OFFSET(6)));
+  printf("DAP0         0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_DAP_OFFSET(0)));
+  printf("DAP1         0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_DAP_OFFSET(1)));
+  printf("DAP2         0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_DAP_OFFSET(2)));
+  printf("DAP3         0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_DAP_OFFSET(3)));
+  printf("DAP4         0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_DAP_OFFSET(4)));
+  printf("DAP5         0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_DAP_OFFSET(5)));
+  printf("DAP6         0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_DAP_OFFSET(6)));
+  printf("DAP7         0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_DAP_OFFSET(6)));
+  printf("DACNF        0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_DACNF_OFFSET));
+  printf("MHRMATCHCONF 0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_MHRMATCHCONF_OFFSET));
+  printf("MHRMATCHMAS  0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_MHRMATCHMAS_OFFSET));
+  printf("MODECNF0     0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_MODECNF0_OFFSET));
+  printf("SFD          0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_SFD_OFFSET));
+  printf("EDCNT        0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_EDCNT_OFFSET));
+  printf("EDSAMPLE     0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_EDSAMPLE_OFFSET));
+  printf("CCACTRL      0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_CCACTRL_OFFSET));
+  printf("POWER        0x%08x\n",
+         nrf52_radio_getreg(dev, NRF52_RADIO_POWER_OFFSET));
+}
+
+/****************************************************************************
+ * Name: nrf52_radio_isr_rx
+ *
+ * Description:
+ *   RX radio interrupt handler
+ *
+ ****************************************************************************/
+
+static int nrf52_radio_isr_rx(FAR struct nrf52_radio_dev_s *dev)
+{
+  /* RX done */
+
+  nxsem_post(&dev->sem_isr);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: nrf52_radio_isr_tx
+ *
+ * Description:
+ *   TX radio interrupt handler
+ *
+ ****************************************************************************/
+
+static int nrf52_radio_isr_tx(FAR struct nrf52_radio_dev_s *dev)
+{
+  /* TX done */
+
+  nxsem_post(&dev->sem_isr);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: nrf52_radio_isr
+ *
+ * Description:
+ *   Radio interrupt handler
+ *
+ ****************************************************************************/
+
+static int nrf52_radio_isr(int irq, FAR void *context, FAR void *arg)
+{
+  FAR struct nrf52_radio_dev_s *dev   = (FAR struct nrf52_radio_dev_s *)arg;
+  int                           ret   = OK;
+  uint32_t                      state = 0;
+
+  DEBUGASSERT(dev);
+
+  /* Get radio state */
+
+  wlinfo("RADIO ISR STATE=%d\n", dev->state);
+
+  /* Handle radio state */
+
+  switch (dev->state)
+    {
+      case NRF52_RADIO_STATE_RX:
+        {
+          /* Transmit DONE */
+
+          ret = nrf52_radio_isr_rx(dev);
+
+          break;
+        }
+
+      case NRF52_RADIO_STATE_TX:
+        {
+          /* Receive DONE */
+
+          ret = nrf52_radio_isr_tx(dev);
+
+          break;
+        }
+
+      case NRF52_RADIO_STATE_DISABLED:
+        {
+          break;
+        }
+
+      default:
+        {
+          ASSERT(0);
+          break;
+        }
+    }
+
+  /* Clear END event */
+
+  nrf52_radio_putreg(dev, NRF52_RADIO_EVENTS_END_OFFSET, 0);
+
+  /* Update radio state
+   * NOTE: shortcut between END and DISABLE is enabled.
+   */
+
+  dev->state = NRF52_RADIO_STATE_DISABLED;
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf52_radio_setup
+ *
+ * Description:
+ *   Initial RADIO setup
+ *
+ ****************************************************************************/
+
+static int nrf52_radio_setup(FAR struct nrf52_radio_dev_s *dev)
+{
+  uint32_t regval = 0;
+  int      ret    = OK;
+
+  DEBUGASSERT(dev);
+
+  /* Configure interrupts:
+   *  1. END - packet sent or received
+   */
+
+  regval = (RADIO_INT_END);
+  nrf52_radio_putreg(dev, NRF52_RADIO_INTENSET_OFFSET, regval);
+
+  /* Configure shortucts:
+   *   1. shortcut between READY and START
+   *   2. shortcut between END and DISABLE
+   */
+
+  regval = RADIO_SHORTS_READY_START;
+  regval |= RADIO_SHORTS_END_DISABLE;
+  nrf52_radio_putreg(dev, NRF52_RADIO_SHORTS_OFFSET, regval);
+
+  /* Power on radio */
+
+  nrf52_radio_power(dev, true);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf52_radio_reset
+ *
+ * Description:
+ *   Reset radio
+ *
+ ****************************************************************************/
+
+static int nrf52_radio_reset(FAR struct nrf52_radio_dev_s *dev)
+{
+  /* Turn off radio power */
+
+  nrf52_radio_power(dev, false);
+
+  /* Wait some time */
+
+  nxsig_usleep(100000);
+
+  /* Turn on radio power */
+
+  nrf52_radio_power(dev, true);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf52_radio_initialize
+ *
+ * Description:
+ *   Initialize NRF52 radio device
+ *
+ ****************************************************************************/
+
+FAR struct nrf52_radio_dev_s *
+nrf52_radio_initialize(int intf, FAR struct nrf52_radio_board_s *board)
+{
+  struct nrf52_radio_dev_s *dev = NULL;
+  int                       ret = OK;
+
+  /* Get radio interface */
+
+  switch (intf)
+    {
+      case 0:
+        {
+          wlinfo("radio0 selecred\n");
+          dev = &g_nrf52_radio_dev_1;
+          break;
+        }
+
+      /* For now only one radio interface is available */
+
+      default:
+        {
+          wlerr("ERROR: No radio interface defined\n");
+          goto errout;
+        }
+    }
+
+  /* Reset some data */
+
+  memset(&dev->pktcfg, 0, sizeof(struct nrf52_radio_pktcfg_s));
+  memset(dev->rxbuf, 0, NRF52_RADIO_RXBUFFER);
+  memset(dev->txbuf, 0, NRF52_RADIO_TXBUFFER);
+
+  /* Attach radio interrupt */
+
+  irq_attach(dev->irq, nrf52_radio_isr, dev);
+  up_enable_irq(dev->irq);
+
+  /* Initialize semaphores */
+
+  nxsem_init(&dev->sem_excl, 0, 1);
+
+  /* This semaphore is used for signaling and, hence, should not have
+   * priority inheritance enabled.
+   */
+
+  nxsem_init(&dev->sem_isr, 0, 0);
+  nxsem_setprotocol(&dev->sem_isr, SEM_PRIO_NONE);
+
+  /* Connect board-specific data */
+
+  dev->board = board;
+
+  /* Reset radio */
+
+  ret = nrf52_radio_reset(dev);
+  if (ret < 0)
+    {
+      wlerr("ERROR: failed to reset radio interface %d\n", ret);
+      errno = ret;
+      goto errout;
+    }
+
+  /* Initial radio setup */
+
+  ret = nrf52_radio_setup(dev);
+  if (ret < 0)
+    {
+      wlerr("ERROR: failed to setup radio interface %d\n", ret);
+      errno = ret;
+      goto errout;
+    }
+
+  return dev;
+
+errout:
+  return NULL;
+}
diff --git a/arch/arm/src/nrf52/nrf52_radio.h b/arch/arm/src/nrf52/nrf52_radio.h
new file mode 100644
index 0000000..2332738
--- /dev/null
+++ b/arch/arm/src/nrf52/nrf52_radio.h
@@ -0,0 +1,281 @@
+/****************************************************************************
+ * arch/arm/src/nrf52/nrf52_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_RADIO_H
+#define __ARCH_ARM_SRC_NRF52_NRF52_RADIO_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+
+#include <nuttx/semaphore.h>
+
+#include "chip.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define NRF52_RADIO_LOGICAL_ADDRESS_MAX (8)
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* Radio mode */
+
+enum nrf52_radio_mode_e
+{
+  NRF52_RADIO_MODE_NRF1MBIT     = 0,
+  NRF52_RADIO_MODE_NRF2MBIT     = 1,
+  NRF52_RADIO_MODE_BLE1MBIT     = 2,
+  NRF52_RADIO_MODE_BLE2MBIT     = 3,
+  NRF52_RADIO_MODE_BLELR125KBIT = 4,
+  NRF52_RADIO_MODE_BLELR500KBIT = 5,
+  NRF52_RADIO_MODE_IEEE802154   = 6
+};
+
+/* Radio state */
+
+enum nrf52_radio_state_e
+{
+  NRF52_RADIO_STATE_DISABLED = 0,
+  NRF52_RADIO_STATE_TX       = 1,
+  NRF52_RADIO_STATE_RX       = 2,
+};
+
+/* Preamble configuration */
+
+enum nrf52_radio_preamble_e
+{
+  NRF52_RADIO_PREAMBLE_8BIT       = 0,
+  NRF52_RADIO_PREAMBLE_16BIT      = 1,
+  NRF52_RADIO_PREAMBLE_32BITZERO  = 2,
+  NRF52_RADIO_PREAMBLE_LONGRANGE  = 3
+};
+
+/* Radio packet CRC length */
+
+enum nrf52_radio_crc_len_e
+{
+  NRF52_RADIO_CRC_LEN_DIS   = 0,
+  NRF52_RADIO_CRC_LEN_1B    = 1,
+  NRF52_RADIO_CRC_LEN_2B    = 2,
+  NRF52_RADIO_CRC_LEN_3B    = 3,
+};
+
+/* Radio packet CRC includes address */
+
+enum nrf52_radio_crc_skipaddr_e
+{
+  NRF52_RADIO_CRC_SKIPADDR_INCLUDE    = 0,
+  NRF52_RADIO_CRC_SKIPADDR_SKIP       = 1,
+  NRF52_RADIO_CRC_SKIPADDR_IEEE802154 = 2,
+};
+
+/* On air packet layout:
+ *
+ * +---------------------------------------+
+ * | FIRST                                 |
+ * |----------+------+--------+----+-------+
+ * | PREAMBLE | BASE | PREFIX | CI | TERM1 |
+ * | LSB      | LSB  | LSB    |    |       |
+ * |          | ADDRESS       |    |       |
+ * +----------+---------------+----+-------+
+ *
+ *
+ * +----------------------------+
+ * | Stored on RAM              |
+ * |----+--------+----+---------|
+ * | S0 | LENGTH | S1 | PAYLOAD |
+ * |    |        |    |         |
+ * |    |        |    |         |
+ * +----+--------+----+---------+
+ *
+ * +---------------+
+ * |         LAST  |
+ * |-------+-------|
+ * | CRC32 | TERM2 |
+ * | MSB   |       |
+ * |       |       |
+ * +-------+-------+
+ *
+ */
+
+/* Radio packet configuration */
+
+struct nrf52_radio_pktcfg_s
+{
+  uint8_t max_len;              /* Maximum length of payload */
+  uint8_t stat_len;             /* Static payload length */
+  uint8_t bal_len;              /* Base address length */
+  uint8_t lf_len;               /* LENGTH length */
+  uint8_t s0_len;               /* S0 length */
+  uint8_t s1_len;               /* S1 length */
+  uint8_t ci_len;               /* CI length */
+  uint8_t pl_len;               /* Preable lenght */
+  uint8_t term_len;             /* TERM length */
+  bool    crcinc;               /* LENGTH includes CRC */
+  bool    endian;               /* On air endianess of packet:
+                                 * 0 - little
+                                 * 1 - big
+                                 */
+  bool   whiteen;               /* Whitening enabled */
+};
+
+/* Radio packet CRC configuration */
+
+struct nrf52_radio_crc_s
+{
+  uint8_t  len;                 /* CRC length in number of bytes */
+  uint8_t  skip;                /* Include or exclude address field out of CRC */
+  uint32_t poly;                /* CRC polynominal */
+  uint32_t init;                /* CRC initial value */
+};
+
+/* NRF52 on air address */
+
+struct nrf52_radio_addr_s
+{
+  uint8_t a0;                   /* PREFIX */
+  uint8_t a1;                   /* BASE[0] */
+  uint8_t a2;                   /* BASE[1] */
+  uint8_t a3;                   /* BASE[2] */
+  uint8_t a4;                   /* BASE[3] */
+};
+
+/* NRF52 radio operations */
+
+struct nrf52_radio_dev_s;
+struct nrf52_radio_ops_s
+{
+  /* Turn-on/turn-off radio power */
+
+  CODE int (*power)(FAR struct nrf52_radio_dev_s *dev, bool state);
+
+  /* Set radio mode */
+
+  CODE int (*mode_set)(FAR struct nrf52_radio_dev_s *dev, uint8_t mode);
+
+  /* Set radio frequency (in MHz) */
+
+  CODE int (*freq_set)(FAR struct nrf52_radio_dev_s *dev, uint32_t freq);
+
+  /* Get RSSI sample */
+
+  CODE int (*rssi_get)(FAR struct nrf52_radio_dev_s *dev, FAR int *rssi);
+
+  /* Set TX power */
+
+  CODE int (*txpower_set)(FAR struct nrf52_radio_dev_s *dev,
+                          uint8_t txpower);
+
+  /* Set hardware interframe spacing time */
+
+  CODE int (*tifs_set)(FAR struct nrf52_radio_dev_s *dev, uint16_t us);
+
+  /* Configure radio packet */
+
+  CODE int (*pkt_cfg)(FAR struct nrf52_radio_dev_s *dev,
+                      FAR struct nrf52_radio_pktcfg_s *cfg);
+
+  /* Configure packet CRC */
+
+  CODE int (*crc_cfg)(FAR struct nrf52_radio_dev_s *dev,
+                      FAR struct nrf52_radio_crc_s *cfg);
+
+  /* Configure data whitening */
+
+  CODE int (*white_set)(FAR struct nrf52_radio_dev_s *dev,
+                        uint8_t init);
+
+  /* Configure logical address */
+
+  CODE int (*addr_set)(FAR struct nrf52_radio_dev_s *dev, uint8_t i,
+                       FAR struct nrf52_radio_addr_s *addr);
+
+  /* Read packet */
+
+  CODE int (*read)(FAR struct nrf52_radio_dev_s *dev,
+                   FAR uint8_t *buf, int len);
+
+  /* Write packet */
+
+  CODE int (*write)(FAR struct nrf52_radio_dev_s *dev,
+                    FAR uint8_t *buf, int len);
+
+  /* Dump radio registers */
+
+  CODE void (*dumpregs)(FAR struct nrf52_radio_dev_s *dev);
+};
+
+/* NRF52 radio board specific data */
+
+struct nrf52_radio_board_s
+{
+  /* TODO: PA/LNA interface */
+
+  uint32_t reserved;
+};
+
+/* NRF52 radio device */
+
+struct nrf52_radio_dev_s
+{
+  FAR struct nrf52_radio_ops_s   *ops;       /* Radio operations */
+  FAR struct nrf52_radio_board_s *board;     /* Radio board-specific */
+  uint32_t                        base;      /* Radio base */
+  uint32_t                        irq;       /* Radio IRQ number */
+  uint8_t                         mode;      /* Radio mode */
+  uint8_t                         state;     /* Radio state */
+  struct nrf52_radio_pktcfg_s     pktcfg;    /* Current packet */
+  uint16_t                        rxbuf_len; /* RX buffer length */
+  uint16_t                        txbuf_len; /* TX buffer length */
+  FAR uint8_t                     *rxbuf;    /* RX buffer */
+  FAR uint8_t                     *txbuf;    /* TX buffer */
+  sem_t                           sem_excl;  /* Mutual exclusion semaphore */
+  sem_t                           sem_isr;   /* Interrupt wait semaphore */
+  uint16_t                        tifs;      /* Interframe spacing time */
+  uint8_t                         txpower;   /* TX power */
+  uint8_t                         txaddr;    /* TX address */
+  uint8_t                         rxaddr;    /* RX addresses */
+  struct nrf52_radio_addr_s       addr[NRF52_RADIO_LOGICAL_ADDRESS_MAX];
+};
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf52_radio_initialize
+ *
+ * Description:
+ *   Initialize NRF52 radio device
+ *
+ ****************************************************************************/
+
+FAR struct nrf52_radio_dev_s *
+nrf52_radio_initialize(int intf, FAR struct nrf52_radio_board_s *board);
+
+#endif /* __ARCH_ARM_SRC_NRF52_NRF52_RADIO_H */