nimble/ll: Fix BIG event scheduling relative to padv

This fixes scheduling of BIG events relative to padv.

The start time of a BIG event should be relative to padv event start,
not padv sched start time which in theory may be different if that's not
for the 1st AUX_SYNC_IND.

Also if padv event start time is in the past, we still need to schedule
BIG event in the future instead of just failing.
This commit is contained in:
Andrzej Kaczmarek
2024-09-23 17:34:41 +02:00
parent 64d5000f72
commit b6d7261d75
3 changed files with 28 additions and 30 deletions
@@ -201,9 +201,9 @@ int ble_ll_adv_periodic_set_info_transfer(const uint8_t *cmdbuf, uint8_t len,
/* Get advertising instance with periodic advertising configured */
struct ble_ll_adv_sm *ble_ll_adv_sync_get(uint8_t handle);
/* Get periodic advertising event scheduled time */
int ble_ll_adv_sync_sched_get(struct ble_ll_adv_sm *advsm,
uint32_t *start_time, uint32_t *end_time);
int ble_ll_adv_padv_event_start_get(struct ble_ll_adv_sm *advsm,
uint32_t *event_start,
uint8_t *event_start_rem_us);
#if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER)
struct ble_ll_iso_big;
+8 -9
View File
@@ -5337,19 +5337,18 @@ ble_ll_adv_sync_get(uint8_t handle)
}
int
ble_ll_adv_sync_sched_get(struct ble_ll_adv_sm *advsm, uint32_t *start_time,
uint32_t *end_time)
ble_ll_adv_padv_event_start_get(struct ble_ll_adv_sm *advsm,
uint32_t *event_start,
uint8_t *event_start_rem_us)
{
struct ble_ll_adv_sync *sync;
if (!advsm || !advsm->periodic_adv_active) {
return -EIO;
return -EINVAL;
}
sync = SYNC_CURRENT(advsm);
*start_time = sync->sch.start_time + g_ble_ll_sched_offset_ticks;
*end_time = sync->sch.end_time;
*event_start = advsm->padv_event_start;
if (event_start_rem_us) {
*event_start_rem_us = advsm->padv_event_start_rem_us;
}
return 0;
}
+17 -18
View File
@@ -1111,41 +1111,40 @@ ble_ll_iso_big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis,
* not enough for some phys to run scheduler item.
*/
uint32_t start_time, end_time, big_time;
uint32_t padv_start_time, big_start_time;
uint32_t sync_delay_ticks = ble_ll_tmr_u2t_up(big->sync_delay);
uint32_t iso_interval_ticks = ble_ll_tmr_u2t_up(big->iso_interval * 1250);
int big_event_fixed;
rc = ble_ll_adv_sync_sched_get(big->advsm, &start_time, &end_time);
rc = ble_ll_adv_padv_event_start_get(big->advsm, &padv_start_time, NULL);
if (rc) {
/* Set 1st BIG one interval after "now", this ensures it's always
* scheduled in the future.
*/
big_time = ble_ll_tmr_get() + iso_interval_ticks;
/* 1st event will be moved by 1 interval before scheduling so this will
* be always in the future */
big_start_time = ble_ll_tmr_get();
big_event_fixed = 0;
} else {
/* Set 1st BIG event directly before periodic advertising event, this
* way it will not overlap it even if periodic advertising data changes.
* Make sure it's in the future.
*/
big_time = start_time - g_ble_ll_sched_offset_ticks - sync_delay_ticks - 1;
while (big_time - g_ble_ll_sched_offset_ticks < ble_ll_tmr_get()) {
big_time += iso_interval_ticks;
}
big_start_time = padv_start_time - g_ble_ll_sched_offset_ticks -
sync_delay_ticks - 1;
big_event_fixed = 1;
}
big->anchor_base_ticks = big_time;
big->anchor_base_ticks = big_start_time;
big->anchor_base_rem_us = 0;
big->anchor_offset = 0;
big_sched_set(big);
do {
big->anchor_offset++;
big_sched_set(big);
rc = ble_ll_sched_iso_big(&big->sch, 1, big_event_fixed);
if (rc < 0) {
ble_ll_iso_big_free(big);
return -EFAULT;
}
if (LL_TMR_LEQ(big->sch.start_time, ble_ll_tmr_get())) {
rc = -1;
} else {
rc = ble_ll_sched_iso_big(&big->sch, 1, big_event_fixed);
}
} while (rc < 0);
ble_ll_iso_big_update_event_start(big);