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" int "Number of Isochronous Tx buffers"
default 3 default 3
range 1 19 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 help
Set the number of Isochronous Tx PDUs to be queued for transmission Set the number of Isochronous Tx PDUs to be queued for transmission
in the controller. in the controller.
@ -502,7 +502,7 @@ config BT_CTLR_ADV_ISO
config BT_CTLR_SYNC_ISO config BT_CTLR_SYNC_ISO
bool "LE Broadcast Isochronous Channel advertising sync" if !BT_LL_SW_SPLIT 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 select BT_CTLR_SYNC_PERIODIC
help help
Enable support for Bluetooth 5.2 LE Isochronous Advertising sync in 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_ADV_PERIODIC_SUPPORT
select BT_CTLR_SYNC_PERIODIC_SUPPORT select BT_CTLR_SYNC_PERIODIC_SUPPORT
select BT_CTLR_ADV_ISO_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_DF_SUPPORT if HAS_HW_NRF_RADIO_BLE_DF
select BT_CTLR_CHAN_SEL_2_SUPPORT select BT_CTLR_CHAN_SEL_2_SUPPORT
select BT_CTLR_MIN_USED_CHAN_SUPPORT select BT_CTLR_MIN_USED_CHAN_SUPPORT
@ -192,6 +193,14 @@ config BT_CTLR_SCAN_SYNC_SET
help help
Maximum supported periodic sync sets. 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 config BT_CTLR_ZLI
bool "Use Zero Latency IRQs" bool "Use Zero Latency IRQs"
depends on ZERO_LATENCY_IRQS depends on ZERO_LATENCY_IRQS

View file

@ -29,6 +29,7 @@
#include "ll_sw/pdu.h" #include "ll_sw/pdu.h"
#include "ll_sw/lll.h" #include "ll_sw/lll.h"
#include "lll_adv.h" #include "lll_adv.h"
#include "lll_sync_iso.h"
#include "ll_sw/lll_scan.h" #include "ll_sw/lll_scan.h"
#include "ll_sw/lll_sync.h" #include "ll_sw/lll_sync.h"
#include "ll_sw/lll_conn.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,
NODE_RX_TYPE_SYNC_REPORT, NODE_RX_TYPE_SYNC_REPORT,
NODE_RX_TYPE_SYNC_LOST, 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_EXT_ADV_TERMINATE,
NODE_RX_TYPE_BIG_COMPLETE, NODE_RX_TYPE_BIG_COMPLETE,
NODE_RX_TYPE_BIG_TERMINATE, NODE_RX_TYPE_BIG_TERMINATE,

View file

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

View file

@ -9,6 +9,7 @@
#include <sys/byteorder.h> #include <sys/byteorder.h>
#include <bluetooth/hci.h> #include <bluetooth/hci.h>
#include <soc.h>
#include "hal/cpu.h" #include "hal/cpu.h"
#include "hal/ccm.h" #include "hal/ccm.h"
@ -36,7 +37,6 @@
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER) #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
#define LOG_MODULE_NAME bt_ctlr_lll_adv_aux #define LOG_MODULE_NAME bt_ctlr_lll_adv_aux
#include "common/log.h" #include "common/log.h"
#include <soc.h>
#include "hal/debug.h" #include "hal/debug.h"
static uint8_t lll_adv_connect_rsp_pdu[PDU_AC_LL_HEADER_SIZE + 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; struct pdu_big_ctrl ctrl;
} __packed; } __packed;
} __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_adv.h"
#include "lll_scan.h" #include "lll_scan.h"
#include "lll_sync.h" #include "lll_sync.h"
#include "lll_sync_iso.h"
#include "lll_conn.h" #include "lll_conn.h"
#include "ull_adv_types.h" #include "ull_adv_types.h"
#include "ull_scan_types.h" #include "ull_scan_types.h"
@ -48,6 +49,7 @@
#include "ull_adv_internal.h" #include "ull_adv_internal.h"
#include "ull_scan_internal.h" #include "ull_scan_internal.h"
#include "ull_sync_internal.h" #include "ull_sync_internal.h"
#include "ull_sync_iso_internal.h"
#include "ull_conn_internal.h" #include "ull_conn_internal.h"
#include "ull_df.h" #include "ull_df.h"
@ -391,6 +393,13 @@ int ll_init(struct k_sem *sem_rx)
if (err) { if (err) {
return 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 */ #endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
#if defined(CONFIG_BT_CONN) #if defined(CONFIG_BT_CONN)
@ -476,6 +485,11 @@ void ll_reset(void)
/* Reset periodic sync sets */ /* Reset periodic sync sets */
err = ull_sync_reset(); err = ull_sync_reset();
LL_ASSERT(!err); 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 */ #endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
#if defined(CONFIG_BT_CTLR_ADV_ISO) || \ #if defined(CONFIG_BT_CTLR_ADV_ISO) || \

View file

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

View file

@ -27,6 +27,7 @@
#include "lll_clock.h" #include "lll_clock.h"
#include "lll_scan.h" #include "lll_scan.h"
#include "lll_sync.h" #include "lll_sync.h"
#include "lll_sync_iso.h"
#include "ull_scan_types.h" #include "ull_scan_types.h"
#include "ull_sync_types.h" #include "ull_sync_types.h"
@ -43,7 +44,6 @@
static int init_reset(void); static int init_reset(void);
static inline struct ll_sync_set *sync_acquire(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 timeout_cleanup(struct ll_sync_set *sync);
static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder, static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
uint16_t lazy, void *param); uint16_t lazy, void *param);
@ -237,7 +237,7 @@ uint8_t ll_sync_terminate(uint16_t handle)
struct ll_sync_set *sync; struct ll_sync_set *sync;
int err; int err;
sync = is_enabled_get(handle); sync = ull_sync_is_enabled_get(handle);
if (!sync) { if (!sync) {
return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER; 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]; 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) uint16_t ull_sync_handle_get(struct ll_sync_set *sync)
{ {
return mem_index_get(sync, ll_sync_pool, sizeof(struct ll_sync_set)); 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); 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) static void timeout_cleanup(struct ll_sync_set *sync)
{ {
uint16_t sync_handle = ull_sync_handle_get(sync); uint16_t sync_handle = ull_sync_handle_get(sync);

View file

@ -7,6 +7,7 @@
int ull_sync_init(void); int ull_sync_init(void);
int ull_sync_reset(void); int ull_sync_reset(void);
uint16_t ull_sync_handle_get(struct ll_sync_set *sync); 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_release(struct ll_sync_set *sync);
void ull_sync_setup(struct ll_scan_set *scan, struct ll_scan_aux_set *aux, 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); struct node_rx_hdr *node_rx, struct pdu_adv_sync_info *si);

View file

@ -11,29 +11,195 @@
#include "common/log.h" #include "common/log.h"
#include "hal/debug.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 ll_big_sync_create(uint8_t big_handle, uint16_t sync_handle,
uint8_t encryption, uint8_t *bcode, uint8_t mse, uint8_t encryption, uint8_t *bcode, uint8_t mse,
uint16_t sync_timeout, uint8_t num_bis, uint16_t sync_timeout, uint8_t num_bis,
uint8_t *bis) uint8_t *bis)
{ {
/* TODO: Implement */ memq_link_t *big_sync_estab;
ARG_UNUSED(big_handle); memq_link_t *big_sync_lost;
ARG_UNUSED(sync_handle); struct lll_sync_iso *lll_sync;
ARG_UNUSED(encryption); struct ll_sync_set *sync;
ARG_UNUSED(bcode); struct ll_sync_iso *sync_iso;
ARG_UNUSED(mse);
ARG_UNUSED(sync_timeout);
ARG_UNUSED(num_bis);
ARG_UNUSED(bis);
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) uint8_t ll_big_sync_terminate(uint8_t big_handle)
{ {
/* TODO: Implement */ memq_link_t *big_sync_estab;
ARG_UNUSED(big_handle); 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_ADDR_MATCH 0x01
#define LL_SYNC_STATE_CREATED 0x02 #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 ll_sync_set {
struct evt_hdr evt; struct evt_hdr evt;
struct ull_hdr ull; struct ull_hdr ull;
@ -29,6 +40,10 @@ struct ll_sync_set {
uint8_t reason; uint8_t reason;
}; };
} node_rx_lost; } 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 { 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