This is an automated email from the ASF dual-hosted git repository.

andk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git

commit b6d7261d75028226ea01decab0fa5281c0eecbe8
Author: Andrzej Kaczmarek <[email protected]>
AuthorDate: Mon Sep 23 17:34:41 2024 +0200

    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.
---
 nimble/controller/include/controller/ble_ll_adv.h |  6 ++--
 nimble/controller/src/ble_ll_adv.c                | 17 ++++++-----
 nimble/controller/src/ble_ll_iso_big.c            | 35 +++++++++++------------
 3 files changed, 28 insertions(+), 30 deletions(-)

diff --git a/nimble/controller/include/controller/ble_ll_adv.h 
b/nimble/controller/include/controller/ble_ll_adv.h
index db35209dc..6c332faf3 100644
--- a/nimble/controller/include/controller/ble_ll_adv.h
+++ b/nimble/controller/include/controller/ble_ll_adv.h
@@ -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;
diff --git a/nimble/controller/src/ble_ll_adv.c 
b/nimble/controller/src/ble_ll_adv.c
index d8eaaaf3a..809a88776 100644
--- a/nimble/controller/src/ble_ll_adv.c
+++ b/nimble/controller/src/ble_ll_adv.c
@@ -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;
 }
diff --git a/nimble/controller/src/ble_ll_iso_big.c 
b/nimble/controller/src/ble_ll_iso_big.c
index b07e5c1d8..19af3e61f 100644
--- a/nimble/controller/src/ble_ll_iso_big.c
+++ b/nimble/controller/src/ble_ll_iso_big.c
@@ -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);
 

Reply via email to