nimble/ll: Fix aux scan timing

We should include clock drift due to sleep clock accuracy and jitter
when calculating aux scan start time (Core 5.3, Vol 6, Part B, 4.2.2).

Slot duration calculation should also include the above and possible
drift due to offset accuracy.
This commit is contained in:
Andrzej Kaczmarek
2023-03-21 12:57:31 +01:00
parent e75ee04614
commit 465de20085
4 changed files with 59 additions and 69 deletions
@@ -29,8 +29,8 @@ extern "C" {
struct ble_ll_scan_aux_data;
void ble_ll_scan_aux_init(void);
int ble_ll_scan_aux_sched(struct ble_ll_scan_aux_data *aux, uint32_t pdu_time,
uint8_t pdu_time_rem, uint32_t aux_ptr);
int ble_ll_scan_aux_sched(struct ble_ll_scan_aux_data *aux, uint32_t pdu_ticks,
uint8_t pdu_rem_us, uint32_t aux_ptr);
int ble_ll_scan_aux_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *rxhdr);
int ble_ll_scan_aux_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok);
void ble_ll_scan_aux_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *rxhdr);
@@ -172,9 +172,7 @@ int ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm * connsm);
int ble_ll_sched_next_time(uint32_t *next_event_time);
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
int ble_ll_sched_scan_aux(struct ble_ll_sched_item *sch, uint32_t pdu_time,
uint8_t pdu_time_rem, uint32_t offset_us,
uint32_t max_aux_time_us);
int ble_ll_sched_scan_aux(struct ble_ll_sched_item *sch);
#endif
/* Stop the scheduler */
+55 -52
View File
@@ -68,7 +68,7 @@ struct ble_ll_scan_aux_data {
uint8_t pri_phy;
uint8_t sec_phy;
uint8_t chan;
uint8_t offset_unit : 1;
uint16_t wfr_us;
uint32_t aux_ptr;
struct ble_ll_sched_item sch;
struct ble_npl_event break_ev;
@@ -111,7 +111,6 @@ static int
ble_ll_scan_aux_sched_cb(struct ble_ll_sched_item *sch)
{
struct ble_ll_scan_aux_data *aux = sch->cb_arg;
uint32_t wfr_us;
#if BLE_LL_BT5_PHY_SUPPORTED
uint8_t phy_mode;
#endif
@@ -158,8 +157,7 @@ ble_ll_scan_aux_sched_cb(struct ble_ll_sched_item *sch)
ble_ll_whitelist_disable();
}
wfr_us = aux->offset_unit ? 300 : 30;
ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_RX, 0, wfr_us);
ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_RX, 0, aux->wfr_us);
aux_data_current = aux;
@@ -683,82 +681,87 @@ ble_ll_scan_aux_break(struct ble_ll_scan_aux_data *aux)
}
static int
ble_ll_scan_aux_parse_aux_ptr(struct ble_ll_scan_aux_data *aux,
uint32_t aux_ptr, uint32_t *offset_us)
ble_ll_scan_aux_phy_to_phy(uint8_t aux_phy, uint8_t *phy)
{
uint8_t offset_unit;
uint32_t offset;
uint8_t chan;
uint8_t phy;
phy = (aux_ptr >> 21) & 0x07;
switch (phy) {
switch (aux_phy) {
case 0:
phy = BLE_PHY_1M;
*phy = BLE_PHY_1M;
break;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
case 1:
phy = BLE_PHY_2M;
*phy = BLE_PHY_2M;
break;
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
case 2:
phy = BLE_PHY_CODED;
*phy = BLE_PHY_CODED;
break;
#endif
default:
return -1;
}
chan = aux_ptr & 0x3f;
if (chan >= BLE_PHY_NUM_DATA_CHANS) {
return -1;
}
offset = 30 * ((aux_ptr >> 8) & 0x1fff);
if ((aux_ptr >> 7) & 0x01) {
offset *= 10;
offset_unit = 1;
} else {
offset_unit = 0;
}
if (offset < BLE_LL_MAFS) {
return -1;
}
aux->sec_phy = phy;
aux->chan = chan;
aux->offset_unit = offset_unit;
*offset_us = offset;
return 0;
}
int
ble_ll_scan_aux_sched(struct ble_ll_scan_aux_data *aux, uint32_t pdu_time,
uint8_t pdu_time_rem, uint32_t aux_ptr)
ble_ll_scan_aux_sched(struct ble_ll_scan_aux_data *aux, uint32_t pdu_ticks,
uint8_t pdu_rem_us, uint32_t aux_ptr)
{
struct ble_ll_sched_item *sch;
uint32_t aux_offset;
uint8_t offset_unit;
uint8_t aux_phy;
uint8_t chan;
uint8_t ca;
uint8_t phy;
uint32_t offset_us;
uint32_t max_aux_time_us;
int rc;
uint16_t pdu_rx_us;
uint16_t aux_ww_us;
uint16_t aux_tx_win_us;
rc = ble_ll_scan_aux_parse_aux_ptr(aux, aux_ptr, &offset_us);
if (rc < 0) {
/* Parse AuxPtr */
chan = aux_ptr & 0x3f;
ca = aux_ptr & 0x40;
offset_unit = aux_ptr & 0x80;
aux_offset = (aux_ptr >> 8) & 0x1fff;
aux_phy = (aux_ptr >> 21) & 0x07;
if (chan >= BLE_PHY_NUM_DATA_CHANS) {
return -1;
}
max_aux_time_us = ble_ll_pdu_us(MYNEWT_VAL(BLE_LL_SCHED_SCAN_AUX_PDU_LEN),
ble_ll_phy_to_phy_mode(aux->sec_phy, 0));
rc = ble_ll_sched_scan_aux(&aux->sch, pdu_time, pdu_time_rem, offset_us,
max_aux_time_us);
if (rc < 0) {
if (ble_ll_scan_aux_phy_to_phy(aux_phy, &phy) < 0) {
return -1;
}
return 0;
/* Actual offset */
offset_us = aux_offset * (offset_unit ? 300 : 30);
/* Time to scan aux PDU */
pdu_rx_us = ble_ll_pdu_us(MYNEWT_VAL(BLE_LL_SCHED_SCAN_AUX_PDU_LEN),
ble_ll_phy_to_phy_mode(phy, 0));
/* Transmit window */
aux_tx_win_us = offset_unit ? 300 : 30;
/* Window widening to include drift due to sleep clock accuracy and jitter */
aux_ww_us = offset_us * (ca ? 50 : 500) / 1000000 + BLE_LL_JITTER_USECS;
aux->sec_phy = phy;
aux->chan = chan;
aux->wfr_us = aux_ww_us + aux_tx_win_us;
sch = &aux->sch;
sch->start_time = pdu_ticks;
sch->remainder = pdu_rem_us;
ble_ll_tmr_add(&sch->start_time, &sch->remainder, offset_us - aux_ww_us);
sch->end_time = sch->start_time +
ble_ll_tmr_u2t_up(sch->remainder + 2 * aux_ww_us +
aux_tx_win_us + pdu_rx_us);
sch->start_time -= g_ble_ll_sched_offset_ticks;
return ble_ll_sched_scan_aux(&aux->sch);
}
int
+1 -12
View File
@@ -1119,22 +1119,11 @@ ble_ll_sched_next_time(uint32_t *next_event_time)
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
int
ble_ll_sched_scan_aux(struct ble_ll_sched_item *sch, uint32_t pdu_time,
uint8_t pdu_time_rem, uint32_t offset_us,
uint32_t max_aux_time_us)
ble_ll_sched_scan_aux(struct ble_ll_sched_item *sch)
{
uint32_t offset_ticks;
os_sr_t sr;
int rc;
offset_us += pdu_time_rem;
offset_ticks = ble_ll_tmr_u2t(offset_us);
sch->start_time = pdu_time + offset_ticks;
sch->remainder = offset_us - ble_ll_tmr_t2u(offset_ticks);
sch->end_time = sch->start_time + ble_ll_tmr_u2t_up(max_aux_time_us);
sch->start_time -= g_ble_ll_sched_offset_ticks;
OS_ENTER_CRITICAL(sr);
rc = ble_ll_sched_insert(sch, 0, preempt_none);