Skip to content

Commit

Permalink
Bluetooth: Controller: Introduce EVENT_MAFS_MIN_US value
Browse files Browse the repository at this point in the history
Introduce Controller dependent EVENT_MAFS_MIN_US value to
use as the value when populating the aux offset between
Extended Advertising primary and auxiliary channel PDUs.

This can be used as workaround for peers having difficulty
receiving Extended Advertising PDUs with near 300 us MAFS
values used in aux offset calculations.

Signed-off-by: Vinayak Kariappa Chettimada <[email protected]>
  • Loading branch information
cvinayak authored and fabiobaltieri committed Aug 14, 2024
1 parent 69d1acc commit 85790c9
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 13 deletions.
3 changes: 3 additions & 0 deletions subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv_pdu.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
* SPDX-License-Identifier: Apache-2.0
*/

/* The Aux Offset shall be at least the length of the packet plus T_MAFS */
#define PDU_ADV_AUX_OFFSET_MIN_US 300

#if defined(CONFIG_BT_CTLR_ADV_PDU_LINK)
#define PDU_ADV_MEM_SIZE MROUND(PDU_AC_LL_HEADER_SIZE + \
PDU_AC_PAYLOAD_SIZE_MAX + \
Expand Down
3 changes: 3 additions & 0 deletions subsys/bluetooth/controller/ll_sw/openisa/lll/lll_adv_pdu.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
* SPDX-License-Identifier: Apache-2.0
*/

/* The Aux Offset shall be at least the length of the packet plus T_MAFS */
#define PDU_ADV_AUX_OFFSET_MIN_US 300

int lll_adv_data_init(struct lll_adv_pdu *pdu);
int lll_adv_data_reset(struct lll_adv_pdu *pdu);
int lll_adv_data_release(struct lll_adv_pdu *pdu);
Expand Down
4 changes: 3 additions & 1 deletion subsys/bluetooth/controller/ll_sw/pdu.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,10 @@
#define EVENT_IFS_US 150
/* Standard allows 2 us timing uncertainty inside the event */
#define EVENT_IFS_MAX_US (EVENT_IFS_US + EVENT_CLOCK_JITTER_US)
/* Controller will layout extended adv with minimum separation */
/* Specification defined Minimum AUX Frame Space (MAFS) */
#define EVENT_MAFS_US 300
/* Controller dependent MAFS minimum used to populate aux_offset */
#define EVENT_MAFS_MIN_US MAX(EVENT_MAFS_US, PDU_ADV_AUX_OFFSET_MIN_US)
/* Standard allows 2 us timing uncertainty inside the event */
#define EVENT_MAFS_MAX_US (EVENT_MAFS_US + EVENT_CLOCK_JITTER_US)
/* Controller defined back to back transmit MAFS for extended advertising */
Expand Down
60 changes: 48 additions & 12 deletions subsys/bluetooth/controller/ll_sw/ull_adv_aux.c
Original file line number Diff line number Diff line change
Expand Up @@ -3120,14 +3120,18 @@ void ull_adv_aux_lll_auxptr_fill(struct pdu_adv *pdu, struct lll_adv *adv)

chan_counter = lll_aux->data_chan_counter;

/* The offset has to be at least T_MAFS microseconds from the end of packet
/* The offset has to be at least T_MAFS microseconds from the end of packet.
*
* BLUETOOTH CORE SPECIFICATION Version 5.4 | Vol 6, Part B, Section 2.3.4.5 AuxPtr field,
* The Aux Offset shall be at least the length of the packet plus T_MAFS
*
* 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
*/
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) {
if (((offset_us / OFFS_UNIT_30_US) * OFFS_UNIT_30_US) < (EVENT_MAFS_MIN_US + pdu_us)) {
uint32_t interval_us;

/* Offset too small, point to next aux packet instead */
Expand Down Expand Up @@ -3165,10 +3169,13 @@ static void mfy_aux_offset_get(void *param)
uint32_t ticks_current;
uint32_t ticks_elapsed;
struct ll_adv_set *adv;
uint16_t chan_counter;
struct pdu_adv *pdu;
uint32_t ticks_now;
uint32_t remainder;
uint32_t offset_us;
uint8_t ticker_id;
uint16_t pdu_us;
uint8_t retry;
uint8_t id;

Expand Down Expand Up @@ -3226,13 +3233,6 @@ static void mfy_aux_offset_get(void *param)
*/
lll_aux->ticks_pri_pdu_offset = ticks_to_expire;

/* 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.
*/
Expand All @@ -3241,8 +3241,43 @@ static void mfy_aux_offset_get(void *param)
/* 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);

/* data channel counter that will be used for auxiliary PDU channel */
chan_counter = lll_aux->data_chan_counter;

/* The offset has to be at least T_MAFS microseconds from the end of packet.
*
* BLUETOOTH CORE SPECIFICATION Version 5.4 | Vol 6, Part B, Section 2.3.4.5 AuxPtr field,
* The Aux Offset shall be at least the length of the packet plus T_MAFS
*
* 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
*/
pdu_us = PDU_AC_US(pdu->len, adv->lll.phy_p, adv->lll.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_MIN_US + pdu_us)) {
uint32_t interval_us;

/* 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++;
}

/* 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);

/* 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;

/* Process channel map update, if any */
if (aux->chm_first != aux->chm_last) {
Expand All @@ -3253,10 +3288,11 @@ static void mfy_aux_offset_get(void *param)
/* Calculate 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);

/* Assertion check for delayed aux_offset calculations */
ticks_now = ticker_ticks_now_get();
ticks_elapsed = ticker_ticks_diff_get(ticks_now, ticks_current);
ticks_to_start = MAX(adv->ull.ticks_active_to_start,
Expand Down

0 comments on commit 85790c9

Please sign in to comment.