You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by an...@apache.org on 2022/02/22 19:52:59 UTC

[mynewt-nimble] branch master updated (894d532 -> 8e7cbbb)

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

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


    from 894d532  babblesim: Remove sbrk
     new b399058  nimble/ll: Remove strict conn scheduling
     new bc19675  nimble/ll: Add conn_move_anchor
     new 22f5201  nimble/ll: Add new connection strict scheduling (css)
     new bf275cf  nimble/ll: Add HCI VS command to control css
     new 8e7cbbb  nimble/ll: Add fixed css option

The 5 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 nimble/controller/include/controller/ble_ll_conn.h |  14 +-
 nimble/controller/include/controller/ble_ll_ctrl.h |   3 +-
 .../controller/include/controller/ble_ll_sched.h   |  64 ++-
 nimble/controller/src/ble_ll_conn.c                | 248 ++++++++++--
 nimble/controller/src/ble_ll_conn_hci.c            |  57 ++-
 nimble/controller/src/ble_ll_conn_priv.h           |  13 +
 nimble/controller/src/ble_ll_ctrl.c                |  27 +-
 nimble/controller/src/ble_ll_hci_vs.c              | 137 +++++++
 nimble/controller/src/ble_ll_sched.c               | 442 +++++++--------------
 nimble/controller/syscfg.yml                       |  55 ++-
 nimble/include/nimble/hci_common.h                 |  22 +
 11 files changed, 676 insertions(+), 406 deletions(-)

[mynewt-nimble] 01/05: nimble/ll: Remove strict conn scheduling

Posted by an...@apache.org.
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 b3990580fb8a7eba88223489f8a9b54a141f1c0c
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Thu Feb 3 17:05:20 2022 +0100

    nimble/ll: Remove strict conn scheduling
    
    This removes strict scheduling code as we'll add new, more configurable
    implementation instead.
---
 nimble/controller/include/controller/ble_ll_conn.h |   4 -
 .../controller/include/controller/ble_ll_sched.h   |  33 ---
 nimble/controller/src/ble_ll_conn.c                |  27 +-
 nimble/controller/src/ble_ll_sched.c               | 296 ---------------------
 nimble/controller/syscfg.yml                       |  33 +--
 5 files changed, 13 insertions(+), 380 deletions(-)

diff --git a/nimble/controller/include/controller/ble_ll_conn.h b/nimble/controller/include/controller/ble_ll_conn.h
index cd219cb..015bac75 100644
--- a/nimble/controller/include/controller/ble_ll_conn.h
+++ b/nimble/controller/include/controller/ble_ll_conn.h
@@ -230,10 +230,6 @@ struct ble_ll_conn_sm
     uint8_t last_unmapped_chan;
     uint8_t num_used_chans;
 
-#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING)
-    uint8_t period_occ_mask;    /* mask: period 0 = 0x01, period 3 = 0x08 */
-#endif
-
     /* Ack/Flow Control */
     uint8_t tx_seqnum;          /* note: can be 1 bit */
     uint8_t next_exp_seqnum;    /* note: can be 1 bit */
diff --git a/nimble/controller/include/controller/ble_ll_sched.h b/nimble/controller/include/controller/ble_ll_sched.h
index 56399d2..b3f7d19 100644
--- a/nimble/controller/include/controller/ble_ll_sched.h
+++ b/nimble/controller/include/controller/ble_ll_sched.h
@@ -79,39 +79,6 @@ extern uint8_t g_ble_ll_sched_offset_ticks;
 struct ble_ll_sched_item;
 typedef int (*sched_cb_func)(struct ble_ll_sched_item *sch);
 typedef void (*sched_remove_cb_func)(struct ble_ll_sched_item *sch);
-/*
- * Strict connection scheduling (for the master) is different than how
- * connections are normally scheduled. With strict connection scheduling we
- * introduce the concept of a "period". A period is a collection of slots. Each
- * slot is 1.25 msecs in length. The number of slots in a period is determined
- * by the syscfg value BLE_LL_CONN_INIT_SLOTS. A collection of periods is called
- * an epoch. The length of an epoch is determined by the number of connections
- * (BLE_MAX_CONNECTIONS plus BLE_LL_ADD_STRICT_SCHED_PERIODS). Connections
- * will be scheduled at period boundaries. Any scanning/initiating/advertising
- * will be done in unused periods, if possible.
- */
-#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING)
-#define BLE_LL_SCHED_PERIODS    (MYNEWT_VAL(BLE_MAX_CONNECTIONS) + \
-                                 MYNEWT_VAL(BLE_LL_ADD_STRICT_SCHED_PERIODS))
-
-struct ble_ll_sched_obj
-{
-    uint8_t sch_num_occ_periods;
-    uint32_t sch_occ_period_mask;
-    uint32_t sch_ticks_per_period;
-    uint32_t sch_ticks_per_epoch;
-    uint32_t sch_epoch_start;
-};
-
-extern struct ble_ll_sched_obj g_ble_ll_sched_data;
-
-/*
- * XXX: TODO:
- * -> How do we know epoch start is up to date? Not wrapped?
- * -> for now, only do this with no more than 32 connections.
- * -> Do not let initiating occur if no empty sched slots
- */
-#endif
 
 /*
  * Schedule item
diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c
index 33a666a..f3e40a2 100644
--- a/nimble/controller/src/ble_ll_conn.c
+++ b/nimble/controller/src/ble_ll_conn.c
@@ -761,10 +761,6 @@ ble_ll_conn_continue_rx_encrypt(void *arg)
 static uint32_t
 ble_ll_conn_get_next_sched_time(struct ble_ll_conn_sm *connsm)
 {
-#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING)
-    uint32_t ce_end;
-    ce_end = connsm->ce_end_time;
-#else
     uint32_t ce_end;
     uint32_t next_sched_time;
     uint8_t rem_us;
@@ -781,7 +777,6 @@ ble_ll_conn_get_next_sched_time(struct ble_ll_conn_sm *connsm)
             ce_end = next_sched_time;
         }
     }
-#endif
 
     return ce_end;
 }
@@ -1934,16 +1929,6 @@ ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err)
     /* Make sure events off queue */
     ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &connsm->conn_ev_end);
 
-#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING)
-    /* Remove from occupied periods */
-    OS_ENTER_CRITICAL(sr);
-    BLE_LL_ASSERT(g_ble_ll_sched_data.sch_num_occ_periods > 0);
-    BLE_LL_ASSERT(g_ble_ll_sched_data.sch_occ_period_mask & connsm->period_occ_mask);
-    --g_ble_ll_sched_data.sch_num_occ_periods;
-    g_ble_ll_sched_data.sch_occ_period_mask &= ~connsm->period_occ_mask;
-    OS_EXIT_CRITICAL(sr);
-#endif
-
     /* Connection state machine is now idle */
     connsm->conn_state = BLE_LL_CONN_STATE_IDLE;
 
@@ -2219,12 +2204,9 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
      * Calculate ce end time. For a peripgheral, we need to add window widening
      * and the transmit window if we still have one.
      */
-#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING)
-    itvl = g_ble_ll_sched_data.sch_ticks_per_period;
-#else
     itvl = ble_ll_tmr_u2t(MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) *
                           BLE_LL_SCHED_USECS_PER_SLOT);
-#endif
+
 #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL)
     if (connsm->conn_role == BLE_LL_CONN_ROLE_PERIPHERAL) {
 
@@ -2333,17 +2315,10 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr)
 
         connsm->periph_cur_tx_win_usecs =
             connsm->tx_win_size * BLE_LL_CONN_TX_WIN_USECS;
-#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING)
-        connsm->ce_end_time = connsm->anchor_point +
-            g_ble_ll_sched_data.sch_ticks_per_period +
-            ble_ll_tmr_u2t(connsm->periph_cur_tx_win_usecs) + 1;
-
-#else
         connsm->ce_end_time = connsm->anchor_point +
                               ble_ll_tmr_u2t(MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) *
                                              BLE_LL_SCHED_USECS_PER_SLOT +
                                              connsm->periph_cur_tx_win_usecs) + 1;
-#endif
 
         /* Start the scheduler for the first connection event */
         while (ble_ll_sched_conn_periph_new(connsm)) {
diff --git a/nimble/controller/src/ble_ll_sched.c b/nimble/controller/src/ble_ll_sched.c
index b7d8cf6..14c8753 100644
--- a/nimble/controller/src/ble_ll_sched.c
+++ b/nimble/controller/src/ble_ll_sched.c
@@ -64,10 +64,6 @@ typedef int (* ble_ll_sched_preempt_cb_t)(struct ble_ll_sched_item *sch,
 static TAILQ_HEAD(ll_sched_qhead, ble_ll_sched_item) g_ble_ll_sched_q;
 static uint8_t g_ble_ll_sched_q_head_changed;
 
-#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING)
-struct ble_ll_sched_obj g_ble_ll_sched_data;
-#endif
-
 static int
 preempt_any(struct ble_ll_sched_item *sch,
             struct ble_ll_sched_item *item)
@@ -284,39 +280,6 @@ done:
     return sch->enqueued ? 0 : -1;
 }
 
-#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING)
-/**
- * Checks if two events in the schedule will overlap in time. NOTE: consecutive
- * schedule items can end and start at the same time.
- *
- * @param s1
- * @param s2
- *
- * @return int 0: dont overlap 1:overlap
- */
-static int
-ble_ll_sched_is_overlap(struct ble_ll_sched_item *s1,
-                        struct ble_ll_sched_item *s2)
-{
-    int rc;
-
-    rc = 1;
-    if (LL_TMR_LT(s1->start_time, s2->start_time)) {
-        /* Make sure this event does not overlap current event */
-        if (LL_TMR_LEQ(s1->end_time, s2->start_time)) {
-            rc = 0;
-        }
-    } else {
-        /* Check for overlap */
-        if (LL_TMR_GEQ(s1->start_time, s2->end_time)) {
-            rc = 0;
-        }
-    }
-
-    return rc;
-}
-#endif
-
 /*
  * Determines if the schedule item overlaps the currently running schedule
  * item. We only care about connection schedule items
@@ -338,21 +301,6 @@ ble_ll_sched_overlaps_current(struct ble_ll_sched_item *sch)
     return rc;
 }
 
-#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING)
-static struct ble_ll_sched_item *
-ble_ll_sched_insert_if_empty(struct ble_ll_sched_item *sch)
-{
-    struct ble_ll_sched_item *entry;
-
-    entry = TAILQ_FIRST(&g_ble_ll_sched_q);
-    if (!entry) {
-        TAILQ_INSERT_HEAD(&g_ble_ll_sched_q, sch, link);
-        sch->enqueued = 1;
-    }
-    return entry;
-}
-#endif
-
 int
 ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm)
 {
@@ -420,241 +368,6 @@ ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm)
  *
  * @return int
  */
-#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING)
-int
-ble_ll_sched_central_new(struct ble_ll_conn_sm *connsm,
-                         struct ble_mbuf_hdr *ble_hdr, uint8_t pyld_len)
-{
-    int rc;
-    os_sr_t sr;
-    uint32_t initial_start;
-    uint32_t earliest_start;
-    uint32_t earliest_end;
-    uint32_t dur;
-    uint32_t itvl_t;
-    uint32_t adv_rxend;
-    int i;
-    uint32_t tpp;
-    uint32_t tse;
-    uint32_t np;
-    uint32_t cp;
-    uint32_t tick_in_period;
-
-    struct ble_ll_sched_item *entry;
-    struct ble_ll_sched_item *sch;
-
-    /* Better have a connsm */
-    BLE_LL_ASSERT(connsm != NULL);
-
-    /* Get schedule element from connection */
-    rc = -1;
-    sch = &connsm->conn_sch;
-
-    /* XXX:
-     * The calculations for the 32kHz crystal bear alot of explanation. The
-     * earliest possible time that the central can start the connection with a
-     * peripheral is 1.25 msecs from the end of the connection request. The
-     * connection request is sent an IFS time from the end of the advertising
-     * packet that was received plus the time it takes to send the connection
-     * request. At 1 Mbps, this is 1752 usecs, or 57.41 ticks. Using 57 ticks
-     * makes us off ~13 usecs. Since we dont want to actually calculate the
-     * receive end time tick (this would take too long), we assume the end of
-     * the advertising PDU is 'now' (we call os_cputime_get32). We dont know
-     * how much time it will take to service the ISR but if we are more than the
-     * rx to tx time of the chip we will not be successful transmitting the
-     * connect request. All this means is that we presume that the peripheral will
-     * receive the connect request later than we expect but no earlier than
-     * 13 usecs before (this is important).
-     *
-     * The code then attempts to schedule the connection at the
-     * earliest time although this may not be possible. When the actual
-     * schedule start time is determined, the central has to determine if this
-     * time is more than a transmit window offset interval (1.25 msecs). The
-     * central has to tell the peripheral how many transmit window offsets there are
-     * from the earliest possible time to when the actual transmit start will
-     * occur. Later in this function you will see the calculation. The actual
-     * transmission start has to occur within the transmit window. The transmit
-     * window interval is in units of 1.25 msecs and has to be at least 1. To
-     * make things a bit easier (but less power efficient for the peripheral), we
-     * use a transmit window of 2. We do this because we dont quite know the
-     * exact start of the transmission and if we are too early or too late we
-     * could miss the transmit window. A final note: the actual transmission
-     * start (the anchor point) is sched offset ticks from the schedule start
-     * time. We dont add this to the calculation when calculating the window
-     * offset. The reason we dont do this is we want to insure we transmit
-     * after the window offset we tell the peripheral. For example, say we think
-     * we are transmitting 1253 usecs from the earliest start. This would cause
-     * us to send a transmit window offset of 1. Since we are actually
-     * transmitting earlier than the peripheral thinks we could end up transmitting
-     * before the window offset. Transmitting later is fine since we have the
-     * transmit window to do so. Transmitting before is bad, since the peripheral
-     * wont be listening. We could do better calculation if we wanted to use
-     * a transmit window of 1 as opposed to 2, but for now we dont care.
-     */
-    dur = ble_ll_tmr_u2t(g_ble_ll_sched_data.sch_ticks_per_period);
-    adv_rxend = ble_ll_tmr_get();
-    if (ble_hdr->rxinfo.channel >= BLE_PHY_NUM_DATA_CHANS) {
-        /*
-         * We received packet on advertising channel which means this is a legacy
-         * PDU on 1 Mbps - we do as described above.
-         */
-        earliest_start = adv_rxend + 57;
-    } else {
-        /*
-         * The calculations are similar as above.
-         *
-         * We received packet on data channel which means this is AUX_ADV_IND
-         * received on secondary adv channel. We can schedule first packet at
-         * the earliest after "T_IFS + AUX_CONNECT_REQ + transmitWindowDelay".
-         * AUX_CONNECT_REQ and transmitWindowDelay times vary depending on which
-         * PHY we received on.
-         *
-         */
-        if (ble_hdr->rxinfo.phy == BLE_PHY_1M) {
-            // 150 + 352 + 2500 = 3002us = 98.37 ticks
-            earliest_start = adv_rxend + 98;
-        } else if (ble_hdr->rxinfo.phy == BLE_PHY_2M) {
-            // 150 + 180 + 2500 = 2830us = 92.73 ticks
-            earliest_start = adv_rxend + 93;
-        } else if (ble_hdr->rxinfo.phy == BLE_PHY_CODED) {
-            // 150 + 2896 + 3750 = 6796us = 222.69 ticks
-            earliest_start = adv_rxend + 223;
-        } else {
-            BLE_LL_ASSERT(0);
-        }
-    }
-    earliest_start += MYNEWT_VAL(BLE_LL_CONN_INIT_MIN_WIN_OFFSET) *
-                      BLE_LL_SCHED_USECS_PER_SLOT;
-    itvl_t = connsm->conn_itvl_ticks;
-
-    /* We have to find a place for this schedule */
-    OS_ENTER_CRITICAL(sr);
-
-    /*
-     * Are there any allocated periods? If not, set epoch start to earliest
-     * time
-     */
-    if (g_ble_ll_sched_data.sch_num_occ_periods == 0) {
-        g_ble_ll_sched_data.sch_epoch_start = earliest_start;
-        cp = 0;
-    } else {
-        /*
-         * Earliest start must occur on period boundary.
-         * (tse = ticks since epoch)
-         */
-        tpp = g_ble_ll_sched_data.sch_ticks_per_period;
-        tse = earliest_start - g_ble_ll_sched_data.sch_epoch_start;
-        np = tse / tpp;
-        cp = np % BLE_LL_SCHED_PERIODS;
-        tick_in_period = tse - (np * tpp);
-        if (tick_in_period != 0) {
-            ++cp;
-            if (cp == BLE_LL_SCHED_PERIODS) {
-                cp = 0;
-            }
-            earliest_start += (tpp - tick_in_period);
-        }
-
-        /* Now find first un-occupied period starting from cp */
-        for (i = 0; i < BLE_LL_SCHED_PERIODS; ++i) {
-            if (g_ble_ll_sched_data.sch_occ_period_mask & (1 << cp)) {
-                ++cp;
-                if (cp == BLE_LL_SCHED_PERIODS) {
-                    cp = 0;
-                }
-                earliest_start += tpp;
-            } else {
-                /* not occupied */
-                break;
-            }
-        }
-        /* Should never happen but if it does... */
-        if (i == BLE_LL_SCHED_PERIODS) {
-            OS_EXIT_CRITICAL(sr);
-            return rc;
-        }
-    }
-
-    sch->start_time = earliest_start;
-    initial_start = earliest_start;
-    earliest_end = earliest_start + dur;
-
-    if (!ble_ll_sched_insert_if_empty(sch)) {
-        /* Nothing in schedule. Schedule as soon as possible */
-        rc = 0;
-        connsm->tx_win_off = MYNEWT_VAL(BLE_LL_CONN_INIT_MIN_WIN_OFFSET);
-    } else {
-        ble_ll_tmr_stop(&g_ble_ll_sched_timer);
-        TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) {
-            /* Set these because overlap function needs them to be set */
-            sch->start_time = earliest_start;
-            sch->end_time = earliest_end;
-
-            /* We can insert if before entry in list */
-            if (LL_TMR_LEQ(sch->end_time, entry->start_time)) {
-                if ((earliest_start - initial_start) <= itvl_t) {
-                    rc = 0;
-                    TAILQ_INSERT_BEFORE(entry, sch, link);
-                }
-                break;
-            }
-
-            /* Check for overlapping events */
-            if (ble_ll_sched_is_overlap(sch, entry)) {
-                /* Earliest start is end of this event since we overlap */
-                earliest_start = entry->end_time;
-                earliest_end = earliest_start + dur;
-            }
-        }
-
-        /* Must be able to schedule within one connection interval */
-        if (!entry) {
-            if ((earliest_start - initial_start) <= itvl_t) {
-                rc = 0;
-                TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link);
-            }
-        }
-
-        if (!rc) {
-            /* calculate number of window offsets. Each offset is 1.25 ms */
-            sch->enqueued = 1;
-            /*
-             * NOTE: we dont add sched offset ticks as we want to under-estimate
-             * the transmit window slightly since the window size is currently
-             * 2 when using a 32768 crystal.
-             */
-            dur = ble_ll_tmr_t2u(earliest_start - initial_start);
-            connsm->tx_win_off = dur / BLE_LL_CONN_TX_OFF_USECS;
-        }
-    }
-
-    if (!rc) {
-        sch->start_time = earliest_start;
-        sch->end_time = earliest_end;
-        /*
-         * Since we have the transmit window to transmit in, we dont need
-         * to set the anchor point usecs; just transmit to the nearest tick.
-         */
-        connsm->anchor_point = earliest_start + g_ble_ll_sched_offset_ticks;
-        connsm->anchor_point_usecs = 0;
-        connsm->ce_end_time = earliest_end;
-        connsm->period_occ_mask = (1 << cp);
-        g_ble_ll_sched_data.sch_occ_period_mask |= connsm->period_occ_mask;
-        ++g_ble_ll_sched_data.sch_num_occ_periods;
-    }
-
-
-    /* Get head of list to restart timer */
-    sch = TAILQ_FIRST(&g_ble_ll_sched_q);
-    ble_ll_rfmgmt_sched_changed(sch);
-
-    OS_EXIT_CRITICAL(sr);
-
-    ble_ll_tmr_start(&g_ble_ll_sched_timer, sch->start_time);
-
-    return rc;
-}
-#else
 int
 ble_ll_sched_conn_central_new(struct ble_ll_conn_sm *connsm,
                               struct ble_mbuf_hdr *ble_hdr, uint8_t pyld_len)
@@ -778,7 +491,6 @@ ble_ll_sched_conn_central_new(struct ble_ll_conn_sm *connsm,
 
     return rc;
 }
-#endif
 
 /**
  * Schedules a peripheral connection for the first time.
@@ -1388,14 +1100,6 @@ ble_ll_sched_init(void)
     /* Initialize cputimer for the scheduler */
     ble_ll_tmr_init(&g_ble_ll_sched_timer, ble_ll_sched_run, NULL);
 
-#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING)
-    memset(&g_ble_ll_sched_data, 0, sizeof(struct ble_ll_sched_obj));
-    g_ble_ll_sched_data.sch_ticks_per_period =
-        ble_ll_tmr_u2t(MYNEWT_VAL(BLE_LL_USECS_PER_PERIOD));
-    g_ble_ll_sched_data.sch_ticks_per_epoch = BLE_LL_SCHED_PERIODS *
-        g_ble_ll_sched_data.sch_ticks_per_period;
-#endif
-
     g_ble_ll_sched_q_head_changed = 0;
 
     return 0;
diff --git a/nimble/controller/syscfg.yml b/nimble/controller/syscfg.yml
index b565ce4..8ecdd2c 100644
--- a/nimble/controller/syscfg.yml
+++ b/nimble/controller/syscfg.yml
@@ -146,27 +146,6 @@ syscfg.defs:
             ensure interoperability with such devices set this value to 2 (or more).
         value: '0'
 
-    # Strict scheduling
-    BLE_LL_STRICT_CONN_SCHEDULING:
-        description: >
-            Forces the scheduler on a central to schedule connections in fixed
-            time intervals called periods. If set to 0, the scheduler is not forced
-            to do this. If set to 1, the scheduler will only schedule connections at
-            period boundaries. See comments in ble_ll_sched.h for more details.
-        value: '0'
-
-    BLE_LL_ADD_STRICT_SCHED_PERIODS:
-        description: >
-            The number of additional periods that will be allocated for strict
-            scheduling. The total # of periods allocated for strict scheduling
-            will be equal to the number of connections plus this number.
-        value: '0'
-
-    BLE_LL_USECS_PER_PERIOD:
-        description: >
-            The number of usecs per period.
-        value: '3250'
-
     # The number of random bytes to store
     BLE_LL_RNG_BUFSIZE:
         description: >
@@ -505,6 +484,18 @@ syscfg.defs:
         description: Superseded by BLE_LL_CFG_FEAT_PERIPH_INIT_FEAT_XCHG
         value: 0
         defaunt: 1
+    BLE_LL_STRICT_CONN_SCHEDULING:
+        description: Superseded by BLE_LL_CONN_STRICT_SCHED
+        value: 0
+        defunct: 1
+    BLE_LL_ADD_STRICT_SCHED_PERIODS:
+        description: Superseded by BLE_LL_CONN_STRICT_SCHED
+        value: 0
+        defunct: 1
+    BLE_LL_USECS_PER_PERIOD:
+        description: Superseded by BLE_LL_CONN_STRICT_SCHED
+        value: 0
+        defunct: 1
 
 syscfg.vals.BLE_LL_CFG_FEAT_LL_EXT_ADV:
     BLE_LL_CFG_FEAT_LE_CSA2: 1

[mynewt-nimble] 04/05: nimble/ll: Add HCI VS command to control css

Posted by an...@apache.org.
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 bf275cf3bacf934bd2fe676fce218ec4613246e5
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Fri Feb 4 01:12:29 2022 +0100

    nimble/ll: Add HCI VS command to control css
    
    This adds hci vs command to control css parameters. The command has few
    sub-commands that allow to:
    - set slot duration and slots per period parameter
    - set slot allocation for next requested connection
    - set slot allocation for existing connection
    
    Reconfiguration of css parameters can only be done only if there are no
    active connections so we do not need to bother with moving existing
    connections around.
---
 nimble/controller/src/ble_ll_hci_vs.c | 133 ++++++++++++++++++++++++++++++++++
 nimble/controller/syscfg.yml          |   3 +
 nimble/include/nimble/hci_common.h    |  22 ++++++
 3 files changed, 158 insertions(+)

diff --git a/nimble/controller/src/ble_ll_hci_vs.c b/nimble/controller/src/ble_ll_hci_vs.c
index f2057ea..5049b39 100644
--- a/nimble/controller/src/ble_ll_hci_vs.c
+++ b/nimble/controller/src/ble_ll_hci_vs.c
@@ -134,11 +134,144 @@ ble_ll_hci_vs_set_tx_power(uint16_t ocf, const uint8_t *cmdbuf, uint8_t cmdlen,
     return BLE_ERR_SUCCESS;
 }
 
+
+#if MYNEWT_VAL(BLE_LL_HCI_VS_CONN_STRICT_SCHED)
+static int
+ble_ll_hci_vs_css_configure(const uint8_t *cmdbuf, uint8_t cmdlen,
+                            uint8_t *rspbuf, uint8_t *rsplen)
+{
+    const struct ble_hci_vs_css_configure_cp *cmd = (const void *)cmdbuf;
+    uint32_t slot_us;
+    uint32_t period_slots;
+
+    if (cmdlen != sizeof(*cmd)) {
+        return BLE_ERR_INV_HCI_CMD_PARMS;
+    }
+
+    if (!SLIST_EMPTY(&g_ble_ll_conn_active_list)) {
+        return BLE_ERR_CTLR_BUSY;
+    }
+
+    slot_us = le32toh(cmd->slot_us);
+    period_slots = le32toh(cmd->period_slots);
+
+    if (slot_us % BLE_LL_CONN_ITVL_USECS) {
+        return BLE_ERR_INV_HCI_CMD_PARMS;
+    }
+
+    if ((slot_us == 0) || (period_slots == 0)) {
+        return BLE_ERR_INV_HCI_CMD_PARMS;
+    }
+
+    ble_ll_sched_css_set_params(slot_us, period_slots);
+
+    return BLE_ERR_SUCCESS;
+}
+
+static int
+ble_ll_hci_vs_css_set_next_slot(const uint8_t *cmdbuf, uint8_t cmdlen,
+                                uint8_t *rspbuf, uint8_t *rsplen)
+{
+    const struct ble_hci_vs_css_set_next_slot_cp *cmd = (const void *)cmdbuf;
+    uint16_t slot_idx;
+
+    if (cmdlen != sizeof(*cmd)) {
+        return BLE_ERR_INV_HCI_CMD_PARMS;
+    }
+
+    slot_idx = le16toh(cmd->slot_idx);
+    if ((slot_idx >= ble_ll_sched_css_get_period_slots()) &&
+        (slot_idx != BLE_LL_CONN_CSS_NO_SLOT)) {
+        return BLE_ERR_INV_HCI_CMD_PARMS;
+    }
+
+    if (ble_ll_conn_css_is_slot_busy(slot_idx)) {
+        return BLE_ERR_CTLR_BUSY;
+    }
+
+    ble_ll_conn_css_set_next_slot(slot_idx);
+
+    return BLE_ERR_SUCCESS;
+}
+
+static int
+ble_ll_hci_vs_css_set_conn_slot(const uint8_t *cmdbuf, uint8_t cmdlen,
+                                uint8_t *rspbuf, uint8_t *rsplen)
+{
+    const struct ble_hci_vs_css_set_conn_slot_cp *cmd = (const void *)cmdbuf;
+    struct ble_ll_conn_sm *connsm;
+    uint16_t conn_handle;
+    uint16_t slot_idx;
+
+    if (cmdlen != sizeof(*cmd)) {
+        return BLE_ERR_INV_HCI_CMD_PARMS;
+    }
+
+    slot_idx = le16toh(cmd->slot_idx);
+    if ((slot_idx >= ble_ll_sched_css_get_period_slots()) &&
+        (slot_idx != BLE_LL_CONN_CSS_NO_SLOT)) {
+        return BLE_ERR_INV_HCI_CMD_PARMS;
+    }
+
+    if (ble_ll_conn_css_is_slot_busy(slot_idx)) {
+        return BLE_ERR_CTLR_BUSY;
+    }
+
+    conn_handle = le16toh(cmd->conn_handle);
+    connsm = ble_ll_conn_find_active_conn(conn_handle);
+    if (!connsm) {
+        return BLE_ERR_UNK_CONN_ID;
+    }
+
+    if (connsm->css_slot_idx_pending != BLE_LL_CONN_CSS_NO_SLOT) {
+        return BLE_ERR_DIFF_TRANS_COLL;
+    }
+
+    if (connsm->css_slot_idx == slot_idx) {
+        return BLE_ERR_CMD_DISALLOWED;
+    }
+
+    if (ble_ll_conn_css_move(connsm, slot_idx) < 0) {
+        return BLE_ERR_CTLR_BUSY;
+    }
+
+    return BLE_ERR_SUCCESS;
+}
+
+static int
+ble_ll_hci_vs_css(uint16_t ocf, const uint8_t *cmdbuf, uint8_t cmdlen,
+                  uint8_t *rspbuf, uint8_t *rsplen)
+{
+    const struct ble_hci_vs_css_cp *cmd = (const void *)cmdbuf;
+
+    if (cmdlen < sizeof(*cmd)) {
+        return BLE_ERR_INV_HCI_CMD_PARMS;
+    }
+
+    *rsplen = 0;
+
+    switch (cmd->opcode) {
+    case BLE_HCI_VS_CSS_OP_CONFIGURE:
+        return ble_ll_hci_vs_css_configure(cmdbuf, cmdlen, rspbuf, rsplen);
+    case BLE_HCI_VS_CSS_OP_SET_NEXT_SLOT:
+        return ble_ll_hci_vs_css_set_next_slot(cmdbuf, cmdlen, rspbuf, rsplen);
+    case BLE_HCI_VS_CSS_OP_SET_CONN_SLOT:
+        return ble_ll_hci_vs_css_set_conn_slot(cmdbuf, cmdlen, rspbuf, rsplen);
+    }
+
+    return BLE_ERR_INV_HCI_CMD_PARMS;
+}
+#endif
+
 static struct ble_ll_hci_vs_cmd g_ble_ll_hci_vs_cmds[] = {
     BLE_LL_HCI_VS_CMD(BLE_HCI_OCF_VS_RD_STATIC_ADDR,
                       ble_ll_hci_vs_rd_static_addr),
     BLE_LL_HCI_VS_CMD(BLE_HCI_OCF_VS_SET_TX_PWR,
             ble_ll_hci_vs_set_tx_power),
+#if MYNEWT_VAL(BLE_LL_HCI_VS_CONN_STRICT_SCHED)
+    BLE_LL_HCI_VS_CMD(BLE_HCI_OCF_VS_CSS,
+                      ble_ll_hci_vs_css),
+#endif
 };
 
 static struct ble_ll_hci_vs_cmd *
diff --git a/nimble/controller/syscfg.yml b/nimble/controller/syscfg.yml
index de6b5ea..8f08dd7 100644
--- a/nimble/controller/syscfg.yml
+++ b/nimble/controller/syscfg.yml
@@ -363,6 +363,9 @@ syscfg.defs:
         description: >
             Enables support for vendor-specific HCI commands.
         value: MYNEWT_VAL(BLE_HCI_VS)
+    BLE_LL_HCI_VS_CONN_STRICT_SCHED:
+        description: xxx
+        value: 0
 
     BLE_LL_HCI_VS_EVENT_ON_ASSERT:
         description: >
diff --git a/nimble/include/nimble/hci_common.h b/nimble/include/nimble/hci_common.h
index 32d06b6..8faebe4 100644
--- a/nimble/include/nimble/hci_common.h
+++ b/nimble/include/nimble/hci_common.h
@@ -1079,6 +1079,28 @@ struct ble_hci_vs_set_tx_pwr_rp {
     int8_t tx_power;
 } __attribute__((packed));
 
+#define BLE_HCI_OCF_VS_CSS                              (0x0003)
+struct ble_hci_vs_css_cp {
+    uint8_t opcode;
+} __attribute__((packed));
+#define BLE_HCI_VS_CSS_OP_CONFIGURE                     0x01
+struct ble_hci_vs_css_configure_cp {
+    uint8_t opcode;
+    uint32_t slot_us;
+    uint32_t period_slots;
+} __attribute__((packed));
+#define BLE_HCI_VS_CSS_OP_SET_NEXT_SLOT                 0x02
+struct ble_hci_vs_css_set_next_slot_cp {
+    uint8_t opcode;
+    uint16_t slot_idx;
+} __attribute__((packed));
+#define BLE_HCI_VS_CSS_OP_SET_CONN_SLOT                 0x03
+struct ble_hci_vs_css_set_conn_slot_cp {
+    uint8_t opcode;
+    uint16_t conn_handle;
+    uint16_t slot_idx;
+} __attribute__((packed));
+
 /* Command Specific Definitions */
 /* --- Set controller to host flow control (OGF 0x03, OCF 0x0031) --- */
 #define BLE_HCI_CTLR_TO_HOST_FC_OFF         (0)

[mynewt-nimble] 02/05: nimble/ll: Add conn_move_anchor

Posted by an...@apache.org.
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 bc196758299f20044f3032342d847a45552e9f84
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Fri Feb 4 14:03:19 2022 +0100

    nimble/ll: Add conn_move_anchor
    
    Central can move anchor to e.g. optimize scheduling.
---
 nimble/controller/include/controller/ble_ll_conn.h |  4 +++
 nimble/controller/include/controller/ble_ll_ctrl.h |  3 +-
 nimble/controller/src/ble_ll_conn.c                | 35 +++++++++++++++++++---
 nimble/controller/src/ble_ll_conn_hci.c            | 10 +++----
 nimble/controller/src/ble_ll_ctrl.c                | 17 ++++++-----
 5 files changed, 51 insertions(+), 18 deletions(-)

diff --git a/nimble/controller/include/controller/ble_ll_conn.h b/nimble/controller/include/controller/ble_ll_conn.h
index 015bac75..9075e7e 100644
--- a/nimble/controller/include/controller/ble_ll_conn.h
+++ b/nimble/controller/include/controller/ble_ll_conn.h
@@ -397,6 +397,10 @@ uint8_t ble_ll_conn_calc_dci(struct ble_ll_conn_sm *conn, uint16_t latency);
 void ble_ll_conn_get_anchor(struct ble_ll_conn_sm *connsm, uint16_t conn_event,
                             uint32_t *anchor, uint8_t *anchor_usecs);
 
+#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL)
+int ble_ll_conn_move_anchor(struct ble_ll_conn_sm *connsm, uint16_t offset);
+#endif
+
 struct ble_ll_scan_addr_data;
 struct ble_ll_scan_pdu_data;
 
diff --git a/nimble/controller/include/controller/ble_ll_ctrl.h b/nimble/controller/include/controller/ble_ll_ctrl.h
index ebac33d..423d13a 100644
--- a/nimble/controller/include/controller/ble_ll_ctrl.h
+++ b/nimble/controller/include/controller/ble_ll_ctrl.h
@@ -292,7 +292,8 @@ struct ble_ll_len_req
 
 /* API */
 struct ble_ll_conn_sm;
-void ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int ctrl_proc);
+void ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int ctrl_proc,
+                            void *data);
 void ble_ll_ctrl_proc_stop(struct ble_ll_conn_sm *connsm, int ctrl_proc);
 int ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om);
 void ble_ll_ctrl_chk_proc_start(struct ble_ll_conn_sm *connsm);
diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c
index f3e40a2..0243577 100644
--- a/nimble/controller/src/ble_ll_conn.c
+++ b/nimble/controller/src/ble_ll_conn.c
@@ -416,7 +416,7 @@ ble_ll_conn_chk_phy_upd_start(struct ble_ll_conn_sm *csm)
     } else {
         csm->phy_data.req_pref_tx_phys_mask = csm->phy_data.host_pref_tx_phys_mask;
         csm->phy_data.req_pref_rx_phys_mask = csm->phy_data.host_pref_rx_phys_mask;
-        ble_ll_ctrl_proc_start(csm, BLE_LL_CTRL_PROC_PHY_UPDATE);
+        ble_ll_ctrl_proc_start(csm, BLE_LL_CTRL_PROC_PHY_UPDATE, NULL);
         rc = 0;
     }
 
@@ -1530,7 +1530,7 @@ ble_ll_conn_auth_pyld_timer_cb(struct ble_npl_event *ev)
 
     connsm = (struct ble_ll_conn_sm *)ble_npl_event_get_arg(ev);
     ble_ll_auth_pyld_tmo_event_send(connsm);
-    ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_LE_PING);
+    ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_LE_PING, NULL);
     ble_ll_conn_auth_pyld_timer_start(connsm);
 }
 
@@ -1994,6 +1994,32 @@ ble_ll_conn_get_anchor(struct ble_ll_conn_sm *connsm, uint16_t conn_event,
 }
 #endif
 
+#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL)
+int
+ble_ll_conn_move_anchor(struct ble_ll_conn_sm *connsm, uint16_t offset)
+{
+    struct ble_ll_conn_params cp = { };
+
+    BLE_LL_ASSERT(connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL);
+
+    if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ) ||
+        IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CONN_UPDATE)) {
+        return -1;
+    }
+
+    /* Keep parameters, we just want to move anchor */
+    cp.interval_max = connsm->conn_itvl;
+    cp.interval_min = connsm->conn_itvl;
+    cp.latency = connsm->periph_latency;
+    cp.timeout = connsm->supervision_tmo;
+    cp.offset0 = offset;
+
+    ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_CONN_UPDATE, &cp);
+
+    return 0;
+}
+#endif
+
 /**
  * Called to move to the next connection event.
  *
@@ -2363,7 +2389,8 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr)
              * models; for peripheral just assume central will initiate features xchg
              * if it has some additional features to use.
              */
-            ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG);
+            ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG,
+                                   NULL);
             break;
 #endif
 #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL)
@@ -3542,7 +3569,7 @@ ble_ll_conn_set_global_chanmap(uint8_t num_used_chans, const uint8_t *chanmap)
     /* Perform channel map update */
     SLIST_FOREACH(connsm, &g_ble_ll_conn_active_list, act_sle) {
         if (connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL) {
-            ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_CHAN_MAP_UPD);
+            ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_CHAN_MAP_UPD, NULL);
         }
     }
 #endif
diff --git a/nimble/controller/src/ble_ll_conn_hci.c b/nimble/controller/src/ble_ll_conn_hci.c
index 6664458..cd3deae 100644
--- a/nimble/controller/src/ble_ll_conn_hci.c
+++ b/nimble/controller/src/ble_ll_conn_hci.c
@@ -860,7 +860,7 @@ ble_ll_conn_hci_read_rem_features(const uint8_t *cmdbuf, uint8_t len)
         }
 #endif
 
-        ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG);
+        ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG, NULL);
     }
 
     connsm->csmflags.cfbit.pending_hci_rd_features = 1;
@@ -980,7 +980,7 @@ ble_ll_conn_hci_update(const uint8_t *cmdbuf, uint8_t len)
         hcu->handle = handle;
 
         /* Start the control procedure */
-        ble_ll_ctrl_proc_start(connsm, ctrl_proc);
+        ble_ll_ctrl_proc_start(connsm, ctrl_proc, NULL);
     }
 
     return rc;
@@ -1257,7 +1257,7 @@ ble_ll_conn_hci_rd_rem_ver_cmd(const uint8_t *cmdbuf, uint8_t len)
      * be queued before the command status.
      */
     if (!connsm->csmflags.cfbit.version_ind_sent) {
-        ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_VERSION_XCHG);
+        ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_VERSION_XCHG, NULL);
     } else {
         connsm->pending_ctrl_procs |= (1 << BLE_LL_CTRL_PROC_VERSION_XCHG);
     }
@@ -1483,7 +1483,7 @@ ble_ll_conn_hci_le_start_encrypt(const uint8_t *cmdbuf, uint8_t len)
         connsm->enc_data.host_rand_num = le64toh(cmd->rand);
         connsm->enc_data.enc_div = le16toh(cmd->div);
         swap_buf(connsm->enc_data.enc_block.key, cmd->ltk, 16);
-        ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_ENCRYPT);
+        ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_ENCRYPT, NULL);
         rc = BLE_ERR_SUCCESS;
     }
 
@@ -1633,7 +1633,7 @@ ble_ll_conn_req_peer_sca(const uint8_t *cmdbuf, uint8_t len,
         return BLE_ERR_CTLR_BUSY;
     }
 
-    ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_SCA_UPDATE);
+    ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_SCA_UPDATE, NULL);
 
     return 0;
 }
diff --git a/nimble/controller/src/ble_ll_ctrl.c b/nimble/controller/src/ble_ll_ctrl.c
index 62272d7..a153a57 100644
--- a/nimble/controller/src/ble_ll_ctrl.c
+++ b/nimble/controller/src/ble_ll_ctrl.c
@@ -1960,7 +1960,7 @@ ble_ll_ctrl_initiate_dle(struct ble_ll_conn_sm *connsm)
         return;
     }
 
-    ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD);
+    ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD, NULL);
 }
 
 static void
@@ -2284,7 +2284,7 @@ ble_ll_ctrl_rx_chanmap_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
  * @param ctrl_proc
  */
 static struct os_mbuf *
-ble_ll_ctrl_proc_init(struct ble_ll_conn_sm *connsm, int ctrl_proc)
+ble_ll_ctrl_proc_init(struct ble_ll_conn_sm *connsm, int ctrl_proc, void *data)
 {
     uint8_t len;
     uint8_t opcode;
@@ -2303,7 +2303,7 @@ ble_ll_ctrl_proc_init(struct ble_ll_conn_sm *connsm, int ctrl_proc)
         switch (ctrl_proc) {
         case BLE_LL_CTRL_PROC_CONN_UPDATE:
             opcode = BLE_LL_CTRL_CONN_UPDATE_IND;
-            ble_ll_ctrl_conn_upd_make(connsm, ctrdata, NULL);
+            ble_ll_ctrl_conn_upd_make(connsm, ctrdata, data);
             break;
         case BLE_LL_CTRL_PROC_CHAN_MAP_UPD:
             opcode = BLE_LL_CTRL_CHANNEL_MAP_REQ;
@@ -2452,7 +2452,7 @@ ble_ll_ctrl_terminate_start(struct ble_ll_conn_sm *connsm)
     BLE_LL_ASSERT(connsm->disconnect_reason != 0);
 
     ctrl_proc = BLE_LL_CTRL_PROC_TERMINATE;
-    om = ble_ll_ctrl_proc_init(connsm, ctrl_proc);
+    om = ble_ll_ctrl_proc_init(connsm, ctrl_proc, NULL);
     if (om) {
         CONN_F_TERMINATE_STARTED(connsm) = 1;
 
@@ -2472,7 +2472,8 @@ ble_ll_ctrl_terminate_start(struct ble_ll_conn_sm *connsm)
  * @param connsm Pointer to connection state machine.
  */
 void
-ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int ctrl_proc)
+ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int ctrl_proc,
+                       void *data)
 {
     struct os_mbuf *om;
 
@@ -2481,7 +2482,7 @@ ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int ctrl_proc)
     om = NULL;
     if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_IDLE) {
         /* Initiate the control procedure. */
-        om = ble_ll_ctrl_proc_init(connsm, ctrl_proc);
+        om = ble_ll_ctrl_proc_init(connsm, ctrl_proc, data);
         if (om) {
             /* Set the current control procedure */
             connsm->cur_ctrl_proc = ctrl_proc;
@@ -2548,7 +2549,7 @@ ble_ll_ctrl_chk_proc_start(struct ble_ll_conn_sm *connsm)
                     ble_ll_hci_ev_rd_rem_ver(connsm, BLE_ERR_SUCCESS);
                     CLR_PENDING_CTRL_PROC(connsm, i);
                 } else {
-                    ble_ll_ctrl_proc_start(connsm, i);
+                    ble_ll_ctrl_proc_start(connsm, i, NULL);
                     break;
                 }
             }
@@ -2863,7 +2864,7 @@ ll_ctrl_send_rsp:
         if (restart_encryption) {
             /* XXX: what happens if this fails? Meaning we cant allocate
                mbuf? */
-            ble_ll_ctrl_proc_init(connsm, BLE_LL_CTRL_PROC_ENCRYPT);
+            ble_ll_ctrl_proc_init(connsm, BLE_LL_CTRL_PROC_ENCRYPT, NULL);
         }
 #endif
     }

[mynewt-nimble] 03/05: nimble/ll: Add new connection strict scheduling (css)

Posted by an...@apache.org.
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 22f5201717bd5709d65f371aae775bbb8bc77935
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Thu Feb 3 23:40:45 2022 +0100

    nimble/ll: Add new connection strict scheduling (css)
    
    This adds new connection strict scheduling code. The idea is based on
    old code, but it was rewritten from scratch to allow more control over
    scheduling.
    
    Scheduling policy in css mode is defined by slot duration and number of
    slots per period (which implicitly defined period duration). Each
    connection in central role is only scheduled on slot boundary and has
    connection interval equal to period duration. This means there can be
    up to number-of-slots connection in central role established.
    
    The main difference to the previous implementation is more control over
    slot allocation for each connection. In particular, it's possible to
    assing an arbitrary slot index to each connection and thus adjust max
    connection event for each connection, depending on requirements.
---
 nimble/controller/include/controller/ble_ll_conn.h |   6 +
 .../controller/include/controller/ble_ll_sched.h   |   8 +
 nimble/controller/src/ble_ll_conn.c                | 186 ++++++++++++++++++++-
 nimble/controller/src/ble_ll_conn_hci.c            |  47 ++++++
 nimble/controller/src/ble_ll_conn_priv.h           |  13 ++
 nimble/controller/src/ble_ll_ctrl.c                |  10 ++
 nimble/controller/src/ble_ll_sched.c               | 138 ++++++++++++++-
 nimble/controller/syscfg.yml                       |  21 +++
 8 files changed, 417 insertions(+), 12 deletions(-)

diff --git a/nimble/controller/include/controller/ble_ll_conn.h b/nimble/controller/include/controller/ble_ll_conn.h
index 9075e7e..133824b 100644
--- a/nimble/controller/include/controller/ble_ll_conn.h
+++ b/nimble/controller/include/controller/ble_ll_conn.h
@@ -351,6 +351,12 @@ struct ble_ll_conn_sm
     uint16_t sync_transfer_skip;
     uint32_t sync_transfer_sync_timeout;
 #endif
+
+#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
+    uint16_t css_slot_idx;
+    uint16_t css_slot_idx_pending;
+    uint8_t css_period_idx;
+#endif
 };
 
 /* Flags */
diff --git a/nimble/controller/include/controller/ble_ll_sched.h b/nimble/controller/include/controller/ble_ll_sched.h
index b3f7d19..a79262a 100644
--- a/nimble/controller/include/controller/ble_ll_sched.h
+++ b/nimble/controller/include/controller/ble_ll_sched.h
@@ -175,6 +175,14 @@ void ble_ll_sched_stop(void);
 int ble_ll_sched_dtm(struct ble_ll_sched_item *sch);
 #endif
 
+#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
+void ble_ll_sched_css_set_params(uint32_t slot_us, uint32_t period_slots);
+void ble_ll_sched_css_set_conn_anchor(struct ble_ll_conn_sm *connsm);
+uint32_t ble_ll_sched_css_get_slot_us(void);
+uint32_t ble_ll_sched_css_get_period_slots(void);
+uint32_t ble_ll_sched_css_get_conn_interval_us(void);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c
index 0243577..6bd9758 100644
--- a/nimble/controller/src/ble_ll_conn.c
+++ b/nimble/controller/src/ble_ll_conn.c
@@ -46,6 +46,10 @@
 extern void bletest_completed_pkt(uint16_t handle);
 #endif
 
+#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
+struct ble_ll_conn_sm *g_ble_ll_conn_css_ref;
+#endif
+
 /* XXX TODO
  * 1) I think if we are initiating and we already have a connection with
  * a device that we will still try and connect to it. Fix this.
@@ -388,6 +392,97 @@ ble_ll_conn_cth_flow_process_cmd(const uint8_t *cmdbuf)
 }
 #endif
 
+
+#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
+static uint16_t g_ble_ll_conn_css_next_slot = BLE_LL_CONN_CSS_NO_SLOT;
+
+void
+ble_ll_conn_css_set_next_slot(uint16_t slot_idx)
+{
+    g_ble_ll_conn_css_next_slot = slot_idx;
+}
+
+uint16_t
+ble_ll_conn_css_get_next_slot(void)
+{
+    struct ble_ll_conn_sm *connsm;
+    uint16_t slot_idx = 0;
+
+    if (g_ble_ll_conn_css_next_slot != BLE_LL_CONN_CSS_NO_SLOT) {
+        return g_ble_ll_conn_css_next_slot;
+    }
+
+    /* CSS connections are sorted in active conn list so just need to find 1st
+     * free value.
+     */
+    SLIST_FOREACH(connsm, &g_ble_ll_conn_active_list, act_sle) {
+        if ((connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL) &&
+            (connsm->css_slot_idx != slot_idx) &&
+            (connsm->css_slot_idx_pending != slot_idx)) {
+            break;
+        }
+        slot_idx++;
+    }
+
+    if (slot_idx >= ble_ll_sched_css_get_period_slots()) {
+        slot_idx = BLE_LL_CONN_CSS_NO_SLOT;
+    }
+
+    return slot_idx;
+}
+
+int
+ble_ll_conn_css_is_slot_busy(uint16_t slot_idx)
+{
+    struct ble_ll_conn_sm *connsm;
+
+    SLIST_FOREACH(connsm, &g_ble_ll_conn_active_list, act_sle) {
+        if ((connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL) &&
+            ((connsm->css_slot_idx == slot_idx) ||
+             (connsm->css_slot_idx_pending == slot_idx))) {
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+int
+ble_ll_conn_css_move(struct ble_ll_conn_sm *connsm, uint16_t slot_idx)
+{
+    int16_t slot_diff;
+    uint32_t offset;
+    int rc;
+
+    /* Assume connsm and slot_idx are valid */
+    BLE_LL_ASSERT(connsm->conn_state != BLE_LL_CONN_STATE_IDLE);
+    BLE_LL_ASSERT(connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL);
+    BLE_LL_ASSERT((slot_idx < ble_ll_sched_css_get_period_slots()) ||
+                  (slot_idx != BLE_LL_CONN_CSS_NO_SLOT));
+
+    slot_diff = slot_idx - connsm->css_slot_idx;
+
+    if (slot_diff > 0) {
+        offset = slot_diff * ble_ll_sched_css_get_slot_us() /
+                  BLE_LL_CONN_ITVL_USECS;
+    } else {
+        offset = (ble_ll_sched_css_get_period_slots() + slot_diff) *
+                 ble_ll_sched_css_get_slot_us() / BLE_LL_CONN_ITVL_USECS;
+    }
+
+    if (offset >= 0xffff) {
+        return -1;
+    }
+
+    rc = ble_ll_conn_move_anchor(connsm, offset);
+    if (!rc) {
+        connsm->css_slot_idx_pending = slot_idx;
+    }
+
+    return rc;
+}
+#endif
+
 #if (BLE_LL_BT5_PHY_SUPPORTED == 1)
 /**
  * Checks to see if we should start a PHY update procedure
@@ -1720,6 +1815,10 @@ void
 ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm)
 {
     struct ble_ll_conn_global_params *conn_params;
+#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
+    struct ble_ll_conn_sm *connsm_css_prev = NULL;
+    struct ble_ll_conn_sm *connsm_css;
+#endif
 
     /* Reset following elements */
     connsm->csmflags.conn_flags = 0;
@@ -1813,7 +1912,35 @@ ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm)
 #endif
 
     /* Add to list of active connections */
+#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
+    if (connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL) {
+        /* We will insert sorted by css_slot_idx to make finding free slot
+         * easier.
+         */
+        SLIST_FOREACH(connsm_css, &g_ble_ll_conn_active_list, act_sle) {
+            if ((connsm_css->conn_role == BLE_LL_CONN_ROLE_CENTRAL) &&
+                (connsm_css->css_slot_idx > connsm->css_slot_idx)) {
+                if (connsm_css_prev) {
+                    SLIST_INSERT_AFTER(connsm_css_prev, connsm, act_sle);
+                }
+                break;
+            }
+            connsm_css_prev = connsm_css;
+        }
+
+        if (!connsm_css_prev) {
+            /* List was empty or need to insert before 1st connection */
+            SLIST_INSERT_HEAD(&g_ble_ll_conn_active_list, connsm, act_sle);
+        } else if (!connsm_css) {
+            /* Insert at the end of list */
+            SLIST_INSERT_AFTER(connsm_css_prev, connsm, act_sle);
+        }
+    } else {
+        SLIST_INSERT_HEAD(&g_ble_ll_conn_active_list, connsm, act_sle);
+    }
+#else
     SLIST_INSERT_HEAD(&g_ble_ll_conn_active_list, connsm, act_sle);
+#endif
 }
 
 void
@@ -1903,6 +2030,20 @@ ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err)
     /* Remove from the active connection list */
     SLIST_REMOVE(&g_ble_ll_conn_active_list, connsm, ble_ll_conn_sm, act_sle);
 
+#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
+    /* If current connection was reference for CSS, we need to find another
+     * one. It does not matter which one we'll pick.
+     */
+    if (connsm == g_ble_ll_conn_css_ref) {
+        SLIST_FOREACH(g_ble_ll_conn_css_ref, &g_ble_ll_conn_active_list,
+                      act_sle) {
+            if (g_ble_ll_conn_css_ref->conn_role == BLE_LL_CONN_ROLE_CENTRAL) {
+                break;
+            }
+        }
+    }
+#endif
+
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
     ble_ll_conn_cth_flow_free_credit(connsm, connsm->cth_flow_pending);
 #endif
@@ -2039,6 +2180,7 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
     uint32_t max_ww;
 #endif
     struct ble_ll_conn_upd_req *upd;
+    uint8_t skip_anchor_calc = 0;
     uint32_t usecs;
 
     /* XXX: deal with connection request procedure here as well */
@@ -2083,15 +2225,32 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
     }
     connsm->event_cntr += latency;
 
-    /* Set next connection event start time */
-    /* We can use pre-calculated values for one interval if latency is 1. */
-    if (latency == 1) {
-        connsm->anchor_point += connsm->conn_itvl_ticks;
-        ble_ll_tmr_add_u(&connsm->anchor_point, &connsm->anchor_point_usecs,
-                         connsm->conn_itvl_usecs);
-    } else {
-        ble_ll_tmr_add(&connsm->anchor_point, &connsm->anchor_point_usecs,
-                       itvl);
+#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
+    if (connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL) {
+        connsm->css_period_idx += latency;
+
+        /* If this is non-reference connection, we set anchor from reference
+         * instead of calculating manually.
+         */
+        if (g_ble_ll_conn_css_ref != connsm) {
+            ble_ll_sched_css_set_conn_anchor(connsm);
+            skip_anchor_calc = 1;
+        }
+    }
+#endif
+
+    if (!skip_anchor_calc) {
+        /* Calculate next anchor point for connection.
+         * We can use pre-calculated values for one interval if latency is 1.
+         */
+        if (latency == 1) {
+            connsm->anchor_point += connsm->conn_itvl_ticks;
+            ble_ll_tmr_add_u(&connsm->anchor_point, &connsm->anchor_point_usecs,
+                             connsm->conn_itvl_usecs);
+        } else {
+            ble_ll_tmr_add(&connsm->anchor_point, &connsm->anchor_point_usecs,
+                           itvl);
+        }
     }
 
     /*
@@ -2134,6 +2293,15 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
         /* Reset the starting point of the connection supervision timeout */
         connsm->last_rxd_pdu_cputime = connsm->anchor_point;
 
+#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
+        if (connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL) {
+            BLE_LL_ASSERT(connsm->css_slot_idx_pending !=
+                          BLE_LL_CONN_CSS_NO_SLOT);
+            connsm->css_slot_idx = connsm->css_slot_idx_pending;
+            connsm->css_slot_idx_pending = BLE_LL_CONN_CSS_NO_SLOT;
+        }
+#endif
+
         /* Reset update scheduled flag */
         connsm->csmflags.cfbit.conn_update_sched = 0;
     }
diff --git a/nimble/controller/src/ble_ll_conn_hci.c b/nimble/controller/src/ble_ll_conn_hci.c
index cd3deae..ac21255 100644
--- a/nimble/controller/src/ble_ll_conn_hci.c
+++ b/nimble/controller/src/ble_ll_conn_hci.c
@@ -513,6 +513,9 @@ ble_ll_conn_hci_create(const uint8_t *cmdbuf, uint8_t len)
     struct ble_ll_conn_sm *connsm;
     uint16_t conn_itvl_min;
     uint16_t conn_itvl_max;
+#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
+    uint16_t css_slot_idx;
+#endif
     int rc;
 
     if (len < sizeof(*cmd)) {
@@ -529,6 +532,14 @@ ble_ll_conn_hci_create(const uint8_t *cmdbuf, uint8_t len)
         return BLE_ERR_CMD_DISALLOWED;
     }
 
+
+#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
+    css_slot_idx = ble_ll_conn_css_get_next_slot();
+    if (css_slot_idx == BLE_LL_CONN_CSS_NO_SLOT) {
+        return BLE_ERR_MEM_CAPACITY;
+    }
+#endif
+
     cc_scan.own_addr_type = cmd->own_addr_type;
     cc_scan.filter_policy = cmd->filter_policy;
     if (cc_scan.filter_policy == 0) {
@@ -560,7 +571,15 @@ ble_ll_conn_hci_create(const uint8_t *cmdbuf, uint8_t len)
         return BLE_ERR_INV_HCI_CMD_PARMS;
     }
 
+#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
+    cc_params.conn_itvl = ble_ll_sched_css_get_conn_interval_us();
+    if ((cc_params.conn_itvl < conn_itvl_min) ||
+        (cc_params.conn_itvl > conn_itvl_max)) {
+        return BLE_ERR_INV_HCI_CMD_PARMS;
+    }
+#else
     cc_params.conn_itvl = conn_itvl_max;
+#endif
     cc_params.conn_latency = le16toh(cmd->conn_latency);
     cc_params.supervision_timeout = le16toh(cmd->tmo);
     cc_params.min_ce_len = le16toh(cmd->min_ce);
@@ -582,6 +601,11 @@ ble_ll_conn_hci_create(const uint8_t *cmdbuf, uint8_t len)
         return BLE_ERR_CONN_LIMIT;
     }
 
+#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
+    connsm->css_slot_idx = css_slot_idx;
+    connsm->css_slot_idx_pending = BLE_LL_CONN_CSS_NO_SLOT;
+#endif
+
     /* Initialize state machine in central role and start state machine */
     ble_ll_conn_central_init(connsm, &cc_scan, &cc_params);
     ble_ll_conn_sm_new(connsm);
@@ -640,7 +664,15 @@ ble_ll_conn_hci_ext_create_parse_params(const struct conn_params *params,
         return BLE_ERR_INV_HCI_CMD_PARMS;
     }
 
+#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
+    cc_params->conn_itvl = ble_ll_sched_css_get_conn_interval_us();
+    if ((cc_params->conn_itvl < conn_itvl_min) ||
+        (cc_params->conn_itvl > conn_itvl_max)) {
+        return BLE_ERR_INV_HCI_CMD_PARMS;
+    }
+#else
     cc_params->conn_itvl = conn_itvl_max;
+#endif
     cc_params->conn_latency = le16toh(params->conn_latency);
     cc_params->supervision_timeout = le16toh(params->supervision_timeout);
     cc_params->min_ce_len = le16toh(params->min_ce);
@@ -699,6 +731,9 @@ ble_ll_conn_hci_ext_create(const uint8_t *cmdbuf, uint8_t len)
     struct ble_ll_conn_create_params *cc_params_fb;
     struct ble_ll_conn_sm *connsm;
     const struct init_phy *init_phy;
+#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
+    uint16_t css_slot_idx;
+#endif
     int rc;
 
     /* validate length */
@@ -717,6 +752,13 @@ ble_ll_conn_hci_ext_create(const uint8_t *cmdbuf, uint8_t len)
         return BLE_ERR_CMD_DISALLOWED;
     }
 
+#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
+    css_slot_idx = ble_ll_conn_css_get_next_slot();
+    if (css_slot_idx == BLE_LL_CONN_CSS_NO_SLOT) {
+        return BLE_ERR_MEM_CAPACITY;
+    }
+#endif
+
     cc_scan.own_addr_type = cmd->own_addr_type;
     cc_scan.filter_policy = cmd->filter_policy;
     if (cc_scan.filter_policy == 0) {
@@ -770,6 +812,11 @@ ble_ll_conn_hci_ext_create(const uint8_t *cmdbuf, uint8_t len)
         return BLE_ERR_CONN_LIMIT;
     }
 
+#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
+    connsm->css_slot_idx = css_slot_idx;
+    connsm->css_slot_idx_pending = BLE_LL_CONN_CSS_NO_SLOT;
+#endif
+
     /* Initialize state machine in central role and start state machine */
     ble_ll_conn_central_init(connsm, &cc_scan,
                              &g_ble_ll_conn_create_sm.params[0]);
diff --git a/nimble/controller/src/ble_ll_conn_priv.h b/nimble/controller/src/ble_ll_conn_priv.h
index c51aef9..3d49f49 100644
--- a/nimble/controller/src/ble_ll_conn_priv.h
+++ b/nimble/controller/src/ble_ll_conn_priv.h
@@ -59,6 +59,10 @@ extern "C" {
 #define BLE_LL_CONN_DEF_AUTH_PYLD_TMO       (3000)
 #define BLE_LL_CONN_AUTH_PYLD_OS_TMO(x)     ble_npl_time_ms_to_ticks32((x) * 10)
 
+#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
+#define BLE_LL_CONN_CSS_NO_SLOT             (UINT16_MAX)
+#endif
+
 /* Global Link Layer connection parameters */
 struct ble_ll_conn_global_params
 {
@@ -127,6 +131,7 @@ struct ble_ll_conn_create_sm {
 };
 
 extern struct ble_ll_conn_create_sm g_ble_ll_conn_create_sm;
+extern struct ble_ll_conn_sm *g_ble_ll_conn_css_ref;
 
 /* Generic interface */
 struct ble_ll_len_req;
@@ -250,6 +255,14 @@ int ble_ll_set_sync_transfer_params(const uint8_t *cmdbuf, uint8_t len,
 int ble_ll_set_default_sync_transfer_params(const uint8_t *cmdbuf, uint8_t len);
 #endif
 
+#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
+void ble_ll_conn_css_set_next_slot(uint16_t slot_idx);
+uint16_t ble_ll_conn_css_get_next_slot(void);
+int ble_ll_conn_css_is_slot_busy(uint16_t slot_idx);
+int ble_ll_conn_css_move(struct ble_ll_conn_sm *connsm, uint16_t slot_idx);
+
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/nimble/controller/src/ble_ll_ctrl.c b/nimble/controller/src/ble_ll_ctrl.c
index a153a57..5212cb5 100644
--- a/nimble/controller/src/ble_ll_ctrl.c
+++ b/nimble/controller/src/ble_ll_ctrl.c
@@ -2106,6 +2106,16 @@ ble_ll_ctrl_rx_conn_param_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
         return BLE_ERR_MAX;
     }
 
+#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
+    /* Reject any attempts to change connection parameters by peripheral */
+    if (connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL) {
+        rsp_opcode = BLE_LL_CTRL_REJECT_IND_EXT;
+        rspbuf[1] = BLE_LL_CTRL_CONN_PARM_REQ;
+        rspbuf[2] = BLE_ERR_UNSUPPORTED;
+        return rsp_opcode;
+    }
+#endif
+
     /* XXX: remember to deal with this on the central: if the peripheral has
      * initiated a procedure we may have received its connection parameter
      * update request and have signaled the host with an event. If that
diff --git a/nimble/controller/src/ble_ll_sched.c b/nimble/controller/src/ble_ll_sched.c
index 14c8753..eb9ed8b 100644
--- a/nimble/controller/src/ble_ll_sched.c
+++ b/nimble/controller/src/ble_ll_sched.c
@@ -45,6 +45,22 @@ int32_t g_ble_ll_sched_max_late;
 int32_t g_ble_ll_sched_max_early;
 #endif
 
+#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
+struct ble_ll_sched_css {
+    uint32_t slot_us;
+    uint32_t period_slots;
+    uint32_t period_anchor_ticks;
+    uint8_t period_anchor_rem_us;
+    uint8_t period_anchor_idx;
+    uint16_t period_anchor_slot_idx;
+};
+
+static struct ble_ll_sched_css g_ble_ll_sched_css = {
+    .slot_us = MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED_SLOT_US),
+    .period_slots = MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED_PERIOD_SLOTS),
+};
+#endif
+
 typedef int (* ble_ll_sched_preempt_cb_t)(struct ble_ll_sched_item *sch,
                                           struct ble_ll_sched_item *item);
 
@@ -304,6 +320,9 @@ ble_ll_sched_overlaps_current(struct ble_ll_sched_item *sch)
 int
 ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm)
 {
+#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
+    struct ble_ll_sched_css *css = &g_ble_ll_sched_css;
+#endif
     struct ble_ll_sched_item *sch;
 #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL)
     uint32_t usecs;
@@ -349,6 +368,17 @@ ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm)
     }
 
     rc = ble_ll_sched_insert(sch, 0, preempt_any_except_conn);
+#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
+    /* Store new anchor point for strict scheduling if successfully scheduled
+     * reference connection.
+     */
+    if ((rc == 0) && (connsm == g_ble_ll_conn_css_ref)) {
+        css->period_anchor_idx = connsm->css_period_idx;
+        css->period_anchor_slot_idx = connsm->css_slot_idx;
+        css->period_anchor_ticks = connsm->anchor_point;
+        css->period_anchor_rem_us = connsm->anchor_point_usecs;
+    }
+#endif
 
     OS_EXIT_CRITICAL(sr);
 
@@ -372,10 +402,16 @@ int
 ble_ll_sched_conn_central_new(struct ble_ll_conn_sm *connsm,
                               struct ble_mbuf_hdr *ble_hdr, uint8_t pyld_len)
 {
+#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
+    struct ble_ll_sched_css *css = &g_ble_ll_sched_css;
+    struct ble_ll_conn_sm *connsm_ref;
+#endif
     struct ble_ll_sched_item *sch;
     uint32_t orig_start_time;
     uint32_t earliest_start;
+#if !MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
     uint32_t min_win_offset;
+#endif
     uint32_t max_delay;
     uint32_t adv_rxend;
     os_sr_t sr;
@@ -457,20 +493,60 @@ ble_ll_sched_conn_central_new(struct ble_ll_conn_sm *connsm,
         }
     }
 
+    orig_start_time = earliest_start - g_ble_ll_sched_offset_ticks;
+
+#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
+    uint8_t rem_us;
+
+    OS_ENTER_CRITICAL(sr);
+
+    connsm_ref = g_ble_ll_conn_css_ref;
+    if (!connsm_ref) {
+        g_ble_ll_conn_css_ref = connsm;
+
+        css->period_anchor_slot_idx = connsm->css_slot_idx;
+        css->period_anchor_idx = 0;
+        css->period_anchor_ticks = adv_rxend;
+        css->period_anchor_rem_us = 0;
+
+        connsm->css_period_idx = 1;
+    } else {
+        connsm->css_period_idx = css->period_anchor_idx + 1;
+    }
+
+    ble_ll_sched_css_set_conn_anchor(connsm);
+
+    sch->start_time = connsm->anchor_point - g_ble_ll_sched_offset_ticks;
+    sch->remainder = connsm->anchor_point_usecs;
+
+    OS_EXIT_CRITICAL(sr);
+
+    sch->end_time = sch->start_time;
+    rem_us = sch->remainder;
+    ble_ll_tmr_add(&sch->end_time, &rem_us, ble_ll_sched_css_get_period_slots());
+    if (rem_us == 0) {
+        sch->end_time--;
+    }
+
+    max_delay = 0;
+
+#else
+
     sch->start_time = earliest_start - g_ble_ll_sched_offset_ticks;
     sch->end_time = earliest_start +
                     ble_ll_tmr_u2t(MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) *
                                    BLE_LL_SCHED_USECS_PER_SLOT);
 
-    orig_start_time = sch->start_time;
-
     min_win_offset = ble_ll_tmr_u2t(MYNEWT_VAL(BLE_LL_CONN_INIT_MIN_WIN_OFFSET) *
                                     BLE_LL_SCHED_USECS_PER_SLOT);
     sch->start_time += min_win_offset;
     sch->end_time += min_win_offset;
+    sch->remainder = 0;
 
     max_delay = connsm->conn_itvl_ticks - min_win_offset;
 
+#endif
+
     OS_ENTER_CRITICAL(sr);
 
     rc = ble_ll_sched_insert(sch, max_delay, preempt_none);
@@ -480,7 +556,7 @@ ble_ll_sched_conn_central_new(struct ble_ll_conn_sm *connsm,
                              BLE_LL_CONN_TX_OFF_USECS;
 
         connsm->anchor_point = sch->start_time + g_ble_ll_sched_offset_ticks;
-        connsm->anchor_point_usecs = 0;
+        connsm->anchor_point_usecs = sch->remainder;
         connsm->ce_end_time = sch->end_time;
 
     }
@@ -1104,3 +1180,59 @@ ble_ll_sched_init(void)
 
     return 0;
 }
+
+#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
+void
+ble_ll_sched_css_set_params(uint32_t slot_us, uint32_t period_slots)
+{
+    g_ble_ll_sched_css.slot_us = slot_us;
+    g_ble_ll_sched_css.period_slots = period_slots;
+}
+
+void
+ble_ll_sched_css_set_conn_anchor(struct ble_ll_conn_sm *connsm)
+{
+    struct ble_ll_sched_css *css = &g_ble_ll_sched_css;
+    int8_t period_diff;
+    int16_t slot_diff;
+    int32_t diff;
+
+    period_diff = connsm->css_period_idx - css->period_anchor_idx;
+    slot_diff = connsm->css_slot_idx - css->period_anchor_slot_idx;
+
+    diff = (period_diff * ble_ll_sched_css_get_period_slots() + slot_diff) *
+           ble_ll_sched_css_get_slot_us();
+
+    connsm->anchor_point = css->period_anchor_ticks;
+    connsm->anchor_point_usecs = css->period_anchor_rem_us;
+
+    if (diff < 0) {
+        ble_ll_tmr_sub(&connsm->anchor_point, &connsm->anchor_point_usecs,
+                       -diff);
+    } else if (diff > 0) {
+        ble_ll_tmr_add(&connsm->anchor_point, &connsm->anchor_point_usecs,
+                       diff);
+    }
+}
+
+inline uint32_t
+ble_ll_sched_css_get_slot_us(void)
+{
+    return g_ble_ll_sched_css.slot_us;
+}
+
+inline uint32_t
+ble_ll_sched_css_get_period_slots(void)
+{
+    return g_ble_ll_sched_css.period_slots;
+}
+
+inline uint32_t
+ble_ll_sched_css_get_conn_interval_us(void)
+{
+    return ble_ll_sched_css_get_period_slots() *
+           ble_ll_sched_css_get_slot_us() /
+           BLE_LL_CONN_ITVL_USECS;
+}
+
+#endif
diff --git a/nimble/controller/syscfg.yml b/nimble/controller/syscfg.yml
index 8ecdd2c..de6b5ea 100644
--- a/nimble/controller/syscfg.yml
+++ b/nimble/controller/syscfg.yml
@@ -146,6 +146,27 @@ syscfg.defs:
             ensure interoperability with such devices set this value to 2 (or more).
         value: '0'
 
+    BLE_LL_CONN_STRICT_SCHED:
+        description: >
+            Enable connection strict scheduling (css).
+            In css mode, connections in central role are scheduled in fixed time
+            intervals called periods. Each period is divided into an arbitrary
+            number of slots and each connection anchor point is always scheduled
+            at slot boundary. This means (assuming only central connections are
+            active) it's possible to reliably schedule up to number-of-slots
+            connections each at period-duration interval, each connection will
+            be allocated at least one slot in each connection event.
+        value: 0
+    BLE_LL_CONN_STRICT_SCHED_SLOT_US:
+        description: >
+            Slot duration in microseconds. Shall be multiply of 1250us.
+        value: 3750
+    BLE_LL_CONN_STRICT_SCHED_PERIOD_SLOTS:
+        description: >
+            Number of slots per period. Duration of slot determines connection
+            interval used for each connection in central role.
+        value: 8
+
     # The number of random bytes to store
     BLE_LL_RNG_BUFSIZE:
         description: >

[mynewt-nimble] 05/05: nimble/ll: Add fixed css option

Posted by an...@apache.org.
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 8e7cbbba3a2a90f08176274bb3f4d35eeb148090
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Fri Feb 4 20:43:01 2022 +0100

    nimble/ll: Add fixed css option
    
    In fixed mode css always uses slot duration and slots per period
    configured with syscfg, configuration hci vs command is not included.
    This allows for some compile-time optimizations.
---
 .../controller/include/controller/ble_ll_sched.h   | 23 ++++++++++++++++++++++
 nimble/controller/src/ble_ll_hci_vs.c              |  4 ++++
 nimble/controller/src/ble_ll_sched.c               |  8 ++++++++
 nimble/controller/syscfg.yml                       |  6 ++++++
 4 files changed, 41 insertions(+)

diff --git a/nimble/controller/include/controller/ble_ll_sched.h b/nimble/controller/include/controller/ble_ll_sched.h
index a79262a..a65b5d4 100644
--- a/nimble/controller/include/controller/ble_ll_sched.h
+++ b/nimble/controller/include/controller/ble_ll_sched.h
@@ -176,12 +176,35 @@ int ble_ll_sched_dtm(struct ble_ll_sched_item *sch);
 #endif
 
 #if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
+#if !MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED_FIXED)
 void ble_ll_sched_css_set_params(uint32_t slot_us, uint32_t period_slots);
+#endif
 void ble_ll_sched_css_set_conn_anchor(struct ble_ll_conn_sm *connsm);
+#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED_FIXED)
+static inline uint32_t
+ble_ll_sched_css_get_slot_us(void)
+{
+    return MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED_SLOT_US);
+}
+
+static inline uint32_t
+ble_ll_sched_css_get_period_slots(void)
+{
+    return MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED_PERIOD_SLOTS);
+}
+
+static inline uint32_t
+ble_ll_sched_css_get_conn_interval_us(void)
+{
+    return ble_ll_sched_css_get_period_slots() *
+           ble_ll_sched_css_get_slot_us() / 1250;
+}
+#else
 uint32_t ble_ll_sched_css_get_slot_us(void);
 uint32_t ble_ll_sched_css_get_period_slots(void);
 uint32_t ble_ll_sched_css_get_conn_interval_us(void);
 #endif
+#endif
 
 #ifdef __cplusplus
 }
diff --git a/nimble/controller/src/ble_ll_hci_vs.c b/nimble/controller/src/ble_ll_hci_vs.c
index 5049b39..2b39092 100644
--- a/nimble/controller/src/ble_ll_hci_vs.c
+++ b/nimble/controller/src/ble_ll_hci_vs.c
@@ -136,6 +136,7 @@ ble_ll_hci_vs_set_tx_power(uint16_t ocf, const uint8_t *cmdbuf, uint8_t cmdlen,
 
 
 #if MYNEWT_VAL(BLE_LL_HCI_VS_CONN_STRICT_SCHED)
+#if !MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED_FIXED)
 static int
 ble_ll_hci_vs_css_configure(const uint8_t *cmdbuf, uint8_t cmdlen,
                             uint8_t *rspbuf, uint8_t *rsplen)
@@ -167,6 +168,7 @@ ble_ll_hci_vs_css_configure(const uint8_t *cmdbuf, uint8_t cmdlen,
 
     return BLE_ERR_SUCCESS;
 }
+#endif
 
 static int
 ble_ll_hci_vs_css_set_next_slot(const uint8_t *cmdbuf, uint8_t cmdlen,
@@ -251,8 +253,10 @@ ble_ll_hci_vs_css(uint16_t ocf, const uint8_t *cmdbuf, uint8_t cmdlen,
     *rsplen = 0;
 
     switch (cmd->opcode) {
+#if !MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED_FIXED)
     case BLE_HCI_VS_CSS_OP_CONFIGURE:
         return ble_ll_hci_vs_css_configure(cmdbuf, cmdlen, rspbuf, rsplen);
+#endif
     case BLE_HCI_VS_CSS_OP_SET_NEXT_SLOT:
         return ble_ll_hci_vs_css_set_next_slot(cmdbuf, cmdlen, rspbuf, rsplen);
     case BLE_HCI_VS_CSS_OP_SET_CONN_SLOT:
diff --git a/nimble/controller/src/ble_ll_sched.c b/nimble/controller/src/ble_ll_sched.c
index eb9ed8b..40139a8 100644
--- a/nimble/controller/src/ble_ll_sched.c
+++ b/nimble/controller/src/ble_ll_sched.c
@@ -47,8 +47,10 @@ int32_t g_ble_ll_sched_max_early;
 
 #if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
 struct ble_ll_sched_css {
+#if !MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED_FIXED)
     uint32_t slot_us;
     uint32_t period_slots;
+#endif
     uint32_t period_anchor_ticks;
     uint8_t period_anchor_rem_us;
     uint8_t period_anchor_idx;
@@ -56,8 +58,10 @@ struct ble_ll_sched_css {
 };
 
 static struct ble_ll_sched_css g_ble_ll_sched_css = {
+#if !MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED_FIXED)
     .slot_us = MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED_SLOT_US),
     .period_slots = MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED_PERIOD_SLOTS),
+#endif
 };
 #endif
 
@@ -1182,12 +1186,14 @@ ble_ll_sched_init(void)
 }
 
 #if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
+#if !MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED_FIXED)
 void
 ble_ll_sched_css_set_params(uint32_t slot_us, uint32_t period_slots)
 {
     g_ble_ll_sched_css.slot_us = slot_us;
     g_ble_ll_sched_css.period_slots = period_slots;
 }
+#endif
 
 void
 ble_ll_sched_css_set_conn_anchor(struct ble_ll_conn_sm *connsm)
@@ -1215,6 +1221,7 @@ ble_ll_sched_css_set_conn_anchor(struct ble_ll_conn_sm *connsm)
     }
 }
 
+#if !MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED_FIXED)
 inline uint32_t
 ble_ll_sched_css_get_slot_us(void)
 {
@@ -1234,5 +1241,6 @@ ble_ll_sched_css_get_conn_interval_us(void)
            ble_ll_sched_css_get_slot_us() /
            BLE_LL_CONN_ITVL_USECS;
 }
+#endif
 
 #endif
diff --git a/nimble/controller/syscfg.yml b/nimble/controller/syscfg.yml
index 8f08dd7..ec1ef93 100644
--- a/nimble/controller/syscfg.yml
+++ b/nimble/controller/syscfg.yml
@@ -157,6 +157,12 @@ syscfg.defs:
             connections each at period-duration interval, each connection will
             be allocated at least one slot in each connection event.
         value: 0
+    BLE_LL_CONN_STRICT_SCHED_FIXED:
+        description: >
+            Enable fixed mode for connection strict scheduling, i.e. slot duration
+            and slots per period values are fixed to syscfg values and cannot
+            be changed in runtime. This allows for some compile-time optimizations.
+        value: 0
     BLE_LL_CONN_STRICT_SCHED_SLOT_US:
         description: >
             Slot duration in microseconds. Shall be multiply of 1250us.