Bluetooth: Controller: Fix repeated per sync drift compensations
Fix repeated periodic sync drift compensation invoked when receiving chain PDUs which caused memory corruptions and bus faults. Use `is_aux_sched` flag in Periodic Sync's LLL context to differentiate between the first AUX_SYNC_IND PDU followed by use of LLL scheduling to receive following AUX_CHAIN_IND PDU versus ULL scheduling being used to receive AUX_CHAIN_IND PDUs. Drift compensation to be done only using the AUX_SYNC_IND PDU and not on reception of AUX_CHAIN_IND PDU using ULL scheduling. Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
parent
a18bc0f4f7
commit
665a8d2c6e
@ -10,6 +10,10 @@ struct lll_sync {
|
||||
uint8_t access_addr[4];
|
||||
uint8_t crc_init[3];
|
||||
|
||||
uint8_t phy:3;
|
||||
uint8_t is_rx_enabled:1;
|
||||
uint8_t is_aux_sched:1;
|
||||
|
||||
uint16_t skip_prepare;
|
||||
uint16_t skip_event;
|
||||
uint16_t event_counter;
|
||||
@ -32,9 +36,6 @@ struct lll_sync {
|
||||
/* used to store lll_aux when chain is being scanned */
|
||||
struct lll_scan_aux *lll_aux;
|
||||
|
||||
uint8_t phy:3;
|
||||
uint8_t is_rx_enabled:1;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX)
|
||||
struct lll_df_sync df_cfg;
|
||||
#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX */
|
||||
|
||||
@ -112,6 +112,9 @@ void lll_sync_aux_prepare_cb(struct lll_sync *lll,
|
||||
{
|
||||
struct node_rx_pdu *node_rx;
|
||||
|
||||
/* Initialize Trx count */
|
||||
trx_cnt = 0U;
|
||||
|
||||
/* Start setting up Radio h/w */
|
||||
radio_reset();
|
||||
|
||||
@ -201,6 +204,9 @@ static int prepare_cb(struct lll_prepare_param *p)
|
||||
lll->window_widening_event_us = lll->window_widening_max_us;
|
||||
}
|
||||
|
||||
/* Reset chain PDU being scheduled by lll_sync context */
|
||||
lll->is_aux_sched = 0U;
|
||||
|
||||
/* Initialize Trx count */
|
||||
trx_cnt = 0U;
|
||||
|
||||
@ -453,7 +459,7 @@ static int isr_rx(struct lll_sync *lll, uint8_t node_type, uint8_t *crc_ok)
|
||||
{
|
||||
uint8_t rssi_ready;
|
||||
uint8_t trx_done;
|
||||
int err = 0;
|
||||
int err;
|
||||
|
||||
/* Read radio status and events */
|
||||
trx_done = radio_is_done();
|
||||
@ -469,14 +475,11 @@ static int isr_rx(struct lll_sync *lll, uint8_t node_type, uint8_t *crc_ok)
|
||||
|
||||
/* No Rx */
|
||||
if (!trx_done) {
|
||||
/* TODO: Combine the early exit with above if-then-else block
|
||||
*/
|
||||
err = -EINVAL;
|
||||
|
||||
goto isr_rx_done;
|
||||
}
|
||||
|
||||
/* Rx-ed */
|
||||
trx_cnt++;
|
||||
|
||||
/* Check CRC and generate Periodic Advertising Report */
|
||||
if (*crc_ok) {
|
||||
struct node_rx_pdu *node_rx;
|
||||
@ -507,29 +510,34 @@ static int isr_rx(struct lll_sync *lll, uint8_t node_type, uint8_t *crc_ok)
|
||||
isr_aux_setup,
|
||||
lll);
|
||||
if (ftr->aux_lll_sched) {
|
||||
lll->is_aux_sched = 1U;
|
||||
err = -EBUSY;
|
||||
} else {
|
||||
err = 0;
|
||||
}
|
||||
|
||||
ull_rx_put(node_rx->hdr.link, node_rx);
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_DF_SCAN_CTE_RX)
|
||||
create_iq_report(lll, rssi_ready, BT_HCI_LE_CTE_CRC_OK);
|
||||
|
||||
(void)create_iq_report(lll, rssi_ready,
|
||||
BT_HCI_LE_CTE_CRC_OK);
|
||||
#endif /* CONFIG_BT_CTLR_DF_SCAN_CTE_RX */
|
||||
|
||||
ull_rx_sched();
|
||||
} else {
|
||||
err = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#if defined(CONFIG_BT_CTLR_DF_SAMPLE_CTE_FOR_PDU_WITH_BAD_CRC)
|
||||
else {
|
||||
err = create_iq_report(lll, rssi_ready,
|
||||
BT_HCI_LE_CTE_CRC_ERR_CTE_BASED_TIME);
|
||||
if (!err) {
|
||||
ull_rx_sched();
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_DF_SAMPLE_CTE_FOR_PDU_WITH_BAD_CRC */
|
||||
|
||||
err = 0;
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_DF_SAMPLE_CTE_FOR_PDU_WITH_BAD_CRC */
|
||||
|
||||
isr_rx_done:
|
||||
return err;
|
||||
@ -548,8 +556,12 @@ static void isr_rx_adv_sync(void *param)
|
||||
/* Save radio ready and address capture timestamp for later use for
|
||||
* drift compensation.
|
||||
*/
|
||||
radio_tmr_aa_save(radio_tmr_aa_get());
|
||||
radio_tmr_ready_save(radio_tmr_ready_get());
|
||||
if (err != -EINVAL) {
|
||||
trx_cnt = 1U;
|
||||
|
||||
radio_tmr_aa_save(radio_tmr_aa_get());
|
||||
radio_tmr_ready_save(radio_tmr_ready_get());
|
||||
}
|
||||
|
||||
if (err == -EBUSY) {
|
||||
return;
|
||||
@ -560,14 +572,14 @@ static void isr_rx_adv_sync(void *param)
|
||||
|
||||
static void isr_rx_aux_chain(void *param)
|
||||
{
|
||||
struct lll_scan_aux *aux_lll;
|
||||
struct lll_scan_aux *lll_aux;
|
||||
struct lll_sync *lll;
|
||||
uint8_t crc_ok;
|
||||
int err;
|
||||
|
||||
lll = param;
|
||||
aux_lll = lll->lll_aux;
|
||||
if (!aux_lll) {
|
||||
lll_aux = lll->lll_aux;
|
||||
if (!lll_aux) {
|
||||
/* auxiliary context not assigned (yet) in ULL execution
|
||||
* context, drop current reception and abort further chain PDU
|
||||
* receptions, if any.
|
||||
@ -583,7 +595,7 @@ static void isr_rx_aux_chain(void *param)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!trx_cnt || !crc_ok) {
|
||||
if (!crc_ok) {
|
||||
struct node_rx_pdu *node_rx;
|
||||
|
||||
node_rx = ull_pdu_rx_alloc();
|
||||
@ -599,7 +611,13 @@ static void isr_rx_aux_chain(void *param)
|
||||
}
|
||||
|
||||
isr_rx_aux_chain_done:
|
||||
isr_rx_done_cleanup(lll, 1U);
|
||||
if (lll->is_aux_sched) {
|
||||
lll->is_aux_sched = 0U;
|
||||
|
||||
isr_rx_done_cleanup(lll, 1U);
|
||||
} else {
|
||||
lll_isr_cleanup(lll);
|
||||
}
|
||||
}
|
||||
|
||||
static void isr_rx_done_cleanup(struct lll_sync *lll, uint8_t crc_ok)
|
||||
|
||||
@ -522,8 +522,6 @@ ull_scan_aux_rx_flush:
|
||||
if (aux) {
|
||||
struct ull_hdr *hdr;
|
||||
|
||||
hdr = &aux->ull;
|
||||
|
||||
/* Enqueue last rx in aux context if possible, otherwise send
|
||||
* immediately since we are in sync context.
|
||||
*/
|
||||
@ -544,6 +542,7 @@ ull_scan_aux_rx_flush:
|
||||
* callback. Flushing here would release aux context and thus
|
||||
* ull_hdr before done event was processed.
|
||||
*/
|
||||
hdr = &aux->ull;
|
||||
LL_ASSERT(ull_ref_get(hdr) < 2);
|
||||
if (ull_ref_get(hdr) == 0) {
|
||||
flush(aux);
|
||||
@ -658,7 +657,7 @@ void ull_scan_aux_release(memq_link_t *link, struct node_rx_hdr *rx)
|
||||
* data properly.
|
||||
*/
|
||||
rx->type = NODE_RX_TYPE_SYNC_REPORT;
|
||||
rx->handle = ull_sync_handle_get(HDR_LLL2ULL(lll));
|
||||
rx->handle = ull_sync_handle_get(param_ull);
|
||||
#endif /* CONFIG_BT_CTLR_SYNC_PERIODIC */
|
||||
} else {
|
||||
LL_ASSERT(0);
|
||||
@ -673,6 +672,7 @@ void ull_scan_aux_release(memq_link_t *link, struct node_rx_hdr *rx)
|
||||
hdr = &aux->ull;
|
||||
|
||||
LL_ASSERT(ull_ref_get(hdr) < 2);
|
||||
|
||||
/* Flush from here of from done event, if one is pending */
|
||||
if (ull_ref_get(hdr) == 0) {
|
||||
flush(aux);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user