You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by bt...@apache.org on 2021/02/02 22:40:36 UTC
[incubator-nuttx] branch master updated: nRF52: add support for
building SoftDevice BLE controller
This is an automated email from the ASF dual-hosted git repository.
btashton 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 45b392b nRF52: add support for building SoftDevice BLE controller
45b392b is described below
commit 45b392be7e67a7d330678c20b716e403bd107cc4
Author: Matias N <ma...@protobits.dev>
AuthorDate: Sun Jan 24 14:19:59 2021 -0300
nRF52: add support for building SoftDevice BLE controller
---
arch/arm/src/nrf52/.gitignore | 4 +
arch/arm/src/nrf52/Kconfig | 73 ++-
arch/arm/src/nrf52/Make.defs | 57 ++
arch/arm/src/nrf52/nrf52_ppi.h | 14 +-
arch/arm/src/nrf52/nrf52_sdc.c | 600 +++++++++++++++++++++
.../arm/src/nrf52/nrf52_sdc.h | 69 +--
arch/arm/src/nrf52/sdc/README.md | 2 +
arch/arm/src/nrf52/sdc/core_cm4.h | 41 ++
arch/arm/src/nrf52/sdc/nrf.h | 84 +++
.../arm/nrf52/nrf52832-mdk/configs/sdc/defconfig | 81 +++
boards/arm/nrf52/nrf52832-mdk/src/nrf52_bringup.c | 21 +
wireless/bluetooth/bt_buf.c | 2 +
12 files changed, 1001 insertions(+), 47 deletions(-)
diff --git a/arch/arm/src/nrf52/.gitignore b/arch/arm/src/nrf52/.gitignore
new file mode 100644
index 0000000..8f9b697
--- /dev/null
+++ b/arch/arm/src/nrf52/.gitignore
@@ -0,0 +1,4 @@
+CMSIS_5*
+sdk-nrfxlib*
+nrfx*
+*.tar.gz
diff --git a/arch/arm/src/nrf52/Kconfig b/arch/arm/src/nrf52/Kconfig
index 0514244..f7c32b1 100644
--- a/arch/arm/src/nrf52/Kconfig
+++ b/arch/arm/src/nrf52/Kconfig
@@ -185,6 +185,7 @@ config NRF52_WDT
config NRF52_RADIO
bool "RADIO"
depends on EXPERIMENTAL
+ depends on !NRF52_SOFTDEVICE_CONTROLLER
default n
config NRF52_NFCT
@@ -198,6 +199,7 @@ config NRF52_SAADC
config NRF52_TIMER0
bool "TIMER0"
select NRF52_TIMER
+ depends on !NRF52_SOFTDEVICE_CONTROLLER
default n
config NRF52_TIMER1
@@ -248,6 +250,7 @@ config NRF52_PPI
config NRF52_RTC0
bool "RTC0"
select NRF52_RTC
+ depends on !NRF52_SOFTDEVICE_CONTROLLER
default n
config NRF52_RTC1
@@ -355,7 +358,8 @@ if NRF52_SYSTIMER_RTC
config NRF52_SYSTIMER_RTC_INSTANCE
int "RTC timer instance"
- default 0
+ default 0 if !NRF52_SOFTDEVICE_CONTROLLER
+ default 1 if NRF52_SOFTDEVICE_CONTROLLER
range 0 2
---help---
Which RTC instance to use to drive the system timer
@@ -654,3 +658,70 @@ config NRF52_I2C_MASTER_COPY_BUF_SIZE
on malloc.
endmenu
+
+menuconfig NRF52_SOFTDEVICE_CONTROLLER
+ bool "SoftDevice Controller"
+ select CONFIG_ARMV7M_USEBASEPRI
+ select CONFIG_ARCH_RAMVECTORS
+ select NRF52_USE_LFCLK
+ select NRF52_LFCLK_XTAL
+ ---help---
+ This enables use of Nordic SoftDevice controller
+ (SDC). It is a library version of a subset of
+ full SoftDevice, which only includes the BLE
+ controller implementation.
+
+ It makes use of RTC0, TIMER0, RADIO and RNG, so
+ these will be unavailable for direct use by user.
+ It also makes use of PPI channel range 17-31.
+
+if NRF52_SOFTDEVICE_CONTROLLER
+
+config NRF52_SDC_CLOCK_ACCURACY
+ int "Clock Accuracy [PPM]"
+ default 250
+ ---help---
+ Select the clock accuracy depending on the chosen low-frequency clock
+ source
+
+config NRF52_SDC_SLAVE_COUNT
+ int "Number of slave roles to support (also master)"
+ default 1
+ ---help---
+ This controls how many slave connections will be supported. It also
+ determines the number of master roles from the following:
+
+ MASTER_ROLES = CONFIG_BLUETOOTH_MAX_CONN - NRF52_SDC_SLAVE_COUNT
+
+ So by choosing these two variables you can control both capabilities.
+
+config NRF52_SDC_ADVERTISING
+ bool "Support advertising"
+ default y
+
+config NRF52_SDC_SCANNING
+ bool "Support scanning"
+ default y
+
+config NRF52_SDC_LE_2M_PHY
+ bool "Support LE 2M PHY"
+ default y
+
+config NRF52_SDC_LE_CODED_PHY
+ bool "Support LE Coded PHY"
+ default y
+
+config NRF52_SDC_DLE
+ bool "Support Data Length Extension (DLE)"
+ default y
+
+config NRF52_SDC_VERSION
+ int "SoftDevice version"
+ default 132 if ARCH_CHIP_NRF52832
+ default 140 if ARCH_CHIP_NRF52840
+ ---help---
+ The softdevice version to use. This depends on the particular chip
+ to use. See official Nordic documentation on which chips are supported
+ in each version.
+endif
+
diff --git a/arch/arm/src/nrf52/Make.defs b/arch/arm/src/nrf52/Make.defs
index 9409876..de8eccb 100644
--- a/arch/arm/src/nrf52/Make.defs
+++ b/arch/arm/src/nrf52/Make.defs
@@ -171,3 +171,60 @@ endif
ifeq ($(CONFIG_PM),y)
CHIP_CSRCS += nrf52_pminitialize.c
endif
+
+ifeq ($(CONFIG_NRF52_SOFTDEVICE_CONTROLLER),y)
+
+NRFXLIB_UNPACK := sdk-nrfxlib
+NRFXLIB_VER := 1.4.2
+NRFXLIB_REF := v$(NRFXLIB_VER)
+NRFXLIB_TGZ := $(NRFXLIB_REF).tar.gz
+NRFXLIB_URL := https://github.com/nrfconnect/sdk-nrfxlib/archive
+
+$(NRFXLIB_TGZ):
+ $(Q) echo "Downloading: NRFXLIB"
+ $(Q) curl -L $(NRFXLIB_URL)/$(NRFXLIB_TGZ) -o chip/$(NRFXLIB_TGZ)
+
+chip/$(NRFXLIB_UNPACK): $(NRFXLIB_TGZ)
+ $(Q) echo "Unpacking: NRXFLIB"
+ $(Q) cd chip && tar zxf $(NRFXLIB_TGZ)
+ $(Q) mv chip/$(NRFXLIB_UNPACK)-$(NRFXLIB_VER)* chip/$(NRFXLIB_UNPACK)
+ $(Q) touch chip/$(NRFXLIB_UNPACK)
+
+context:: chip/$(NRFXLIB_UNPACK)
+
+clean_context::
+ $(call DELFILE, chip/$(NRFXLIB_TGZ))
+ $(call DELDIR, chip/$(NRFXLIB_UNPACK))
+
+CHIP_CSRCS += nrf52_sdc.c
+
+NRFX_DIR = $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)nrfx
+NRFXLIB_DIR = $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)sdk-nrfxlib
+CMSIS_DIR = $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)CMSIS_5
+
+INCLUDES += \
+ $(shell $(INCDIR) "$(CC)" $(ARCH_SRCDIR)$(DELIM)chip$(DELIM)sdc) \
+ $(shell $(INCDIR) "$(CC)" $(NRFXLIB_DIR)$(DELIM)mpsl$(DELIM)include) \
+ $(shell $(INCDIR) "$(CC)" $(NRFXLIB_DIR)$(DELIM)softdevice_controller$(DELIM)include)
+
+ifeq ($(CONFIG_ARCH_CHIP_NRF52832),y)
+ CFLAGS += -DNRF52832_XXAB
+else
+ ifeq ($(CONFIG_ARCH_CHIP_NRF52840),y)
+ CFLAGS += -DNRF52840_XXAB
+ endif
+endif
+
+ifeq ($(CONFIG_ARCH_FPU),y)
+ LIB_VARIANT=hard-float
+else
+ LIB_VARIANT=soft-float
+endif
+
+EXTRA_LIBPATHS += \
+ -L $(NRFXLIB_DIR)$(DELIM)mpsl$(DELIM)lib$(DELIM)cortex-m4$(DELIM)$(LIB_VARIANT) \
+ -L $(NRFXLIB_DIR)$(DELIM)softdevice_controller$(DELIM)lib$(DELIM)cortex-m4$(DELIM)$(LIB_VARIANT)
+
+EXTRA_LIBS += -lmpsl -lsoftdevice_controller_s$(CONFIG_NRF52_SDC_VERSION)
+
+endif
diff --git a/arch/arm/src/nrf52/nrf52_ppi.h b/arch/arm/src/nrf52/nrf52_ppi.h
index 9f7b283..f7b82b8 100644
--- a/arch/arm/src/nrf52/nrf52_ppi.h
+++ b/arch/arm/src/nrf52/nrf52_ppi.h
@@ -32,9 +32,17 @@
* Pre-processor Definitions
****************************************************************************/
-#define NRF52_PPI_NUM_CHANNELS 32 /* Total number of PPI channels */
-#define NRF52_PPI_NUM_CONFIGURABLE_CHANNELS 20 /* Number of configurable PPI channels */
-#define NRF52_PPI_NUM_GROUPS 6 /* Number of PPI channel groups */
+/* Nordic SDC makes use of PPI channels 17-31 */
+
+#ifdef CONFIG_NRF52_SOFTDEVICE_CONTROLLER
+# define NRF52_PPI_NUM_CHANNELS 16 /* Total number of PPI channels */
+# define NRF52_PPI_NUM_CONFIGURABLE_CHANNELS 16 /* Number of configurable PPI channels */
+# define NRF52_PPI_NUM_GROUPS 6 /* Number of PPI channel groups */
+#else
+# define NRF52_PPI_NUM_CHANNELS 32 /* Total number of PPI channels */
+# define NRF52_PPI_NUM_CONFIGURABLE_CHANNELS 20 /* Number of configurable PPI channels */
+# define NRF52_PPI_NUM_GROUPS 6 /* Number of PPI channel groups */
+#endif
/****************************************************************************
* Public Types
diff --git a/arch/arm/src/nrf52/nrf52_sdc.c b/arch/arm/src/nrf52/nrf52_sdc.c
new file mode 100644
index 0000000..8c23213
--- /dev/null
+++ b/arch/arm/src/nrf52/nrf52_sdc.c
@@ -0,0 +1,600 @@
+/****************************************************************************
+ * arch/arm/src/chip/nrf52_sdc.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 <nuttx/net/bluetooth.h>
+#include <nuttx/wireless/bluetooth/bt_hci.h>
+#include <nuttx/wireless/bluetooth/bt_driver.h>
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <arch/armv7-m/nvicpri.h>
+#include <arch/nrf52/nrf52_irq.h>
+#include <nuttx/wqueue.h>
+
+#include "arm_internal.h"
+#include "ram_vectors.h"
+#include "arm_arch.h"
+
+#include <mpsl.h>
+#include <sdc.h>
+#include <sdc_hci.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#if defined(CONFIG_SDC_SLAVE_COUNT) && \
+ CONFIG_SDC_SLAVE_COUNT > CONFIG_BLUETOOTH_MAX_CONN
+# error "Cannot support more BLE slave roles than connections"
+#endif
+
+#define SDC_MASTER_COUNT (CONFIG_BLUETOOTH_MAX_CONN - \
+ CONFIG_NRF52_SDC_SLAVE_COUNT)
+
+/* Todo: check central/peripheral against master/slave count */
+
+#define MASTER_MEM_SIZE (SDC_MEM_PER_MASTER_LINK( \
+ SDC_DEFAULT_TX_PACKET_SIZE, \
+ SDC_DEFAULT_RX_PACKET_SIZE, \
+ SDC_DEFAULT_TX_PACKET_COUNT, \
+ SDC_DEFAULT_RX_PACKET_COUNT) \
+ + SDC_MEM_MASTER_LINKS_SHARED)
+
+#define SLAVE_MEM_SIZE (SDC_MEM_PER_SLAVE_LINK( \
+ SDC_DEFAULT_TX_PACKET_SIZE, \
+ SDC_DEFAULT_RX_PACKET_SIZE, \
+ SDC_DEFAULT_TX_PACKET_COUNT, \
+ SDC_DEFAULT_RX_PACKET_COUNT) \
+ + SDC_MEM_SLAVE_LINKS_SHARED)
+
+#define MEMPOOL_SIZE ((CONFIG_NRF52_SDC_SLAVE_COUNT * SLAVE_MEM_SIZE) + \
+ (SDC_MASTER_COUNT * MASTER_MEM_SIZE))
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct nrf52_sdc_dev_s
+{
+ uint8_t mempool[MEMPOOL_SIZE];
+ uint8_t msg_buffer[HCI_MSG_BUFFER_MAX_SIZE];
+
+ sem_t exclsem;
+ struct work_s work;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static void mpsl_assert_handler(const char *const file, const uint32_t line);
+static void sdc_fault_handler(const char *file, const uint32_t line);
+
+static int bt_open(FAR const struct bt_driver_s *btdev);
+static int bt_hci_send(FAR const struct bt_driver_s *btdev,
+ FAR struct bt_buf_s *buf);
+
+static void on_hci(void);
+static void on_hci_worker(void *arg);
+
+static void low_prio_worker(void *arg);
+
+static int swi_isr(int irq, FAR void *context, FAR void *arg);
+static int power_clock_isr(int irq, FAR void *context, FAR void *arg);
+
+static void rng_handler(void);
+static void rtc0_handler(void);
+static void timer0_handler(void);
+static void radio_handler(void);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct bt_driver_s g_bt_driver =
+{
+ .head_reserve = 0,
+ .open = bt_open,
+ .send = bt_hci_send
+};
+
+static const mpsl_clock_lfclk_cfg_t g_clock_config =
+{
+ .source = MPSL_CLOCK_LF_SRC_XTAL,
+ .rc_ctiv = 0,
+ .rc_temp_ctiv = 0,
+ .accuracy_ppm = CONFIG_NRF52_SDC_CLOCK_ACCURACY,
+ .skip_wait_lfclk_started = false
+};
+
+static struct nrf52_sdc_dev_s g_sdc_dev;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: bt_open
+ ****************************************************************************/
+
+static int bt_open(FAR const struct bt_driver_s *btdev)
+{
+ return 0;
+}
+
+/****************************************************************************
+ * Name: bt_open
+ ****************************************************************************/
+
+static int bt_hci_send(FAR const struct bt_driver_s *btdev,
+ FAR struct bt_buf_s *buf)
+{
+ int ret = OK;
+
+ /* Pass HCI CMD/DATA to SDC */
+
+ if (buf->type == BT_CMD)
+ {
+ struct bt_hci_cmd_hdr_s *cmd = (struct bt_hci_cmd_hdr_s *)buf->data;
+
+ wlinfo("passing CMD %d to softdevice\n", cmd->opcode);
+
+ /* Ensure non-concurrent access to SDC operations */
+
+ nxsem_wait_uninterruptible(&g_sdc_dev.exclsem);
+
+ if (sdc_hci_cmd_put(buf->data) < 0)
+ {
+ wlerr("sdc_hci_cmd_put() failed\n");
+ ret = -EIO;
+ }
+
+ nxsem_post(&g_sdc_dev.exclsem);
+
+ work_queue(LPWORK, &g_sdc_dev.work, on_hci_worker, NULL, 0);
+ }
+ else if (buf->type == BT_ACL_OUT)
+ {
+ wlinfo("passing ACL to softdevice\n");
+
+ /* Ensure non-concurrent access to SDC operations */
+
+ nxsem_wait_uninterruptible(&g_sdc_dev.exclsem);
+
+ if (sdc_hci_data_put(buf->data) < 0)
+ {
+ wlerr("sdc_hci_data_put() failed\n");
+ ret = -EIO;
+ }
+
+ nxsem_post(&g_sdc_dev.exclsem);
+
+ work_queue(LPWORK, &g_sdc_dev.work, on_hci_worker, NULL, 0);
+ }
+
+ if (ret < 0)
+ {
+ wlerr("bt_hci_send() failed: %d\n", ret);
+ return ret;
+ }
+ else
+ {
+ return buf->len;
+ }
+}
+
+/****************************************************************************
+ * Name: sdc_fault_handler
+ ****************************************************************************/
+
+static void sdc_fault_handler(const char *file, const uint32_t line)
+{
+ _alert("SoftDevice Controller Fault\n");
+ up_assert(file, line);
+}
+
+/****************************************************************************
+ * Name: mpsl_assert_handler
+ ****************************************************************************/
+
+static void mpsl_assert_handler(const char *const file, const uint32_t line)
+{
+ _alert("MPSL assertion failed\n");
+ up_assert(file, line);
+}
+
+/****************************************************************************
+ * Name: low_prio_worker
+ ****************************************************************************/
+
+static void low_prio_worker(void *arg)
+{
+ /* Invoke MPSL low priority process handler. This will call on_hci()
+ * internally when required.
+ */
+
+ nxsem_wait_uninterruptible(&g_sdc_dev.exclsem);
+ mpsl_low_priority_process();
+ nxsem_post(&g_sdc_dev.exclsem);
+}
+
+/****************************************************************************
+ * Name: on_hci_worker
+ ****************************************************************************/
+
+static void on_hci_worker(void *arg)
+{
+ /* We use this worker to force a call to on_hci() right after sending
+ * an HCI command as MPSL/SDC does not always signal the low priority
+ * worker
+ */
+
+ nxsem_wait_uninterruptible(&g_sdc_dev.exclsem);
+ on_hci();
+ nxsem_post(&g_sdc_dev.exclsem);
+}
+
+/****************************************************************************
+ * Name: on_hci
+ ****************************************************************************/
+
+static void on_hci(void)
+{
+ struct bt_buf_s *outbuf;
+ size_t len;
+ int ret;
+ bool check_again = true;
+
+ while (check_again)
+ {
+ check_again = false;
+
+ /* Check for EVT by trying to get pending data into a generic
+ * buffer and then create an actual bt_buf_s, depending on msg length
+ */
+
+ ret = sdc_hci_evt_get(g_sdc_dev.msg_buffer);
+
+ if (ret == 0)
+ {
+ struct bt_hci_evt_hdr_s *hdr =
+ (struct bt_hci_evt_hdr_s *)g_sdc_dev.msg_buffer;
+
+ len = sizeof(*hdr) + hdr->len;
+
+#ifdef CONFIG_DEBUG_WIRELESS_INFO
+ if (hdr->evt == BT_HCI_EVT_CMD_COMPLETE)
+ {
+ struct hci_evt_cmd_complete_s *cmd_complete =
+ (struct hci_evt_cmd_complete_s *)
+ (g_sdc_dev.msg_buffer + sizeof(*hdr));
+ uint8_t *status = (uint8_t *)cmd_complete + 1;
+
+ wlinfo("received CMD_COMPLETE from softdevice "
+ "(opcode: %d, status: 0x%x)\n",
+ cmd_complete->opcode, *status);
+ }
+ else
+ {
+ wlinfo("received HCI EVT from softdevice "
+ "(evt: %d, len: %zu)\n", hdr->evt, len);
+ }
+#endif
+
+ outbuf = bt_buf_alloc(BT_EVT, NULL, BLUETOOTH_H4_HDRLEN);
+ bt_buf_extend(outbuf, len);
+
+ memcpy(outbuf->data, g_sdc_dev.msg_buffer, len);
+
+ bt_hci_receive(outbuf);
+
+ check_again = true;
+ }
+
+ /* Same for ACL */
+
+ ret = sdc_hci_data_get(g_sdc_dev.msg_buffer);
+
+ if (ret == 0)
+ {
+ struct bt_hci_acl_hdr_s *hdr =
+ (struct bt_hci_acl_hdr_s *)g_sdc_dev.msg_buffer;
+
+ wlinfo("received HCI ACL from softdevice (handle: %d)\n",
+ hdr->handle);
+
+ len = sizeof(*hdr) + hdr->len;
+
+ outbuf = bt_buf_alloc(BT_ACL_IN, NULL, BLUETOOTH_H4_HDRLEN);
+ bt_buf_extend(outbuf, len);
+
+ memcpy(outbuf->data, g_sdc_dev.msg_buffer, len);
+
+ bt_hci_receive(outbuf);
+
+ check_again = true;
+ }
+ }
+}
+
+/****************************************************************************
+ * Name: swi_isr
+ ****************************************************************************/
+
+static int swi_isr(int irq, FAR void *context, FAR void *arg)
+{
+ work_queue(LPWORK, &g_sdc_dev.work, low_prio_worker, NULL, 0);
+
+ return 0;
+}
+
+/****************************************************************************
+ * Name: rng_handler
+ ****************************************************************************/
+
+static void rng_handler(void)
+{
+ sdc_RNG_IRQHandler();
+}
+
+/****************************************************************************
+ * Name: power_clock_isr
+ ****************************************************************************/
+
+static int power_clock_isr(int irq, FAR void *context, FAR void *arg)
+{
+ MPSL_IRQ_CLOCK_Handler();
+
+ return 0;
+}
+
+/****************************************************************************
+ * Name: rtc0_handler
+ ****************************************************************************/
+
+static void rtc0_handler(void)
+{
+ MPSL_IRQ_RTC0_Handler();
+}
+
+/****************************************************************************
+ * Name: timer0_handler
+ ****************************************************************************/
+
+static void timer0_handler(void)
+{
+ MPSL_IRQ_TIMER0_Handler();
+}
+
+/****************************************************************************
+ * Name: radio_handler
+ ****************************************************************************/
+
+static void radio_handler(void)
+{
+ MPSL_IRQ_RADIO_Handler();
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int nrf52_sdc_initialize(void)
+{
+ int ret;
+ int32_t required_memory;
+ sdc_cfg_t cfg;
+
+ /* Initialize device data */
+
+ memset(&g_sdc_dev, 0, sizeof(g_sdc_dev));
+ nxsem_init(&g_sdc_dev.exclsem, 0, 1);
+
+ /* Register interrupt handler for normal-priority events. SWI5 will be
+ * used by MPSL to delegate low-priority work
+ */
+
+ irq_attach(NRF52_IRQ_SWI5_EGU5, swi_isr, NULL);
+ irq_attach(NRF52_IRQ_POWER_CLOCK, power_clock_isr, NULL);
+
+ up_enable_irq(NRF52_IRQ_SWI5_EGU5);
+ up_enable_irq(NRF52_IRQ_POWER_CLOCK);
+
+ up_prioritize_irq(NRF52_IRQ_SWI5_EGU5, NVIC_SYSH_PRIORITY_DEFAULT);
+ up_prioritize_irq(NRF52_IRQ_POWER_CLOCK, NVIC_SYSH_PRIORITY_DEFAULT);
+
+ /* Use zero-latency interrupt for RNG as we're expected to not add any
+ * processing to the ISR
+ */
+
+ arm_ramvec_attach(NRF52_IRQ_RNG, rng_handler);
+ up_prioritize_irq(NRF52_IRQ_RNG, NVIC_SYSH_MAXNORMAL_PRIORITY);
+ up_enable_irq(NRF52_IRQ_RNG);
+
+ /* Register high-priority interrupts for specific peripherals */
+
+ arm_ramvec_attach(NRF52_IRQ_RTC0, rtc0_handler);
+ arm_ramvec_attach(NRF52_IRQ_TIMER0, timer0_handler);
+ arm_ramvec_attach(NRF52_IRQ_RADIO, radio_handler);
+
+ up_prioritize_irq(NRF52_IRQ_RTC0, MPSL_HIGH_IRQ_PRIORITY);
+ up_prioritize_irq(NRF52_IRQ_TIMER0, MPSL_HIGH_IRQ_PRIORITY);
+ up_prioritize_irq(NRF52_IRQ_RADIO, MPSL_HIGH_IRQ_PRIORITY);
+
+ up_enable_irq(NRF52_IRQ_RTC0);
+ up_enable_irq(NRF52_IRQ_TIMER0);
+ up_enable_irq(NRF52_IRQ_RADIO);
+
+ /* TODO: how do WFI again after high priority interrupt wakes MCU up? */
+
+ /* Initialize MPSL */
+
+ ret = mpsl_init(&g_clock_config, NRF52_IRQ_SWI5_EGU5 - NRF52_IRQ_EXTINT,
+ &mpsl_assert_handler);
+
+ if (ret < 0)
+ {
+ wlerr("mpsl init failed: %d\n", ret);
+ return ret;
+ }
+
+ /* Initialize SDC */
+
+ ret = sdc_init(&sdc_fault_handler);
+
+ if (ret < 0)
+ {
+ wlerr("mpsl init failed: %d\n", ret);
+ return ret;
+ }
+
+ /* Set some parameters */
+
+ cfg.master_count.count = SDC_MASTER_COUNT;
+ ret = sdc_cfg_set(SDC_DEFAULT_RESOURCE_CFG_TAG,
+ SDC_CFG_TYPE_MASTER_COUNT, &cfg);
+
+ if (ret < 0)
+ {
+ wlerr("Failed to set master role count: %d\n", ret);
+ return ret;
+ }
+
+ cfg.slave_count.count = CONFIG_NRF52_SDC_SLAVE_COUNT;
+ ret = sdc_cfg_set(SDC_DEFAULT_RESOURCE_CFG_TAG,
+ SDC_CFG_TYPE_SLAVE_COUNT, &cfg);
+
+ if (ret < 0)
+ {
+ wlerr("Failed to set slave role count: %d\n", ret);
+ return ret;
+ }
+
+ cfg.buffer_cfg.rx_packet_size = SDC_DEFAULT_RX_PACKET_SIZE;
+ cfg.buffer_cfg.tx_packet_size = SDC_DEFAULT_TX_PACKET_SIZE;
+ cfg.buffer_cfg.rx_packet_count = SDC_DEFAULT_RX_PACKET_COUNT;
+ cfg.buffer_cfg.tx_packet_count = SDC_DEFAULT_TX_PACKET_COUNT;
+
+ required_memory =
+ sdc_cfg_set(SDC_DEFAULT_RESOURCE_CFG_TAG,
+ SDC_CFG_TYPE_BUFFER_CFG, &cfg);
+
+ if (required_memory < 0)
+ {
+ wlerr("Failed to set packet size/count: %ld\n", required_memory);
+ return ret;
+ }
+
+ /* Verify we have enough memory for our configuration */
+
+ ASSERT(required_memory <= sizeof(g_sdc_dev.mempool));
+
+ /* Turn on specific features */
+
+#ifdef CONFIG_NRF52_SDC_ADVERTISING
+ ret = sdc_support_adv();
+
+ if (ret < 0)
+ {
+ wlerr("Could not enable advertising feature: %d\n", ret);
+ return ret;
+ }
+#endif
+
+#ifdef CONFIG_NRF52_SDC_SCANNING
+ ret = sdc_support_scan();
+
+ if (ret < 0)
+ {
+ wlerr("Could not enable scanning feature: %d\n", ret);
+ return ret;
+ }
+#endif
+
+#if SDC_MASTER_COUNT > 0
+ ret = sdc_support_master();
+
+ if (ret < 0)
+ {
+ wlerr("Could not enable master feature: %d\n", ret);
+ return ret;
+ }
+#endif
+
+#if CONFIG_NRF52_SDC_SLAVE_COUNT > 0
+ ret = sdc_support_slave();
+
+ if (ret < 0)
+ {
+ wlerr("Could not enable slave feature: %d\n", ret);
+ return ret;
+ }
+#endif
+
+#ifdef CONFIG_NRF52_SDC_DLE
+ ret = sdc_support_dle();
+
+ if (ret < 0)
+ {
+ wlerr("Could not enable DLE feature: %d\n", ret);
+ return ret;
+ }
+#endif
+
+#ifdef CONFIG_NRF52_SDC_LE_2M_PHY
+ ret = sdc_support_le_2m_phy();
+
+ if (ret < 0)
+ {
+ wlerr("Could not enable 2M PHY feature: %d\n", ret);
+ return ret;
+ }
+#endif
+
+#ifdef CONFIG_NRF52_SDC_LE_CODED_PHY
+ ret = sdc_support_le_coded_phy();
+
+ if (ret < 0)
+ {
+ wlerr("Could not enable Coded PHY feature: %d\n", ret);
+ return ret;
+ }
+#endif
+
+ /* Finally enable SoftDevice Controller */
+
+ ret = sdc_enable(on_hci, g_sdc_dev.mempool);
+
+ if (ret < 0)
+ {
+ wlerr("SoftDevice controller enable failed: %d\n", ret);
+ return ret;
+ }
+
+ /* Register network device */
+
+ ret = bt_netdev_register(&g_bt_driver);
+
+ return ret;
+}
diff --git a/boards/arm/nrf52/nrf52832-mdk/src/nrf52_bringup.c b/arch/arm/src/nrf52/nrf52_sdc.h
similarity index 59%
copy from boards/arm/nrf52/nrf52832-mdk/src/nrf52_bringup.c
copy to arch/arm/src/nrf52/nrf52_sdc.h
index 280824f..3399435 100644
--- a/boards/arm/nrf52/nrf52832-mdk/src/nrf52_bringup.c
+++ b/arch/arm/src/nrf52/nrf52_sdc.h
@@ -1,5 +1,5 @@
/****************************************************************************
- * boards/arm/nrf52/nrf52832-mdk/src/nrf52_bringup.c
+ * arch/arm/src/chip/nrf52_sdc.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -18,65 +18,48 @@
*
****************************************************************************/
+#ifndef __ARCH_ARM_SRC_NRF52_NRF52_SDC_H
+#define __ARCH_ARM_SRC_NRF52_NRF52_SDC_H
+
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
-#include <sys/types.h>
-#include <syslog.h>
-
-#ifdef CONFIG_NRF52_WDT
-# include "nrf52_wdt_lowerhalf.h"
-#endif
-
-#ifdef CONFIG_USERLED
-# include <nuttx/leds/userled.h>
-#endif
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
/****************************************************************************
- * Public Functions
+ * Public Types
****************************************************************************/
/****************************************************************************
- * Name: nrf52_bringup
- *
- * Description:
- * Perform architecture-specific initialization
- *
- * CONFIG_BOARD_LATE_INITIALIZE=y :
- * Called from board_late_initialize().
- *
- * CONFIG_BOARD_LATE_INITIALIZE=n && CONFIG_LIB_BOARDCTL=y :
- * Called from the NSH library
- *
+ * Public Data
****************************************************************************/
-int nrf52_bringup(void)
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C"
{
- int ret;
+#else
+#define EXTERN extern
+#endif
-#ifdef CONFIG_NRF52_WDT
- /* Start Watchdog timer */
+/****************************************************************************
+ * Inline Functions
+ ****************************************************************************/
- ret = nrf52_wdt_initialize(CONFIG_WATCHDOG_DEVPATH, 1, 1);
- if (ret < 0)
- {
- syslog(LOG_ERR, "ERROR: nrf52_wdt_initialize failed: %d\n", ret);
- }
-#endif
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
-#ifdef CONFIG_USERLED
- /* Register the LED driver */
+int nrf52_sdc_initialize(void);
- ret = userled_lower_initialize(CONFIG_EXAMPLES_LEDS_DEVPATH);
- if (ret < 0)
- {
- syslog(LOG_ERR, "ERROR: userled_lower_initialize() failed: %d\n", ret);
- }
+#undef EXTERN
+#ifdef __cplusplus
+}
#endif
- UNUSED(ret);
- return OK;
-}
+#endif /* __ARCH_ARM_SRC_NRF52_NRF52_SDC_H */
diff --git a/arch/arm/src/nrf52/sdc/README.md b/arch/arm/src/nrf52/sdc/README.md
new file mode 100644
index 0000000..0ab5f25
--- /dev/null
+++ b/arch/arm/src/nrf52/sdc/README.md
@@ -0,0 +1,2 @@
+This directory holds stub files for building Nordic SoftDevice Controller without having to pull
+NRFX and CMSIS just to have a few definitions.
diff --git a/arch/arm/src/nrf52/sdc/core_cm4.h b/arch/arm/src/nrf52/sdc/core_cm4.h
new file mode 100644
index 0000000..2c925c6
--- /dev/null
+++ b/arch/arm/src/nrf52/sdc/core_cm4.h
@@ -0,0 +1,41 @@
+/****************************************************************************
+ * arch/arm/src/chip/nrf52_sdc.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.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_NRF52_SDC_CORE_CM4_H__
+#define __ARCH_ARM_SRC_NRF52_SDC_CORE_CM4_H__
+
+/****************************************************************************
+ * Preprocessor Definitions
+ ****************************************************************************/
+
+/* These are the definitions needed from CMSIS */
+
+#ifdef __cplusplus
+# define __I volatile
+#else
+# define __I volatile const
+#endif
+#define __O volatile
+#define __IO volatile
+#define __IM volatile const
+#define __OM volatile
+#define __IOM volatile
+
+#endif /* __ARCH_ARM_SRC_NRF52_SDC_CORE_CM4_H__ */
diff --git a/arch/arm/src/nrf52/sdc/nrf.h b/arch/arm/src/nrf52/sdc/nrf.h
new file mode 100644
index 0000000..46eb32f
--- /dev/null
+++ b/arch/arm/src/nrf52/sdc/nrf.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+ * arch/arm/src/chip/nrf52_sdc.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.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_NRF52_SDC_NRF_H__
+#define __ARCH_ARM_SRC_NRF52_SDC_NRF_H__
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* This is the only definition we need from NRFX. We could simply do a
+ * typedef to an integer but we cannot ensure it will end up being the right
+ * size, so we replicate all values here.
+ */
+
+typedef enum
+{
+ Reset_IRQn = -15,
+ NonMaskableInt_IRQn = -14,
+ HardFault_IRQn = -13,
+ MemoryManagement_IRQn = -12,
+ BusFault_IRQn = -11,
+ UsageFault_IRQn = -10,
+ SVCall_IRQn = -5,
+ DebugMonitor_IRQn = -4,
+ PendSV_IRQn = -2,
+ SysTick_IRQn = -1,
+ POWER_CLOCK_IRQn = 0,
+ RADIO_IRQn = 1,
+ UARTE0_UART0_IRQn = 2,
+ SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn = 3,
+ SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQn = 4,
+ NFCT_IRQn = 5,
+ GPIOTE_IRQn = 6,
+ SAADC_IRQn = 7,
+ TIMER0_IRQn = 8,
+ TIMER1_IRQn = 9,
+ TIMER2_IRQn = 10,
+ RTC0_IRQn = 11,
+ TEMP_IRQn = 12,
+ RNG_IRQn = 13,
+ ECB_IRQn = 14,
+ CCM_AAR_IRQn = 15,
+ WDT_IRQn = 16,
+ RTC1_IRQn = 17,
+ QDEC_IRQn = 18,
+ COMP_LPCOMP_IRQn = 19,
+ SWI0_EGU0_IRQn = 20,
+ SWI1_EGU1_IRQn = 21,
+ SWI2_EGU2_IRQn = 22,
+ SWI3_EGU3_IRQn = 23,
+ SWI4_EGU4_IRQn = 24,
+ SWI5_EGU5_IRQn = 25,
+ TIMER3_IRQn = 26,
+ TIMER4_IRQn = 27,
+ PWM0_IRQn = 28,
+ PDM_IRQn = 29,
+ MWU_IRQn = 32,
+ PWM1_IRQn = 33,
+ PWM2_IRQn = 34,
+ SPIM2_SPIS2_SPI2_IRQn = 35,
+ RTC2_IRQn = 36,
+ I2S_IRQn = 37,
+ FPU_IRQn = 38
+} IRQn_Type;
+
+#endif /* __ARCH_ARM_SRC_NRF52_SDC_NRF_H__ */
diff --git a/boards/arm/nrf52/nrf52832-mdk/configs/sdc/defconfig b/boards/arm/nrf52/nrf52832-mdk/configs/sdc/defconfig
new file mode 100644
index 0000000..77ec310
--- /dev/null
+++ b/boards/arm/nrf52/nrf52832-mdk/configs/sdc/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_NET_ETHERNET is not set
+# CONFIG_NET_IPv4 is not set
+# CONFIG_NRF52_SDC_DLE is not set
+# CONFIG_NRF52_SDC_LE_2M_PHY is not set
+# CONFIG_NRF52_SDC_LE_CODED_PHY is not set
+# CONFIG_WIRELESS_BLUETOOTH_HOST is not set
+CONFIG_ARCH="arm"
+CONFIG_ARCH_BOARD="nrf52832-mdk"
+CONFIG_ARCH_BOARD_NRF52832_MDK=y
+CONFIG_ARCH_CHIP="nrf52"
+CONFIG_ARCH_CHIP_NRF52832=y
+CONFIG_ARCH_CHIP_NRF52=y
+CONFIG_ARCH_HIPRI_INTERRUPT=y
+CONFIG_ARCH_RAMVECTORS=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_ARCH_STDARG_H=y
+CONFIG_ARMV7M_SYSTICK=y
+CONFIG_BLUETOOTH_TXCMD_NMSGS=8
+CONFIG_BLUETOOTH_TXCMD_STACKSIZE=1024
+CONFIG_BLUETOOTH_TXCONN_NMSGS=8
+CONFIG_BLUETOOTH_TXCONN_STACKSIZE=1024
+CONFIG_BOARD_LOOPSPERMSEC=5500
+CONFIG_BUILTIN=y
+CONFIG_CLOCK_MONOTONIC=y
+CONFIG_FAT_LCNAMES=y
+CONFIG_FAT_LFN=y
+CONFIG_FS_FAT=y
+CONFIG_FS_PROCFS=y
+CONFIG_IDLETHREAD_STACKSIZE=2048
+CONFIG_MAX_TASKS=16
+CONFIG_MM_REGIONS=2
+CONFIG_NET=y
+CONFIG_NETDEV_LATEINIT=y
+CONFIG_NET_BLUETOOTH=y
+CONFIG_NET_BLUETOOTH_BACKLOG=0
+CONFIG_NFILE_DESCRIPTORS=8
+CONFIG_NIMBLE=y
+CONFIG_NIMBLE_REF="5fbb6660a433217b8eaf1b95de410379f868616c"
+CONFIG_NRF52_DCDC=y
+CONFIG_NRF52_HFCLK_XTAL=y
+CONFIG_NRF52_RTC1=y
+CONFIG_NRF52_SOFTDEVICE_CONTROLLER=y
+CONFIG_NRF52_SYSTIMER_RTC=y
+CONFIG_NRF52_UART0=y
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_LINELEN=64
+CONFIG_NSH_READLINE=y
+CONFIG_PREALLOC_MQ_MSGS=16
+CONFIG_PREALLOC_TIMERS=4
+CONFIG_PTHREAD_MUTEX_TYPES=y
+CONFIG_RAM_SIZE=65535
+CONFIG_RAM_START=0x20000000
+CONFIG_RAW_BINARY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_TICKLESS_LIMIT_MAX_SLEEP=y
+CONFIG_SCHED_WAITPID=y
+CONFIG_SDCLONE_DISABLE=y
+CONFIG_SIG_DEFAULT=y
+CONFIG_SIG_EVTHREAD=y
+CONFIG_SIG_SIGALRM_ACTION=y
+CONFIG_SIG_SIGUSR1_ACTION=y
+CONFIG_SIG_SIGUSR2_ACTION=y
+CONFIG_START_DAY=26
+CONFIG_START_MONTH=3
+CONFIG_SYMTAB_ORDEREDBYNAME=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_TIMER=y
+CONFIG_UART0_SERIAL_CONSOLE=y
+CONFIG_USEC_PER_TICK=10000
+CONFIG_USER_ENTRYPOINT="nsh_main"
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_BLUETOOTH=y
diff --git a/boards/arm/nrf52/nrf52832-mdk/src/nrf52_bringup.c b/boards/arm/nrf52/nrf52832-mdk/src/nrf52_bringup.c
index 280824f..1421ebb 100644
--- a/boards/arm/nrf52/nrf52832-mdk/src/nrf52_bringup.c
+++ b/boards/arm/nrf52/nrf52832-mdk/src/nrf52_bringup.c
@@ -27,6 +27,10 @@
#include <sys/types.h>
#include <syslog.h>
+#ifdef CONFIG_FS_PROCFS
+#include <sys/mount.h>
+#endif
+
#ifdef CONFIG_NRF52_WDT
# include "nrf52_wdt_lowerhalf.h"
#endif
@@ -35,6 +39,10 @@
# include <nuttx/leds/userled.h>
#endif
+#ifdef CONFIG_NRF52_SOFTDEVICE_CONTROLLER
+#include "nrf52_sdc.h"
+#endif
+
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -57,6 +65,10 @@ int nrf52_bringup(void)
{
int ret;
+#ifdef CONFIG_FS_PROCFS
+ mount(NULL, "/proc", "procfs", 0, NULL);
+#endif
+
#ifdef CONFIG_NRF52_WDT
/* Start Watchdog timer */
@@ -77,6 +89,15 @@ int nrf52_bringup(void)
}
#endif
+#ifdef CONFIG_NRF52_SOFTDEVICE_CONTROLLER
+ ret = nrf52_sdc_initialize();
+
+ if (ret < 0)
+ {
+ syslog(LOG_ERR, "ERROR: nrf52_sdc_initialize() failed: %d\n", ret);
+ }
+#endif
+
UNUSED(ret);
return OK;
}
diff --git a/wireless/bluetooth/bt_buf.c b/wireless/bluetooth/bt_buf.c
index f39b2d9..26cdc83 100644
--- a/wireless/bluetooth/bt_buf.c
+++ b/wireless/bluetooth/bt_buf.c
@@ -396,6 +396,8 @@ void bt_buf_release(FAR struct bt_buf_s *buf)
wlinfo("buf %p ref %u type %d\n", buf, buf->ref, buf->type);
+ DEBUGASSERT(buf->ref > 0);
+
if (--buf->ref > 0)
{
wlinfo("Remaining references: %d\n", buf->ref);