Bluetooth: controller: Use new ticker feature to get offsets

Updated the 3 places in extended advertising where the ticker was
previously inquired about the expiration of another ticker ID in a
separate mayfly (adv_aux, adv_sync and adv_iso). It will now use the
new ticker feature where another ticker IDs expiration info will be
added to the callback.

Channel map updates are now handled in ticker_cb and applied immediately
if the ticker is not running

Signed-off-by: Troels Nilsson <trnn@demant.com>
This commit is contained in:
Troels Nilsson 2022-11-30 15:12:56 +01:00 committed by Fabio Baltieri
parent e990ab941d
commit 714d74b77b
16 changed files with 429 additions and 383 deletions

View File

@ -546,6 +546,7 @@ config BT_CTLR_ADV_EXT
depends on BT_CTLR_ADV_EXT_SUPPORT
select BT_CTLR_CHAN_SEL_2 if BT_LL_SW_SPLIT && BT_BROADCASTER
select BT_CTLR_SCAN_REQ_NOTIFY if BT_LL_SW_SPLIT && BT_BROADCASTER
select BT_TICKER_EXT
default y if BT_EXT_ADV
help
Enable support for Bluetooth 5.0 LE Advertising Extensions in the

View File

@ -833,7 +833,6 @@ config BT_TICKER_NEXT_SLOT_GET_MATCH
config BT_TICKER_EXT
bool "Ticker extensions"
depends on !BT_TICKER_LOW_LAT && !BT_TICKER_SLOT_AGNOSTIC
default y if BT_BROADCASTER
help
This option enables ticker extensions such as re-scheduling of

View File

@ -82,6 +82,10 @@ struct lll_adv_iso {
uint8_t giv[8];
struct ccm ccm_tx;
/* contains the offset in ticks from the adv_sync pointing to this ISO */
uint32_t ticks_sync_pdu_offset;
uint16_t iso_lazy;
uint16_t stream_handle[BT_CTLR_ADV_ISO_STREAM_MAX];
};
@ -111,6 +115,10 @@ struct lll_adv_sync {
struct pdu_adv *last_pdu;
#endif /* CONFIG_BT_CTLR_ADV_PDU_LINK */
/* contains the offset in us from adv_aux pointing to this sync */
uint32_t us_adv_sync_pdu_offset;
uint16_t sync_lazy;
#if defined(CONFIG_BT_CTLR_ADV_ISO)
struct lll_adv_iso *iso;
uint8_t volatile iso_chm_done_req;

View File

@ -12,3 +12,5 @@ extern uint8_t ull_adv_aux_lll_handle_get(struct lll_adv_aux *lll);
extern struct pdu_adv_aux_ptr *
ull_adv_aux_lll_offset_fill(struct pdu_adv *pdu, uint32_t ticks_offset,
uint32_t remainder_us, uint32_t start_us);
extern void ull_adv_aux_lll_auxptr_fill(struct pdu_adv *pdu, struct lll_adv *lll_adv);

View File

@ -10,3 +10,5 @@ void lll_adv_iso_create_prepare(void *param);
void lll_adv_iso_prepare(void *param);
extern struct lll_adv_iso_stream *ull_adv_iso_lll_stream_get(uint16_t handle);
extern void ull_adv_iso_lll_biginfo_fill(struct pdu_adv *pdu, struct lll_adv_sync *lll_sync);

View File

@ -9,3 +9,5 @@ int lll_adv_sync_reset(void);
void lll_adv_sync_prepare(void *param);
extern uint16_t ull_adv_sync_lll_handle_get(struct lll_adv_sync *lll);
extern void ull_adv_sync_lll_syncinfo_fill(struct pdu_adv *pdu, struct lll_adv_aux *lll_aux);

View File

@ -1039,6 +1039,20 @@ static int prepare_cb(struct lll_prepare_param *p)
{
uint32_t ret;
#if defined(CONFIG_BT_CTLR_ADV_EXT)
if (lll->aux) {
/* fill in aux ptr in pdu */
ull_adv_aux_lll_auxptr_fill(pdu, lll);
/* NOTE: as first primary channel PDU does not use remainder, the packet
* timer is started one tick in advance to start the radio with
* microsecond precision, hence compensate for the higher start_us value
* captured at radio start of the first primary channel PDU.
*/
lll->aux->ticks_pri_pdu_offset += 1U;
}
#endif
ret = lll_prepare_done(lll);
LL_ASSERT(!ret);
}

View File

@ -35,6 +35,7 @@
#include "lll_adv.h"
#include "lll_adv_pdu.h"
#include "lll_adv_aux.h"
#include "lll_adv_sync.h"
#include "lll_filter.h"
#include "lll_internal.h"
@ -42,6 +43,8 @@
#include "lll_adv_internal.h"
#include "lll_prof_internal.h"
#include "ull_adv_types.h"
#include "hal/debug.h"
static int init_reset(void);
@ -107,17 +110,16 @@ static int init_reset(void)
static int prepare_cb(struct lll_prepare_param *p)
{
struct pdu_adv_com_ext_adv *pri_com_hdr;
struct pdu_adv_com_ext_adv *com_hdr;
uint32_t ticks_at_event, ticks_at_start;
struct pdu_adv *pri_pdu, *sec_pdu;
struct pdu_adv_aux_ptr *aux_ptr;
struct pdu_adv_ext_hdr *pri_hdr;
struct ll_adv_aux_set *aux;
struct pdu_adv *pdu;
struct lll_adv_aux *lll;
struct lll_adv *lll_adv;
struct ull_hdr *ull;
uint32_t remainder;
uint32_t start_us;
uint8_t *pri_dptr;
uint8_t chan_idx;
uint8_t phy_s;
uint8_t upd;
uint32_t aa;
@ -125,55 +127,18 @@ static int prepare_cb(struct lll_prepare_param *p)
DEBUG_RADIO_START_A(1);
lll = p->param;
aux = HDR_LLL2ULL(lll);
/* FIXME: get latest only when primary PDU without Aux PDUs */
upd = 0U;
sec_pdu = lll_adv_aux_data_latest_get(lll, &upd);
LL_ASSERT(sec_pdu);
pdu = lll_adv_aux_data_latest_get(lll, &upd);
LL_ASSERT(pdu);
/* Get reference to primary PDU */
lll_adv = lll->adv;
pri_pdu = lll_adv_data_curr_get(lll_adv);
LL_ASSERT(pri_pdu->type == PDU_ADV_TYPE_EXT_IND);
/* Get reference to extended header */
pri_com_hdr = (void *)&pri_pdu->adv_ext_ind;
pri_hdr = (void *)pri_com_hdr->ext_hdr_adv_data;
pri_dptr = pri_hdr->data;
/* NOTE: We shall be here in auxiliary PDU prepare due to
* aux_ptr flag being set in the extended common header
* flags. Hence, ext_hdr_len is non-zero, an explicit check
* is not needed.
*/
LL_ASSERT(pri_com_hdr->ext_hdr_len);
/* traverse through adv_addr, if present */
if (pri_hdr->adv_addr) {
pri_dptr += BDADDR_SIZE;
}
/* traverse through tgt_addr, if present */
if (pri_hdr->tgt_addr) {
pri_dptr += BDADDR_SIZE;
}
/* No CTEInfo flag in primary and secondary channel PDU */
/* traverse through adi, if present */
if (pri_hdr->adi) {
pri_dptr += sizeof(struct pdu_adv_adi);
}
aux_ptr = (void *)pri_dptr;
/* Abort if no aux_ptr filled */
if (unlikely(!pri_hdr->aux_ptr || !PDU_ADV_AUX_PTR_OFFSET_GET(aux_ptr))) {
radio_isr_set(lll_isr_early_abort, lll);
radio_disable();
return 0;
}
chan_idx = lll_chan_sel_2(lll->data_chan_counter, aux->data_chan_id,
aux->chm[aux->chm_first].data_chan_map,
aux->chm[aux->chm_first].data_chan_count);
/* Increment counter used in ULL for channel index calculation */
lll->data_chan_counter++;
@ -200,14 +165,17 @@ static int prepare_cb(struct lll_prepare_param *p)
radio_crc_configure(PDU_CRC_POLYNOMIAL,
PDU_AC_CRC_IV);
/* Use channel idx in aux_ptr */
lll_chan_set(aux_ptr->chan_idx);
/* Set the channel index */
lll_chan_set(chan_idx);
/* Set the Radio Tx Packet */
radio_pkt_tx_set(sec_pdu);
radio_pkt_tx_set(pdu);
/* Get reference to extended header */
com_hdr = (void *)&pdu->adv_ext_ind;
/* Switch to Rx if connectable or scannable */
if (pri_com_hdr->adv_mode & (BT_HCI_LE_ADV_PROP_CONN |
if (com_hdr->adv_mode & (BT_HCI_LE_ADV_PROP_CONN |
BT_HCI_LE_ADV_PROP_SCAN)) {
struct pdu_adv *scan_pdu;
@ -227,7 +195,7 @@ static int prepare_cb(struct lll_prepare_param *p)
* into the scan response.
*/
memcpy(&scan_pdu->adv_ext_ind.ext_hdr.data[ADVA_OFFSET],
&sec_pdu->adv_ext_ind.ext_hdr.data[ADVA_OFFSET],
&pdu->adv_ext_ind.ext_hdr.data[ADVA_OFFSET],
BDADDR_SIZE);
}
@ -255,9 +223,9 @@ static int prepare_cb(struct lll_prepare_param *p)
}
#if defined(CONFIG_BT_CTLR_ADV_AUX_PDU_BACK2BACK)
} else if (sec_pdu->adv_ext_ind.ext_hdr_len &&
sec_pdu->adv_ext_ind.ext_hdr.aux_ptr) {
lll->last_pdu = sec_pdu;
} else if (pdu->adv_ext_ind.ext_hdr_len &&
pdu->adv_ext_ind.ext_hdr.aux_ptr) {
lll->last_pdu = pdu;
radio_isr_set(isr_tx_chain, lll);
radio_tmr_tifs_set(EVENT_B2B_MAFS_US);
@ -306,6 +274,12 @@ static int prepare_cb(struct lll_prepare_param *p)
{
uint32_t ret;
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
if (pdu->adv_ext_ind.ext_hdr_len && pdu->adv_ext_ind.ext_hdr.sync_info) {
ull_adv_sync_lll_syncinfo_fill(pdu, lll);
}
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
ret = lll_prepare_done(lll);
LL_ASSERT(!ret);
}

View File

@ -33,6 +33,7 @@
#include "lll_adv.h"
#include "lll_adv_pdu.h"
#include "lll_adv_sync.h"
#include "lll_adv_iso.h"
#include "lll_df_types.h"
#include "lll_internal.h"
@ -247,6 +248,12 @@ static int prepare_cb(struct lll_prepare_param *p)
{
uint32_t ret;
#if defined(CONFIG_BT_CTLR_ADV_ISO)
if (lll->iso) {
ull_adv_iso_lll_biginfo_fill(pdu, lll);
}
#endif /* CONFIG_BT_CTLR_ADV_ISO */
ret = lll_prepare_done(lll);
LL_ASSERT(!ret);
}

View File

@ -79,6 +79,7 @@ static uint16_t adv_time_get(struct pdu_adv *pdu, struct pdu_adv *pdu_scan,
static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
uint32_t remainder, uint16_t lazy, uint8_t force,
void *param);
static void ticker_update_op_cb(uint32_t status, void *param);
#if defined(CONFIG_BT_PERIPHERAL)
@ -1277,15 +1278,36 @@ uint8_t ll_adv_enable(uint8_t enable)
lll->is_hdcd = !interval && (pdu_adv->type == PDU_ADV_TYPE_DIRECT_IND);
if (lll->is_hdcd) {
ret_cb = TICKER_STATUS_BUSY;
ret = ticker_start(TICKER_INSTANCE_ID_CTLR,
#if defined(CONFIG_BT_TICKER_EXT)
#if !defined(CONFIG_BT_CTLR_JIT_SCHEDULING)
ll_adv_ticker_ext[handle].ticks_slot_window = 0;
#endif /* CONFIG_BT_CTLR_JIT_SCHEDULING */
ll_adv_ticker_ext[handle].ext_timeout_func = ticker_cb;
ll_adv_ticker_ext[handle].expire_info_id = TICKER_NULL;
ret = ticker_start_ext(
#else
ret = ticker_start(
#endif
TICKER_INSTANCE_ID_CTLR,
TICKER_USER_ID_THREAD,
(TICKER_ID_ADV_BASE + handle),
ticks_anchor, 0,
(adv->ull.ticks_slot + ticks_slot_overhead),
TICKER_NULL_REMAINDER, TICKER_NULL_LAZY,
(adv->ull.ticks_slot + ticks_slot_overhead),
ticker_cb, adv,
ull_ticker_status_give, (void *)&ret_cb);
#if defined(CONFIG_BT_TICKER_EXT)
NULL,
#else
ticker_cb,
#endif /* CONFIG_BT_TICKER_EXT */
adv,
ull_ticker_status_give, (void *)&ret_cb
#if defined(CONFIG_BT_TICKER_EXT)
,
&ll_adv_ticker_ext[handle]
#endif /* CONFIG_BT_TICKER_EXT */
);
ret = ull_ticker_status_take(ret, &ret_cb);
if (ret != TICKER_STATUS_SUCCESS) {
goto failure_cleanup;
@ -1467,8 +1489,24 @@ uint8_t ll_adv_enable(uint8_t enable)
ret_cb = TICKER_STATUS_BUSY;
#if defined(CONFIG_BT_TICKER_EXT)
#if !defined(CONFIG_BT_CTLR_JIT_SCHEDULING)
ll_adv_ticker_ext[handle].ticks_slot_window =
ULL_ADV_RANDOM_DELAY + ticks_slot;
#endif /* CONFIG_BT_CTLR_JIT_SCHEDULING */
ll_adv_ticker_ext[handle].ext_timeout_func = ticker_cb;
#if defined(CONFIG_BT_CTLR_ADV_EXT)
if (lll->aux) {
uint8_t aux_handle = ull_adv_aux_handle_get(aux);
ll_adv_ticker_ext[handle].expire_info_id = TICKER_ID_ADV_AUX_BASE +
aux_handle;
} else
#endif /* CONFIG_BT_CTLR_ADV_EXT */
{
ll_adv_ticker_ext[handle].expire_info_id = TICKER_NULL;
}
ret = ticker_start_ext(
#else
@ -1489,7 +1527,12 @@ uint8_t ll_adv_enable(uint8_t enable)
TICKER_NULL_LAZY,
#endif /* !CONFIG_BT_TICKER_LOW_LAT && !CONFIG_BT_CTLR_LOW_LAT */
ticks_slot,
ticker_cb, adv,
#if defined(CONFIG_BT_TICKER_EXT)
NULL,
#else
ticker_cb,
#endif /* CONFIG_BT_TICKER_EXT */
adv,
ull_ticker_status_give,
(void *)&ret_cb
#if defined(CONFIG_BT_TICKER_EXT)
@ -1722,6 +1765,19 @@ struct ll_adv_set *ull_adv_is_created_get(uint8_t handle)
return adv;
}
void ull_adv_aux_created(struct ll_adv_set *adv)
{
if (adv->lll.aux && adv->is_enabled) {
uint8_t aux_handle = ull_adv_aux_handle_get(HDR_LLL2ULL(adv->lll.aux));
uint8_t handle = ull_adv_handle_get(adv);
ticker_update_ext(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
(TICKER_ID_ADV_BASE + handle), 0, 0, 0, 0, 0, 0,
ticker_update_op_cb, adv, 0,
TICKER_ID_ADV_AUX_BASE + aux_handle);
}
}
#endif /* CONFIG_BT_CTLR_ADV_EXT */
uint8_t ull_adv_data_set(struct ll_adv_set *adv, uint8_t len,
@ -2239,7 +2295,12 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
static memq_link_t link;
static struct mayfly mfy = {0, 0, &link, NULL, lll_adv_prepare};
static struct lll_prepare_param p;
#if defined(CONFIG_BT_TICKER_EXT)
struct ticker_ext_context *context = param;
struct ll_adv_set *adv = context->context;
#else
struct ll_adv_set *adv = param;
#endif /* CONFIG_BT_TICKER_EXT */
uint32_t random_delay;
struct lll_adv *lll;
uint32_t ret;
@ -2280,17 +2341,29 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
p.param = lll;
mfy.param = &p;
#if defined(CONFIG_BT_CTLR_ADV_EXT) && (CONFIG_BT_CTLR_ADV_AUX_SET > 0)
if (adv->lll.aux) {
uint32_t ticks_to_expire;
uint32_t other_remainder;
LL_ASSERT(context->other_expire_info);
/* Adjust ticks to expire based on remainder value */
ticks_to_expire = context->other_expire_info->ticks_to_expire;
other_remainder = context->other_expire_info->remainder;
hal_ticker_remove_jitter(&ticks_to_expire, &other_remainder);
/* Store the ticks and remainder offset for aux ptr population in LLL */
adv->lll.aux->ticks_pri_pdu_offset = ticks_to_expire;
adv->lll.aux->us_pri_pdu_offset = other_remainder;
}
#endif /* CONFIG_BT_CTLR_ADV_EXT && (CONFIG_BT_CTLR_ADV_AUX_SET > 0) */
/* Kick LLL prepare */
ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH,
TICKER_USER_ID_LLL, 0, &mfy);
LL_ASSERT(!ret);
#if defined(CONFIG_BT_CTLR_ADV_EXT) && (CONFIG_BT_CTLR_ADV_AUX_SET > 0)
if (adv->lll.aux) {
ull_adv_aux_offset_get(adv);
}
#endif /* CONFIG_BT_CTLR_ADV_EXT && (CONFIG_BT_CTLR_ADV_AUX_SET > 0) */
#if defined(CONFIG_BT_CTLR_JIT_SCHEDULING)
adv->ticks_at_expire = ticks_at_expire;
adv->delay_at_expire = adv->delay;

View File

@ -58,14 +58,16 @@ static uint32_t aux_time_get(const struct ll_adv_aux_set *aux,
static uint32_t aux_time_min_get(const struct ll_adv_aux_set *aux);
static uint8_t aux_time_update(struct ll_adv_aux_set *aux, struct pdu_adv *pdu,
struct pdu_adv *pdu_scan);
static void mfy_aux_offset_get(void *param);
static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
uint32_t remainder, uint16_t lazy, uint8_t force,
void *param);
static void ticker_op_cb(uint32_t status, void *param);
static struct ll_adv_aux_set ll_adv_aux_pool[CONFIG_BT_CTLR_ADV_AUX_SET];
static void *adv_aux_free;
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
static struct ticker_ext ll_adv_aux_ticker_ext[CONFIG_BT_CTLR_ADV_AUX_SET];
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
#endif /* (CONFIG_BT_CTLR_ADV_AUX_SET > 0) */
static uint16_t did_unique[PDU_ADV_SID_COUNT];
@ -1397,6 +1399,14 @@ uint8_t ull_adv_aux_chm_update(void)
aux->chm[chm_last].data_chan_count =
ull_chan_map_get(aux->chm[chm_last].data_chan_map);
aux->chm_last = chm_last;
if (!aux->is_started) {
/* Ticker not started yet, apply new channel map now
* Note that it should be safe to modify chm_first here
* since advertising is not active
*/
aux->chm_first = aux->chm_last;
}
}
/* TODO: Should failure due to Channel Map Update being already in
@ -1494,6 +1504,7 @@ uint8_t ull_adv_aux_hdr_set_clear(struct ll_adv_set *adv,
}
lll_aux = &aux->lll;
ull_adv_aux_created(adv);
is_aux_new = 1U;
} else {
@ -2475,6 +2486,42 @@ uint32_t ull_adv_aux_evt_init(struct ll_adv_aux_set *aux,
return ticks_slot_overhead;
}
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
static void ticker_update_op_cb(uint32_t status, void *param)
{
LL_ASSERT(status == TICKER_STATUS_SUCCESS ||
param == ull_disable_mark_get());
}
void ull_adv_sync_started_stopped(struct ll_adv_aux_set *aux)
{
if (aux->is_started) {
struct lll_adv_sync *lll_sync = aux->lll.adv->sync;
struct ll_adv_sync_set *sync;
uint8_t aux_handle;
LL_ASSERT(lll_sync);
sync = HDR_LLL2ULL(lll_sync);
aux_handle = ull_adv_aux_handle_get(aux);
if (sync->is_started) {
uint8_t sync_handle = ull_adv_sync_handle_get(sync);
ticker_update_ext(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
(TICKER_ID_ADV_AUX_BASE + aux_handle), 0, 0, 0, 0, 0, 0,
ticker_update_op_cb, aux, 0,
TICKER_ID_ADV_SYNC_BASE + sync_handle);
} else {
ticker_update_ext(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
(TICKER_ID_ADV_AUX_BASE + aux_handle), 0, 0, 0, 0, 0, 0,
ticker_update_op_cb, aux, 0,
TICKER_NULL);
}
}
}
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
uint32_t ull_adv_aux_start(struct ll_adv_aux_set *aux, uint32_t ticks_anchor,
uint32_t ticks_slot_overhead)
{
@ -2487,15 +2534,40 @@ uint32_t ull_adv_aux_start(struct ll_adv_aux_set *aux, uint32_t ticks_anchor,
aux_handle = ull_adv_aux_handle_get(aux);
interval_us = aux->interval * PERIODIC_INT_UNIT_US;
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
ll_adv_aux_ticker_ext[aux_handle].ext_timeout_func = ticker_cb;
if (aux->lll.adv->sync) {
struct ll_adv_sync_set *sync = HDR_LLL2ULL(aux->lll.adv->sync);
uint8_t sync_handle = ull_adv_sync_handle_get(sync);
ll_adv_aux_ticker_ext[aux_handle].expire_info_id = TICKER_ID_ADV_SYNC_BASE +
sync_handle;
} else {
ll_adv_aux_ticker_ext[aux_handle].expire_info_id = TICKER_NULL;
}
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
ret_cb = TICKER_STATUS_BUSY;
ret = ticker_start(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
ret = ticker_start_ext(
TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
(TICKER_ID_ADV_AUX_BASE + aux_handle),
ticks_anchor, 0U,
HAL_TICKER_US_TO_TICKS(interval_us),
HAL_TICKER_REMAINDER(interval_us), TICKER_NULL_LAZY,
(aux->ull.ticks_slot + ticks_slot_overhead),
ticker_cb, aux,
ull_ticker_status_give, (void *)&ret_cb);
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
NULL,
#else
ticker_cb,
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
aux,
ull_ticker_status_give, (void *)&ret_cb,
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
&ll_adv_aux_ticker_ext[aux_handle]);
#else
NULL);
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
ret = ull_ticker_status_take(ret, &ret_cb);
return ret;
@ -2587,23 +2659,6 @@ uint32_t ull_adv_aux_time_get(const struct ll_adv_aux_set *aux, uint8_t pdu_len,
return aux_time_get(aux, pdu, pdu_len, pdu_scan_len);
}
void ull_adv_aux_offset_get(struct ll_adv_set *adv)
{
static memq_link_t link;
static struct mayfly mfy = {0, 0, &link, NULL, mfy_aux_offset_get};
uint32_t ret;
/* NOTE: Single mayfly instance is sufficient as primary channel PDUs
* use time reservation, and this mayfly shall complete within
* the radio event. Multiple advertising sets do not need
* independent mayfly allocations.
*/
mfy.param = adv;
ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 1,
&mfy);
LL_ASSERT(!ret);
}
struct pdu_adv_aux_ptr *ull_adv_aux_lll_offset_fill(struct pdu_adv *pdu,
uint32_t ticks_offset,
uint32_t remainder_us,
@ -2955,97 +3010,50 @@ static uint8_t aux_time_update(struct ll_adv_aux_set *aux, struct pdu_adv *pdu,
return BT_HCI_ERR_SUCCESS;
}
static void mfy_aux_offset_get(void *param)
void ull_adv_aux_lll_auxptr_fill(struct pdu_adv *pdu, struct lll_adv *adv)
{
struct lll_adv_aux *lll_aux = adv->aux;
struct pdu_adv_aux_ptr *aux_ptr;
struct lll_adv_aux *lll_aux;
struct ll_adv_aux_set *aux;
uint32_t ticks_to_expire;
uint8_t data_chan_count;
uint8_t *data_chan_map;
uint32_t ticks_current;
struct ll_adv_set *adv;
struct pdu_adv *pdu;
uint32_t remainder;
uint8_t ticker_id;
uint8_t retry;
uint8_t id;
uint16_t chan_counter;
uint32_t offset_us;
uint16_t pdu_us;
adv = param;
lll_aux = adv->lll.aux;
aux = HDR_LLL2ULL(lll_aux);
ticker_id = TICKER_ID_ADV_AUX_BASE + ull_adv_aux_handle_get(aux);
id = TICKER_NULL;
ticks_to_expire = 0U;
ticks_current = 0U;
retry = 4U;
do {
uint32_t volatile ret_cb;
uint32_t ticks_previous;
uint32_t ret;
bool success;
chan_counter = lll_aux->data_chan_counter;
ticks_previous = ticks_current;
ret_cb = TICKER_STATUS_BUSY;
ret = ticker_next_slot_get_ext(TICKER_INSTANCE_ID_CTLR,
TICKER_USER_ID_ULL_LOW,
&id, &ticks_current,
&ticks_to_expire, &remainder,
NULL, NULL, NULL,
ticker_op_cb, (void *)&ret_cb);
if (ret == TICKER_STATUS_BUSY) {
while (ret_cb == TICKER_STATUS_BUSY) {
ticker_job_sched(TICKER_INSTANCE_ID_CTLR,
TICKER_USER_ID_ULL_LOW);
}
}
success = (ret_cb == TICKER_STATUS_SUCCESS);
LL_ASSERT(success);
LL_ASSERT((ticks_current == ticks_previous) || retry--);
LL_ASSERT(id != TICKER_NULL);
} while (id != ticker_id);
/* Adjust ticks to expire based on remainder value */
hal_ticker_remove_jitter(&ticks_to_expire, &remainder);
/* Store the ticks offset for population in other advertising primary
* channel PDUs.
/* The offset has to be at least T_MAFS microseconds from the end of packet
* In addition, the offset recorded in the aux ptr has the same requirement and this
* offset is in steps of 30 microseconds; So use the quantized value in check
*/
lll_aux->ticks_pri_pdu_offset = ticks_to_expire;
pdu_us = PDU_AC_US(pdu->len, adv->phy_p, adv->phy_flags);
offset_us = HAL_TICKER_TICKS_TO_US(lll_aux->ticks_pri_pdu_offset) +
lll_aux->us_pri_pdu_offset;
if ((offset_us/OFFS_UNIT_30_US)*OFFS_UNIT_30_US < EVENT_MAFS_US + pdu_us) {
struct ll_adv_aux_set *aux = HDR_LLL2ULL(lll_aux);
uint32_t interval_us;
/* NOTE: as first primary channel PDU does not use remainder, the packet
* timer is started one tick in advance to start the radio with
* microsecond precision, hence compensate for the higher start_us value
* captured at radio start of the first primary channel PDU.
*/
lll_aux->ticks_pri_pdu_offset += 1U;
/* Store the microsecond remainder offset for population in other
* advertising primary channel PDUs.
*/
lll_aux->us_pri_pdu_offset = remainder;
/* Fill the aux offset in the first Primary channel PDU */
/* FIXME: we are in ULL_LOW context, fill offset in LLL context? */
pdu = lll_adv_data_latest_peek(&adv->lll);
aux_ptr = ull_adv_aux_lll_offset_fill(pdu, ticks_to_expire, remainder,
0U);
/* Process channel map update, if any */
if (aux->chm_first != aux->chm_last) {
/* Use channelMapNew */
aux->chm_first = aux->chm_last;
/* Offset too small, point to next aux packet instead */
interval_us = aux->interval * PERIODIC_INT_UNIT_US;
offset_us = offset_us + interval_us;
lll_aux->ticks_pri_pdu_offset = HAL_TICKER_US_TO_TICKS(offset_us);
lll_aux->us_pri_pdu_offset = offset_us -
HAL_TICKER_TICKS_TO_US(lll_aux->ticks_pri_pdu_offset);
chan_counter++;
}
/* Calculate the radio channel to use */
/* Fill the aux offset */
aux_ptr = ull_adv_aux_lll_offset_fill(pdu, lll_aux->ticks_pri_pdu_offset,
lll_aux->us_pri_pdu_offset, 0U);
/* Calculate and fill the radio channel to use */
data_chan_map = aux->chm[aux->chm_first].data_chan_map;
data_chan_count = aux->chm[aux->chm_first].data_chan_count;
aux_ptr->chan_idx = lll_chan_sel_2(lll_aux->data_chan_counter,
aux_ptr->chan_idx = lll_chan_sel_2(chan_counter,
aux->data_chan_id,
data_chan_map, data_chan_count);
}
@ -3057,7 +3065,12 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
static memq_link_t link;
static struct mayfly mfy = {0, 0, &link, NULL, lll_adv_aux_prepare};
static struct lll_prepare_param p;
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
struct ticker_ext_context *context = param;
struct ll_adv_aux_set *aux = context->context;
#else
struct ll_adv_aux_set *aux = param;
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
struct lll_adv_aux *lll;
uint32_t ret;
uint8_t ref;
@ -3078,33 +3091,57 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
p.param = lll;
mfy.param = &p;
/* Kick LLL prepare */
ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH,
TICKER_USER_ID_LLL, 0, &mfy);
LL_ASSERT(!ret);
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
struct ll_adv_set *adv;
adv = HDR_LLL2ULL(lll->adv);
if (adv->lll.sync) {
struct lll_adv_sync *lll_sync = adv->lll.sync;
struct ll_adv_sync_set *sync;
sync = HDR_LLL2ULL(adv->lll.sync);
sync = HDR_LLL2ULL(adv->lll.sync);
if (sync->is_started) {
sync->aux_remainder = remainder;
ull_adv_sync_offset_get(adv);
uint32_t ticks_to_expire;
uint32_t sync_remainder_us;
LL_ASSERT(context->other_expire_info);
/* Reduce a tick for negative remainder and return positive remainder
* value.
*/
ticks_to_expire = context->other_expire_info->ticks_to_expire;
sync_remainder_us = context->other_expire_info->remainder;
hal_ticker_remove_jitter(&ticks_to_expire, &sync_remainder_us);
/* Add a tick for negative remainder and return positive remainder
* value.
*/
hal_ticker_add_jitter(&ticks_to_expire, &remainder);
/* Store the offset in us */
lll_sync->us_adv_sync_pdu_offset = HAL_TICKER_TICKS_TO_US(ticks_to_expire) +
sync_remainder_us - remainder;
/* store the lazy value */
lll_sync->sync_lazy = context->other_expire_info->lazy;
}
}
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
/* Process channel map update, if any */
if (aux->chm_first != aux->chm_last) {
/* Use channelMapNew */
aux->chm_first = aux->chm_last;
}
/* Kick LLL prepare */
ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH,
TICKER_USER_ID_LLL, 0, &mfy);
LL_ASSERT(!ret);
DEBUG_RADIO_PREPARE_A(1);
}
static void ticker_op_cb(uint32_t status, void *param)
{
*((uint32_t volatile *)param) = status;
}
#else /* !(CONFIG_BT_CTLR_ADV_AUX_SET > 0) */
static int init_reset(void)

View File

@ -107,9 +107,6 @@ struct ll_adv_aux_set *ull_adv_aux_get(uint8_t handle);
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);
/* Below are BT Spec v5.2, Vol 6, Part B Section 2.3.4 Table 2.12 defined */
#define ULL_ADV_PDU_HDR_FIELD_NONE 0
#define ULL_ADV_PDU_HDR_FIELD_ADVA BIT(0)
@ -165,6 +162,9 @@ void ull_adv_sync_pdu_init(struct pdu_adv *pdu, uint8_t ext_hdr_flags,
uint8_t ull_adv_sync_pdu_cte_info_set(struct pdu_adv *pdu, const struct pdu_cte_info *cte_info);
#if defined(CONFIG_BT_CTLR_ADV_EXT)
/* notify adv_set that an aux instance has been created for it */
void ull_adv_aux_created(struct ll_adv_set *adv);
/* helper to get information whether ADI field is avaialbe in extended advertising PDU */
static inline bool ull_adv_sync_pdu_had_adi(const struct pdu_adv *pdu)
{
@ -197,6 +197,13 @@ ull_adv_aux_hdr_len_fill(struct pdu_adv_com_ext_adv *com_hdr, uint8_t len)
{
com_hdr->ext_hdr_len = len - PDU_AC_EXT_HEADER_SIZE_MIN;
}
/* notify adv_aux_set that a sync instance has been started/stopped for it */
void ull_adv_sync_started_stopped(struct ll_adv_aux_set *aux);
/* notify adv_sync_set that an iso instance has been created for it */
void ull_adv_iso_created(struct ll_adv_sync_set *sync);
#endif /* CONFIG_BT_CTLR_ADV_EXT */
/* helper function to get next unique DID value */
@ -222,6 +229,9 @@ 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);
/* Return the sync set handle given the sync set instance */
uint16_t ull_adv_sync_handle_get(struct ll_adv_sync_set *sync);
/* helper function to release periodic advertising instance */
void ull_adv_sync_release(struct ll_adv_sync_set *sync);
@ -276,9 +286,6 @@ void ull_adv_sync_extra_data_set_clear(void *extra_data_prev,
uint16_t hdr_rem_fields,
void *data);
/* helper function to schedule a mayfly to get sync offset */
void ull_adv_sync_offset_get(struct ll_adv_set *adv);
int ull_adv_iso_init(void);
int ull_adv_iso_reset(void);
@ -291,9 +298,6 @@ uint8_t ull_adv_iso_chm_update(void);
/* helper function to cleanup after channel map update complete */
void ull_adv_iso_chm_complete(struct node_rx_hdr *rx);
/* helper function to schedule a mayfly to get BIG offset */
void ull_adv_iso_offset_get(struct ll_adv_sync_set *sync);
/* helper function to handle adv ISO done BIG complete events */
void ull_adv_iso_done_complete(struct node_rx_event_done *done);

View File

@ -62,7 +62,6 @@ static uint32_t adv_iso_start(struct ll_adv_iso_set *adv_iso,
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);
static void pdu_big_info_chan_map_phy_set(uint8_t *chm_phy, uint8_t *chan_map,
uint8_t phy);
static inline struct pdu_big_info *big_info_get(struct pdu_adv *pdu);
@ -72,7 +71,6 @@ static inline void big_info_offset_fill(struct pdu_big_info *bi,
static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
uint32_t remainder, uint16_t lazy, uint8_t force,
void *param);
static void ticker_op_cb(uint32_t status, void *param);
static void ticker_stop_op_cb(uint32_t status, void *param);
static void adv_iso_disable(void *param);
static void disabled_cb(void *param);
@ -485,6 +483,9 @@ uint8_t ll_big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis,
/* Associate the ISO instance with a Periodic Advertising */
lll_adv_sync->iso = lll_adv_iso;
/* Notify the sync instance */
ull_adv_iso_created(HDR_LLL2ULL(lll_adv_sync));
/* Commit the BIGInfo in the ACAD field of Periodic Advertising */
lll_adv_sync_data_enqueue(lll_adv_sync, ter_idx);
@ -709,18 +710,6 @@ uint8_t ll_adv_iso_by_hci_handle_new(uint8_t hci_handle, uint8_t *handle)
}
#endif /* CONFIG_BT_CTLR_HCI_ADV_HANDLE_MAPPING */
void ull_adv_iso_offset_get(struct ll_adv_sync_set *sync)
{
static memq_link_t link;
static struct mayfly mfy = {0U, 0U, &link, NULL, mfy_iso_offset_get};
uint32_t ret;
mfy.param = sync;
ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 1,
&mfy);
LL_ASSERT(!ret);
}
void ull_adv_iso_done_complete(struct node_rx_event_done *done)
{
struct ll_adv_iso_set *adv_iso;
@ -1063,71 +1052,32 @@ static void adv_iso_chm_complete_commit(struct lll_adv_iso *lll_iso)
lll_adv_sync_data_enqueue(lll_sync, ter_idx);
}
static void mfy_iso_offset_get(void *param)
void ull_adv_iso_lll_biginfo_fill(struct pdu_adv *pdu, struct lll_adv_sync *lll_sync)
{
struct lll_adv_sync *lll_sync;
struct ll_adv_sync_set *sync;
struct lll_adv_iso *lll_iso;
uint32_t ticks_to_expire;
uint16_t latency_prepare;
struct pdu_big_info *bi;
uint32_t ticks_current;
uint64_t payload_count;
struct pdu_adv *pdu;
uint8_t ticker_id;
uint16_t lazy;
uint8_t retry;
uint8_t id;
sync = param;
lll_sync = &sync->lll;
lll_iso = lll_sync->iso;
ticker_id = TICKER_ID_ADV_ISO_BASE + lll_iso->handle;
id = TICKER_NULL;
ticks_to_expire = 0U;
ticks_current = 0U;
retry = 4U;
do {
uint32_t volatile ret_cb;
uint32_t ticks_previous;
uint32_t ret;
bool success;
/* Calculate current payload count. If refcount is non-zero, we have called
* prepare and the LLL implementation has incremented latency_prepare already.
* In this case we need to subtract lazy + 1 from latency_prepare
*/
latency_prepare = lll_iso->latency_prepare;
if (ull_ref_get(HDR_LLL2ULL(lll_iso))) {
/* We are in post-prepare. latency_prepare is already
* incremented by lazy + 1 for next event
*/
latency_prepare -= lll_iso->iso_lazy + 1;
}
ticks_previous = ticks_current;
payload_count = lll_iso->payload_count + ((latency_prepare +
lll_iso->iso_lazy) * lll_iso->bn);
ret_cb = TICKER_STATUS_BUSY;
ret = ticker_next_slot_get_ext(TICKER_INSTANCE_ID_CTLR,
TICKER_USER_ID_ULL_LOW,
&id, &ticks_current,
&ticks_to_expire, NULL, &lazy,
NULL, NULL,
ticker_op_cb, (void *)&ret_cb);
if (ret == TICKER_STATUS_BUSY) {
/* Busy wait until Ticker Job is enabled after any Radio
* event is done using the Radio hardware. Ticker Job
* ISR is disabled during Radio events in LOW_LAT
* feature to avoid Radio ISR latencies.
*/
while (ret_cb == TICKER_STATUS_BUSY) {
ticker_job_sched(TICKER_INSTANCE_ID_CTLR,
TICKER_USER_ID_ULL_LOW);
}
}
success = (ret_cb == TICKER_STATUS_SUCCESS);
LL_ASSERT(success);
LL_ASSERT((ticks_current == ticks_previous) || retry--);
LL_ASSERT(id != TICKER_NULL);
} while (id != ticker_id);
payload_count = lll_iso->payload_count + ((lll_iso->latency_prepare +
lazy) * lll_iso->bn);
pdu = lll_adv_sync_data_latest_peek(lll_sync);
bi = big_info_get(pdu);
big_info_offset_fill(bi, ticks_to_expire, 0U);
big_info_offset_fill(bi, lll_iso->ticks_sync_pdu_offset, 0U);
bi->payload_count_framing[0] = payload_count;
bi->payload_count_framing[1] = payload_count >> 8;
bi->payload_count_framing[2] = payload_count >> 16;
@ -1243,11 +1193,6 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
DEBUG_RADIO_PREPARE_A(1);
}
static void ticker_op_cb(uint32_t status, void *param)
{
*((uint32_t volatile *)param) = status;
}
static void ticker_stop_op_cb(uint32_t status, void *param)
{
static memq_link_t link;

View File

@ -51,23 +51,21 @@ static int init_reset(void);
static uint8_t adv_type_check(struct ll_adv_set *adv);
static inline struct ll_adv_sync_set *sync_acquire(void);
static inline void sync_release(struct ll_adv_sync_set *sync);
static inline uint16_t sync_handle_get(struct ll_adv_sync_set *sync);
static uint32_t sync_time_get(const struct ll_adv_sync_set *sync,
const struct pdu_adv *pdu);
static inline uint8_t sync_remove(struct ll_adv_sync_set *sync,
struct ll_adv_set *adv, uint8_t enable);
static uint8_t sync_chm_update(uint8_t handle);
static void mfy_sync_offset_get(void *param);
static inline struct pdu_adv_sync_info *sync_info_get(struct pdu_adv *pdu);
static inline void sync_info_offset_fill(struct pdu_adv_sync_info *si,
uint32_t ticks_offset,
uint32_t remainder_us,
uint32_t start_us);
uint32_t offs);
#if defined(CONFIG_BT_CTLR_ADV_ISO)
static struct ticker_ext ll_adv_sync_ticker_ext[CONFIG_BT_CTLR_ADV_SYNC_SET];
#endif /* CONFIG_BT_CTLR_ADV_ISO */
static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
uint32_t remainder, uint16_t lazy, uint8_t force,
void *param);
static void ticker_op_cb(uint32_t status, void *param);
static struct ll_adv_sync_set ll_adv_sync_pool[CONFIG_BT_CTLR_ADV_SYNC_SET];
static void *adv_sync_free;
@ -212,6 +210,26 @@ uint8_t ll_adv_sync_param_set(uint8_t handle, uint16_t interval, uint16_t flags)
return 0;
}
#if defined(CONFIG_BT_CTLR_ADV_ISO)
static void ticker_update_op_cb(uint32_t status, void *param)
{
LL_ASSERT(status == TICKER_STATUS_SUCCESS ||
param == ull_disable_mark_get());
}
void ull_adv_iso_created(struct ll_adv_sync_set *sync)
{
if (sync->lll.iso && sync->is_started) {
uint8_t iso_handle = sync->lll.iso->handle;
uint8_t handle = ull_adv_sync_handle_get(sync);
ticker_update_ext(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
(TICKER_ID_ADV_SYNC_BASE + handle), 0, 0, 0, 0, 0, 0,
ticker_update_op_cb, sync, 0, TICKER_ID_ADV_ISO_BASE + iso_handle);
}
}
#endif /* CONFIG_BT_CTLR_ADV_ISO */
uint8_t ll_adv_sync_ad_data_set(uint8_t handle, uint8_t op, uint8_t len,
uint8_t const *const data)
{
@ -961,6 +979,9 @@ uint8_t ll_adv_sync_enable(uint8_t handle, uint8_t enable)
}
aux->is_started = 1U;
} else {
/* notify the auxiliary set */
ull_adv_sync_started_stopped(HDR_LLL2ULL(lll_aux));
}
}
@ -1047,9 +1068,14 @@ struct ll_adv_sync_set *ull_adv_sync_get(uint8_t handle)
return &ll_adv_sync_pool[handle];
}
uint16_t ull_adv_sync_handle_get(struct ll_adv_sync_set *sync)
{
return mem_index_get(sync, ll_adv_sync_pool, sizeof(struct ll_adv_sync_set));
}
uint16_t ull_adv_sync_lll_handle_get(struct lll_adv_sync *lll)
{
return sync_handle_get((void *)lll->hdr.parent);
return ull_adv_sync_handle_get((void *)lll->hdr.parent);
}
void ull_adv_sync_release(struct ll_adv_sync_set *sync)
@ -1134,17 +1160,38 @@ uint32_t ull_adv_sync_start(struct ll_adv_set *adv,
interval_us = (uint32_t)sync->interval * PERIODIC_INT_UNIT_US;
sync_handle = sync_handle_get(sync);
sync_handle = ull_adv_sync_handle_get(sync);
#if defined(CONFIG_BT_CTLR_ADV_ISO)
ll_adv_sync_ticker_ext[sync_handle].ext_timeout_func = ticker_cb;
if (sync->lll.iso) {
ll_adv_sync_ticker_ext[sync_handle].expire_info_id =
TICKER_ID_ADV_ISO_BASE + sync->lll.iso->handle;
} else {
ll_adv_sync_ticker_ext[sync_handle].expire_info_id = TICKER_NULL;
}
#endif /* CONFIG_BT_CTLR_ADV_ISO */
ret_cb = TICKER_STATUS_BUSY;
ret = ticker_start(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
ret = ticker_start_ext(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
(TICKER_ID_ADV_SYNC_BASE + sync_handle),
ticks_anchor, 0U,
HAL_TICKER_US_TO_TICKS(interval_us),
HAL_TICKER_REMAINDER(interval_us), TICKER_NULL_LAZY,
(sync->ull.ticks_slot + ticks_slot_overhead),
ticker_cb, sync,
ull_ticker_status_give, (void *)&ret_cb);
#if defined(CONFIG_BT_CTLR_ADV_ISO)
NULL,
#else
ticker_cb,
#endif /* CONFIG_BT_CTLR_ADV_ISO */
sync,
ull_ticker_status_give, (void *)&ret_cb,
#if defined(CONFIG_BT_CTLR_ADV_ISO)
&ll_adv_sync_ticker_ext[sync_handle]
#else
NULL
#endif /* CONFIG_BT_CTLR_ADV_ISO */
);
ret = ull_ticker_status_take(ret, &ret_cb);
return ret;
@ -1175,7 +1222,7 @@ uint8_t ull_adv_sync_time_update(struct ll_adv_sync_set *sync,
ret_cb = TICKER_STATUS_BUSY;
ret = ticker_update(TICKER_INSTANCE_ID_CTLR,
TICKER_USER_ID_THREAD,
(TICKER_ID_ADV_SYNC_BASE + sync_handle_get(sync)),
(TICKER_ID_ADV_SYNC_BASE + ull_adv_sync_handle_get(sync)),
0, 0, ticks_plus, ticks_minus, 0, 0,
ull_ticker_status_give, (void *)&ret_cb);
ret = ull_ticker_status_take(ret, &ret_cb);
@ -1316,18 +1363,6 @@ void ull_adv_sync_info_fill(struct ll_adv_sync_set *sync,
si->evt_cntr = 0U;
}
void ull_adv_sync_offset_get(struct ll_adv_set *adv)
{
static memq_link_t link;
static struct mayfly mfy = {0, 0, &link, NULL, mfy_sync_offset_get};
uint32_t ret;
mfy.param = adv;
ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 1,
&mfy);
LL_ASSERT(!ret);
}
void ull_adv_sync_pdu_init(struct pdu_adv *pdu, uint8_t ext_hdr_flags,
uint8_t phy_s, uint8_t phy_flags,
struct pdu_cte_info *cte_info)
@ -1924,12 +1959,6 @@ static inline void sync_release(struct ll_adv_sync_set *sync)
mem_release(sync, &adv_sync_free);
}
static inline uint16_t sync_handle_get(struct ll_adv_sync_set *sync)
{
return mem_index_get(sync, ll_adv_sync_pool,
sizeof(struct ll_adv_sync_set));
}
static uint32_t sync_time_get(const struct ll_adv_sync_set *sync,
const struct pdu_adv *pdu)
{
@ -1952,7 +1981,7 @@ static uint8_t sync_stop(struct ll_adv_sync_set *sync)
uint8_t sync_handle;
int err;
sync_handle = sync_handle_get(sync);
sync_handle = ull_adv_sync_handle_get(sync);
err = ull_ticker_stop_with_mark(TICKER_ID_ADV_SYNC_BASE + sync_handle,
sync, &sync->lll);
@ -1992,6 +2021,11 @@ static inline uint8_t sync_remove(struct ll_adv_sync_set *sync,
}
sync->is_started = 0U;
if (adv->lll.aux) {
/* notify the auxiliary set */
ull_adv_sync_started_stopped(HDR_LLL2ULL(adv->lll.aux));
}
}
if (!enable) {
@ -2007,6 +2041,7 @@ static uint8_t sync_chm_update(uint8_t handle)
ULL_ADV_HDR_DATA_ACAD_PTR_SIZE];
struct pdu_adv_sync_chm_upd_ind *chm_upd_ind;
struct lll_adv_sync *lll_sync;
struct ll_adv_sync_set *sync;
struct pdu_adv *pdu_prev;
struct ll_adv_set *adv;
uint8_t acad_len_prev;
@ -2090,92 +2125,37 @@ static uint8_t sync_chm_update(uint8_t handle)
ull_chan_map_get(lll_sync->chm[chm_last].data_chan_map);
lll_sync->chm_instant = instant;
/* Commit the Channel Map Indication in the ACAD field of Periodic
* Advertising
*/
lll_adv_sync_data_enqueue(lll_sync, ter_idx);
sync = HDR_LLL2ULL(lll_sync);
if (sync->is_started) {
/* Commit the Channel Map Indication in the ACAD field of Periodic
* Advertising
*/
lll_adv_sync_data_enqueue(lll_sync, ter_idx);
}
/* Initiate the Channel Map Indication */
lll_sync->chm_last = chm_last;
if (!sync->is_started) {
/* Sync not started yet, apply new channel map now */
lll_sync->chm_first = lll_sync->chm_last;
}
return 0;
}
static void mfy_sync_offset_get(void *param)
void ull_adv_sync_lll_syncinfo_fill(struct pdu_adv *pdu, struct lll_adv_aux *lll_aux)
{
struct ll_adv_set *adv = param;
struct lll_adv_sync *lll_sync;
struct ll_adv_sync_set *sync;
struct pdu_adv_sync_info *si;
uint32_t sync_remainder_us;
uint32_t aux_remainder_us;
uint32_t ticks_to_expire;
uint32_t ticks_current;
struct pdu_adv *pdu;
uint32_t remainder;
uint8_t chm_first;
uint8_t ticker_id;
uint16_t lazy;
uint8_t retry;
uint8_t id;
lll_sync = adv->lll.sync;
sync = HDR_LLL2ULL(lll_sync);
ticker_id = TICKER_ID_ADV_SYNC_BASE + sync_handle_get(sync);
lll_sync = lll_aux->adv->sync;
id = TICKER_NULL;
ticks_to_expire = 0U;
ticks_current = 0U;
retry = 4U;
do {
uint32_t volatile ret_cb;
uint32_t ticks_previous;
uint32_t ret;
bool success;
ticks_previous = ticks_current;
ret_cb = TICKER_STATUS_BUSY;
ret = ticker_next_slot_get_ext(TICKER_INSTANCE_ID_CTLR,
TICKER_USER_ID_ULL_LOW,
&id, &ticks_current,
&ticks_to_expire, &remainder,
&lazy, NULL, NULL,
ticker_op_cb, (void *)&ret_cb);
if (ret == TICKER_STATUS_BUSY) {
while (ret_cb == TICKER_STATUS_BUSY) {
ticker_job_sched(TICKER_INSTANCE_ID_CTLR,
TICKER_USER_ID_ULL_LOW);
}
}
success = (ret_cb == TICKER_STATUS_SUCCESS);
LL_ASSERT(success);
LL_ASSERT((ticks_current == ticks_previous) || retry--);
LL_ASSERT(id != TICKER_NULL);
} while (id != ticker_id);
/* Reduced a tick for negative remainder and return positive remainder
* value.
*/
hal_ticker_remove_jitter(&ticks_to_expire, &remainder);
sync_remainder_us = remainder;
/* Add a tick for negative remainder and return positive remainder
* value.
*/
remainder = sync->aux_remainder;
hal_ticker_add_jitter(&ticks_to_expire, &remainder);
aux_remainder_us = remainder;
pdu = lll_adv_aux_data_latest_peek(adv->lll.aux);
si = sync_info_get(pdu);
sync_info_offset_fill(si, ticks_to_expire, sync_remainder_us,
aux_remainder_us);
sync_info_offset_fill(si, lll_sync->us_adv_sync_pdu_offset);
si->evt_cntr = lll_sync->event_counter + lll_sync->latency_prepare +
lazy;
lll_sync->sync_lazy;
/* Fill the correct channel map to use if at or past the instant */
if (lll_sync->chm_first != lll_sync->chm_last) {
@ -2238,14 +2218,8 @@ static inline struct pdu_adv_sync_info *sync_info_get(struct pdu_adv *pdu)
}
static inline void sync_info_offset_fill(struct pdu_adv_sync_info *si,
uint32_t ticks_offset,
uint32_t remainder_us,
uint32_t start_us)
uint32_t offs)
{
uint32_t offs;
offs = HAL_TICKER_TICKS_TO_US(ticks_offset) + remainder_us - start_us;
if (offs >= OFFS_ADJUST_US) {
offs -= OFFS_ADJUST_US;
si->offs_adjust = 1U;
@ -2269,7 +2243,12 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
static memq_link_t link;
static struct mayfly mfy = {0, 0, &link, NULL, lll_adv_sync_prepare};
static struct lll_prepare_param p;
#if defined(CONFIG_BT_CTLR_ADV_ISO)
struct ticker_ext_context *context = param;
struct ll_adv_sync_set *sync = context->context;
#else
struct ll_adv_sync_set *sync = param;
#endif /* CONFIG_BT_CTLR_ADV_ISO */
struct lll_adv_sync *lll;
uint32_t ret;
uint8_t ref;
@ -2290,21 +2269,22 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
p.param = lll;
mfy.param = &p;
#if defined(CONFIG_BT_CTLR_ADV_ISO)
if (lll->iso) {
struct lll_adv_iso *lll_iso = lll->iso;
LL_ASSERT(context->other_expire_info);
/* Check: No need for remainder in this case? */
lll_iso->ticks_sync_pdu_offset = context->other_expire_info->ticks_to_expire;
lll_iso->iso_lazy = context->other_expire_info->lazy;
}
#endif /* CONFIG_BT_CTLR_ADV_ISO */
/* Kick LLL prepare */
ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH,
TICKER_USER_ID_LLL, 0, &mfy);
LL_ASSERT(!ret);
#if defined(CONFIG_BT_CTLR_ADV_ISO)
if (lll->iso) {
ull_adv_iso_offset_get(sync);
}
#endif /* CONFIG_BT_CTLR_ADV_ISO */
DEBUG_RADIO_PREPARE_A(1);
}
static void ticker_op_cb(uint32_t status, void *param)
{
*((uint32_t volatile *)param) = status;
}

View File

@ -91,8 +91,6 @@ struct ll_adv_sync_set {
uint8_t is_enabled:1;
uint8_t is_started:1;
uint8_t is_data_cmplt:1;
uint32_t aux_remainder;
};
struct ll_adv_iso_set {

View File

@ -1299,7 +1299,7 @@ void ticker_worker(void *param)
struct ticker_expire_info_internal *expire_info;
struct ticker_ext_context ext_context;
ticker_timeout_func timeout_func;
timeout_func = ticker->ext_data->ext_timeout_func;
expire_info = ticker->ext_data->other_expire_info;