Bluetooth: Controller: Fix overlapping advertising events

When multiple advertising sets are support then use advanced
scheduling implementation to place multiple auxiliary PDUs
and periodic advertising PDUs in a non-overlapping schedule.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
Vinayak Kariappa Chettimada 2022-05-13 16:44:49 +05:30 committed by Carles Cufí
commit fab4511164
10 changed files with 326 additions and 122 deletions

View file

@ -114,8 +114,7 @@ if(CONFIG_BT_LL_SW_SPLIT)
)
endif()
endif()
if(CONFIG_BT_CTLR_SCHED_ADVANCED AND
(CONFIG_BT_CONN OR CONFIG_BT_CTLR_ADV_ISO))
if(CONFIG_BT_CTLR_SCHED_ADVANCED)
zephyr_library_sources(
ll_sw/ull_sched.c
)

View file

@ -341,8 +341,11 @@ config BT_CTLR_XTAL_THRESHOLD
config BT_CTLR_SCHED_ADVANCED
bool "Advanced scheduling"
depends on (BT_MAX_CONN != 0) && BT_CTLR_SCHED_ADVANCED_SUPPORT
default y if !(BT_PERIPHERAL && !BT_CENTRAL)
depends on BT_CTLR_SCHED_ADVANCED_SUPPORT && \
(BT_CONN || \
(BT_CTLR_ADV_EXT && (BT_CTLR_ADV_AUX_SET > 1)) || \
BT_CTLR_ADV_ISO)
default y if BT_CENTRAL || (BT_BROADCASTER && BT_CTLR_ADV_EXT) || BT_CTLR_ADV_ISO
help
Enable non-overlapping placement of observer, initiator and central
roles in timespace. Uses window offset in connection updates and uses

View file

@ -101,7 +101,8 @@ static inline void lll_adv_aux_data_enqueue(struct lll_adv_aux *lll,
lll_adv_pdu_enqueue(&lll->data, idx);
}
static inline struct pdu_adv *lll_adv_aux_data_peek(struct lll_adv_aux *lll)
static inline struct pdu_adv *
lll_adv_aux_data_peek(const struct lll_adv_aux *const lll)
{
return (void *)lll->data.pdu[lll->data.last];
}

View file

@ -1407,7 +1407,8 @@ uint8_t ll_adv_enable(uint8_t enable)
EVENT_OVERHEAD_START_US +
(EVENT_TICKER_RES_MARGIN_US << 1));
ticks_slot_overhead_aux = ull_adv_aux_evt_init(aux);
ticks_slot_overhead_aux =
ull_adv_aux_evt_init(aux, &ticks_anchor_aux);
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
/* Start periodic advertising if enabled and not already

View file

@ -39,6 +39,7 @@
#include "ull_internal.h"
#include "ull_chan_internal.h"
#include "ull_adv_internal.h"
#include "ull_sched_internal.h"
#include "ll.h"
@ -168,7 +169,8 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref,
*/
ticks_anchor = ticker_ticks_now_get();
ticks_slot_overhead = ull_adv_aux_evt_init(aux);
ticks_slot_overhead =
ull_adv_aux_evt_init(aux, &ticks_anchor);
ret = ull_adv_aux_start(aux, ticks_anchor,
ticks_slot_overhead);
@ -1039,7 +1041,8 @@ uint8_t ull_adv_aux_lll_handle_get(struct lll_adv_aux *lll)
return ull_adv_aux_handle_get((void *)lll->hdr.parent);
}
uint32_t ull_adv_aux_evt_init(struct ll_adv_aux_set *aux)
uint32_t ull_adv_aux_evt_init(struct ll_adv_aux_set *aux,
uint32_t *ticks_anchor)
{
uint32_t ticks_slot_overhead;
struct lll_adv_aux *lll_aux;
@ -1071,6 +1074,26 @@ uint32_t ull_adv_aux_evt_init(struct ll_adv_aux_set *aux)
ticks_slot_overhead = 0;
}
#if defined(CONFIG_BT_CTLR_SCHED_ADVANCED)
uint32_t ticks_anchor_aux;
uint32_t ticks_slot;
int err;
time_us = ull_adv_aux_time_get(aux, PDU_AC_PAYLOAD_SIZE_MAX,
PDU_AC_PAYLOAD_SIZE_MAX);
ticks_slot = HAL_TICKER_US_TO_TICKS(time_us);
err = ull_sched_adv_aux_sync_free_slot_get(TICKER_USER_ID_THREAD,
(ticks_slot +
ticks_slot_overhead),
&ticks_anchor_aux);
if (!err) {
*ticks_anchor = ticks_anchor_aux;
*ticks_anchor += HAL_TICKER_US_TO_TICKS(
EVENT_TICKER_RES_MARGIN_US);
}
#endif /* CONFIG_BT_CTLR_SCHED_ADVANCED */
return ticks_slot_overhead;
}
@ -1082,15 +1105,14 @@ uint32_t ull_adv_aux_start(struct ll_adv_aux_set *aux, uint32_t ticks_anchor,
uint8_t aux_handle;
uint32_t ret;
interval_us = aux->interval * PERIODIC_INT_UNIT_US;
ull_hdr_init(&aux->ull);
aux_handle = ull_adv_aux_handle_get(aux);
interval_us = aux->interval * PERIODIC_INT_UNIT_US;
ret_cb = TICKER_STATUS_BUSY;
ret = ticker_start(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
(TICKER_ID_ADV_AUX_BASE + aux_handle),
ticks_anchor, 0,
ticks_anchor, 0U,
HAL_TICKER_US_TO_TICKS(interval_us),
TICKER_NULL_REMAINDER, TICKER_NULL_LAZY,
(aux->ull.ticks_slot + ticks_slot_overhead),
@ -1168,6 +1190,59 @@ void ull_adv_aux_release(struct ll_adv_aux_set *aux)
aux_release(aux);
}
struct ll_adv_aux_set *ull_adv_aux_get(uint8_t handle)
{
if (handle >= CONFIG_BT_CTLR_ADV_AUX_SET) {
return NULL;
}
return &ll_adv_aux_pool[handle];
}
uint32_t ull_adv_aux_time_get(const struct ll_adv_aux_set *aux, uint8_t pdu_len,
uint8_t pdu_scan_len)
{
const struct lll_adv_aux *lll_aux;
const struct lll_adv *lll;
const struct pdu_adv *pdu;
uint32_t time_us;
lll_aux = &aux->lll;
lll = lll_aux->adv;
/* NOTE: 16-bit values are sufficient for minimum radio event time
* reservation, 32-bit are used here so that reservations for
* whole back-to-back chaining of PDUs can be accomodated where
* the required microseconds could overflow 16-bits, example,
* back-to-back chained Coded PHY PDUs.
*/
time_us = PDU_AC_US(pdu_len, lll->phy_s, lll->phy_flags) +
EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US;
pdu = lll_adv_aux_data_peek(lll_aux);
if ((pdu->adv_ext_ind.adv_mode & BT_HCI_LE_ADV_PROP_CONN) ==
BT_HCI_LE_ADV_PROP_CONN) {
const uint16_t conn_req_us =
PDU_AC_MAX_US((INITA_SIZE + ADVA_SIZE + LLDATA_SIZE),
lll->phy_s);
const uint16_t conn_rsp_us =
PDU_AC_US((PDU_AC_EXT_HEADER_SIZE_MIN + ADVA_SIZE +
TARGETA_SIZE), lll->phy_s, lll->phy_flags);
time_us += EVENT_IFS_MAX_US * 2 + conn_req_us + conn_rsp_us;
} else if ((pdu->adv_ext_ind.adv_mode & BT_HCI_LE_ADV_PROP_SCAN) ==
BT_HCI_LE_ADV_PROP_SCAN) {
const uint16_t scan_req_us =
PDU_AC_MAX_US((SCANA_SIZE + ADVA_SIZE), lll->phy_s);
const uint16_t scan_rsp_us =
PDU_AC_US(pdu_scan_len, lll->phy_s, lll->phy_flags);
time_us += EVENT_IFS_MAX_US * 2 + scan_req_us + scan_rsp_us;
}
return time_us;
}
void ull_adv_aux_offset_get(struct ll_adv_set *adv)
{
static memq_link_t link;

View file

@ -84,7 +84,8 @@ uint8_t ull_adv_aux_handle_get(struct ll_adv_aux_set *aux);
uint8_t ull_adv_aux_chm_update(void);
/* helper function to initialize event timings */
uint32_t ull_adv_aux_evt_init(struct ll_adv_aux_set *aux);
uint32_t ull_adv_aux_evt_init(struct ll_adv_aux_set *aux,
uint32_t *ticks_anchor);
/* helper function to start auxiliary advertising */
uint32_t ull_adv_aux_start(struct ll_adv_aux_set *aux, uint32_t ticks_anchor,
@ -99,6 +100,13 @@ struct ll_adv_aux_set *ull_adv_aux_acquire(struct lll_adv *lll);
/* helper function to release auxiliary advertising instance */
void ull_adv_aux_release(struct ll_adv_aux_set *aux);
/* helper function to give the auxiliary context */
struct ll_adv_aux_set *ull_adv_aux_get(uint8_t handle);
/* helper function to return time reservation for auxiliary PDU */
uint32_t ull_adv_aux_time_get(const struct ll_adv_aux_set *aux, uint8_t pdu_len,
uint8_t pdu_scan_len);
/* helper function to schedule a mayfly to get aux offset */
void ull_adv_aux_offset_get(struct ll_adv_set *adv);

View file

@ -805,7 +805,7 @@ static uint32_t adv_iso_start(struct ll_adv_iso_set *adv_iso,
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,
err = ull_sched_adv_aux_sync_free_slot_get(TICKER_USER_ID_THREAD,
ticks_slot, &ticks_anchor);
if (err) {
ticks_anchor = ticker_ticks_now_get();

View file

@ -740,11 +740,15 @@ uint8_t ll_adv_sync_enable(uint8_t handle, uint8_t enable)
lll_aux = adv->lll.aux;
aux = HDR_LLL2ULL(lll_aux);
ticks_anchor_aux = ticker_ticks_now_get();
ticks_slot_overhead_aux = ull_adv_aux_evt_init(aux);
ticks_anchor_sync =
ticks_anchor_aux + ticks_slot_overhead_aux +
aux->ull.ticks_slot +
HAL_TICKER_US_TO_TICKS(EVENT_MAFS_US);
ticks_slot_overhead_aux =
ull_adv_aux_evt_init(aux, &ticks_anchor_aux);
ticks_anchor_sync = ticks_anchor_aux +
ticks_slot_overhead_aux + aux->ull.ticks_slot +
HAL_TICKER_US_TO_TICKS(
MAX(EVENT_MAFS_US,
EVENT_OVERHEAD_START_US) -
EVENT_OVERHEAD_START_US +
(EVENT_TICKER_RES_MARGIN_US << 1));
}
ret = ull_adv_sync_start(adv, sync, ticks_anchor_sync);

View file

@ -49,8 +49,6 @@
#include "common/log.h"
#include "hal/debug.h"
typedef struct ull_hdr *(*ull_hdr_get_func)(uint8_t ticker_id);
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
#if defined(CONFIG_BT_LL_SW_LLCP_LEGACY)
static void win_offset_calc(struct ll_conn *conn_curr, uint8_t is_select,
@ -60,6 +58,14 @@ static void win_offset_calc(struct ll_conn *conn_curr, uint8_t is_select,
#endif
#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
#if defined(CONFIG_BT_CONN)
static void after_cen_offset_get(uint16_t conn_interval, uint32_t ticks_slot,
uint32_t ticks_anchor,
uint32_t *win_offset_us);
#endif /* CONFIG_BT_CONN */
typedef struct ull_hdr *(*ull_hdr_get_func)(uint8_t ticker_id,
uint32_t *ticks_slot);
static uint8_t after_match_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
ticker_op_match_func ticker_match_op_cb,
ull_hdr_get_func ull_hdr_get_cb,
@ -67,23 +73,13 @@ static uint8_t after_match_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
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,
static bool ticker_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_cen_offset_get(uint16_t conn_interval, uint32_t ticks_slot,
uint32_t ticks_anchor,
uint32_t *win_offset_us);
#endif /* CONFIG_BT_CONN */
static struct ull_hdr *ull_hdr_get_cb(uint8_t ticker_id, uint32_t *ticks_slot);
#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,
#if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_BROADCASTER)
int ull_sched_adv_aux_sync_free_slot_get(uint8_t user_id,
uint32_t ticks_slot_abs,
uint32_t *ticks_anchor)
{
uint32_t ticks_to_expire;
@ -91,25 +87,63 @@ int ull_sched_after_adv_sync_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
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);
ticker_match_op_cb, 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;
if (false) {
time_us = ull_adv_sync_time_get(sync, PDU_AC_PAYLOAD_SIZE_MAX);
} else if (IN_RANGE(ticker_id, TICKER_ID_ADV_AUX_BASE,
TICKER_ID_ADV_AUX_LAST)) {
const struct ll_adv_aux_set *aux;
aux = (void *)ull_hdr_get_cb(ticker_id, &ticks_slot);
*ticks_anchor += ticks_to_expire;
*ticks_anchor += HAL_TICKER_US_TO_TICKS(time_us);
*ticks_anchor += ticks_slot;
if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
*ticks_anchor +=
MAX(aux->ull.ticks_active_to_start,
aux->ull.ticks_prepare_to_start);
}
return 0;
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
} else if (IN_RANGE(ticker_id, TICKER_ID_ADV_SYNC_BASE,
TICKER_ID_ADV_SYNC_LAST)) {
const struct ll_adv_sync_set *sync;
sync = (void *)ull_hdr_get_cb(ticker_id, &ticks_slot);
*ticks_anchor += ticks_to_expire;
*ticks_anchor += ticks_slot;
if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
*ticks_anchor +=
MAX(sync->ull.ticks_active_to_start,
sync->ull.ticks_prepare_to_start);
}
return 0;
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
#if defined(CONFIG_BT_CONN)
} else if (IN_RANGE(ticker_id, TICKER_ID_CONN_BASE,
TICKER_ID_CONN_LAST)) {
*ticks_anchor += ticks_to_expire;
*ticks_anchor += ticks_slot;
return 0;
#endif /* CONFIG_BT_CONN */
}
}
return -ECHILD;
}
#endif /* CONFIG_BT_CTLR_ADV_ISO */
#endif /* CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_BROADCASTER */
#if defined(CONFIG_BT_CONN)
int ull_sched_after_cen_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
@ -120,9 +154,9 @@ int ull_sched_after_cen_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
uint8_t ticker_id;
ticker_id = after_match_slot_get(user_id, ticks_slot_abs,
ticker_conn_match_op_cb,
conn_ull_hdr_get_cb, ticks_anchor,
&ticks_to_expire, &ticks_slot);
ticker_match_op_cb, ull_hdr_get_cb,
ticks_anchor, &ticks_to_expire,
&ticks_slot);
if (ticker_id != TICKER_NULL) {
*us_offset = HAL_TICKER_TICKS_TO_US(ticks_to_expire +
ticks_slot) +
@ -560,6 +594,45 @@ static void win_offset_calc(struct ll_conn *conn_curr, uint8_t is_select,
}
#endif /* CONFIG_BT_LL_SW_LLCP_LEGACY */
#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
static void after_cen_offset_get(uint16_t conn_interval, uint32_t ticks_slot,
uint32_t ticks_anchor,
uint32_t *win_offset_us)
{
uint32_t ticks_anchor_offset = ticks_anchor;
int err;
err = ull_sched_after_cen_slot_get(TICKER_USER_ID_ULL_LOW, ticks_slot,
&ticks_anchor_offset,
win_offset_us);
if (err) {
return;
}
if ((ticks_anchor_offset - ticks_anchor) & BIT(HAL_TICKER_CNTR_MSBIT)) {
*win_offset_us -= HAL_TICKER_TICKS_TO_US(
ticker_ticks_diff_get(ticks_anchor,
ticks_anchor_offset));
} else {
*win_offset_us += HAL_TICKER_TICKS_TO_US(
ticker_ticks_diff_get(ticks_anchor_offset,
ticks_anchor));
}
/* Round positive offset value in the future to within one connection
* interval value.
* Offsets in the past, value with MSBit set, are handled by caller by
* adding radio end time and connection interval as necessary to get a
* window offset in future when establishing a connection.
*/
if ((*win_offset_us & BIT(31)) == 0) {
uint32_t conn_interval_us = conn_interval * CONN_INT_UNIT_US;
while (*win_offset_us > conn_interval_us) {
*win_offset_us -= conn_interval_us;
}
}
}
#endif /* CONFIG_BT_CONN */
static uint8_t after_match_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
@ -571,19 +644,40 @@ static uint8_t after_match_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
{
uint32_t ticks_to_expire_prev;
uint32_t ticks_slot_abs_prev;
uint32_t ticks_anchor_prev;
uint32_t ticks_to_expire;
uint8_t ticker_id_prev;
uint8_t ticker_id;
uint8_t retry;
/* As we may place the event between two other events, ensure there is
* space for 3 times +/- 16 us jitter. I.e. with 32KHz sleep clock,
* ~30.517 us after previous event, ~30.517 us before and after current
* event, and an ~30.517 us before next event. Hence 8 time of ceil
* value 16 us (30.517 / 2).
*/
ticks_slot_abs += HAL_TICKER_US_TO_TICKS(EVENT_JITTER_US << 3);
/* There is a possibility that ticker nodes expire during iterations in
* this function causing the reference ticks_anchor returned for the
* found ticker to change. In this case the iterations have to be
* restarted with the new reference ticks_anchor value.
* Simultaneous continuous scanning on 1M and Coded PHY, alongwith
* directed advertising and one other state/role could expire in quick
* succession, hence have a retry count of 4.
*/
retry = 4U;
/* Initialize variable required for iterations to find a free slot */
ticker_id = ticker_id_prev = TICKER_NULL;
ticks_anchor_prev = 0U;
ticks_to_expire = ticks_to_expire_prev = 0U;
ticks_slot_abs_prev = 0U;
while (1) {
uint32_t ticks_slot_abs_curr = 0U;
uint32_t ticks_to_expire_normal;
uint32_t volatile ret_cb;
uint32_t ticks_slot;
struct ull_hdr *hdr;
uint32_t ret;
bool success;
@ -619,6 +713,21 @@ static uint8_t after_match_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
success = (ret_cb == TICKER_STATUS_SUCCESS);
LL_ASSERT(success);
/* There is a possibility that tickers expire while we
* iterate through the active list of tickers, start over with
* a fresh iteration.
*/
if ((ticker_id_prev != TICKER_NULL) &&
(*ticks_anchor != ticks_anchor_prev)) {
LL_ASSERT(retry);
retry--;
ticker_id = ticker_id_prev = TICKER_NULL;
continue;
}
/* No more active tickers with slot */
if (ticker_id == TICKER_NULL) {
break;
}
@ -629,7 +738,7 @@ static uint8_t after_match_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
}
#endif /* CONFIG_BT_TICKER_NEXT_SLOT_GET_MATCH */
hdr = ull_hdr_get_cb(ticker_id);
hdr = ull_hdr_get_cb(ticker_id, &ticks_slot);
if (!hdr) {
continue;
}
@ -658,7 +767,7 @@ static uint8_t after_match_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
}
#endif
ticks_slot_abs_curr += hdr->ticks_slot;
ticks_slot_abs_curr += ticks_slot;
if ((ticker_id_prev != TICKER_NULL) &&
(ticker_ticks_diff_get(ticks_to_expire_normal,
@ -667,6 +776,7 @@ static uint8_t after_match_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
break;
}
ticks_anchor_prev = *ticks_anchor;
ticker_id_prev = ticker_id;
ticks_to_expire_prev = ticks_to_expire_normal;
ticks_slot_abs_prev = ticks_slot_abs_curr;
@ -685,86 +795,88 @@ 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,
static bool ticker_match_op_cb(uint8_t ticker_id, uint32_t ticks_slot,
uint32_t ticks_to_expire, void *op_context)
{
ARG_UNUSED(ticks_slot);
ARG_UNUSED(ticks_to_expire);
ARG_UNUSED(op_context);
return (ticker_id >= TICKER_ID_CONN_BASE) &&
(ticker_id <= TICKER_ID_CONN_LAST);
}
return false ||
static struct ull_hdr *conn_ull_hdr_get_cb(uint8_t ticker_id)
{
struct ll_conn *conn;
#if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_BROADCASTER)
IN_RANGE(ticker_id, TICKER_ID_ADV_AUX_BASE,
TICKER_ID_ADV_AUX_LAST) ||
conn = ll_conn_get(ticker_id - TICKER_ID_CONN_BASE);
if (!conn || conn->lll.role) {
return NULL;
}
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
IN_RANGE(ticker_id, TICKER_ID_ADV_SYNC_BASE,
TICKER_ID_ADV_SYNC_LAST) ||
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
#endif /* CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_BROADCASTER */
return &conn->ull;
}
static void after_cen_offset_get(uint16_t conn_interval, uint32_t ticks_slot,
uint32_t ticks_anchor,
uint32_t *win_offset_us)
{
uint32_t ticks_anchor_offset = ticks_anchor;
int err;
err = ull_sched_after_cen_slot_get(TICKER_USER_ID_ULL_LOW, ticks_slot,
&ticks_anchor_offset,
win_offset_us);
if (err) {
return;
}
if ((ticks_anchor_offset - ticks_anchor) & BIT(HAL_TICKER_CNTR_MSBIT)) {
*win_offset_us -= HAL_TICKER_TICKS_TO_US(
ticker_ticks_diff_get(ticks_anchor,
ticks_anchor_offset));
} else {
*win_offset_us += HAL_TICKER_TICKS_TO_US(
ticker_ticks_diff_get(ticks_anchor_offset,
ticks_anchor));
}
if ((*win_offset_us & BIT(31)) == 0) {
uint32_t conn_interval_us = conn_interval * CONN_INT_UNIT_US;
while (*win_offset_us > conn_interval_us) {
*win_offset_us -= conn_interval_us;
}
}
}
#if defined(CONFIG_BT_CONN)
IN_RANGE(ticker_id, TICKER_ID_CONN_BASE,
TICKER_ID_CONN_LAST) ||
#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)
{
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);
false;
}
static struct ull_hdr *adv_sync_ull_hdr_get_cb(uint8_t ticker_id)
static struct ull_hdr *ull_hdr_get_cb(uint8_t ticker_id, uint32_t *ticks_slot)
{
if (false) {
#if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_BROADCASTER)
} else if (IN_RANGE(ticker_id, TICKER_ID_ADV_AUX_BASE,
TICKER_ID_ADV_AUX_LAST)) {
struct ll_adv_aux_set *aux;
aux = ull_adv_aux_get(ticker_id - TICKER_ID_ADV_AUX_BASE);
if (aux) {
uint32_t time_us;
time_us = ull_adv_aux_time_get(aux,
PDU_AC_PAYLOAD_SIZE_MAX,
PDU_AC_PAYLOAD_SIZE_MAX);
*ticks_slot = HAL_TICKER_US_TO_TICKS(time_us);
return &aux->ull;
}
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
} else if (IN_RANGE(ticker_id, TICKER_ID_ADV_SYNC_BASE,
TICKER_ID_ADV_SYNC_LAST)) {
struct ll_adv_sync_set *sync;
sync = ull_adv_sync_get(ticker_id - TICKER_ID_ADV_SYNC_BASE);
if (!sync) {
return NULL;
}
if (sync) {
uint32_t time_us;
time_us = ull_adv_sync_time_get(sync,
PDU_AC_PAYLOAD_SIZE_MAX);
*ticks_slot = HAL_TICKER_US_TO_TICKS(time_us);
return &sync->ull;
}
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
#endif /* CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_BROADCASTER */
#if defined(CONFIG_BT_CONN)
} else if (IN_RANGE(ticker_id, TICKER_ID_CONN_BASE,
TICKER_ID_CONN_LAST)) {
struct ll_conn *conn;
conn = ll_conn_get(ticker_id - TICKER_ID_CONN_BASE);
if (conn && !conn->lll.role) {
*ticks_slot = conn->ull.ticks_slot;
return &conn->ull;
}
#endif /* CONFIG_BT_CONN */
}
return NULL;
}
#endif /* CONFIG_BT_CTLR_ADV_ISO */

View file

@ -4,10 +4,11 @@
* SPDX-License-Identifier: Apache-2.0
*/
int ull_sched_adv_aux_sync_free_slot_get(uint8_t user_id,
uint32_t ticks_slot_abs,
uint32_t *ticks_anchor);
int ull_sched_after_cen_slot_get(uint8_t user_id, uint32_t ticks_slot_abs,
uint32_t *ticks_anchor, uint32_t *us_offset);
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);