arch/nrf53: add SoftDevice support

This commit is contained in:
raiden00pl 2023-03-05 13:24:18 +01:00 committed by Alan Carvalho de Assis
parent 5fd321e54d
commit 9dc8f27dda
9 changed files with 1189 additions and 2 deletions

View File

@ -68,7 +68,7 @@ config ALLOW_MIT_COMPONENTS
config ALLOW_BSDNORDIC_COMPONENTS
bool "Use components that have 5-Clause Nordic licenses"
depends on ARCH_CHIP_NRF52
depends on ARCH_CHIP_NRF52 || ARCH_CHIP_NRF53
default n
---help---
When this option is enabled the project will allow the use

2
arch/arm/src/nrf53/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
sdk-nrfxlib*
*.tar.gz

View File

@ -163,3 +163,90 @@ config NRF53_SYSTIMER_SYSTICK
endchoice
endmenu # System Timer
menuconfig NRF53_SOFTDEVICE_CONTROLLER
bool "SoftDevice Controller"
depends on ALLOW_BSDNORDIC_COMPONENTS
depends on NRF53_NETCORE
select ARMV8M_USEBASEPRI
select ARCH_RAMVECTORS
select ARCH_IRQPRIO
select CRYPTO
select CRYPTO_RANDOM_POOL
select NRF53_USE_LFCLK
---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 and RADIO so
these will be unavailable for direct use by user.
It also makes use of DPPI channel range 0-13.
if NRF53_SOFTDEVICE_CONTROLLER
config NRF53_SDC_CLOCK_ACCURACY
int "Clock Accuracy [PPM]"
default 250
---help---
Select the clock accuracy depending on the chosen low-frequency clock
source
config NRF53_SDC_PERIPHERAL_COUNT
int "Number of peripheral roles to support (also central)"
default 1
---help---
This controls how many peripheral connections will be supported. It also
determines the number of central roles from the following:
CENTRAL_ROLES = CONFIG_BLUETOOTH_MAX_CONN - NRF53_SDC_PERIPHERAL_COUNT
So by choosing these two variables you can control both capabilities.
config NRF53_SDC_ADVERTISING
bool "Support advertising"
default y
config NRF53_SDC_SCANNING
bool "Support scanning"
default y
if NRF53_SDC_SCANNING
config NRF53_SDC_SCAN_BUFFER_COUNT
int "Scanning buffer count"
default 3
---help---
The minimum allowed number of buffers is 2.
endif
config NRF53_SDC_LE_2M_PHY
bool "Support LE 2M PHY"
default y
config NRF53_SDC_LE_CODED_PHY
bool "Support LE Coded PHY"
default n if ARCH_CHIP_NRF53832
default y if ARCH_CHIP_NRF53840
depends on NRF53_SDC_MULTIROLE
config NRF53_SDC_DLE
bool "Support Data Length Extension (DLE)"
default y
config NRF53_BLE_TTY_NAME
string "BLE TTY device name"
default "/dev/ttyHCI0"
depends on UART_BTH4
config NRF53_SDC_FICR_STATIC_ADDR
bool "Configure factory generated static random address"
default n
config NRF53_SDC_PUB_ADDR
hex "Configure BT public address"
default 0x0000000000
endif

View File

@ -40,4 +40,54 @@ endif
ifeq ($(CONFIG_NRF53_APPCORE),y)
CHIP_CSRCS += nrf53_cpunet.c
endif
endif
ifeq ($(CONFIG_NRF53_SOFTDEVICE_CONTROLLER),y)
NRFXLIB_UNPACK := sdk-nrfxlib
NRFXLIB_VER := 2.3.0
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)
ifeq ($(wildcard chip/$(NRFXLIB_UNPACK)/.git),)
context:: chip/$(NRFXLIB_UNPACK)
distclean::
$(call DELFILE, chip/$(NRFXLIB_TGZ))
$(call DELDIR, chip/$(NRFXLIB_UNPACK))
endif
CHIP_CSRCS += nrf53_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)
CFLAGS += -DNRF53_SERIES
LIB_VARIANT=soft-float
EXTRA_LIBPATHS += \
-L $(NRFXLIB_DIR)$(DELIM)mpsl$(DELIM)lib$(DELIM)cortex-m33+nodsp$(DELIM)$(LIB_VARIANT) \
-L $(NRFXLIB_DIR)$(DELIM)softdevice_controller$(DELIM)lib$(DELIM)cortex-m33+nodsp$(DELIM)$(LIB_VARIANT)
EXTRA_LIBS += -lmpsl
EXTRA_LIBS += -lsoftdevice_controller_multirole
endif

View File

@ -0,0 +1,921 @@
/****************************************************************************
* arch/arm/src/nrf53/nrf53_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 <assert.h>
#include <debug.h>
#include <stdlib.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 <nuttx/mutex.h>
#include <arch/armv8-m/nvicpri.h>
#include <arch/nrf53/nrf5340_irq_cpunet.h>
#include <nuttx/wqueue.h>
#if defined(CONFIG_UART_BTH4)
# include <nuttx/serial/uart_bth4.h>
#endif
#include "arm_internal.h"
#include "ram_vectors.h"
#include "hardware/nrf53_ficr.h"
#include <mpsl.h>
#include <sdc.h>
#include <sdc_hci.h>
#include <sdc_soc.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifndef CONFIG_NRF53_NETCORE
# error Only for the NET core
#endif
/* Connections configuration ************************************************/
#if defined(CONFIG_SDC_PERIPHERAL_COUNT) && \
CONFIG_SDC_PERIPHERAL_COUNT > CONFIG_BLUETOOTH_MAX_CONN
# error "Cannot support more BLE peripheral roles than connections"
#endif
#define SDC_CENTRAL_COUNT (CONFIG_BLUETOOTH_MAX_CONN - \
CONFIG_NRF53_SDC_PERIPHERAL_COUNT)
/* Memory configuration *****************************************************/
#define CENTRAL_MEM_SIZE (SDC_MEM_PER_CENTRAL_LINK( \
SDC_DEFAULT_TX_PACKET_SIZE, \
SDC_DEFAULT_RX_PACKET_SIZE, \
SDC_DEFAULT_TX_PACKET_COUNT, \
SDC_DEFAULT_RX_PACKET_COUNT) + \
SDC_MEM_CENTRAL_LINKS_SHARED)
#define PERIPHERAL_MEM_SIZE (SDC_MEM_PER_PERIPHERAL_LINK( \
SDC_DEFAULT_TX_PACKET_SIZE, \
SDC_DEFAULT_RX_PACKET_SIZE, \
SDC_DEFAULT_TX_PACKET_COUNT, \
SDC_DEFAULT_RX_PACKET_COUNT) + \
SDC_MEM_PERIPHERAL_LINKS_SHARED)
/* Scan supported if central present */
#ifdef CONFIG_NRF53_SDC_SCANNING
# if SDC_CENTRAL_COUNT == 0
# error Scanning enabled but central count is 0
# endif
#endif
/* Advertising supported if peripheral present */
#ifdef CONFIG_NRF53_SDC_ADVERTISING
# if CONFIG_NRF53_SDC_PERIPHERAL_COUNT == 0
# error Advertising enabled but peripheral count is 0
# endif
#endif
/* Observer configuration */
#ifdef CONFIG_NRF53_SDC_SCANNING
# if CONFIG_NRF53_SDC_SCAN_BUFFER_COUNT < 2
# error The minimum allowed number of scan buffers is 2.
# endif
# define SCAN_MEM_SIZE (SDC_MEM_SCAN_BUFFER(CONFIG_NRF53_SDC_SCAN_BUFFER_COUNT))
# define SCAN_MEM_COUNT (CONFIG_NRF53_SDC_SCAN_BUFFER_COUNT)
#else
# define SCAN_MEM_SIZE (0)
# define SCAN_MEM_COUNT (0)
#endif
/* Broadcaster configuration */
#ifdef CONFIG_NRF53_SDC_ADVERTISING
/* Advertising extensions not supported for now */
# define ADV_SET_COUNT (1)
# define ADV_BUF_SIZE (SDC_DEFAULT_ADV_BUF_SIZE)
# define ADV_MEM_SIZE (ADV_SET_COUNT * SDC_MEM_PER_ADV_SET(ADV_BUF_SIZE))
#else
# define ADV_SET_COUNT (0)
# define ADV_BUF_SIZE (0)
# define ADV_MEM_SIZE (0)
#endif
/* Periodic advertising not supported */
#define PERIODIC_ADV_MEM_SIZE (0)
#define PERIODIC_ADV_RESP_MEM_SIZE (0)
#define PERIODIC_ADV_LIST_MEM_SIZE (0)
#define PERIODIC_SYNC_MEM_SIZE (0)
/* Memory poll size */
#define MEMPOOL_SIZE ((CONFIG_NRF53_SDC_PERIPHERAL_COUNT * PERIPHERAL_MEM_SIZE) + \
(SDC_CENTRAL_COUNT * CENTRAL_MEM_SIZE)+ \
SCAN_MEM_SIZE+ \
ADV_MEM_SIZE + \
PERIODIC_ADV_MEM_SIZE + \
PERIODIC_ADV_RESP_MEM_SIZE + \
PERIODIC_ADV_LIST_MEM_SIZE +\
PERIODIC_SYNC_MEM_SIZE)
/* BT address configuration *************************************************/
#if (CONFIG_NRF53_SDC_PUB_ADDR > 0) || \
defined(CONFIG_NRF53_SDC_FICR_STATIC_ADDR)
# define HAVE_BTADDR_CONFIGURE
#endif
/* Calls to MPSL ************************************************************/
#define MPSL_IRQ_CLOCK_HANDLER MPSL_IRQ_CLOCK_Handler
#define MPSL_IRQ_RTC0_HANDLER MPSL_IRQ_RTC0_Handler
#define MPSL_IRQ_TIMER0_HANDLER MPSL_IRQ_TIMER0_Handler
#define MPSL_IRQ_RADIO_HANDLER MPSL_IRQ_RADIO_Handler
/****************************************************************************
* Private Types
****************************************************************************/
struct nrf53_sdc_dev_s
{
uint8_t *mempool; /* Must be 8 bytes aligned */
uint8_t msg_buffer[HCI_MSG_BUFFER_MAX_SIZE];
mutex_t lock;
struct work_s work;
};
begin_packed_struct struct sdc_hci_cmd_vs_zephyr_write_bd_addr_s
{
uint8_t bd_addr[6];
} end_packed_struct;
begin_packed_struct struct sdc_hci_cmd_le_set_random_address_s
{
uint8_t bd_addr[6];
} end_packed_struct;
/****************************************************************************
* External Function Prototypes
****************************************************************************/
uint8_t sdc_hci_cmd_vs_zephyr_write_bd_addr(
const struct sdc_hci_cmd_vs_zephyr_write_bd_addr_s *p_params);
uint8_t sdc_hci_cmd_le_set_random_address(
const struct sdc_hci_cmd_le_set_random_address_s *p_params);
/****************************************************************************
* 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(struct bt_driver_s *btdev);
static int bt_hci_send(struct bt_driver_s *btdev,
enum bt_buf_type_e type,
void *data, size_t len);
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, void *context, void *arg);
static int power_clock_isr(int irq, void *context, void *arg);
static void rtc0_handler(void);
static void timer0_handler(void);
static void radio_handler(void);
/****************************************************************************
* Private Data
****************************************************************************/
static 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_NRF53_SDC_CLOCK_ACCURACY,
.skip_wait_lfclk_started = false
};
/* Must be 8 bytes aligned */
static uint8_t g_sdc_mempool[MEMPOOL_SIZE] aligned_data(8);
static struct nrf53_sdc_dev_s g_sdc_dev =
{
.mempool = g_sdc_mempool,
.lock = NXMUTEX_INITIALIZER,
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: bt_open
****************************************************************************/
static int bt_open(struct bt_driver_s *btdev)
{
return 0;
}
/****************************************************************************
* Name: bt_open
****************************************************************************/
static int bt_hci_send(struct bt_driver_s *btdev,
enum bt_buf_type_e type,
void *data, size_t len)
{
int ret = -EIO;
/* Pass HCI CMD/DATA to SDC */
if (type == BT_CMD || type == BT_ACL_OUT)
{
wlinfo("passing type %s to softdevice\n",
(type == BT_CMD) ? "CMD" : "ACL");
/* Ensure non-concurrent access to SDC operations */
nxmutex_lock(&g_sdc_dev.lock);
if (type == BT_CMD)
{
ret = sdc_hci_cmd_put(data);
}
else
{
ret = sdc_hci_data_put(data);
}
nxmutex_unlock(&g_sdc_dev.lock);
if (ret >= 0)
{
ret = len;
work_queue(LPWORK, &g_sdc_dev.work, on_hci_worker, NULL, 0);
}
}
return ret;
}
/****************************************************************************
* Name: sdc_fault_handler
****************************************************************************/
static void sdc_fault_handler(const char *file, const uint32_t line)
{
_assert(file, line, "SoftDevice Controller Fault");
}
/****************************************************************************
* Name: mpsl_assert_handler
****************************************************************************/
static void mpsl_assert_handler(const char *const file, const uint32_t line)
{
_assert(file, line, "MPSL assertion failed");
}
/****************************************************************************
* 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.
*/
nxmutex_lock(&g_sdc_dev.lock);
mpsl_low_priority_process();
nxmutex_unlock(&g_sdc_dev.lock);
}
/****************************************************************************
* 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
*/
nxmutex_lock(&g_sdc_dev.lock);
on_hci();
nxmutex_unlock(&g_sdc_dev.lock);
}
/****************************************************************************
* Name: on_hci
****************************************************************************/
static void on_hci(void)
{
sdc_hci_msg_type_t type;
bool check_again;
size_t len;
int ret;
do
{
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_get(g_sdc_dev.msg_buffer, &type);
if (ret == 0)
{
if (type == SDC_HCI_MSG_TYPE_EVT)
{
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 + 3;
wlinfo("received CMD_COMPLETE from softdevice "
"(opcode: 0x%x, status: 0x%x)\n",
cmd_complete->opcode, *status);
}
else
{
wlinfo("received HCI EVT from softdevice "
"(evt: %d, len: %zu)\n", hdr->evt, len);
}
#endif
bt_netdev_receive(&g_bt_driver, BT_EVT,
g_sdc_dev.msg_buffer, len);
check_again = true;
}
if (type == SDC_HCI_MSG_TYPE_DATA)
{
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;
bt_netdev_receive(&g_bt_driver, BT_ACL_IN,
g_sdc_dev.msg_buffer, len);
check_again = true;
}
}
}
while (check_again);
}
/****************************************************************************
* Name: swi_isr
****************************************************************************/
static int swi_isr(int irq, void *context, void *arg)
{
work_queue(LPWORK, &g_sdc_dev.work, low_prio_worker, NULL, 0);
return 0;
}
/****************************************************************************
* Name: power_clock_isr
****************************************************************************/
static int power_clock_isr(int irq, void *context, 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();
}
#ifdef HAVE_BTADDR_CONFIGURE
/****************************************************************************
* Name: nrf53_sdc_btaddr_configure
****************************************************************************/
static int nrf53_sdc_btaddr_configure(void)
{
#if CONFIG_NRF53_SDC_PUB_ADDR > 0
struct sdc_hci_cmd_vs_zephyr_write_bd_addr_s pub_addr;
#endif
#ifdef CONFIG_NRF53_SDC_FICR_STATIC_ADDR
struct sdc_hci_cmd_le_set_random_address_s rand_addr;
uint32_t addr[2];
uint32_t addrtype = 0;
#endif
int ret = OK;
#ifdef CONFIG_NRF53_SDC_FICR_STATIC_ADDR
/* Get device address type */
addrtype = getreg32(NRF53_FICR_DEVICEADDRTYPE);
/* Get device addr from FICR */
addr[0] = getreg32(NRF53_FICR_DEVICEADDR0);
addr[1] = getreg32(NRF53_FICR_DEVICEADDR1);
if ((addrtype & 0x01) == FICR_DEVICEADDRTYPE_RANDOM)
{
/* Configure static random address */
memcpy(&rand_addr.bd_addr[0], &addr[0], 4);
memcpy(&rand_addr.bd_addr[4], &addr[1], 2);
/* The two most significant bits of the address shall be set */
rand_addr.bd_addr[4] |= 0x0c;
ret = sdc_hci_cmd_le_set_random_address(&rand_addr);
if (ret < 0)
{
wlerr("sdc_hci_cmd_le_set_random_address failed: %d\n", ret);
goto errout;
}
}
else
{
wlerr("Static random address not available\n");
ret = -EINVAL;
goto errout;
}
#endif
#if CONFIG_NRF53_SDC_PUB_ADDR > 0
/* Configure public address if available */
pub_addr.bd_addr[0] = (CONFIG_NRF53_SDC_PUB_ADDR >> (8 * 5)) & 0xff;
pub_addr.bd_addr[1] = (CONFIG_NRF53_SDC_PUB_ADDR >> (8 * 4)) & 0xff;
pub_addr.bd_addr[2] = (CONFIG_NRF53_SDC_PUB_ADDR >> (8 * 3)) & 0xff;
pub_addr.bd_addr[3] = (CONFIG_NRF53_SDC_PUB_ADDR >> (8 * 2)) & 0xff;
pub_addr.bd_addr[4] = (CONFIG_NRF53_SDC_PUB_ADDR >> (8 * 1)) & 0xff;
pub_addr.bd_addr[5] = (CONFIG_NRF53_SDC_PUB_ADDR >> (8 * 0)) & 0xff;
ret = sdc_hci_cmd_vs_zephyr_write_bd_addr(&pub_addr);
if (ret < 0)
{
wlerr("sdc_hci_cmd_vs_zephyr_write_bd_addr failed: %d\n", ret);
goto errout;
}
#endif
errout:
return ret;
}
#endif
/****************************************************************************
* Name: nrf53_rand_prio_low_get
****************************************************************************/
static uint8_t nrf53_rand_prio_low_get(uint8_t *p_buff, uint8_t length)
{
arc4random_buf(p_buff, length);
return length;
}
/****************************************************************************
* Name: nrf53_rand_prio_high_get
****************************************************************************/
static uint8_t nrf53_rand_prio_high_get(uint8_t *p_buff, uint8_t length)
{
arc4random_buf(p_buff, length);
return length;
}
/****************************************************************************
* Name: nrf53_rand_poll
****************************************************************************/
static void nrf53_rand_poll(uint8_t *p_buff, uint8_t length)
{
arc4random_buf(p_buff, length);
}
/****************************************************************************
* Name: nrf53_configure_features
****************************************************************************/
static int nrf53_configure_features(void)
{
int ret = OK;
/* Turn on specific features */
#ifdef CONFIG_NRF53_SDC_ADVERTISING
ret = sdc_support_adv();
if (ret < 0)
{
wlerr("Could not enable advertising feature: %d\n", ret);
goto errout;
}
#endif
#ifdef CONFIG_NRF53_SDC_SCANNING
ret = sdc_support_scan();
if (ret < 0)
{
wlerr("Could not enable scanning feature: %d\n", ret);
goto errout;
}
#endif
#if SDC_CENTRAL_COUNT > 0
ret = sdc_support_central();
if (ret < 0)
{
wlerr("Could not enable central feature: %d\n", ret);
goto errout;
}
#endif
#if CONFIG_NRF53_SDC_PERIPHERAL_COUNT > 0
ret = sdc_support_peripheral();
if (ret < 0)
{
wlerr("Could not enable peripheral feature: %d\n", ret);
goto errout;
}
#endif
#ifdef CONFIG_NRF53_SDC_DLE
# if SDC_CENTRAL_COUNT > 0
ret = sdc_support_dle_central();
if (ret < 0)
{
wlerr("Could not enable DLE central feature: %d\n", ret);
goto errout;
}
# endif
# if CONFIG_NRF53_SDC_PERIPHERAL_COUNT > 0
ret = sdc_support_dle_peripheral();
if (ret < 0)
{
wlerr("Could not enable DLE peripheral feature: %d\n", ret);
goto errout;
}
# endif
#endif
#ifdef CONFIG_NRF53_SDC_LE_2M_PHY
ret = sdc_support_le_2m_phy();
if (ret < 0)
{
wlerr("Could not enable 2M PHY feature: %d\n", ret);
goto errout;
}
#endif
#ifdef CONFIG_NRF53_SDC_LE_CODED_PHY
ret = sdc_support_le_coded_phy();
if (ret < 0)
{
wlerr("Could not enable Coded PHY feature: %d\n", ret);
goto errout;
}
#endif
#ifdef HAVE_BTADDR_CONFIGURE
/* Configure BT address */
ret = nrf53_sdc_btaddr_configure();
if (ret < 0)
{
wlerr("Could not configure BT addr: %d\n", ret);
goto errout;
}
#endif
errout:
return ret;
}
/****************************************************************************
* Name: nrf53_configure_memory
****************************************************************************/
static int nrf53_configure_memory(void)
{
int32_t required_memory = 0;
int ret = OK;
sdc_cfg_t cfg;
/* Configure SoftDevice memory.
* NOTE: sdc_cfg_set() API must be set before sdc_enable() and
* sdc_support_*() calls.
*/
/* Configure scanner memory */
cfg.scan_buffer_cfg.count = SCAN_MEM_COUNT;
ret = sdc_cfg_set(SDC_DEFAULT_RESOURCE_CFG_TAG,
SDC_CFG_TYPE_SCAN_BUFFER_CFG, &cfg);
if (ret < 0)
{
wlerr("Failed to set scan count: %d\n", ret);
goto errout;
}
/* Configure advertisers memory */
cfg.adv_count.count = ADV_SET_COUNT;
ret = sdc_cfg_set(SDC_DEFAULT_RESOURCE_CFG_TAG,
SDC_CFG_TYPE_ADV_COUNT, &cfg);
if (ret < 0)
{
wlerr("Failed to set advertising count: %d\n", ret);
goto errout;
}
cfg.adv_buffer_cfg.max_adv_data = ADV_BUF_SIZE;
ret = sdc_cfg_set(SDC_DEFAULT_RESOURCE_CFG_TAG,
SDC_CFG_TYPE_ADV_BUFFER_CFG, &cfg);
if (ret < 0)
{
wlerr("Failed to set advertising buffer: %d\n", ret);
goto errout;
}
/* Configure central connections memory */
cfg.central_count.count = SDC_CENTRAL_COUNT;
ret = sdc_cfg_set(SDC_DEFAULT_RESOURCE_CFG_TAG,
SDC_CFG_TYPE_CENTRAL_COUNT, &cfg);
if (ret < 0)
{
wlerr("Failed to set central role count: %d\n", ret);
goto errout;
}
/* Configure peripheral connections memory */
cfg.peripheral_count.count = CONFIG_NRF53_SDC_PERIPHERAL_COUNT;
ret = sdc_cfg_set(SDC_DEFAULT_RESOURCE_CFG_TAG,
SDC_CFG_TYPE_PERIPHERAL_COUNT, &cfg);
if (ret < 0)
{
wlerr("Failed to set peripheral role count: %d\n", ret);
goto errout;
}
/* Configure buffers memory and get the final required memory */
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);
goto errout;
}
/* Verify we have enough memory for our configuration */
ASSERT(required_memory <= MEMPOOL_SIZE);
errout:
return ret;
}
/****************************************************************************
* Name: nrf53_configure_rand
****************************************************************************/
static int nrf53_configure_rand(void)
{
sdc_rand_source_t rand_func;
int ret = OK;
/* REVISIT: should we feed entropy poll with some data,
* or leave it to be handled by user ?
*/
/* Enable rand source */
rand_func.rand_prio_low_get = nrf53_rand_prio_low_get;
rand_func.rand_prio_high_get = nrf53_rand_prio_high_get;
rand_func.rand_poll = nrf53_rand_poll;
ret = sdc_rand_source_register(&rand_func);
if (ret < 0)
{
wlerr("sdc_rand_source_register failed %d\n", ret);
goto errout;
}
errout:
return ret;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: nrf53_sdc_initialize
****************************************************************************/
int nrf53_sdc_initialize(void)
{
int ret = OK;
/* Register interrupt handler for normal-priority events. SWI3 will be
* used by MPSL to delegate low-priority work
*/
irq_attach(NRF53_IRQ_SWI3, swi_isr, NULL);
irq_attach(NRF53_IRQ_POWER_CLOCK, power_clock_isr, NULL);
up_enable_irq(NRF53_IRQ_SWI3);
up_enable_irq(NRF53_IRQ_POWER_CLOCK);
up_prioritize_irq(NRF53_IRQ_SWI3, NVIC_SYSH_PRIORITY_DEFAULT);
up_prioritize_irq(NRF53_IRQ_POWER_CLOCK, NVIC_SYSH_PRIORITY_DEFAULT);
/* Configure SoftDevice random sources */
ret = nrf53_configure_rand();
if (ret < 0)
{
wlerr("nrf53_configure_rand failed: %d\n", ret);
return ret;
}
/* Register high-priority interrupts for specific peripherals */
arm_ramvec_attach(NRF53_IRQ_RTC0, rtc0_handler);
arm_ramvec_attach(NRF53_IRQ_TIMER0, timer0_handler);
arm_ramvec_attach(NRF53_IRQ_RADIO, radio_handler);
up_prioritize_irq(NRF53_IRQ_RTC0, MPSL_HIGH_IRQ_PRIORITY);
up_prioritize_irq(NRF53_IRQ_TIMER0, MPSL_HIGH_IRQ_PRIORITY);
up_prioritize_irq(NRF53_IRQ_RADIO, MPSL_HIGH_IRQ_PRIORITY);
up_enable_irq(NRF53_IRQ_RTC0);
up_enable_irq(NRF53_IRQ_TIMER0);
up_enable_irq(NRF53_IRQ_RADIO);
/* TODO: how do WFI again after high priority interrupt wakes MCU up? */
/* Initialize MPSL */
ret = mpsl_init(&g_clock_config, NRF53_IRQ_SWI3 - NRF53_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("sdc_init failed: %d\n", ret);
return ret;
}
/* Configure SoftDevice features */
ret = nrf53_configure_features();
if (ret < 0)
{
wlerr("nrf53_configure_features failed: %d\n", ret);
return ret;
}
/* Configure SoftDevice memory */
ret = nrf53_configure_memory();
if (ret < 0)
{
wlerr("nrf53_configure_memory failed: %d\n", ret);
return ret;
}
/* Finally enable SoftDevice Controller */
ret = sdc_enable(on_hci, g_sdc_dev.mempool);
if (ret < 0)
{
wlerr("sdc_enable failed: %d\n", ret);
return ret;
}
#ifdef CONFIG_UART_BTH4
/* Register UART BT H4 device */
ret = uart_bth4_register(CONFIG_NRF53_BLE_TTY_NAME, &g_bt_driver);
if (ret < 0)
{
wlerr("bt_bth4_register error: %d\n", ret);
return ret;
}
#elif defined(CONFIG_NET_BLUETOOTH)
/* Register network device */
ret = bt_netdev_register(&g_bt_driver);
if (ret < 0)
{
wlerr("bt_netdev_register error: %d\n", ret);
return ret;
}
#else
# error
#endif
return ret;
}

View File

@ -0,0 +1,65 @@
/****************************************************************************
* arch/arm/src/nrf53/nrf53_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_NRF53_NRF53_SDC_H
#define __ARCH_ARM_SRC_NRF53_NRF53_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 nrf53_sdc_initialize(void);
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* __ARCH_ARM_SRC_NRF53_NRF53_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,30 @@
/****************************************************************************
* arch/arm/src/nrf53/sdc/nrf.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_NRF53_SDC_NRF_H
#define __ARCH_ARM_SRC_NRF53_SDC_NRF_H
/****************************************************************************
* Public Types
****************************************************************************/
typedef int IRQn_Type;
#endif /* __ARCH_ARM_SRC_NRF53_SDC_NRF_H */

View File

@ -0,0 +1,30 @@
/****************************************************************************
* arch/arm/src/nrf53/sdc/nrf_peripherals.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_NRF53_SDC_NRF_PERIPHERALS_H
#define __ARCH_ARM_SRC_NRF53_SDC_NRF_PERIPHERALS_H
/****************************************************************************
* Public Definitions
****************************************************************************/
#define DPPIC_PRESENT 1
#endif /* __ARCH_ARM_SRC_NRF53_SDC_NRF_PERIPHERALS_H */