Bluetooth: Controller: Schedule BIG event after Periodic Adv event

Add implementation to find free slot after Periodic
Advertising event, to place the BIG event.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
Vinayak Kariappa Chettimada 2022-02-18 06:20:56 +05:30 committed by Carles Cufí
parent 62144e4326
commit 3a6b8e1bc0
6 changed files with 129 additions and 29 deletions

View file

@ -111,11 +111,12 @@ if(CONFIG_BT_LL_SW_SPLIT)
ll_sw/ull_central_iso.c
)
endif()
if(CONFIG_BT_CTLR_SCHED_ADVANCED)
zephyr_library_sources(
ll_sw/ull_sched.c
)
endif()
endif()
if(CONFIG_BT_CTLR_SCHED_ADVANCED AND
(CONFIG_BT_CONN OR CONFIG_BT_CTLR_ADV_ISO))
zephyr_library_sources(
ll_sw/ull_sched.c
)
endif()
if(CONFIG_BT_CTLR_DF)
zephyr_library_sources(

View file

@ -181,6 +181,9 @@ int ull_adv_sync_init(void);
int ull_adv_sync_reset(void);
int ull_adv_sync_reset_finalize(void);
/* Return ll_adv_sync_set context (unconditional) */
struct ll_adv_sync_set *ull_adv_sync_get(uint8_t handle);
/* helper function to release periodic advertising instance */
void ull_adv_sync_release(struct ll_adv_sync_set *sync);

View file

@ -36,6 +36,7 @@
#include "ull_internal.h"
#include "ull_adv_internal.h"
#include "ull_chan_internal.h"
#include "ull_sched_internal.h"
#include "ll.h"
#include "ll_feat.h"
@ -53,7 +54,7 @@ static uint16_t adv_iso_stream_handle_get(struct lll_adv_iso_stream *stream);
static uint8_t ptc_calc(const struct lll_adv_iso *lll, uint32_t latency_pdu,
uint32_t latency_packing, uint32_t ctrl_spacing);
static uint32_t adv_iso_start(struct ll_adv_iso_set *adv_iso,
uint32_t ticks_anchor, uint32_t iso_interval_us);
uint32_t iso_interval_us);
static uint8_t adv_iso_chm_update(uint8_t big_handle);
static void adv_iso_chm_complete_commit(struct lll_adv_iso *lll_iso);
static void mfy_iso_offset_get(void *param);
@ -93,7 +94,6 @@ uint8_t ll_big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis,
struct pdu_adv *pdu_prev, *pdu;
struct pdu_big_info *big_info;
uint8_t pdu_big_info_size;
uint32_t ticks_anchor_iso;
uint32_t iso_interval_us;
memq_link_t *link_cmplt;
memq_link_t *link_term;
@ -377,15 +377,8 @@ uint8_t ll_big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis,
/* Initialise LLL header members */
lll_hdr_init(lll_adv_iso, adv_iso);
/* TODO: Find the anchor after the group of active Periodic Advertising
* events such that BIG events are placed in non-overlapping
* timeline when auxiliary sets, Periodic Advertising and BIG
* events have similar event interval.
*/
ticks_anchor_iso = ticker_ticks_now_get();
/* Start sending BIS empty data packet for each BIS */
ret = adv_iso_start(adv_iso, ticks_anchor_iso, iso_interval_us);
ret = adv_iso_start(adv_iso, iso_interval_us);
if (ret) {
/* FIXME: release resources */
return BT_HCI_ERR_CMD_DISALLOWED;
@ -756,13 +749,16 @@ static uint8_t ptc_calc(const struct lll_adv_iso *lll, uint32_t latency_pdu,
}
static uint32_t adv_iso_start(struct ll_adv_iso_set *adv_iso,
uint32_t ticks_anchor, uint32_t iso_interval_us)
uint32_t iso_interval_us)
{
uint32_t ticks_slot_overhead;
uint32_t ticks_slot_offset;
uint32_t volatile ret_cb;
uint32_t ticks_anchor;
uint32_t ticks_slot;
uint32_t slot_us;
uint32_t ret;
int err;
ull_hdr_init(&adv_iso->ull);
@ -784,6 +780,14 @@ static uint32_t adv_iso_start(struct ll_adv_iso_set *adv_iso,
} else {
ticks_slot_overhead = 0U;
}
ticks_slot = adv_iso->ull.ticks_slot + ticks_slot_overhead;
/* Find the slot after Periodic Advertisings events */
err = ull_sched_after_adv_sync_slot_get(TICKER_USER_ID_THREAD,
ticks_slot, &ticks_anchor);
if (err) {
ticks_anchor = ticker_ticks_now_get();
}
/* setup to use ISO create prepare function for first radio event */
mfy_lll_prepare.fp = lll_adv_iso_create_prepare;
@ -794,9 +798,7 @@ static uint32_t adv_iso_start(struct ll_adv_iso_set *adv_iso,
ticks_anchor, 0U,
HAL_TICKER_US_TO_TICKS(iso_interval_us),
HAL_TICKER_REMAINDER(iso_interval_us),
TICKER_NULL_LAZY,
(adv_iso->ull.ticks_slot + ticks_slot_overhead),
ticker_cb, adv_iso,
TICKER_NULL_LAZY, ticks_slot, ticker_cb, adv_iso,
ull_ticker_status_give, (void *)&ret_cb);
ret = ull_ticker_status_take(ret, &ret_cb);

View file

@ -766,6 +766,15 @@ int ull_adv_sync_reset_finalize(void)
return 0;
}
struct ll_adv_sync_set *ull_adv_sync_get(uint8_t handle)
{
if (handle >= CONFIG_BT_CTLR_ADV_SYNC_SET) {
return NULL;
}
return &ll_adv_sync_pool[handle];
}
uint16_t ull_adv_sync_lll_handle_get(struct lll_adv_sync *lll)
{
return sync_handle_get((void *)lll->hdr.parent);

View file

@ -23,6 +23,10 @@
#include "lll.h"
#include "lll/lll_vendor.h"
#include "lll/lll_adv_types.h"
#include "lll_adv.h"
#include "lll/lll_adv_pdu.h"
#include "lll_adv_sync.h"
#include "lll_scan.h"
#include "lll/lll_df_types.h"
#include "lll_conn.h"
@ -31,10 +35,12 @@
#include "ull_tx_queue.h"
#endif
#include "ull_adv_types.h"
#include "ull_scan_types.h"
#include "ull_conn_types.h"
#include "ull_internal.h"
#include "ull_adv_internal.h"
#include "ull_conn_internal.h"
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
@ -59,14 +65,52 @@ static uint8_t after_match_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
uint32_t *ticks_anchor,
uint32_t *ticks_to_expire_match,
uint32_t *ticks_slot_match);
static void ticker_op_cb(uint32_t status, void *param);
#if defined(CONFIG_BT_CONN)
static bool ticker_conn_match_op_cb(uint8_t ticker_id, uint32_t ticks_slot,
uint32_t ticks_to_expire, void *op_context);
static struct ull_hdr *conn_ull_hdr_get_cb(uint8_t ticker_id);
static void after_mstr_offset_get(uint16_t conn_interval, uint32_t ticks_slot,
uint32_t ticks_anchor,
uint32_t *win_offset_us);
static void ticker_op_cb(uint32_t status, void *param);
#endif /* CONFIG_BT_CONN */
#if defined(CONFIG_BT_CTLR_ADV_ISO)
static bool ticker_adv_sync_match_op_cb(uint8_t ticker_id, uint32_t ticks_slot,
uint32_t ticks_to_expire,
void *op_context);
static struct ull_hdr *adv_sync_ull_hdr_get_cb(uint8_t ticker_id);
int ull_sched_after_adv_sync_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
uint32_t *ticks_anchor)
{
uint32_t ticks_to_expire;
uint32_t ticks_slot;
uint8_t ticker_id;
ticker_id = after_match_slot_get(user_id, ticks_slot_abs,
ticker_adv_sync_match_op_cb,
adv_sync_ull_hdr_get_cb, ticks_anchor,
&ticks_to_expire, &ticks_slot);
if (ticker_id != TICKER_NULL) {
const struct ll_adv_sync_set *sync =
(void *)adv_sync_ull_hdr_get_cb(ticker_id);
uint32_t time_us;
time_us = ull_adv_sync_time_get(sync, PDU_AC_PAYLOAD_SIZE_MAX);
*ticks_anchor += ticks_to_expire;
*ticks_anchor += HAL_TICKER_US_TO_TICKS(time_us);
return 0;
}
return -ECHILD;
}
#endif /* CONFIG_BT_CTLR_ADV_ISO */
#if defined(CONFIG_BT_CONN)
int ull_sched_after_mstr_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
uint32_t *ticks_anchor, uint32_t *us_offset)
{
@ -281,7 +325,6 @@ void ull_sched_mfy_win_offset_select(void *param)
#undef OFFSET_M_MAX
}
#if defined(CONFIG_BT_LL_SW_LLCP_LEGACY)
static void win_offset_calc(struct ll_conn *conn_curr, uint8_t is_select,
uint32_t *ticks_to_offset_next,
@ -351,6 +394,12 @@ static void win_offset_calc(struct ll_conn *conn_curr, uint8_t is_select,
}
}
/* Using a local variable to address the Coverity rule:
* Incorrect expression (ASSERT_SIDE_EFFECT)
* Argument "ret_cb" of LL_ASSERT() has a side effect
* because the variable is volatile. The containing function
* might work differently in a non-debug build.
*/
success = (ret_cb == TICKER_STATUS_SUCCESS);
LL_ASSERT(success);
@ -509,8 +558,8 @@ static void win_offset_calc(struct ll_conn *conn_curr, uint8_t is_select,
*offset_max = offset_index;
}
#endif /* CONFIG_BT_LL_SW_LLCP_LEGACY */
#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
#endif /* CONFIG_BT_CONN */
static uint8_t after_match_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
ticker_op_match_func ticker_match_op_cb,
@ -531,7 +580,7 @@ static uint8_t after_match_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
ticks_to_expire = ticks_to_expire_prev = 0U;
ticks_slot_abs_prev = 0U;
while (1) {
uint32_t ticks_slot_abs_curr = 0;
uint32_t ticks_slot_abs_curr = 0U;
uint32_t ticks_to_expire_normal;
uint32_t volatile ret_cb;
struct ull_hdr *hdr;
@ -547,12 +596,12 @@ static uint8_t after_match_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
ticker_match_op_cb,
NULL, /* match_op_context */
ticker_op_cb, (void *)&ret_cb);
#else
#else /* !CONFIG_BT_TICKER_NEXT_SLOT_GET_MATCH */
ret = ticker_next_slot_get(TICKER_INSTANCE_ID_CTLR, user_id,
&ticker_id, ticks_anchor,
&ticks_to_expire,
ticker_op_cb, (void *)&ret_cb);
#endif /* CONFIG_BT_TICKER_NEXT_SLOT_GET_MATCH */
#endif /* !CONFIG_BT_TICKER_NEXT_SLOT_GET_MATCH */
if (ret == TICKER_STATUS_BUSY) {
while (ret_cb == TICKER_STATUS_BUSY) {
ticker_job_sched(TICKER_INSTANCE_ID_CTLR,
@ -560,6 +609,12 @@ static uint8_t after_match_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
}
}
/* Using a local variable to address the Coverity rule:
* Incorrect expression (ASSERT_SIDE_EFFECT)
* Argument "ret_cb" of LL_ASSERT() has a side effect
* because the variable is volatile. The containing function
* might work differently in a non-debug build.
*/
success = (ret_cb == TICKER_STATUS_SUCCESS);
LL_ASSERT(success);
@ -583,7 +638,7 @@ static uint8_t after_match_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
#if defined(CONFIG_BT_CTLR_LOW_LAT)
#if defined(CONFIG_BT_CTLR_XTAL_ADVANCED)
if (hdr->ticks_prepare_to_start & XON_BITMASK) {
uint32_t ticks_prepare_to_start =
const uint32_t ticks_prepare_to_start =
MAX(hdr->ticks_active_to_start,
hdr->ticks_preempt_to_start);
@ -594,7 +649,7 @@ static uint8_t after_match_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
} else
#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
{
uint32_t ticks_prepare_to_start =
const uint32_t ticks_prepare_to_start =
MAX(hdr->ticks_active_to_start,
hdr->ticks_prepare_to_start);
@ -624,6 +679,12 @@ static uint8_t after_match_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
return ticker_id_prev;
}
static void ticker_op_cb(uint32_t status, void *param)
{
*((uint32_t volatile *)param) = status;
}
#if defined(CONFIG_BT_CONN)
static bool ticker_conn_match_op_cb(uint8_t ticker_id, uint32_t ticks_slot,
uint32_t ticks_to_expire, void *op_context)
{
@ -679,8 +740,30 @@ static void after_mstr_offset_get(uint16_t conn_interval, uint32_t ticks_slot,
}
}
}
#endif /* CONFIG_BT_CONN */
static void ticker_op_cb(uint32_t status, void *param)
#if defined(CONFIG_BT_CTLR_ADV_ISO)
static bool ticker_adv_sync_match_op_cb(uint8_t ticker_id, uint32_t ticks_slot,
uint32_t ticks_to_expire,
void *op_context)
{
*((uint32_t volatile *)param) = status;
ARG_UNUSED(ticks_slot);
ARG_UNUSED(ticks_to_expire);
ARG_UNUSED(op_context);
return (ticker_id >= TICKER_ID_ADV_SYNC_BASE) &&
(ticker_id <= TICKER_ID_ADV_SYNC_LAST);
}
static struct ull_hdr *adv_sync_ull_hdr_get_cb(uint8_t ticker_id)
{
struct ll_adv_sync_set *sync;
sync = ull_adv_sync_get(ticker_id - TICKER_ID_ADV_SYNC_BASE);
if (!sync) {
return NULL;
}
return &sync->ull;
}
#endif /* CONFIG_BT_CTLR_ADV_ISO */

View file

@ -9,3 +9,5 @@ int ull_sched_after_mstr_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
void ull_sched_mfy_win_offset_use(void *param);
void ull_sched_mfy_free_win_offset_calc(void *param);
void ull_sched_mfy_win_offset_select(void *param);
int ull_sched_after_adv_sync_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
uint32_t *ticks_anchor);