From 45b392be7e67a7d330678c20b716e403bd107cc4 Mon Sep 17 00:00:00 2001 From: Matias N Date: Sun, 24 Jan 2021 14:19:59 -0300 Subject: [PATCH] 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 ++++++++++++++++++ arch/arm/src/nrf52/nrf52_sdc.h | 65 ++ 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 +++ .../nrf52/nrf52832-mdk/configs/sdc/defconfig | 81 +++ .../nrf52/nrf52832-mdk/src/nrf52_bringup.c | 21 + wireless/bluetooth/bt_buf.c | 2 + 12 files changed, 1040 insertions(+), 4 deletions(-) create mode 100644 arch/arm/src/nrf52/.gitignore create mode 100644 arch/arm/src/nrf52/nrf52_sdc.c create mode 100644 arch/arm/src/nrf52/nrf52_sdc.h create mode 100644 arch/arm/src/nrf52/sdc/README.md create mode 100644 arch/arm/src/nrf52/sdc/core_cm4.h create mode 100644 arch/arm/src/nrf52/sdc/nrf.h create mode 100644 boards/arm/nrf52/nrf52832-mdk/configs/sdc/defconfig diff --git a/arch/arm/src/nrf52/.gitignore b/arch/arm/src/nrf52/.gitignore new file mode 100644 index 0000000000..8f9b697c03 --- /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 05142449bc..f7c32b132e 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 9409876370..de8eccb18a 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 9f7b283fcb..f7b82b839b 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 0000000000..8c23213493 --- /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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "arm_internal.h" +#include "ram_vectors.h" +#include "arm_arch.h" + +#include +#include +#include + +/**************************************************************************** + * 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/arch/arm/src/nrf52/nrf52_sdc.h b/arch/arm/src/nrf52/nrf52_sdc.h new file mode 100644 index 0000000000..3399435619 --- /dev/null +++ b/arch/arm/src/nrf52/nrf52_sdc.h @@ -0,0 +1,65 @@ +/**************************************************************************** + * 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 + * 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_SDC_H +#define __ARCH_ARM_SRC_NRF52_NRF52_SDC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +int nrf52_sdc_initialize(void); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#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 0000000000..0ab5f253fe --- /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 0000000000..2c925c6bfb --- /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 0000000000..46eb32f126 --- /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 0000000000..77ec3105d7 --- /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 280824f2f3..1421ebb788 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 #include +#ifdef CONFIG_FS_PROCFS +#include +#endif + #ifdef CONFIG_NRF52_WDT # include "nrf52_wdt_lowerhalf.h" #endif @@ -35,6 +39,10 @@ # include #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 f39b2d9f01..26cdc83dc1 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);