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/04/07 12:18:58 UTC

[mynewt-nimble] 02/04: nimble/ll: Add calculations for subrated conn events

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 d95165ce75d566b0b6f52fe762d0df139fc3ed59
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Tue Feb 8 14:06:12 2022 +0100

    nimble/ll: Add calculations for subrated conn events
    
    This adds basic calculations to support subrated connection events. If
    feature is disabled, we always use subrate_factor=1 and most of the
    additional code is compiled out.
---
 nimble/controller/include/controller/ble_ll_conn.h |  9 +-
 nimble/controller/src/ble_ll_conn.c                | 95 +++++++++++++++++-----
 nimble/controller/syscfg.yml                       |  9 ++
 3 files changed, 91 insertions(+), 22 deletions(-)

diff --git a/nimble/controller/include/controller/ble_ll_conn.h b/nimble/controller/include/controller/ble_ll_conn.h
index aaa72fb1..85f59bcf 100644
--- a/nimble/controller/include/controller/ble_ll_conn.h
+++ b/nimble/controller/include/controller/ble_ll_conn.h
@@ -269,7 +269,6 @@ struct ble_ll_conn_sm
 
     /* Connection timing */
     uint16_t conn_itvl;
-    uint16_t periph_latency;
     uint16_t supervision_tmo;
     uint16_t min_ce_len;
     uint16_t max_ce_len;
@@ -283,6 +282,14 @@ struct ble_ll_conn_sm
     uint32_t periph_cur_window_widening;
     uint32_t last_rxd_pdu_cputime;  /* Used exclusively for supervision timer */
 
+    uint16_t periph_latency;
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE)
+    uint16_t subrate_base_event;
+    uint16_t subrate_factor;
+    uint16_t cont_num;
+    uint16_t last_pdu_event;
+#endif
+
     /*
      * Used to mark that identity address was used as InitA
      */
diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c
index 6d131095..b328296d 100644
--- a/nimble/controller/src/ble_ll_conn.c
+++ b/nimble/controller/src/ble_ll_conn.c
@@ -1853,6 +1853,13 @@ ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm)
     connsm->conn_rssi = BLE_LL_CONN_UNKNOWN_RSSI;
     connsm->inita_identity_used = 0;
 
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE)
+    connsm->subrate_base_event = 0;
+    connsm->subrate_factor = 1;
+    connsm->cont_num = 0;
+    connsm->last_pdu_event = 0;
+#endif
+
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER)
     connsm->sync_transfer_sync_timeout = g_ble_ll_conn_sync_transfer_params.sync_timeout_us;
     connsm->sync_transfer_mode = g_ble_ll_conn_sync_transfer_params.mode;
@@ -2191,8 +2198,8 @@ ble_ll_conn_move_anchor(struct ble_ll_conn_sm *connsm, uint16_t offset)
 static int
 ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
 {
-    uint16_t latency;
-    uint32_t itvl;
+    uint32_t conn_itvl_us;
+    uint32_t ce_duration;
 #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL)
     uint32_t cur_ww;
     uint32_t max_ww;
@@ -2200,6 +2207,12 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
     struct ble_ll_conn_upd_req *upd;
     uint8_t skip_anchor_calc = 0;
     uint32_t usecs;
+    uint8_t use_periph_latency;
+    uint16_t base_event_cntr;
+    uint16_t next_event_cntr;
+    uint8_t next_is_subrated;
+    uint16_t subrate_factor;
+    uint16_t event_cntr_diff;
 
     /* XXX: deal with connection request procedure here as well */
     ble_ll_conn_chk_csm_flags(connsm);
@@ -2217,6 +2230,22 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
         connsm->periph_latency = 0;
     }
 
+    next_is_subrated = 1;
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE)
+    base_event_cntr = connsm->subrate_base_event;
+    subrate_factor = connsm->subrate_factor;
+
+    if ((connsm->cont_num > 0) &&
+        (connsm->event_cntr + 1 == connsm->subrate_base_event +
+                                   connsm->subrate_factor) &&
+        (connsm->event_cntr - connsm->last_pdu_event < connsm->cont_num)) {
+        next_is_subrated = 0;
+    }
+#else
+    base_event_cntr = connsm->event_cntr;
+    subrate_factor = 1;
+#endif
+
     /*
      * XXX: TODO Probably want to add checks to see if we need to start
      * a control procedure here as an instant may have prevented us from
@@ -2230,22 +2259,39 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
      * the instant
      */
     /* Set event counter to the next connection event that we will tx/rx in */
-    itvl = connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS;
-    latency = 1;
-    if (connsm->csmflags.cfbit.allow_periph_latency     &&
-        !connsm->csmflags.cfbit.conn_update_sched       &&
-        !CONN_F_PHY_UPDATE_SCHED(connsm)                &&
-        !connsm->csmflags.cfbit.chanmap_update_scheduled) {
-        if (connsm->csmflags.cfbit.pkt_rxd) {
-            latency += connsm->periph_latency;
-            itvl = itvl * latency;
+
+    use_periph_latency = next_is_subrated &&
+                         connsm->csmflags.cfbit.allow_periph_latency &&
+                         !connsm->csmflags.cfbit.conn_update_sched &&
+                         !connsm->csmflags.cfbit.phy_update_sched &&
+                         !connsm->csmflags.cfbit.chanmap_update_scheduled &&
+                         connsm->csmflags.cfbit.pkt_rxd;
+
+    if (next_is_subrated) {
+        next_event_cntr = base_event_cntr + subrate_factor;
+        if (use_periph_latency) {
+            next_event_cntr += subrate_factor * connsm->periph_latency;
         }
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE)
+        /* Make this our next base event. This is technically incorrect, because
+         * subrate base event is determined by LL_SUBRATE_IND and shall only be
+         * changed if counter wrapped, but that does not really matter as once
+         * set it's only used internally.
+         */
+        connsm->subrate_base_event = next_event_cntr;
+#endif
+    } else {
+        next_event_cntr = connsm->event_cntr + 1;
     }
-    connsm->event_cntr += latency;
+
+    event_cntr_diff = next_event_cntr - connsm->event_cntr;
+    BLE_LL_ASSERT(event_cntr_diff > 0);
+
+    connsm->event_cntr = next_event_cntr;
 
 #if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
     if (connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL) {
-        connsm->css_period_idx += latency;
+        connsm->css_period_idx += event_cntr_diff;
 
         /* If this is non-reference connection, we set anchor from reference
          * instead of calculating manually.
@@ -2261,13 +2307,15 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
         /* Calculate next anchor point for connection.
          * We can use pre-calculated values for one interval if latency is 1.
          */
-        if (latency == 1) {
+        if (event_cntr_diff == 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 {
+            conn_itvl_us = connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS;
+
             ble_ll_tmr_add(&connsm->anchor_point, &connsm->anchor_point_usecs,
-                           itvl);
+                           conn_itvl_us * event_cntr_diff);
         }
     }
 
@@ -2399,7 +2447,7 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
 #endif
 
     /* Calculate data channel index of next connection event */
-    connsm->data_chan_index = ble_ll_conn_calc_dci(connsm, latency);
+    connsm->data_chan_index = ble_ll_conn_calc_dci(connsm, event_cntr_diff);
 
     /*
      * If we are trying to terminate connection, check if next wake time is
@@ -2416,8 +2464,8 @@ 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.
      */
-    itvl = ble_ll_tmr_u2t(MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) *
-                          BLE_LL_SCHED_USECS_PER_SLOT);
+    ce_duration = ble_ll_tmr_u2t(MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) *
+                                 BLE_LL_SCHED_USECS_PER_SLOT);
 
 #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL)
     if (connsm->conn_role == BLE_LL_CONN_ROLE_PERIPHERAL) {
@@ -2431,11 +2479,12 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
         }
         cur_ww += BLE_LL_JITTER_USECS;
         connsm->periph_cur_window_widening = cur_ww;
-        itvl += ble_ll_tmr_u2t(cur_ww + connsm->periph_cur_tx_win_usecs);
+        ce_duration += ble_ll_tmr_u2t(cur_ww +
+                                      connsm->periph_cur_tx_win_usecs);
     }
 #endif
-    itvl -= g_ble_ll_sched_offset_ticks;
-    connsm->ce_end_time = connsm->anchor_point + itvl;
+    ce_duration -= g_ble_ll_sched_offset_ticks;
+    connsm->ce_end_time = connsm->anchor_point + ce_duration;
 
     return 0;
 }
@@ -3162,6 +3211,10 @@ ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr)
     acl_len = rxbuf[1];
     llid = hdr_byte & BLE_LL_DATA_HDR_LLID_MASK;
 
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE)
+    connsm->last_pdu_event = connsm->event_cntr;
+#endif
+
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
     if (BLE_MBUF_HDR_MIC_FAILURE(hdr)) {
diff --git a/nimble/controller/syscfg.yml b/nimble/controller/syscfg.yml
index ebf7e1dd..1cd43355 100644
--- a/nimble/controller/syscfg.yml
+++ b/nimble/controller/syscfg.yml
@@ -327,6 +327,15 @@ syscfg.defs:
         restrictions:
             - '(BLE_VERSION >= 52) if 1'
 
+    BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE:
+        description: >
+            Enables support LE Enhanced Connection Update.
+            This allows to use Conenction Subrate Update and Connection Subrate
+            Request procedures to modify subrate paramters for a connection.
+        value: 0
+        restrictions:
+            - '(BLE_VERSION >= 53) if 1'
+
     BLE_LL_CFG_FEAT_LL_ISO:
         description: >
             This option is used to enable/disable support for LE Isochronous Channels