nRF52: add support for building SoftDevice BLE controller

This commit is contained in:
Matias N 2021-01-24 14:19:59 -03:00 committed by Brennan Ashton
parent 74e7e2b5b2
commit 45b392be7e
12 changed files with 1040 additions and 4 deletions

4
arch/arm/src/nrf52/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
CMSIS_5*
sdk-nrfxlib*
nrfx*
*.tar.gz

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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 <nuttx/config.h>
/****************************************************************************
* 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 */

View File

@ -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.

View File

@ -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__ */

View File

@ -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__ */

View File

@ -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

View File

@ -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;
}

View File

@ -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);