Bluetooth: controller: Implements BIG sync commands in the ULL

Implements handling of the BIG sync commands in the ULL.
LLL support and handling of ACAD (biginfo) remaining.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
Emil Gydesen 2020-11-09 16:31:01 +01:00 committed by Carles Cufí
commit 9d4d6d06a0
16 changed files with 336 additions and 32 deletions

View file

@ -199,7 +199,7 @@ config BT_CTLR_ISO_TX_BUFFERS
int "Number of Isochronous Tx buffers"
default 3
range 1 19
depends on BT_CTLR_ADV_ISO || BT_CTLR_CENTRAL_ISO || BT_CTLR_PERIPHERAL_ISO
depends on BT_CTLR_ADV_ISO || BT_CTLR_SYNC_ISO || BT_CTLR_CENTRAL_ISO || BT_CTLR_PERIPHERAL_ISO
help
Set the number of Isochronous Tx PDUs to be queued for transmission
in the controller.
@ -502,7 +502,7 @@ config BT_CTLR_ADV_ISO
config BT_CTLR_SYNC_ISO
bool "LE Broadcast Isochronous Channel advertising sync" if !BT_LL_SW_SPLIT
depends on BT_BROADCASTER && BT_CTLR_ADV_ISO_SUPPORT
depends on BT_OBSERVER && BT_CTLR_SYNC_ISO_SUPPORT
select BT_CTLR_SYNC_PERIODIC
help
Enable support for Bluetooth 5.2 LE Isochronous Advertising sync in

View file

@ -30,6 +30,7 @@ config BT_LLL_VENDOR_NORDIC
select BT_CTLR_ADV_PERIODIC_SUPPORT
select BT_CTLR_SYNC_PERIODIC_SUPPORT
select BT_CTLR_ADV_ISO_SUPPORT
select BT_CTLR_SYNC_ISO_SUPPORT
select BT_CTLR_DF_SUPPORT if HAS_HW_NRF_RADIO_BLE_DF
select BT_CTLR_CHAN_SEL_2_SUPPORT
select BT_CTLR_MIN_USED_CHAN_SUPPORT
@ -192,6 +193,14 @@ config BT_CTLR_SCAN_SYNC_SET
help
Maximum supported periodic sync sets.
config BT_CTLR_SCAN_SYNC_ISO_MAX
int "Maximum Broadcast Isochronous Groups syncs"
depends on BT_CTLR_SYNC_ISO
range 1 64
default 1
help
Maximum supported broadcast isochronous groups (BIGs) syncs.
config BT_CTLR_ZLI
bool "Use Zero Latency IRQs"
depends on ZERO_LATENCY_IRQS

View file

@ -29,6 +29,7 @@
#include "ll_sw/pdu.h"
#include "ll_sw/lll.h"
#include "lll_adv.h"
#include "lll_sync_iso.h"
#include "ll_sw/lll_scan.h"
#include "ll_sw/lll_sync.h"
#include "ll_sw/lll_conn.h"

View file

@ -176,6 +176,8 @@ enum node_rx_type {
NODE_RX_TYPE_SYNC,
NODE_RX_TYPE_SYNC_REPORT,
NODE_RX_TYPE_SYNC_LOST,
NODE_RX_TYPE_SYNC_ISO,
NODE_RX_TYPE_SYNC_ISO_LOST,
NODE_RX_TYPE_EXT_ADV_TERMINATE,
NODE_RX_TYPE_BIG_COMPLETE,
NODE_RX_TYPE_BIG_TERMINATE,

View file

@ -10,6 +10,7 @@
#include <bluetooth/hci.h>
#include <sys/byteorder.h>
#include <soc.h>
#include "hal/cpu.h"
#include "hal/ccm.h"
@ -42,7 +43,6 @@
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
#define LOG_MODULE_NAME bt_ctlr_lll_adv
#include "common/log.h"
#include <soc.h>
#include "hal/debug.h"
static int init_reset(void);

View file

@ -9,6 +9,7 @@
#include <sys/byteorder.h>
#include <bluetooth/hci.h>
#include <soc.h>
#include "hal/cpu.h"
#include "hal/ccm.h"
@ -36,7 +37,6 @@
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
#define LOG_MODULE_NAME bt_ctlr_lll_adv_aux
#include "common/log.h"
#include <soc.h>
#include "hal/debug.h"
static uint8_t lll_adv_connect_rsp_pdu[PDU_AC_LL_HEADER_SIZE +

View file

@ -0,0 +1,11 @@
/*
* Copyright (c) 2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
struct lll_sync_iso {
struct lll_hdr hdr;
uint8_t is_enabled:1;
};

View file

@ -732,3 +732,59 @@ struct pdu_bis {
struct pdu_big_ctrl ctrl;
} __packed;
} __packed;
struct pdu_biginfo {
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
uint32_t offset:14;
uint32_t offset_units:1;
uint32_t iso_interval:12;
uint32_t num_bis:5;
uint32_t nse:5;
uint32_t bn:3;
uint32_t sub_interval:20;
uint32_t pto:4;
uint32_t spacing:20;
uint32_t irc:4;
uint32_t max_pdu:8;
uint8_t rfu;
uint32_t seed_access_addr;
uint32_t sdu_interval:20;
uint32_t max_sdu:12;
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
uint32_t num_bis:5;
uint32_t iso_interval:12;
uint32_t offset_units:1;
uint32_t offset:14;
uint32_t pto:4;
uint32_t sub_interval:20;
uint32_t bn:3;
uint32_t nse:5;
uint32_t max_pdu:8;
uint32_t irc:4;
uint32_t spacing:20;
uint8_t rfu;
uint32_t seed_access_addr;
uint32_t max_sdu:12;
uint32_t sdu_interval:20;
#else
#error "Unsupported endianness"
#endif /* __BYTE_ORDER__ */
uint16_t base_crc_init;
uint8_t chm_phy[5]; /* 37 bit chm; 3 bit phy */
uint8_t payload_count_framing[5]; /* 39 bit count; 1 bit framing */
uint8_t giv; /* encryption required */
uint16_t gskd; /* encryption required */
} __packed;

View file

@ -36,6 +36,7 @@
#include "lll_adv.h"
#include "lll_scan.h"
#include "lll_sync.h"
#include "lll_sync_iso.h"
#include "lll_conn.h"
#include "ull_adv_types.h"
#include "ull_scan_types.h"
@ -48,6 +49,7 @@
#include "ull_adv_internal.h"
#include "ull_scan_internal.h"
#include "ull_sync_internal.h"
#include "ull_sync_iso_internal.h"
#include "ull_conn_internal.h"
#include "ull_df.h"
@ -391,6 +393,13 @@ int ll_init(struct k_sem *sem_rx)
if (err) {
return err;
}
#if defined(CONFIG_BT_CTLR_SYNC_ISO)
err = ull_sync_iso_init();
if (err) {
return err;
}
#endif /* CONFIG_BT_CTLR_SYNC_ISO */
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
#if defined(CONFIG_BT_CONN)
@ -476,6 +485,11 @@ void ll_reset(void)
/* Reset periodic sync sets */
err = ull_sync_reset();
LL_ASSERT(!err);
#if defined(CONFIG_BT_CTLR_SYNC_ISO)
/* Reset periodic sync sets */
err = ull_sync_iso_reset();
LL_ASSERT(!err);
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
#if defined(CONFIG_BT_CTLR_ADV_ISO) || \

View file

@ -22,6 +22,7 @@
#include "lll_scan.h"
#include "lll_scan_aux.h"
#include "lll_sync.h"
#include "lll_sync_iso.h"
#include "ull_scan_types.h"
#include "ull_sync_types.h"

View file

@ -27,6 +27,7 @@
#include "lll_clock.h"
#include "lll_scan.h"
#include "lll_sync.h"
#include "lll_sync_iso.h"
#include "ull_scan_types.h"
#include "ull_sync_types.h"
@ -43,7 +44,6 @@
static int init_reset(void);
static inline struct ll_sync_set *sync_acquire(void);
static struct ll_sync_set *is_enabled_get(uint16_t handle);
static void timeout_cleanup(struct ll_sync_set *sync);
static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
uint16_t lazy, void *param);
@ -237,7 +237,7 @@ uint8_t ll_sync_terminate(uint16_t handle)
struct ll_sync_set *sync;
int err;
sync = is_enabled_get(handle);
sync = ull_sync_is_enabled_get(handle);
if (!sync) {
return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
}
@ -296,6 +296,18 @@ struct ll_sync_set *ull_sync_set_get(uint16_t handle)
return &ll_sync_pool[handle];
}
struct ll_sync_set *ull_sync_is_enabled_get(uint16_t handle)
{
struct ll_sync_set *sync;
sync = ull_sync_set_get(handle);
if (!sync || !sync->timeout_reload) {
return NULL;
}
return sync;
}
uint16_t ull_sync_handle_get(struct ll_sync_set *sync)
{
return mem_index_get(sync, ll_sync_pool, sizeof(struct ll_sync_set));
@ -548,18 +560,6 @@ static inline struct ll_sync_set *sync_acquire(void)
return mem_acquire(&sync_free);
}
static struct ll_sync_set *is_enabled_get(uint16_t handle)
{
struct ll_sync_set *sync;
sync = ull_sync_set_get(handle);
if (!sync || !sync->timeout_reload) {
return NULL;
}
return sync;
}
static void timeout_cleanup(struct ll_sync_set *sync)
{
uint16_t sync_handle = ull_sync_handle_get(sync);

View file

@ -7,6 +7,7 @@
int ull_sync_init(void);
int ull_sync_reset(void);
uint16_t ull_sync_handle_get(struct ll_sync_set *sync);
struct ll_sync_set *ull_sync_is_enabled_get(uint16_t handle);
void ull_sync_release(struct ll_sync_set *sync);
void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux,
struct node_rx_hdr *node_rx, struct pdu_adv_sync_info *si);

View file

@ -11,29 +11,195 @@
#include "common/log.h"
#include "hal/debug.h"
#include "util/util.h"
#include "util/mem.h"
#include "util/memq.h"
#include "util/mayfly.h"
#include "hal/ccm.h"
#include "hal/radio.h"
#include "hal/ticker.h"
#include "ticker/ticker.h"
#include "pdu.h"
#include "ll.h"
#include "lll.h"
#include "lll_vendor.h"
#include "lll_clock.h"
#include "lll_scan.h"
#include "lll_sync.h"
#include "lll_sync_iso.h"
#include "ull_scan_types.h"
#include "ull_sync_types.h"
#include "ull_internal.h"
#include "ull_scan_internal.h"
#include "ull_sync_internal.h"
#include "ull_sync_iso_internal.h"
static struct ll_sync_iso ll_sync_iso_pool[CONFIG_BT_CTLR_SCAN_SYNC_ISO_MAX];
static void *sync_iso_free;
static int init_reset(void);
static inline struct ll_sync_iso *sync_iso_acquire(void);
uint8_t ll_big_sync_create(uint8_t big_handle, uint16_t sync_handle,
uint8_t encryption, uint8_t *bcode, uint8_t mse,
uint16_t sync_timeout, uint8_t num_bis,
uint8_t *bis)
{
/* TODO: Implement */
ARG_UNUSED(big_handle);
ARG_UNUSED(sync_handle);
ARG_UNUSED(encryption);
ARG_UNUSED(bcode);
ARG_UNUSED(mse);
ARG_UNUSED(sync_timeout);
ARG_UNUSED(num_bis);
ARG_UNUSED(bis);
memq_link_t *big_sync_estab;
memq_link_t *big_sync_lost;
struct lll_sync_iso *lll_sync;
struct ll_sync_set *sync;
struct ll_sync_iso *sync_iso;
return BT_HCI_ERR_CMD_DISALLOWED;
sync = ull_sync_is_enabled_get(sync_handle);
if (!sync || sync->sync_iso) {
return BT_HCI_ERR_CMD_DISALLOWED;
}
sync_iso = sync_iso_acquire();
if (!sync_iso) {
return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
}
big_sync_estab = ll_rx_link_alloc();
if (!big_sync_estab) {
return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
}
big_sync_lost = ll_rx_link_alloc();
if (!big_sync_lost) {
ll_rx_link_release(big_sync_estab);
return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
}
sync_iso->node_rx_lost.link = big_sync_lost;
sync_iso->node_rx_estab.link = big_sync_estab;
lll_sync = &sync_iso->lll;
/* Initialise ULL and LLL headers */
ull_hdr_init(&sync_iso->ull);
lll_hdr_init(lll_sync, sync);
lll_sync->is_enabled = true;
return BT_HCI_ERR_SUCCESS;
}
uint8_t ll_big_sync_terminate(uint8_t big_handle)
{
/* TODO: Implement */
ARG_UNUSED(big_handle);
memq_link_t *big_sync_estab;
memq_link_t *big_sync_lost;
struct ll_sync_iso *sync_iso;
void *mark;
return BT_HCI_ERR_CMD_DISALLOWED;
sync_iso = ull_sync_iso_get(big_handle);
if (!sync_iso) {
return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
}
if (!sync_iso->lll.is_enabled) {
return BT_HCI_ERR_CMD_DISALLOWED;
}
mark = ull_disable_mark(sync_iso);
LL_ASSERT(mark == sync_iso);
/* TODO: Stop ticker */
mark = ull_disable_unmark(sync_iso);
LL_ASSERT(mark == sync_iso);
big_sync_lost = sync_iso->node_rx_lost.link;
ll_rx_link_release(big_sync_lost);
big_sync_estab = sync_iso->node_rx_estab.link;
ll_rx_link_release(big_sync_estab);
sync_iso->lll.is_enabled = false;
ull_sync_iso_release(sync_iso);
return BT_HCI_ERR_SUCCESS;
}
int ull_sync_iso_init(void)
{
int err;
err = init_reset();
if (err) {
return err;
}
return 0;
}
int ull_sync_iso_reset(void)
{
int err;
err = init_reset();
if (err) {
return err;
}
return 0;
}
struct ll_sync_iso *ull_sync_iso_get(uint8_t handle)
{
if (handle >= CONFIG_BT_CTLR_SCAN_SYNC_ISO_MAX) {
return NULL;
}
return &ll_sync_iso_pool[handle];
}
uint8_t ull_sync_iso_handle_get(struct ll_sync_iso *sync)
{
return mem_index_get(sync, ll_sync_iso_pool,
sizeof(struct ll_sync_iso));
}
uint8_t ull_sync_iso_lll_handle_get(struct lll_sync_iso *lll)
{
return ull_sync_handle_get((void *)HDR_LLL2EVT(lll));
}
void ull_sync_iso_release(struct ll_sync_iso *sync_iso)
{
mem_release(sync_iso, &sync_iso_free);
}
void ull_sync_iso_setup(struct ll_sync_iso *sync_iso,
struct node_rx_hdr *node_rx,
struct pdu_biginfo *biginfo)
{
/* TODO: Implement and start ticker.
* Depends on ACAD (biginfo) support
*/
ARG_UNUSED(sync_iso);
ARG_UNUSED(node_rx);
ARG_UNUSED(biginfo);
}
static int init_reset(void)
{
/* Initialize sync pool. */
mem_init(ll_sync_iso_pool, sizeof(struct ll_sync_iso),
sizeof(ll_sync_iso_pool) / sizeof(struct ll_sync_iso),
&sync_iso_free);
return 0;
}
static inline struct ll_sync_iso *sync_iso_acquire(void)
{
return mem_acquire(&sync_iso_free);
}

View file

@ -0,0 +1,15 @@
/*
* Copyright (c) 2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
int ull_sync_iso_init(void);
int ull_sync_iso_reset(void);
struct ll_sync_iso *ull_sync_iso_get(uint8_t handle);
uint8_t ull_sync_iso_handle_get(struct ll_sync_iso *sync);
uint8_t ull_sync_iso_lll_handle_get(struct lll_sync_iso *lll);
void ull_sync_iso_release(struct ll_sync_iso *sync_iso);
void ull_sync_iso_setup(struct ll_sync_iso *sync_iso,
struct node_rx_hdr *node_rx,
struct pdu_biginfo *biginfo);

View file

@ -8,6 +8,17 @@
#define LL_SYNC_STATE_ADDR_MATCH 0x01
#define LL_SYNC_STATE_CREATED 0x02
#if defined(CONFIG_BT_CTLR_SYNC_ISO)
struct ll_sync_iso {
struct evt_hdr evt;
struct ull_hdr ull;
struct lll_sync_iso lll;
struct node_rx_hdr node_rx_lost;
struct node_rx_hdr node_rx_estab;
};
#endif /* CONFIG_BT_CTLR_SYNC_ISO */
struct ll_sync_set {
struct evt_hdr evt;
struct ull_hdr ull;
@ -29,6 +40,10 @@ struct ll_sync_set {
uint8_t reason;
};
} node_rx_lost;
#if defined(CONFIG_BT_CTLR_SYNC_ISO)
struct ll_sync_iso *sync_iso;
#endif /* CONFIG_BT_CTLR_SYNC_ISO */
};
struct node_rx_sync {

View file

@ -0,0 +1,13 @@
CONFIG_BT=y
CONFIG_BT_CTLR=y
CONFIG_BT_BROADCASTER=n
CONFIG_BT_PERIPHERAL=n
CONFIG_BT_OBSERVER=y
CONFIG_BT_CENTRAL=n
CONFIG_BT_EXT_ADV=y
CONFIG_BT_PER_ADV_SYNC=y
CONFIG_BT_CTLR_ADV_EXT=y
CONFIG_BT_CTLR_SYNC_PERIODIC=y
CONFIG_BT_CTLR_SYNC_ISO=y
CONFIG_BT_LL_SW_SPLIT=y
CONFIG_ZTEST=y