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 2019/12/17 15:57:44 UTC

[mynewt-nimble] branch master updated (30b6791 -> cfaa870)

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 30b6791  apps/blecent: Fix not inferring own address type
     new e0ddae3  nimble/ll: Remove unused functions
     new e3de291  nimble/ll: Properly schedule start of DTM RX
     new 3014f20  nimble/ll: Improve scan interval/window time handling
     new 37478fa  nimble/ll: Improve scanner PHY toggling
     new 1d9bc2c  nimble/ll: Simplify scan proc
     new 491a37e  nimble/ll: Refactor rfclk management from LL
     new 31badec  nimble/ll: Use scanp name consistently
     new 35efdba  nimble/ll: Rename BLE_XTAL_SETTLE_TIME
     new cfaa870  nimble/ll: Add missing APIs to native PHY

The 9 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.h      |  36 --
 .../controller/include/controller/ble_ll_rfmgmt.h  |  63 +++
 nimble/controller/include/controller/ble_ll_scan.h |  19 +-
 .../controller/include/controller/ble_ll_sched.h   |   5 -
 nimble/controller/include/controller/ble_ll_xcvr.h |  48 --
 nimble/controller/src/ble_ll.c                     |  57 +-
 nimble/controller/src/ble_ll_adv.c                 |  83 ++-
 nimble/controller/src/ble_ll_conn.c                |  14 +-
 nimble/controller/src/ble_ll_dtm.c                 |  41 +-
 nimble/controller/src/ble_ll_rfmgmt.c              | 346 ++++++++++++
 nimble/controller/src/ble_ll_scan.c                | 601 ++++++++-------------
 nimble/controller/src/ble_ll_sched.c               | 135 +----
 nimble/controller/src/ble_ll_sync.c                |  25 +-
 nimble/controller/src/ble_ll_xcvr.c                | 169 ------
 nimble/controller/syscfg.yml                       |  23 +-
 nimble/drivers/native/src/ble_phy.c                |  10 +
 nimble/drivers/nrf51/src/ble_phy.c                 |  11 -
 nimble/drivers/nrf52/src/ble_phy.c                 |  11 -
 18 files changed, 769 insertions(+), 928 deletions(-)
 create mode 100644 nimble/controller/include/controller/ble_ll_rfmgmt.h
 delete mode 100644 nimble/controller/include/controller/ble_ll_xcvr.h
 create mode 100644 nimble/controller/src/ble_ll_rfmgmt.c
 delete mode 100644 nimble/controller/src/ble_ll_xcvr.c


[mynewt-nimble] 07/09: nimble/ll: Use scanp name consistently

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 31badecefe8e66bf613c8c15cf01f34d7edce305
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Thu Dec 12 01:37:12 2019 +0100

    nimble/ll: Use scanp name consistently
    
    Use 'scanp' name for ble_ll_scan_params variables consistently.
---
 nimble/controller/include/controller/ble_ll_scan.h |   8 +-
 nimble/controller/src/ble_ll_scan.c                | 140 ++++++++++-----------
 2 files changed, 74 insertions(+), 74 deletions(-)

diff --git a/nimble/controller/include/controller/ble_ll_scan.h b/nimble/controller/include/controller/ble_ll_scan.h
index f63c27c..6b254d4 100644
--- a/nimble/controller/include/controller/ble_ll_scan.h
+++ b/nimble/controller/include/controller/ble_ll_scan.h
@@ -179,12 +179,12 @@ struct ble_ll_scan_sm
     uint8_t ext_scanning;
 #endif
 
-    struct ble_ll_scan_params *scanp;
-    struct ble_ll_scan_params *scanp_next;
-
     uint8_t restart_timer_needed;
     struct ble_ll_aux_data *cur_aux_data;
-    struct ble_ll_scan_params phy_data[BLE_LL_SCAN_PHY_NUMBER];
+
+    struct ble_ll_scan_params *scanp;
+    struct ble_ll_scan_params *scanp_next;
+    struct ble_ll_scan_params scanp_phys[BLE_LL_SCAN_PHY_NUMBER];
 };
 
 /* Scan types */
diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c
index f707ebf..150ac33 100644
--- a/nimble/controller/src/ble_ll_scan.c
+++ b/nimble/controller/src/ble_ll_scan.c
@@ -974,21 +974,21 @@ static void
 ble_ll_get_chan_to_scan(struct ble_ll_scan_sm *scansm, uint8_t *chan,
                         int *phy)
 {
-    struct ble_ll_scan_params *scanphy = scansm->scanp;
+    struct ble_ll_scan_params *scanp = scansm->scanp;
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
     struct ble_ll_aux_data *aux_data = scansm->cur_aux_data;
 
     if (!scansm->ext_scanning || !aux_data || !aux_data->scanning) {
-        *chan = scanphy->scan_chan;
-        *phy = scanphy->phy;
+        *chan = scanp->scan_chan;
+        *phy = scanp->phy;
         return;
     }
 
     *chan = aux_data->chan;
     *phy = aux_data->aux_phy;
 #else
-    *chan = scanphy->scan_chan;
-    *phy = scanphy->phy;
+    *chan = scanp->scan_chan;
+    *phy = scanp->phy;
 #endif
 }
 /**
@@ -1004,7 +1004,7 @@ static int
 ble_ll_scan_start(struct ble_ll_scan_sm *scansm, struct ble_ll_sched_item *sch)
 {
     int rc;
-    struct ble_ll_scan_params *scanphy = scansm->scanp;
+    struct ble_ll_scan_params *scanp = scansm->scanp;
     uint8_t scan_chan;
 #if (BLE_LL_BT5_PHY_SUPPORTED == 1)
     uint8_t phy_mode;
@@ -1066,14 +1066,14 @@ ble_ll_scan_start(struct ble_ll_scan_sm *scansm, struct ble_ll_sched_item *sch)
         rc = 0;
 
         /* Enable/disable whitelisting */
-        if (scanphy->scan_filt_policy & 1) {
+        if (scanp->scan_filt_policy & 1) {
             ble_ll_whitelist_enable();
         } else {
             ble_ll_whitelist_disable();
         }
 
         /* Set link layer state to scanning */
-        if (scanphy->scan_type == BLE_SCAN_TYPE_INITIATE) {
+        if (scanp->scan_type == BLE_SCAN_TYPE_INITIATE) {
             ble_ll_state_set(BLE_LL_STATE_INITIATING);
         } else {
             ble_ll_state_set(BLE_LL_STATE_SCANNING);
@@ -1528,13 +1528,13 @@ ble_ll_scan_rx_isr_start(uint8_t pdu_type, uint16_t *rxflags)
 {
     int rc;
     struct ble_ll_scan_sm *scansm;
-    struct ble_ll_scan_params *scanphy;
+    struct ble_ll_scan_params *scanp;
 
     rc = 0;
     scansm = &g_ble_ll_scan_sm;
-    scanphy = scansm->scanp;
+    scanp = scansm->scanp;
 
-    switch (scanphy->scan_type) {
+    switch (scanp->scan_type) {
     case BLE_SCAN_TYPE_ACTIVE:
         /* If adv ind or scan ind, we may send scan request */
         if ((pdu_type == BLE_ADV_PDU_TYPE_ADV_IND) ||
@@ -2083,7 +2083,7 @@ ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok)
     uint8_t *rxbuf;
     struct ble_mbuf_hdr *ble_hdr;
     struct ble_ll_scan_sm *scansm;
-    struct ble_ll_scan_params *scanphy;
+    struct ble_ll_scan_params *scanp;
     int ext_adv_mode = -1;
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
     uint8_t phy_mode;
@@ -2097,7 +2097,7 @@ ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok)
 
     /* Get scanning state machine */
     scansm = &g_ble_ll_scan_sm;
-    scanphy = scansm->scanp;
+    scanp = scansm->scanp;
 
     /*
      * The reason we do something different here (as opposed to failed CRC) is
@@ -2199,7 +2199,7 @@ ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok)
         }
 
         if ((ext_adv_mode == BLE_LL_EXT_ADV_MODE_SCAN) &&
-                (scanphy->scan_type == BLE_SCAN_TYPE_ACTIVE)) {
+                (scanp->scan_type == BLE_SCAN_TYPE_ACTIVE)) {
             chk_send_req = 1;
         }
         chk_wl = 1;
@@ -2207,7 +2207,7 @@ ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok)
 #endif
     case BLE_ADV_PDU_TYPE_ADV_IND:
     case BLE_ADV_PDU_TYPE_ADV_SCAN_IND:
-        if (scanphy->scan_type == BLE_SCAN_TYPE_ACTIVE) {
+        if (scanp->scan_type == BLE_SCAN_TYPE_ACTIVE) {
             chk_send_req = 1;
         }
         chk_wl = 1;
@@ -2225,7 +2225,7 @@ ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok)
     adv_addr = adva;
     adv_addr_type = adva_type;
 
-    if ((scanphy->scan_filt_policy & 1) == 0) {
+    if ((scanp->scan_filt_policy & 1) == 0) {
         chk_wl = 0;
     }
     resolved = 0;
@@ -3435,7 +3435,7 @@ ble_ll_scan_set_enable(uint8_t enable, uint8_t filter_dups, uint16_t period,
     int rc;
     struct ble_ll_scan_sm *scansm;
     struct ble_ll_scan_params *scanp;
-    struct ble_ll_scan_params *scanphy;
+    struct ble_ll_scan_params *scanp_phy;
     int i;
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
     uint32_t period_ticks = 0;
@@ -3493,9 +3493,9 @@ ble_ll_scan_set_enable(uint8_t enable, uint8_t filter_dups, uint16_t period,
     if (scansm->scan_enabled) {
         /* Controller does not allow initiating and scanning.*/
         for (i = 0; i < BLE_LL_SCAN_PHY_NUMBER; i++) {
-            scanphy = &scansm->phy_data[i];
-            if (scanphy->configured &&
-                                scanphy->scan_type == BLE_SCAN_TYPE_INITIATE) {
+            scanp_phy = &scansm->scanp_phys[i];
+            if (scanp_phy->configured &&
+                                scanp_phy->scan_type == BLE_SCAN_TYPE_INITIATE) {
                 return BLE_ERR_CMD_DISALLOWED;
             }
         }
@@ -3526,27 +3526,27 @@ ble_ll_scan_set_enable(uint8_t enable, uint8_t filter_dups, uint16_t period,
     scansm->scanp_next = NULL;
 
     for (i = 0; i < BLE_LL_SCAN_PHY_NUMBER; i++) {
-        scanphy = &scansm->phy_data[i];
+        scanp_phy = &scansm->scanp_phys[i];
         scanp = &g_ble_ll_scan_params[i];
 
         if (!scanp->configured) {
             continue;
         }
 
-        scanphy->configured = scanp->configured;
-        scanphy->scan_type = scanp->scan_type;
-        scanphy->timing = scanp->timing;
-        scanphy->scan_filt_policy = scanp->scan_filt_policy;
-        scanphy->own_addr_type = scanp->own_addr_type;
+        scanp_phy->configured = scanp->configured;
+        scanp_phy->scan_type = scanp->scan_type;
+        scanp_phy->timing = scanp->timing;
+        scanp_phy->scan_filt_policy = scanp->scan_filt_policy;
+        scanp_phy->own_addr_type = scanp->own_addr_type;
 
         if (!scansm->scanp) {
-            scansm->scanp = scanphy;
+            scansm->scanp = scanp_phy;
             /* Take own_addr_type from the first configured PHY.
              * Note: All configured PHYs shall have the same own_addr_type
              */
-            scansm->own_addr_type = scanphy->own_addr_type;
+            scansm->own_addr_type = scanp_phy->own_addr_type;
         } else {
-            scansm->scanp_next = scanphy;
+            scansm->scanp_next = scanp_phy;
         }
     }
 
@@ -3556,18 +3556,18 @@ ble_ll_scan_set_enable(uint8_t enable, uint8_t filter_dups, uint16_t period,
      * Parameters defaults.
      */
     if (!scansm->scanp) {
-        scansm->scanp = &scansm->phy_data[PHY_UNCODED];
+        scansm->scanp = &scansm->scanp_phys[PHY_UNCODED];
         scansm->own_addr_type = BLE_ADDR_PUBLIC;
 
-        scanphy = scansm->scanp;
-        scanphy->configured = 1;
-        scanphy->scan_type = BLE_SCAN_TYPE_PASSIVE;
-        scanphy->timing.interval =
+        scanp_phy = scansm->scanp;
+        scanp_phy->configured = 1;
+        scanp_phy->scan_type = BLE_SCAN_TYPE_PASSIVE;
+        scanp_phy->timing.interval =
                         ble_ll_scan_time_hci_to_ticks(BLE_HCI_SCAN_ITVL_DEF);
-        scanphy->timing.window =
+        scanp_phy->timing.window =
                         ble_ll_scan_time_hci_to_ticks(BLE_HCI_SCAN_WINDOW_DEF);
-        scanphy->scan_filt_policy = BLE_HCI_SCAN_FILT_NO_WL;
-        scanphy->own_addr_type = BLE_ADDR_PUBLIC;
+        scanp_phy->scan_filt_policy = BLE_HCI_SCAN_FILT_NO_WL;
+        scanp_phy->own_addr_type = BLE_ADDR_PUBLIC;
     }
 
     rc = ble_ll_scan_sm_start(scansm);
@@ -3621,11 +3621,11 @@ ble_ll_scan_can_chg_whitelist(void)
 {
     int rc;
     struct ble_ll_scan_sm *scansm;
-    struct ble_ll_scan_params *params;
+    struct ble_ll_scan_params *scanp;
 
     scansm = &g_ble_ll_scan_sm;
-    params = scansm->scanp;
-    if (scansm->scan_enabled && (params->scan_filt_policy & 1)) {
+    scanp = scansm->scanp;
+    if (scansm->scan_enabled && (scanp->scan_filt_policy & 1)) {
         rc = 0;
     } else {
         rc = 1;
@@ -3639,7 +3639,7 @@ ble_ll_scan_initiator_start(struct hci_create_conn *hcc,
                             struct ble_ll_scan_sm **sm)
 {
     struct ble_ll_scan_sm *scansm;
-    struct ble_ll_scan_params *scanphy;
+    struct ble_ll_scan_params *scanp;
     int rc;
 
     scansm = &g_ble_ll_scan_sm;
@@ -3647,14 +3647,14 @@ ble_ll_scan_initiator_start(struct hci_create_conn *hcc,
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
     scansm->ext_scanning = 0;
 #endif
-    scansm->scanp = &scansm->phy_data[PHY_UNCODED];
+    scansm->scanp = &scansm->scanp_phys[PHY_UNCODED];
     scansm->scanp_next = NULL;
 
-    scanphy = scansm->scanp;
-    scanphy->scan_filt_policy = hcc->filter_policy;
-    scanphy->timing.interval = ble_ll_scan_time_hci_to_ticks(hcc->scan_itvl);
-    scanphy->timing.window = ble_ll_scan_time_hci_to_ticks(hcc->scan_window);
-    scanphy->scan_type = BLE_SCAN_TYPE_INITIATE;
+    scanp = scansm->scanp;
+    scanp->scan_filt_policy = hcc->filter_policy;
+    scanp->timing.interval = ble_ll_scan_time_hci_to_ticks(hcc->scan_itvl);
+    scanp->timing.window = ble_ll_scan_time_hci_to_ticks(hcc->scan_window);
+    scanp->scan_type = BLE_SCAN_TYPE_INITIATE;
 
     rc = ble_ll_scan_sm_start(scansm);
     if (sm == NULL) {
@@ -3676,8 +3676,8 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc,
                                 struct ble_ll_scan_sm **sm)
 {
     struct ble_ll_scan_sm *scansm;
-    struct ble_ll_scan_params *uncoded;
-    struct ble_ll_scan_params *coded;
+    struct ble_ll_scan_params *scanp_uncoded;
+    struct ble_ll_scan_params *scanp_coded;
     struct hci_ext_conn_params *params;
     int rc;
 
@@ -3689,41 +3689,41 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc,
 
     if (hcc->init_phy_mask & BLE_PHY_MASK_1M) {
         params = &hcc->params[0];
-        uncoded = &scansm->phy_data[PHY_UNCODED];
+        scanp_uncoded = &scansm->scanp_phys[PHY_UNCODED];
 
-        uncoded->timing.interval = ble_ll_scan_time_hci_to_ticks(params->scan_itvl);
-        uncoded->timing.window = ble_ll_scan_time_hci_to_ticks(params->scan_window);
-        uncoded->scan_type = BLE_SCAN_TYPE_INITIATE;
-        uncoded->scan_filt_policy = hcc->filter_policy;
-        scansm->scanp = uncoded;
+        scanp_uncoded->timing.interval = ble_ll_scan_time_hci_to_ticks(params->scan_itvl);
+        scanp_uncoded->timing.window = ble_ll_scan_time_hci_to_ticks(params->scan_window);
+        scanp_uncoded->scan_type = BLE_SCAN_TYPE_INITIATE;
+        scanp_uncoded->scan_filt_policy = hcc->filter_policy;
+        scansm->scanp = scanp_uncoded;
     }
 
     if (hcc->init_phy_mask & BLE_PHY_MASK_CODED) {
         params = &hcc->params[2];
-        coded = &scansm->phy_data[PHY_CODED];
+        scanp_coded = &scansm->scanp_phys[PHY_CODED];
 
-        coded->timing.interval = ble_ll_scan_time_hci_to_ticks(params->scan_itvl);
-        coded->timing.window = ble_ll_scan_time_hci_to_ticks(params->scan_window);
-        coded->scan_type = BLE_SCAN_TYPE_INITIATE;
-        coded->scan_filt_policy = hcc->filter_policy;
+        scanp_coded->timing.interval = ble_ll_scan_time_hci_to_ticks(params->scan_itvl);
+        scanp_coded->timing.window = ble_ll_scan_time_hci_to_ticks(params->scan_window);
+        scanp_coded->scan_type = BLE_SCAN_TYPE_INITIATE;
+        scanp_coded->scan_filt_policy = hcc->filter_policy;
         if (scansm->scanp) {
-            scansm->scanp_next = coded;
+            scansm->scanp_next = scanp_coded;
         } else {
-            scansm->scanp = coded;
+            scansm->scanp = scanp_coded;
         }
     }
 
     /* if any of PHYs is configured for continuous scan we alter interval to
      * fit other PHY
      */
-    if (scansm->scanp && scansm->scanp_next && coded->configured &&
-        uncoded->configured) {
-        if (coded->timing.interval == coded->timing.window) {
-            coded->timing.interval += uncoded->timing.window;
+    if (scansm->scanp && scansm->scanp_next && scanp_coded->configured &&
+        scanp_uncoded->configured) {
+        if (scanp_coded->timing.interval == scanp_coded->timing.window) {
+            scanp_coded->timing.interval += scanp_uncoded->timing.window;
         }
 
-        if (uncoded->timing.interval == uncoded->timing.window) {
-            uncoded->timing.interval += coded->timing.window;
+        if (scanp_uncoded->timing.interval == scanp_uncoded->timing.window) {
+            scanp_uncoded->timing.interval += scanp_coded->timing.window;
         }
     }
 
@@ -3836,9 +3836,9 @@ ble_ll_scan_common_init(void)
                         ble_ll_scan_time_hci_to_ticks(BLE_HCI_SCAN_WINDOW_DEF);
     }
 
-    scansm->phy_data[PHY_UNCODED].phy = BLE_PHY_1M;
+    scansm->scanp_phys[PHY_UNCODED].phy = BLE_PHY_1M;
 #if (BLE_LL_SCAN_PHY_NUMBER == 2)
-    scansm->phy_data[PHY_CODED].phy = BLE_PHY_CODED;
+    scansm->scanp_phys[PHY_CODED].phy = BLE_PHY_CODED;
 #endif
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)


[mynewt-nimble] 02/09: nimble/ll: Properly schedule start of DTM RX

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 e3de2917e3bbe47e9cdc37afc258d61e76036531
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Wed Dec 11 19:29:06 2019 +0100

    nimble/ll: Properly schedule start of DTM RX
    
    We need to schedule start of DTM RX instead of starting it "now". This
    is required for upcoming rfclk rework to work properly.
---
 nimble/controller/src/ble_ll_dtm.c | 27 +++++++++++++++++++++++----
 1 file changed, 23 insertions(+), 4 deletions(-)

diff --git a/nimble/controller/src/ble_ll_dtm.c b/nimble/controller/src/ble_ll_dtm.c
index 673d31b..0b8314b 100644
--- a/nimble/controller/src/ble_ll_dtm.c
+++ b/nimble/controller/src/ble_ll_dtm.c
@@ -424,23 +424,42 @@ ble_ll_dtm_rx_start(void)
 }
 
 static int
+ble_ll_dtm_rx_sched_cb(struct ble_ll_sched_item *sch)
+{
+    if (ble_ll_dtm_rx_start() != 0) {
+        ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_dtm_ctx.evt);
+        STATS_INC(ble_ll_dtm_stats, rx_failed);
+    }
+
+    return BLE_LL_SCHED_STATE_DONE;
+}
+
+static int
 ble_ll_dtm_rx_create_ctx(uint8_t rf_channel, uint8_t phy_mode)
 {
+    struct ble_ll_sched_item *sch = &g_ble_ll_dtm_ctx.sch;
+    int rc;
+
     g_ble_ll_dtm_ctx.phy_mode = phy_mode;
     g_ble_ll_dtm_ctx.rf_channel = rf_channel;
-    g_ble_ll_dtm_ctx.active = 1;
 
     STATS_CLEAR(ble_ll_dtm_stats, rx_count);
 
     ble_npl_event_init(&g_ble_ll_dtm_ctx.evt, ble_ll_dtm_ev_rx_restart_cb,
                        NULL);
 
-    if (ble_ll_dtm_rx_start() != 0) {
-        return 1;
-    }
+    sch->sched_cb = ble_ll_dtm_rx_sched_cb;
+    sch->cb_arg = &g_ble_ll_dtm_ctx;
+    sch->sched_type = BLE_LL_SCHED_TYPE_DTM;
+    sch->start_time =  os_cputime_get32() +
+                                       os_cputime_usecs_to_ticks(5000);
+
+    rc = ble_ll_sched_dtm(sch);
+    BLE_LL_ASSERT(rc == 0);
 
     ble_phy_enable_dtm();
 
+    g_ble_ll_dtm_ctx.active = 1;
     return 0;
 }
 


[mynewt-nimble] 03/09: nimble/ll: Improve scan interval/window time handling

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 3014f20b8a99d755adaac17bc48af1e2acc1a279
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Mon Dec 9 13:22:39 2019 +0100

    nimble/ll: Improve scan interval/window time handling
    
    This improves handling of scan interval and window handling by
    converting them to native ticks before writing to scansm instead of
    converting them over and over again everywhere in the code.
    
    In addition, all values related to timing (interval, window and window
    start time) are stored in single struct so it's easier to pass them
    around and it's more intuitive that they all have the same unit which
    is ticks.
---
 nimble/controller/include/controller/ble_ll_scan.h |  11 +-
 nimble/controller/src/ble_ll_scan.c                | 218 +++++++++++----------
 2 files changed, 120 insertions(+), 109 deletions(-)

diff --git a/nimble/controller/include/controller/ble_ll_scan.h b/nimble/controller/include/controller/ble_ll_scan.h
index faad1dc..8bbcc2d 100644
--- a/nimble/controller/include/controller/ble_ll_scan.h
+++ b/nimble/controller/include/controller/ble_ll_scan.h
@@ -74,6 +74,13 @@ extern "C" {
 #define BLE_LL_EXT_ADV_MODE_CONN        (0x01)
 #define BLE_LL_EXT_ADV_MODE_SCAN        (0x02)
 
+/* All values are stored as ticks */
+struct ble_ll_scan_timing {
+    uint32_t interval;
+    uint32_t window;
+    uint32_t start_time;
+};
+
 struct ble_ll_scan_params
 {
     uint8_t phy;
@@ -82,9 +89,7 @@ struct ble_ll_scan_params
     uint8_t configured;
     uint8_t scan_type;
     uint8_t scan_chan;
-    uint16_t scan_itvl;
-    uint16_t scan_window;
-    uint32_t scan_win_start_time;
+    struct ble_ll_scan_timing timing;
 };
 
 #define BLE_LL_AUX_HAS_ADVA                     0x01
diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c
index 27c1033..78ab84c 100644
--- a/nimble/controller/src/ble_ll_scan.c
+++ b/nimble/controller/src/ble_ll_scan.c
@@ -247,6 +247,12 @@ ble_ll_scan_ext_adv_init(struct ble_ll_aux_data **aux_data)
 }
 #endif
 
+static inline uint32_t
+ble_ll_scan_time_hci_to_ticks(uint16_t value)
+{
+    return os_cputime_usecs_to_ticks(value * BLE_HCI_SCAN_ITVL);
+}
+
 /* See Vol 6 Part B Section 4.4.3.2. Active scanning backoff */
 static void
 ble_ll_scan_req_backoff(struct ble_ll_scan_sm *scansm, int success)
@@ -1122,19 +1128,17 @@ ble_ll_scan_get_next_adv_prim_chan(uint8_t chan)
 static uint32_t
 ble_ll_scan_get_scan_win(struct ble_ll_scan_params *scanphy, uint32_t cputime)
 {
-    uint32_t itvl;
-
-    /* if pass current window, move to next interval */
-    itvl = os_cputime_usecs_to_ticks(scanphy->scan_itvl * BLE_HCI_SCAN_ITVL);
-    while ((int32_t)(cputime - scanphy->scan_win_start_time) >= (int32_t)itvl) {
-        scanphy->scan_win_start_time += itvl;
+    /* if past current window, move to next interval */
+    while (CPUTIME_GEQ(cputime - scanphy->timing.start_time,
+                       scanphy->timing.interval)) {
+        scanphy->timing.start_time += scanphy->timing.interval;
 
         /* update channel if moving to next interval */
         scanphy->scan_chan =
-                ble_ll_scan_get_next_adv_prim_chan(scanphy->scan_chan);
+                        ble_ll_scan_get_next_adv_prim_chan(scanphy->scan_chan);
     }
 
-    return scanphy->scan_win_start_time;
+    return scanphy->timing.start_time;
 }
 /**
  * Called to determine if we are inside or outside the scan window. If we
@@ -1150,28 +1154,25 @@ ble_ll_scan_get_scan_win(struct ble_ll_scan_params *scanphy, uint32_t cputime)
 static int
 ble_ll_scan_window_chk(struct ble_ll_scan_sm *scansm, uint32_t cputime)
 {
-    uint32_t win;
+    struct ble_ll_scan_params *scanphy = &scansm->phy_data[scansm->cur_phy];
     uint32_t dt;
     uint32_t win_start;
-    struct ble_ll_scan_params *scanphy = &scansm->phy_data[scansm->cur_phy];
-#ifdef BLE_XCVR_RFCLK
-    uint32_t itvl;
-#endif
 
     win_start = ble_ll_scan_get_scan_win(scanphy, cputime);
 
-    if (scanphy->scan_window != scanphy->scan_itvl) {
-        win = os_cputime_usecs_to_ticks(scanphy->scan_window * BLE_HCI_SCAN_ITVL);
-        dt = cputime - win_start;
-        if (dt >= win) {
+    if (scanphy->timing.window == scanphy->timing.interval) {
+        /* always inside window in continuous scan */
+        return 0;
+    }
+
+    dt = cputime - win_start;
+    if (dt >= scanphy->timing.window) {
 #ifdef BLE_XCVR_RFCLK
-            itvl = os_cputime_usecs_to_ticks(scanphy->scan_itvl * BLE_HCI_SCAN_ITVL);
-            if (dt < (itvl - g_ble_ll_data.ll_xtal_ticks)) {
-                ble_ll_scan_rfclk_chk_stop();
-            }
-#endif
-            return 1;
+        if (dt < (scanphy->timing.interval - g_ble_ll_data.ll_xtal_ticks)) {
+            ble_ll_scan_rfclk_chk_stop();
         }
+#endif
+        return 1;
     }
 
     return 0;
@@ -1316,10 +1317,21 @@ ble_ll_scan_sm_stop(int chk_disable)
 static int
 ble_ll_scan_sm_start(struct ble_ll_scan_sm *scansm)
 {
+    struct ble_ll_scan_params *scanphy_cur;
+    struct ble_ll_scan_params *scanphy_next;
+
     if (!ble_ll_is_valid_own_addr_type(scansm->own_addr_type, g_random_addr)) {
         return BLE_ERR_INV_HCI_CMD_PARMS;
     }
 
+    BLE_LL_ASSERT(scansm->cur_phy != PHY_NOT_CONFIGURED);
+    scanphy_cur = &scansm->phy_data[scansm->cur_phy];
+    if (scansm->next_phy != PHY_NOT_CONFIGURED) {
+        scanphy_next = &scansm->phy_data[scansm->next_phy];
+    } else {
+        scanphy_next = NULL;
+    }
+
     /* Count # of times started */
     STATS_INC(ble_ll_stats, scan_starts);
 
@@ -1327,12 +1339,9 @@ ble_ll_scan_sm_start(struct ble_ll_scan_sm *scansm)
     scansm->scan_enabled = 1;
 
     /* Set first advertising channel */
-    BLE_LL_ASSERT(scansm->cur_phy != PHY_NOT_CONFIGURED);
-    scansm->phy_data[scansm->cur_phy].scan_chan = BLE_PHY_ADV_CHAN_START;
-
-    if (scansm->next_phy != PHY_NOT_CONFIGURED &&
-            scansm->next_phy != scansm->cur_phy) {
-        scansm->phy_data[scansm->next_phy].scan_chan = BLE_PHY_ADV_CHAN_START;
+    scanphy_cur->scan_chan = BLE_PHY_ADV_CHAN_START;
+    if (scanphy_next) {
+        scanphy_next->scan_chan = BLE_PHY_ADV_CHAN_START;
     }
 
     /* Reset scan request backoff parameters to default */
@@ -1348,13 +1357,12 @@ ble_ll_scan_sm_start(struct ble_ll_scan_sm *scansm)
 
     /* XXX: align to current or next slot???. */
     /* Schedule start time now */
-    scansm->phy_data[scansm->cur_phy].scan_win_start_time = os_cputime_get32();
+    scanphy_cur->timing.start_time = os_cputime_get32();
 
-    if (scansm->next_phy != PHY_NOT_CONFIGURED) {
+    if (scanphy_next) {
         /* Schedule start time right after first phy */
-        scansm->phy_data[scansm->next_phy].scan_win_start_time =
-                scansm->phy_data[scansm->cur_phy].scan_win_start_time +
-                os_cputime_usecs_to_ticks(scansm->phy_data[scansm->cur_phy].scan_window * BLE_HCI_SCAN_ITVL);
+        scanphy_next->timing.start_time = scanphy_cur->timing.start_time +
+                                          scanphy_cur->timing.window;
     }
 
     /* Post scanning event to start off the scanning process */
@@ -1430,34 +1438,31 @@ ble_ll_scan_interrupted_event_cb(struct ble_npl_event *ev)
 }
 
 static int
-check_phy_window(struct ble_ll_scan_params *scanphy, uint32_t now,
-                 uint32_t *next_event_time, uint32_t *dt, uint32_t *win,
-                 uint32_t *scan_itvl)
+check_phy_window(struct ble_ll_scan_params *scanphy, uint32_t now, uint32_t *dt,
+                 struct ble_ll_scan_timing *timing)
 {
     uint32_t win_start;
 
     win_start = ble_ll_scan_get_scan_win(scanphy, now);
 
-    /* Determine on/off state based on scan window */
-    *scan_itvl = os_cputime_usecs_to_ticks(scanphy->scan_itvl *
-                                                    BLE_HCI_SCAN_ITVL);
+    timing->interval = scanphy->timing.interval;
 
-    /* for continues scan assume we are always inside window */
-    if (scanphy->scan_window == scanphy->scan_itvl) {
-        *next_event_time = win_start + *scan_itvl;
+    /* for continuous scan assume we are always inside window */
+    if (scanphy->timing.window == scanphy->timing.interval) {
+        timing->start_time = win_start + scanphy->timing.interval;
         return 1;
     }
 
-    *win = os_cputime_usecs_to_ticks(scanphy->scan_window * BLE_HCI_SCAN_ITVL);
+    timing->window = scanphy->timing.window;
 
     /* Check if we are in scan window */
     *dt = now - win_start;
-    if (*dt < *win) {
-        *next_event_time = win_start + *win;
+    if (*dt < scanphy->timing.window) {
+        timing->start_time = win_start + scanphy->timing.window;
         return 1;
     }
 
-    *next_event_time = win_start + *scan_itvl;
+    timing->start_time = win_start + scanphy->timing.interval;
     return 0;
 }
 
@@ -1471,22 +1476,18 @@ check_phy_window(struct ble_ll_scan_params *scanphy, uint32_t now,
 static void
 ble_ll_scan_event_proc(struct ble_npl_event *ev)
 {
+    struct ble_ll_scan_sm *scansm;
     os_sr_t sr;
     int inside_window;
     int start_scan;
     uint32_t now;
-    uint32_t dt = 0;
-    uint32_t win = 0;
-    uint32_t scan_itvl = 0;
-    uint32_t next_event_time;
-    struct ble_ll_scan_sm *scansm;
+    uint32_t dt;
     struct ble_ll_scan_params *scanphy;
+    struct ble_ll_scan_timing timing;
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
     uint32_t dt_next;
-    uint32_t win_next;
-    uint32_t scan_itvl_next;
-    uint32_t next_event_time_next;
     struct ble_ll_scan_params *scanphy_next;
+    struct ble_ll_scan_timing timing_next;
 #endif
 
 #ifdef BLE_XCVR_RFCLK
@@ -1519,8 +1520,9 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev)
     now = os_cputime_get32();
 
     /* check current phy */
-    inside_window = check_phy_window(scanphy, now, &next_event_time, &dt, &win,
-                                     &scan_itvl);
+    inside_window = check_phy_window(scanphy, now, &dt, &timing);
+
+    /* timing.start_time is start time for *next* window */
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
     if (!inside_window) {
@@ -1528,21 +1530,18 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev)
             scanphy_next = &scansm->phy_data[scansm->next_phy];
 
             /* check next phy */
-            inside_window = check_phy_window(scanphy_next, now,
-                                             &next_event_time_next, &dt_next,
-                                             &win_next, &scan_itvl_next);
+            inside_window = check_phy_window(scanphy_next, now, &dt_next,
+                                             &timing_next);
 
             /* Update current PHY if either next phy is in window or
              * closest window is for next-PHY
              */
-            if (inside_window ||
-                    CPUTIME_LEQ(next_event_time_next, next_event_time)) {
+            if (inside_window || CPUTIME_LEQ(timing_next.start_time,
+                                             timing.start_time)) {
                 ble_ll_scan_switch_current_phy(scansm);
 
                 dt = dt_next;
-                win = win_next;
-                scan_itvl = scan_itvl_next;
-                next_event_time = next_event_time_next;
+                timing = timing_next;
             }
         }
     }
@@ -1597,8 +1596,8 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev)
              * Only bother if we have enough time to receive anything
              * here. The next event time will turn off the clock.
              */
-            if (win != 0) {
-                if ((win - dt) <= xtal_ticks)  {
+            if (timing.window != 0) {
+                if ((timing.window - dt) <= xtal_ticks)  {
                     goto done;
                 }
             }
@@ -1610,7 +1609,7 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev)
             if (xtal_state == BLE_RFCLK_STATE_OFF) {
                 ble_ll_xcvr_rfclk_start_now();
             }
-            next_event_time = now + xtal_ticks;
+            timing.start_time = now + xtal_ticks;
             goto done;
         }
 #endif
@@ -1625,16 +1624,16 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev)
          * to make sure the rfclock is on. If we are close to being on,
          * enable the rfclock. If not, set wakeup time.
          */
-        if (dt >= (scan_itvl - g_ble_ll_data.ll_xtal_ticks)) {
+        if (dt >= (timing.interval - g_ble_ll_data.ll_xtal_ticks)) {
             /* Start the clock if necessary */
             if (start_scan) {
                 if (ble_ll_xcvr_rfclk_state() == BLE_RFCLK_STATE_OFF) {
                     ble_ll_xcvr_rfclk_start_now();
-                    next_event_time = now + g_ble_ll_data.ll_xtal_ticks;
+                    timing.start_time = now + g_ble_ll_data.ll_xtal_ticks;
                 }
             }
         } else {
-            next_event_time -= g_ble_ll_data.ll_xtal_ticks;
+            timing.start_time -= g_ble_ll_data.ll_xtal_ticks;
             if (start_scan) {
                 ble_ll_scan_rfclk_chk_stop();
             }
@@ -1644,7 +1643,7 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev)
 
 done:
     OS_EXIT_CRITICAL(sr);
-    os_cputime_timer_start(&scansm->scan_timer, next_event_time);
+    os_cputime_timer_start(&scansm->scan_timer, timing.start_time);
 }
 
 /**
@@ -3355,8 +3354,8 @@ ble_ll_scan_set_scan_params(const uint8_t *cmdbuf, uint8_t len)
     scanp = &g_ble_ll_scan_params[PHY_UNCODED];
     scanp->configured = 1;
     scanp->scan_type = cmd->scan_type;
-    scanp->scan_itvl = scan_itvl;
-    scanp->scan_window = scan_window;
+    scanp->timing.interval = ble_ll_scan_time_hci_to_ticks(scan_itvl);
+    scanp->timing.window = ble_ll_scan_time_hci_to_ticks(scan_window);
     scanp->scan_filt_policy = cmd->filter_policy;
     scanp->own_addr_type = cmd->own_addr_type;
 
@@ -3398,6 +3397,8 @@ ble_ll_set_ext_scan_params(const uint8_t *cmdbuf, uint8_t len)
     struct ble_ll_scan_params new_params[BLE_LL_SCAN_PHY_NUMBER] = { };
     struct ble_ll_scan_params *uncoded = &new_params[PHY_UNCODED];
     struct ble_ll_scan_params *coded = &new_params[PHY_CODED];
+    uint16_t interval;
+    uint16_t window;
     int rc;
 
     if (len <= sizeof(*cmd)) {
@@ -3440,17 +3441,18 @@ ble_ll_set_ext_scan_params(const uint8_t *cmdbuf, uint8_t len)
             return BLE_ERR_INV_HCI_CMD_PARMS;
         }
 
-        uncoded->scan_type = params->type;
-        uncoded->scan_itvl = le16toh(params->itvl);
-        uncoded->scan_window = le16toh(params->window);
+        interval = le16toh(params->itvl);
+        window = le16toh(params->window);
 
-        rc = ble_ll_check_scan_params(uncoded->scan_type,
-                                      uncoded->scan_itvl,
-                                      uncoded->scan_window);
+        rc = ble_ll_check_scan_params(params->type, interval, window);
         if (rc) {
             return rc;
         }
 
+        uncoded->scan_type = params->type;
+        uncoded->timing.interval = ble_ll_scan_time_hci_to_ticks(interval);
+        uncoded->timing.window = ble_ll_scan_time_hci_to_ticks(window);
+
         /* That means user wants to use this PHY for scanning */
         uncoded->configured = 1;
         params++;
@@ -3463,17 +3465,18 @@ ble_ll_set_ext_scan_params(const uint8_t *cmdbuf, uint8_t len)
             return BLE_ERR_INV_HCI_CMD_PARMS;
         }
 
-        coded->scan_type = params->type;
-        coded->scan_itvl = le16toh(params->itvl);
-        coded->scan_window = le16toh(params->window);
+        interval = le16toh(params->itvl);
+        window = le16toh(params->window);
 
-        rc = ble_ll_check_scan_params(coded->scan_type,
-                                      coded->scan_itvl,
-                                      coded->scan_window);
+        rc = ble_ll_check_scan_params(params->type, interval, window);
         if (rc) {
             return rc;
         }
 
+        coded->scan_type = params->type;
+        coded->timing.interval = ble_ll_scan_time_hci_to_ticks(interval);
+        coded->timing.window = ble_ll_scan_time_hci_to_ticks(window);
+
         /* That means user wants to use this PHY for scanning */
         coded->configured = 1;
     }
@@ -3483,12 +3486,12 @@ ble_ll_set_ext_scan_params(const uint8_t *cmdbuf, uint8_t len)
      * fit other PHY
      */
     if (coded->configured && uncoded->configured) {
-        if (coded->scan_itvl == coded->scan_window) {
-            coded->scan_itvl += uncoded->scan_window;
+        if (coded->timing.interval == coded->timing.window) {
+            coded->timing.interval += uncoded->timing.window;
         }
 
-        if (uncoded->scan_itvl == uncoded->scan_window) {
-            uncoded->scan_itvl += coded->scan_window;
+        if (uncoded->timing.interval == uncoded->timing.window) {
+            uncoded->timing.window += coded->timing.window;
         }
     }
 
@@ -3666,8 +3669,7 @@ ble_ll_scan_set_enable(uint8_t enable, uint8_t filter_dups, uint16_t period,
 
         scanphy->configured = scanp->configured;
         scanphy->scan_type = scanp->scan_type;
-        scanphy->scan_itvl = scanp->scan_itvl;
-        scanphy->scan_window = scanp->scan_window;
+        scanphy->timing = scanp->timing;
         scanphy->scan_filt_policy = scanp->scan_filt_policy;
         scanphy->own_addr_type = scanp->own_addr_type;
 
@@ -3695,8 +3697,10 @@ ble_ll_scan_set_enable(uint8_t enable, uint8_t filter_dups, uint16_t period,
 
         scanphy->configured = 1;
         scanphy->scan_type = BLE_SCAN_TYPE_PASSIVE;
-        scanphy->scan_itvl = 0x0010;
-        scanphy->scan_window = 0x0010;
+        scanphy->timing.interval =
+                        ble_ll_scan_time_hci_to_ticks(BLE_HCI_SCAN_ITVL_DEF);
+        scanphy->timing.window =
+                        ble_ll_scan_time_hci_to_ticks(BLE_HCI_SCAN_WINDOW_DEF);
         scanphy->scan_filt_policy = BLE_HCI_SCAN_FILT_NO_WL;
         scanphy->own_addr_type = BLE_ADDR_PUBLIC;
     }
@@ -3783,8 +3787,8 @@ ble_ll_scan_initiator_start(struct hci_create_conn *hcc,
 
     scanphy = &scansm->phy_data[scansm->cur_phy];
     scanphy->scan_filt_policy = hcc->filter_policy;
-    scanphy->scan_itvl = hcc->scan_itvl;
-    scanphy->scan_window = hcc->scan_window;
+    scanphy->timing.interval = ble_ll_scan_time_hci_to_ticks(hcc->scan_itvl);
+    scanphy->timing.window = ble_ll_scan_time_hci_to_ticks(hcc->scan_window);
     scanphy->scan_type = BLE_SCAN_TYPE_INITIATE;
 
     rc = ble_ll_scan_sm_start(scansm);
@@ -3822,8 +3826,8 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc,
         params = &hcc->params[0];
         uncoded = &scansm->phy_data[PHY_UNCODED];
 
-        uncoded->scan_itvl = params->scan_itvl;
-        uncoded->scan_window = params->scan_window;
+        uncoded->timing.interval = ble_ll_scan_time_hci_to_ticks(params->scan_itvl);
+        uncoded->timing.window = ble_ll_scan_time_hci_to_ticks(params->scan_window);
         uncoded->scan_type = BLE_SCAN_TYPE_INITIATE;
         uncoded->scan_filt_policy = hcc->filter_policy;
         scansm->cur_phy = PHY_UNCODED;
@@ -3833,8 +3837,8 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc,
         params = &hcc->params[2];
         coded = &scansm->phy_data[PHY_CODED];
 
-        coded->scan_itvl = params->scan_itvl;
-        coded->scan_window = params->scan_window;
+        coded->timing.interval = ble_ll_scan_time_hci_to_ticks(params->scan_itvl);
+        coded->timing.window = ble_ll_scan_time_hci_to_ticks(params->scan_window);
         coded->scan_type = BLE_SCAN_TYPE_INITIATE;
         coded->scan_filt_policy = hcc->filter_policy;
         if (scansm->cur_phy == PHY_NOT_CONFIGURED) {
@@ -3848,12 +3852,12 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc,
      * fit other PHY
      */
     if (coded->configured && uncoded->configured) {
-        if (coded->scan_itvl == coded->scan_window) {
-            coded->scan_itvl += uncoded->scan_window;
+        if (coded->timing.interval == coded->timing.window) {
+            coded->timing.interval += uncoded->timing.window;
         }
 
-        if (uncoded->scan_itvl == uncoded->scan_window) {
-            uncoded->scan_itvl += coded->scan_window;
+        if (uncoded->timing.interval == uncoded->timing.window) {
+            uncoded->timing.interval += coded->timing.window;
         }
     }
 
@@ -3963,8 +3967,10 @@ ble_ll_scan_common_init(void)
     for (i = 0; i < BLE_LL_SCAN_PHY_NUMBER; i++) {
         /* Set all non-zero default parameters */
         scanp = &g_ble_ll_scan_params[i];
-        scanp->scan_itvl = BLE_HCI_SCAN_ITVL_DEF;
-        scanp->scan_window = BLE_HCI_SCAN_WINDOW_DEF;
+        scanp->timing.interval =
+                        ble_ll_scan_time_hci_to_ticks(BLE_HCI_SCAN_ITVL_DEF);
+        scanp->timing.window =
+                        ble_ll_scan_time_hci_to_ticks(BLE_HCI_SCAN_WINDOW_DEF);
     }
 
     scansm->phy_data[PHY_UNCODED].phy = BLE_PHY_1M;


[mynewt-nimble] 06/09: nimble/ll: Refactor rfclk management from LL

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 491a37e31fc364308a64841bb01bbb3a581b1044
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Fri Dec 6 14:47:32 2019 +0100

    nimble/ll: Refactor rfclk management from LL
    
    Recently we found multiple issues due to invalid rfclk management, i.e.
    either rfclk was enabled when it should be disabled or the other way
    around. The reason for this is rfclk is triggered at various places due
    to either items in scheduler or scannning, but there is no single state
    which can be used to calculate required rfclk state at any given time.
    And this is also more and more complex with all the new cool features we
    added recently.
    
    So now we have such state: ble_ll_rfmgmt (referred to as rfmgmt from now
    on). This is basically ble_ll_xcvr rewritten from scratch. The name was
    changed since in theory this can be used not only to enable RF clock,
    but RF in general - it's up to PHY what it actually does.
    
    rfmgmt is the only place where RF can be enabled (with one exception -
    more on this later) or disabled. This decision is made based on state
    updates from scanner and scheduler:
    - each time scanner moves to new scan window, rfmgmt needs to be notified
      on its start time ,
    - each time 1st item in scheduler is changed, rfmgmt needs to be notified
      on current start time
    - each time there is done-like event which ends conn/adv/whatever event,
      rfmgmt needs to be notified that RF is no longer needed
    
    This basically means:
    - ble_ll_rfmgmt_scan_changed() shall be only called from ble_ll_scan,
    - ble_ll_rfmgmt_sched_changed() shall be only called from ble_ll_sched,
    - ble_ll_rfmgmt_release() can be called whenever we don't RF anymore.
    
    RF is not disabled immediately after calling release, this is postponed
    to LL task so any scan or scheduler update done after release will still
    keep RF running if necessary - all this means that it's safe to simply
    call release at the beginning of function and then do other stuff.
    
    One exception mentioned earlier is when we need to enable RF and this is
    not triggered from other RF activity. Currently this applies to 1st scan
    window, 1st advertising PDU or 1st PDU in DTM. In these cases we just
    basically want to start "now" so it's done as follows:
    - call ble_ll_rfmgmt_enable_now() to enable RF instantly, if disabled
    - this returns tick at which RF is fully enabled (can be "now" if RF is
      already enabled) and this is also the time which should be used to
      start new activity
    
    And last but not least: we do not need "#ifdef BLE_LL_RFCLK" everywhere
    in code anymore!
---
 nimble/controller/include/controller/ble_ll.h      |  30 --
 .../controller/include/controller/ble_ll_rfmgmt.h  |  63 ++++
 .../controller/include/controller/ble_ll_sched.h   |   5 -
 nimble/controller/include/controller/ble_ll_xcvr.h |  48 ---
 nimble/controller/src/ble_ll.c                     |  34 +-
 nimble/controller/src/ble_ll_adv.c                 |  80 ++---
 nimble/controller/src/ble_ll_conn.c                |  12 +-
 nimble/controller/src/ble_ll_dtm.c                 |  20 +-
 nimble/controller/src/ble_ll_rfmgmt.c              | 346 +++++++++++++++++++++
 nimble/controller/src/ble_ll_scan.c                | 177 +++--------
 nimble/controller/src/ble_ll_sched.c               | 134 ++------
 nimble/controller/src/ble_ll_sync.c                |  21 +-
 nimble/controller/src/ble_ll_xcvr.c                | 169 ----------
 nimble/drivers/nrf51/src/ble_phy.c                 |  11 -
 nimble/drivers/nrf52/src/ble_phy.c                 |  11 -
 15 files changed, 519 insertions(+), 642 deletions(-)

diff --git a/nimble/controller/include/controller/ble_ll.h b/nimble/controller/include/controller/ble_ll.h
index a07f8c8..b748e10 100644
--- a/nimble/controller/include/controller/ble_ll.h
+++ b/nimble/controller/include/controller/ble_ll.h
@@ -56,27 +56,6 @@ extern "C" {
 #else
 #define BLE_LL_ASSERT(cond) assert(cond)
 #endif
-/*
- * XXX:
- * I guess this should not depend on the 32768 crystal to be honest. This
- * should be done for TIMER0 as well since the rf clock chews up more current.
- * Deal with this later.
- *
- * Another note: BLE_XTAL_SETTLE_TIME should be bsp related (I guess). There
- * should be a note in there that the converted usecs to ticks value of this
- * should not be 0. Thus: if you are using a 32.768 os cputime freq, the min
- * value of settle time should be 31 usecs. I would suspect all settling times
- * would exceed 31 usecs.
- */
-
-/* Determines if we need to turn on/off rf clock */
-#undef BLE_XCVR_RFCLK
-
-/* We will turn on/off rf clock */
-#if MYNEWT_VAL(BLE_XTAL_SETTLE_TIME) != 0
-#define BLE_XCVR_RFCLK
-
-#endif
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) || MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
 #define BLE_LL_BT5_PHY_SUPPORTED    (1)
@@ -116,15 +95,6 @@ struct ble_ll_obj
     uint8_t ll_pref_tx_phys;
     uint8_t ll_pref_rx_phys;
 
-#ifdef BLE_XCVR_RFCLK
-    uint8_t ll_rfclk_state;
-    uint8_t ll_rfclk_is_sched;
-    uint16_t ll_xtal_ticks;
-    uint32_t ll_rfclk_start_time;
-    uint32_t ll_rfclk_sched_time;
-    struct hal_timer ll_rfclk_timer;
-#endif
-
     /* Task event queue */
     struct ble_npl_eventq ll_evq;
 
diff --git a/nimble/controller/include/controller/ble_ll_rfmgmt.h b/nimble/controller/include/controller/ble_ll_rfmgmt.h
new file mode 100644
index 0000000..da584e5
--- /dev/null
+++ b/nimble/controller/include/controller/ble_ll_rfmgmt.h
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_BLE_LL_RFMGMT_
+#define H_BLE_LL_RFMGMT_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void ble_ll_rfmgmt_init(void);
+
+#if MYNEWT_VAL(BLE_XTAL_SETTLE_TIME) > 0
+
+void ble_ll_rfmgmt_reset(void);
+
+/* Notify rfmgmt that scan window has changed (only called from ble_ll_scan) */
+void ble_ll_rfmgmt_scan_changed(bool enabled, uint32_t next_window);
+
+/* Notify rfmgmt that 1st scheduled item has changed (only called from ble_ll_sched) */
+void ble_ll_rfmgmt_sched_changed(struct ble_ll_sched_item *first);
+
+/* Notify rfmgmt that RF is no longer needed by current event */
+void ble_ll_rfmgmt_release(void);
+
+/* Enables RF immediately and returns tick at which RF will be fully enabled */
+uint32_t ble_ll_rfmgmt_enable_now(void);
+
+/* Returns true only if RF is currently fully enabled (i.e. not off or enabling) */
+bool ble_ll_rfmgmt_is_enabled(void);
+
+#else
+
+static inline void ble_ll_rfmgmt_reset(void) { }
+static inline void ble_ll_rfmgmt_scan_changed(bool e, uint32_t n) { }
+static inline void ble_ll_rfmgmt_sched_changed(struct ble_ll_sched_item *f) { }
+static inline void ble_ll_rfmgmt_release(void) { }
+static inline uint32_t ble_ll_rfmgmt_enable_now(void) { return 0; }
+static inline bool ble_ll_rfmgmt_is_enabled(void) { return true; }
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_BLE_LL_RFMGMT_ */
diff --git a/nimble/controller/include/controller/ble_ll_sched.h b/nimble/controller/include/controller/ble_ll_sched.h
index 9c638e5..72d5c73 100644
--- a/nimble/controller/include/controller/ble_ll_sched.h
+++ b/nimble/controller/include/controller/ble_ll_sched.h
@@ -210,11 +210,6 @@ int ble_ll_sched_scan_req_over_aux_ptr(uint32_t chan, uint8_t phy_mode);
 /* Stop the scheduler */
 void ble_ll_sched_stop(void);
 
-#ifdef BLE_XCVR_RFCLK
-/* Check if RF clock needs to be restarted */
-void ble_ll_sched_rfclk_chk_restart(void);
-#endif
-
 #if MYNEWT_VAL(BLE_LL_DTM)
 int ble_ll_sched_dtm(struct ble_ll_sched_item *sch);
 #endif
diff --git a/nimble/controller/include/controller/ble_ll_xcvr.h b/nimble/controller/include/controller/ble_ll_xcvr.h
deleted file mode 100644
index a7ab0e8..0000000
--- a/nimble/controller/include/controller/ble_ll_xcvr.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#ifndef H_BLE_LL_XCVR_
-#define H_BLE_LL_XCVR_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef BLE_XCVR_RFCLK
-
-/* RF clock states */
-#define BLE_RFCLK_STATE_OFF     (0)
-#define BLE_RFCLK_STATE_ON      (1)
-#define BLE_RFCLK_STATE_SETTLED (2)
-
-int ble_ll_xcvr_rfclk_state(void);
-void ble_ll_xcvr_rfclk_start_now(void);
-void ble_ll_xcvr_rfclk_stop(void);
-void ble_ll_xcvr_rfclk_enable(void);
-void ble_ll_xcvr_rfclk_disable(void);
-uint32_t ble_ll_xcvr_rfclk_time_till_settled(void);
-void ble_ll_xcvr_rfclk_timer_exp(void *arg);
-void ble_ll_xcvr_rfclk_timer_start(uint32_t cputime);
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* H_LL_ */
diff --git a/nimble/controller/src/ble_ll.c b/nimble/controller/src/ble_ll.c
index 68fffda..3ab918b 100644
--- a/nimble/controller/src/ble_ll.c
+++ b/nimble/controller/src/ble_ll.c
@@ -40,7 +40,7 @@
 #include "controller/ble_ll_hci.h"
 #include "controller/ble_ll_whitelist.h"
 #include "controller/ble_ll_resolv.h"
-#include "controller/ble_ll_xcvr.h"
+#include "controller/ble_ll_rfmgmt.h"
 #include "controller/ble_ll_trace.h"
 #include "controller/ble_ll_sync.h"
 #include "ble_ll_conn_priv.h"
@@ -1326,16 +1326,12 @@ ble_ll_reset(void)
     int rc;
     os_sr_t sr;
 
-    /* Stop the phy */
-    ble_phy_disable();
-
-    /* Stop any wait for response timer */
     OS_ENTER_CRITICAL(sr);
+    ble_phy_disable();
     ble_ll_sched_stop();
-    OS_EXIT_CRITICAL(sr);
-
-    /* Stop any scanning */
     ble_ll_scan_reset();
+    ble_ll_rfmgmt_reset();
+    OS_EXIT_CRITICAL(sr);
 
     /* Stop any advertising */
     ble_ll_adv_reset();
@@ -1372,13 +1368,6 @@ ble_ll_reset(void)
     /* Set state to standby */
     ble_ll_state_set(BLE_LL_STATE_STANDBY);
 
-#ifdef BLE_XCVR_RFCLK
-    OS_ENTER_CRITICAL(sr);
-    /* Stops rf clock and rfclock timer */
-    ble_ll_xcvr_rfclk_stop();
-    OS_EXIT_CRITICAL(sr);
-#endif
-
     /* Reset our random address */
     memset(g_random_addr, 0, BLE_DEV_ADDR_LEN);
 
@@ -1508,9 +1497,6 @@ ble_ll_init(void)
 {
     int rc;
     uint32_t features;
-#ifdef BLE_XCVR_RFCLK
-    uint32_t xtal_ticks;
-#endif
     ble_addr_t addr;
     struct ble_ll_obj *lldata;
 
@@ -1533,17 +1519,7 @@ ble_ll_init(void)
         }
     }
 
-#ifdef BLE_XCVR_RFCLK
-    /* Settling time of crystal, in ticks */
-    xtal_ticks = MYNEWT_VAL(BLE_XTAL_SETTLE_TIME);
-    BLE_LL_ASSERT(xtal_ticks != 0);
-    g_ble_ll_data.ll_xtal_ticks = ble_ll_usecs_to_ticks_round_up(xtal_ticks);
-
-    /* Initialize rf clock timer */
-    os_cputime_timer_init(&g_ble_ll_data.ll_rfclk_timer,
-                          ble_ll_xcvr_rfclk_timer_exp, NULL);
-
-#endif
+    ble_ll_rfmgmt_init();
 
     /* Get pointer to global data object */
     lldata = &g_ble_ll_data;
diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c
index dd98609..22cd559 100644
--- a/nimble/controller/src/ble_ll_adv.c
+++ b/nimble/controller/src/ble_ll_adv.c
@@ -39,7 +39,7 @@
 #include "controller/ble_ll_resolv.h"
 #include "controller/ble_ll_trace.h"
 #include "controller/ble_ll_utils.h"
-#include "controller/ble_ll_xcvr.h"
+#include "controller/ble_ll_rfmgmt.h"
 #include "ble_ll_conn_priv.h"
 
 /* XXX: TODO
@@ -1853,6 +1853,8 @@ ble_ll_adv_sm_stop(struct ble_ll_adv_sm *advsm)
     os_sr_t sr;
 
     if (advsm->adv_enabled) {
+        ble_ll_rfmgmt_release();
+
         /* Remove any scheduled advertising items */
         ble_ll_sched_rmv_elem(&advsm->adv_sch);
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
@@ -1879,9 +1881,6 @@ ble_ll_adv_sm_stop(struct ble_ll_adv_sm *advsm)
             ble_ll_scan_chk_resume();
         }
 #endif
-#ifdef BLE_XCVR_RFCLK
-        ble_ll_sched_rfclk_chk_restart();
-#endif
         OS_EXIT_CRITICAL(sr);
 
         ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev);
@@ -2413,6 +2412,8 @@ ble_ll_adv_periodic_done(struct ble_ll_adv_sm *advsm)
     assert(advsm->periodic_adv_active);
     assert(advsm->periodic_sync_active);
 
+    ble_ll_rfmgmt_release();
+
     sync = SYNC_CURRENT(advsm);
     sync_next = SYNC_NEXT(advsm);
 
@@ -2430,11 +2431,6 @@ ble_ll_adv_periodic_done(struct ble_ll_adv_sm *advsm)
     /* Check if we need to resume scanning */
     ble_ll_scan_chk_resume();
 
-    /* Turn off the clock if not doing anything else */
-#ifdef BLE_XCVR_RFCLK
-    ble_ll_sched_rfclk_chk_restart();
-#endif
-
     advsm->periodic_sync_active = 0;
     ble_ll_adv_update_periodic_data(advsm);
     ble_ll_adv_reschedule_periodic_event(advsm);
@@ -2502,6 +2498,8 @@ ble_ll_adv_sm_stop_periodic(struct ble_ll_adv_sm *advsm)
 {
     os_sr_t sr;
 
+    ble_ll_rfmgmt_release();
+
     if (!advsm->periodic_adv_active) {
         return;
     }
@@ -2533,10 +2531,6 @@ ble_ll_adv_sm_stop_periodic(struct ble_ll_adv_sm *advsm)
         g_ble_ll_cur_adv_sm = NULL;
         ble_ll_scan_chk_resume();
     }
-
-#ifdef BLE_XCVR_RFCLK
-    ble_ll_sched_rfclk_chk_restart();
-#endif
     OS_EXIT_CRITICAL(sr);
 
     ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING);
@@ -2569,11 +2563,9 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm)
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2)
     uint32_t access_addr;
 #endif
-#ifdef BLE_XCVR_RFCLK
-    int xtal_state;
-    os_sr_t sr;
-#endif
     const uint8_t *random_addr;
+    uint32_t earliest_start_time;
+    int32_t delta;
 
     /* only clear flags that are not set from HCI */
     ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_TX_ADD |
@@ -2656,32 +2648,31 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm)
     advsm->adv_chan = adv_chan;
 
     /*
-     * Set initial start time (randomized similar to interval)
-     * NOTE: adv_event_start_time gets set by the sched_adv_new
+     * Scheduling 1st PDU is a bit tricky.
+     * Earliest possible start time is after RF is enabled so just force RF to
+     * start here to see when if will be fully enabled - it will be too early,
+     * but this is the only reliable way to have it enabled on time.
+     * Next we calculate expected start time (randomize it a bit) and this is
+     * used to setup start time for scheduler item.
+     * Then we check if start time for scheduler item (which includes scheduler
+     * overhead) is no earlier than calculated earliest possible start time and
+     * adjust scheduler item if necessary.
      */
+    earliest_start_time = ble_ll_rfmgmt_enable_now();
+
     start_delay_us = rand() % (BLE_LL_ADV_DELAY_MS_MAX * 1000);
     advsm->adv_pdu_start_time = os_cputime_get32() +
                                 os_cputime_usecs_to_ticks(start_delay_us);
 
-#ifdef BLE_XCVR_RFCLK
-    OS_ENTER_CRITICAL(sr);
-    xtal_state = ble_ll_xcvr_rfclk_state();
-    if (xtal_state != BLE_RFCLK_STATE_SETTLED) {
-        if (xtal_state == BLE_RFCLK_STATE_OFF) {
-            advsm->adv_pdu_start_time += g_ble_ll_data.ll_xtal_ticks;
-            ble_ll_xcvr_rfclk_start_now();
-        } else {
-            advsm->adv_pdu_start_time += ble_ll_xcvr_rfclk_time_till_settled();
-        }
+    ble_ll_adv_set_sched(advsm);
+
+    delta = (int32_t)(advsm->adv_sch.start_time - earliest_start_time);
+    if (delta < 0) {
+        advsm->adv_sch.start_time -= delta;
+        advsm->adv_sch.end_time -= delta;
     }
-    OS_EXIT_CRITICAL(sr);
-#endif
 
-    /*
-     * Schedule advertising. We set the initial schedule start and end
-     * times to the earliest possible start/end.
-     */
-    ble_ll_adv_set_sched(advsm);
+    /* This does actual scheduling */
     ble_ll_sched_adv_new(&advsm->adv_sch, ble_ll_adv_scheduled, NULL);
 
     /* we start periodic before AE since we need PDU start time in SyncInfo */
@@ -4473,6 +4464,8 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm)
 
     assert(advsm->adv_enabled);
 
+    ble_ll_rfmgmt_release();
+
     ble_ll_adv_update_adv_scan_rsp_data(advsm);
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
@@ -4504,14 +4497,8 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm)
         }
 #endif
 
-        /* Check if we need to resume scanning */
         ble_ll_scan_chk_resume();
 
-        /* Turn off the clock if not doing anything else */
-#ifdef BLE_XCVR_RFCLK
-        ble_ll_sched_rfclk_chk_restart();
-#endif
-
         /* This event is over. Set adv channel to first one */
         advsm->adv_chan = ble_ll_adv_first_chan(advsm);
 
@@ -4663,6 +4650,9 @@ ble_ll_adv_sec_done(struct ble_ll_adv_sm *advsm)
     aux = AUX_CURRENT(advsm);
     aux_next = AUX_NEXT(advsm);
 
+    /* We don't need RF anymore */
+    ble_ll_rfmgmt_release();
+
     if (advsm->aux_not_scanned) {
         ble_ll_sched_rmv_elem(&aux_next->sch);
     }
@@ -4685,14 +4675,8 @@ ble_ll_adv_sec_done(struct ble_ll_adv_sm *advsm)
         return;
     }
 
-    /* Check if we need to resume scanning */
     ble_ll_scan_chk_resume();
 
-    /* Turn off the clock if not doing anything else */
-#ifdef BLE_XCVR_RFCLK
-    ble_ll_sched_rfclk_chk_restart();
-#endif
-
     /* Check if advertising timed out */
     if (advsm->duration && (advsm->adv_pdu_start_time >= advsm->adv_end_time)) {
         ble_ll_adv_sm_stop_timeout(advsm);
diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c
index ffb3995..98fe9b7 100644
--- a/nimble/controller/src/ble_ll_conn.c
+++ b/nimble/controller/src/ble_ll_conn.c
@@ -38,6 +38,7 @@
 #include "controller/ble_ll_resolv.h"
 #include "controller/ble_ll_adv.h"
 #include "controller/ble_ll_trace.h"
+#include "controller/ble_ll_rfmgmt.h"
 #include "controller/ble_phy.h"
 #include "controller/ble_hw.h"
 #include "controller/ble_ll_utils.h"
@@ -2367,6 +2368,8 @@ ble_ll_conn_event_end(struct ble_npl_event *ev)
     uint32_t tmo;
     struct ble_ll_conn_sm *connsm;
 
+    ble_ll_rfmgmt_release();
+
     /* Better be a connection state machine! */
     connsm = (struct ble_ll_conn_sm *)ble_npl_event_get_arg(ev);
     BLE_LL_ASSERT(connsm);
@@ -2382,10 +2385,6 @@ ble_ll_conn_event_end(struct ble_npl_event *ev)
         ble_ll_state_set(BLE_LL_STATE_STANDBY);
 
         ble_ll_scan_chk_resume();
-#ifdef BLE_XCVR_RFCLK
-        ble_ll_sched_rfclk_chk_restart();
-#endif
-
         return;
     }
 
@@ -2393,13 +2392,8 @@ ble_ll_conn_event_end(struct ble_npl_event *ev)
     ble_ll_trace_u32x2(BLE_LL_TRACE_ID_CONN_EV_END, connsm->conn_handle,
                        connsm->event_cntr);
 
-    /* Check if we need to resume scanning */
     ble_ll_scan_chk_resume();
 
-#ifdef BLE_XCVR_RFCLK
-    ble_ll_sched_rfclk_chk_restart();
-#endif
-
     /* If we have transmitted the terminate IND successfully, we are done */
     if ((connsm->csmflags.cfbit.terminate_ind_txd) ||
                     (connsm->csmflags.cfbit.terminate_ind_rxd &&
diff --git a/nimble/controller/src/ble_ll_dtm.c b/nimble/controller/src/ble_ll_dtm.c
index 0b8314b..fa284e0 100644
--- a/nimble/controller/src/ble_ll_dtm.c
+++ b/nimble/controller/src/ble_ll_dtm.c
@@ -28,7 +28,7 @@
 #include "controller/ble_ll.h"
 #include "controller/ble_phy.h"
 #include "controller/ble_ll_sched.h"
-#include "controller/ble_ll_xcvr.h"
+#include "controller/ble_ll_rfmgmt.h"
 #include "ble_ll_dtm_priv.h"
 
 STATS_SECT_START(ble_ll_dtm_stats)
@@ -368,8 +368,7 @@ schedule:
     sch->sched_cb = ble_ll_dtm_tx_sched_cb;
     sch->cb_arg = &g_ble_ll_dtm_ctx;
     sch->sched_type = BLE_LL_SCHED_TYPE_DTM;
-    sch->start_time =  os_cputime_get32() +
-                                       os_cputime_usecs_to_ticks(5000);
+    sch->start_time =  ble_ll_rfmgmt_enable_now();
 
     /* Prepare os_event */
     ble_npl_event_init(&g_ble_ll_dtm_ctx.evt, ble_ll_dtm_ev_tx_resched_cb,
@@ -412,14 +411,6 @@ ble_ll_dtm_rx_start(void)
 
     ble_ll_state_set(BLE_LL_STATE_DTM);
 
-#ifdef BLE_XCVR_RFCLK
-    OS_ENTER_CRITICAL(sr);
-    if (ble_ll_xcvr_rfclk_state() == BLE_RFCLK_STATE_OFF) {
-        ble_ll_xcvr_rfclk_start_now();
-    }
-    OS_EXIT_CRITICAL(sr);
-#endif
-
     return 0;
 }
 
@@ -451,8 +442,7 @@ ble_ll_dtm_rx_create_ctx(uint8_t rf_channel, uint8_t phy_mode)
     sch->sched_cb = ble_ll_dtm_rx_sched_cb;
     sch->cb_arg = &g_ble_ll_dtm_ctx;
     sch->sched_type = BLE_LL_SCHED_TYPE_DTM;
-    sch->start_time =  os_cputime_get32() +
-                                       os_cputime_usecs_to_ticks(5000);
+    sch->start_time =  ble_ll_rfmgmt_enable_now();
 
     rc = ble_ll_sched_dtm(sch);
     BLE_LL_ASSERT(rc == 0);
@@ -480,9 +470,7 @@ ble_ll_dtm_ctx_free(struct dtm_ctx * ctx)
     ble_phy_disable();
     ble_phy_disable_dtm();
     ble_ll_state_set(BLE_LL_STATE_STANDBY);
-#ifdef BLE_XCVR_RFCLK
-    ble_ll_xcvr_rfclk_stop();
-#endif
+    ble_ll_rfmgmt_release();
 
     os_mbuf_free_chain(ctx->om);
     memset(ctx, 0, sizeof(*ctx));
diff --git a/nimble/controller/src/ble_ll_rfmgmt.c b/nimble/controller/src/ble_ll_rfmgmt.c
new file mode 100644
index 0000000..58dad7c
--- /dev/null
+++ b/nimble/controller/src/ble_ll_rfmgmt.c
@@ -0,0 +1,346 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+#include <assert.h>
+#include <stddef.h>
+#include "syscfg/syscfg.h"
+#include "os/os_cputime.h"
+#include "controller/ble_phy.h"
+#include "controller/ble_ll.h"
+#include "controller/ble_ll_sched.h"
+#include "controller/ble_ll_rfmgmt.h"
+
+#if MYNEWT_VAL(BLE_XTAL_SETTLE_TIME) > 0
+
+enum ble_ll_rfmgmt_state {
+    RFMGMT_STATE_OFF = 0,
+    RFMGMT_STATE_ENABLING = 1,
+    RFMGMT_STATE_ENABLED = 2,
+};
+
+struct ble_ll_rfmgmt_data {
+    enum ble_ll_rfmgmt_state state;
+    uint16_t ticks_to_enabled;
+
+    struct hal_timer timer;
+    bool timer_scheduled;
+    uint32_t timer_scheduled_at;
+
+    bool enable_scan;
+    bool enable_sched;
+    uint32_t enable_scan_at;
+    uint32_t enable_sched_at;
+
+    uint32_t enabled_at;
+
+    struct ble_npl_event release_ev;
+};
+
+static struct ble_ll_rfmgmt_data g_ble_ll_rfmgmt_data;
+
+static void
+ble_ll_rfmgmt_enable(void)
+{
+    OS_ASSERT_CRITICAL();
+
+    if (g_ble_ll_rfmgmt_data.state == RFMGMT_STATE_OFF) {
+        g_ble_ll_rfmgmt_data.state = RFMGMT_STATE_ENABLING;
+        g_ble_ll_rfmgmt_data.enabled_at = os_cputime_get32();
+        ble_phy_rfclk_enable();
+    }
+}
+
+static void
+ble_ll_rfmgmt_disable(void)
+{
+    OS_ASSERT_CRITICAL();
+
+    if (g_ble_ll_rfmgmt_data.state != RFMGMT_STATE_OFF) {
+        ble_phy_rfclk_disable();
+        g_ble_ll_rfmgmt_data.state = RFMGMT_STATE_OFF;
+    }
+}
+
+static void
+ble_ll_rfmgmt_timer_reschedule(void)
+{
+    struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data;
+    uint32_t enable_at;
+
+    /* Figure out when we need to enable RF */
+    if (rfmgmt->enable_scan && rfmgmt->enable_sched) {
+        if (CPUTIME_LT(rfmgmt->enable_scan_at, rfmgmt->enable_sched_at)) {
+            enable_at = rfmgmt->enable_scan_at;
+        } else {
+            enable_at = rfmgmt->enable_sched_at;
+        }
+    } else if (rfmgmt->enable_scan) {
+        enable_at = rfmgmt->enable_scan_at;
+    } else if (rfmgmt->enable_sched) {
+        enable_at = rfmgmt->enable_sched_at;
+    } else {
+        rfmgmt->timer_scheduled = false;
+        os_cputime_timer_stop(&rfmgmt->timer);
+        return;
+    }
+
+    if (rfmgmt->timer_scheduled) {
+        /*
+         * If there is timer already scheduled at the same time we do not need
+         * to do anything. Otherwise we need to stop timer and schedule it again
+         * regardless if it's earlier or later to make sure it fires at the time
+         * something expects it.
+         */
+
+        if (rfmgmt->timer_scheduled_at == enable_at) {
+            return;
+        }
+
+        rfmgmt->timer_scheduled = false;
+        os_cputime_timer_stop(&rfmgmt->timer);
+    }
+
+    /*
+     * In case timer was requested to be enabled before current time, just make
+     * sure it's enabled and assume caller can deal with this. This will happen
+     * if something is scheduled "now" since "enable_at" is in the past, but in
+     * such case it's absolutely harmless since we already have clock enabled
+     * and this will do nothing.
+     */
+    if (CPUTIME_LEQ(enable_at, os_cputime_get32())) {
+        ble_ll_rfmgmt_enable();
+        return;
+    }
+
+    rfmgmt->timer_scheduled = true;
+    rfmgmt->timer_scheduled_at = enable_at;
+    os_cputime_timer_start(&rfmgmt->timer, enable_at);
+}
+
+static void
+ble_ll_rfmgmt_timer_exp(void *arg)
+{
+    g_ble_ll_rfmgmt_data.timer_scheduled = false;
+    ble_ll_rfmgmt_enable();
+}
+
+static void
+ble_ll_rfmgmt_release_ev(struct ble_npl_event *ev)
+{
+    struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data;
+    uint32_t now;
+    bool can_disable;
+    uint8_t lls;
+    os_sr_t sr;
+
+    OS_ENTER_CRITICAL(sr);
+
+    now = os_cputime_get32();
+
+    can_disable = true;
+    lls = ble_ll_state_get();
+
+    if (rfmgmt->enable_scan && CPUTIME_GEQ(now, rfmgmt->enable_scan_at)) {
+        /* Blocked by scan */
+        can_disable = false;
+    } else if (rfmgmt->enable_sched && CPUTIME_GEQ(now, rfmgmt->enable_sched_at)) {
+        /* Blocked by scheduler item */
+        can_disable = false;
+    } else if (lls != BLE_LL_STATE_STANDBY) {
+        /* Blocked by LL state */
+        can_disable = false;
+    }
+
+    if (can_disable) {
+        ble_ll_rfmgmt_disable();
+    }
+
+    OS_EXIT_CRITICAL(sr);
+}
+
+static uint32_t
+ble_ll_rfmgmt_ticks_to_enabled(void)
+{
+    struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data;
+    uint32_t rem_ticks;
+    uint32_t now;
+
+    switch (rfmgmt->state) {
+    case RFMGMT_STATE_OFF:
+        rem_ticks = rfmgmt->ticks_to_enabled;
+        break;
+    case RFMGMT_STATE_ENABLING:
+        now = os_cputime_get32();
+        if (CPUTIME_LT(now, rfmgmt->enabled_at + rfmgmt->ticks_to_enabled)) {
+            rem_ticks = rfmgmt->enabled_at + rfmgmt->ticks_to_enabled - now;
+            break;
+        }
+        rfmgmt->state = RFMGMT_STATE_ENABLED;
+        /* no break */
+    case RFMGMT_STATE_ENABLED:
+        rem_ticks = 0;
+        break;
+    default:
+        BLE_LL_ASSERT(0);
+        rem_ticks = 0;
+        break;
+    }
+
+    return rem_ticks;
+}
+
+void
+ble_ll_rfmgmt_init(void)
+{
+    struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data;
+
+    rfmgmt->state = RFMGMT_STATE_OFF;
+
+    rfmgmt->ticks_to_enabled =
+            ble_ll_usecs_to_ticks_round_up(MYNEWT_VAL(BLE_XTAL_SETTLE_TIME));
+
+    rfmgmt->timer_scheduled = false;
+    os_cputime_timer_init(&rfmgmt->timer, ble_ll_rfmgmt_timer_exp, NULL);
+
+    ble_npl_event_init(&rfmgmt->release_ev, ble_ll_rfmgmt_release_ev, NULL);
+}
+
+void
+ble_ll_rfmgmt_reset(void)
+{
+    struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data;
+
+    rfmgmt->timer_scheduled = false;
+    rfmgmt->timer_scheduled_at = 0;
+    os_cputime_timer_stop(&rfmgmt->timer);
+
+    ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &rfmgmt->release_ev);
+
+    ble_ll_rfmgmt_disable();
+
+    rfmgmt->enable_scan = false;
+    rfmgmt->enable_scan_at = 0;
+    rfmgmt->enable_sched = false;
+    rfmgmt->enable_sched_at = 0;
+
+    rfmgmt->enabled_at = 0;
+}
+
+void
+ble_ll_rfmgmt_scan_changed(bool enabled, uint32_t next_window)
+{
+    struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data;
+    os_sr_t sr;
+
+    OS_ENTER_CRITICAL(sr);
+
+    rfmgmt->enable_scan = enabled;
+    rfmgmt->enable_scan_at = next_window - rfmgmt->ticks_to_enabled;
+
+    ble_ll_rfmgmt_timer_reschedule();
+
+    OS_EXIT_CRITICAL(sr);
+}
+
+void
+ble_ll_rfmgmt_sched_changed(struct ble_ll_sched_item *first)
+{
+    struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data;
+    os_sr_t sr;
+
+    OS_ENTER_CRITICAL(sr);
+
+    rfmgmt->enable_sched = (first != NULL);
+    if (first) {
+        rfmgmt->enable_sched_at = first->start_time - rfmgmt->ticks_to_enabled;
+    }
+
+    ble_ll_rfmgmt_timer_reschedule();
+
+    OS_EXIT_CRITICAL(sr);
+}
+
+void
+ble_ll_rfmgmt_release(void)
+{
+    struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data;
+    os_sr_t sr;
+
+    OS_ENTER_CRITICAL(sr);
+
+    ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &rfmgmt->release_ev);
+
+    if (g_ble_ll_rfmgmt_data.state != RFMGMT_STATE_OFF) {
+        ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &rfmgmt->release_ev);
+    }
+
+    OS_EXIT_CRITICAL(sr);
+}
+
+uint32_t
+ble_ll_rfmgmt_enable_now(void)
+{
+    struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data;
+    uint32_t enabled_at;
+    os_sr_t sr;
+
+    OS_ENTER_CRITICAL(sr);
+
+    ble_ll_rfmgmt_enable();
+
+    if (rfmgmt->state == RFMGMT_STATE_ENABLED) {
+        enabled_at = os_cputime_get32();
+    } else {
+        enabled_at = rfmgmt->enabled_at + rfmgmt->ticks_to_enabled + 1;
+    }
+
+    OS_EXIT_CRITICAL(sr);
+
+    return enabled_at;
+}
+
+bool
+ble_ll_rfmgmt_is_enabled(void)
+{
+    bool ret;
+
+    OS_ASSERT_CRITICAL();
+
+    ret = ble_ll_rfmgmt_ticks_to_enabled() == 0;
+
+    return ret;
+}
+
+#else
+
+void
+ble_ll_rfmgmt_init(void)
+{
+    static bool enabled = false;
+
+    if (!enabled) {
+        ble_phy_rfclk_enable();
+    }
+
+    enabled = true;
+}
+
+#endif
diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c
index 456553f..f707ebf 100644
--- a/nimble/controller/src/ble_ll_scan.c
+++ b/nimble/controller/src/ble_ll_scan.c
@@ -37,7 +37,7 @@
 #include "controller/ble_ll_hci.h"
 #include "controller/ble_ll_whitelist.h"
 #include "controller/ble_ll_resolv.h"
-#include "controller/ble_ll_xcvr.h"
+#include "controller/ble_ll_rfmgmt.h"
 #include "controller/ble_ll_trace.h"
 #include "controller/ble_ll_sync.h"
 #include "ble_ll_conn_priv.h"
@@ -1083,36 +1083,6 @@ ble_ll_scan_start(struct ble_ll_scan_sm *scansm, struct ble_ll_sched_item *sch)
     return rc;
 }
 
-#ifdef BLE_XCVR_RFCLK
-static void
-ble_ll_scan_rfclk_chk_stop(void)
-{
-    int stop;
-    int32_t time_till_next;
-    os_sr_t sr;
-    uint32_t next_time;
-
-    stop = 0;
-    OS_ENTER_CRITICAL(sr);
-    if (ble_ll_sched_next_time(&next_time)) {
-        /*
-         * If the time until the next event is too close, dont bother to turn
-         * off the clock
-         */
-        time_till_next = (int32_t)(next_time - os_cputime_get32());
-        if (time_till_next > g_ble_ll_data.ll_xtal_ticks) {
-            stop = 1;
-        }
-    } else {
-        stop = 1;
-    }
-    if (stop) {
-        ble_ll_xcvr_rfclk_disable();
-    }
-    OS_EXIT_CRITICAL(sr);
-}
-#endif
-
 static uint8_t
 ble_ll_scan_get_next_adv_prim_chan(uint8_t chan)
 {
@@ -1148,7 +1118,6 @@ static bool
 ble_ll_scan_is_inside_window(struct ble_ll_scan_params *scanp, uint32_t time)
 {
     uint32_t start_time;
-    uint32_t dt;
 
     /* Make sure we are checking against closest window */
     start_time = ble_ll_scan_move_window_to(scanp, time);
@@ -1158,19 +1127,10 @@ ble_ll_scan_is_inside_window(struct ble_ll_scan_params *scanp, uint32_t time)
         return true;
     }
 
-    if (CPUTIME_LT(time, start_time) ||
-        CPUTIME_GEQ(time, start_time + scanp->timing.window)) {
-#ifdef BLE_XCVR_RFCLK
-        dt = time - start_time;
-        if (dt < (scanp->timing.interval - g_ble_ll_data.ll_xtal_ticks)) {
-            ble_ll_scan_rfclk_chk_stop();
-        }
-#endif
-        return false;
-    }
-
-    return true;
+    return CPUTIME_GEQ(time, start_time) &&
+           CPUTIME_LT(time, start_time + scanp->timing.window);
 }
+
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
 static void
 ble_ll_scan_aux_data_free(struct ble_ll_aux_data *aux_data)
@@ -1256,6 +1216,7 @@ ble_ll_scan_sm_stop(int chk_disable)
     os_cputime_timer_stop(&scansm->scan_timer);
 
     OS_ENTER_CRITICAL(sr);
+
     /* Disable scanning state machine */
     scansm->scan_enabled = 0;
     scansm->restart_timer_needed = 0;
@@ -1264,6 +1225,7 @@ ble_ll_scan_sm_stop(int chk_disable)
     if (scansm->ext_scanning) {
         ble_ll_scan_clean_cur_aux_data();
         ble_ll_sched_rmv_elem_type(BLE_LL_SCHED_TYPE_AUX_SCAN, ble_ll_scan_sched_remove);
+        scansm->ext_scanning = 0;
     }
 #endif
 
@@ -1289,23 +1251,15 @@ ble_ll_scan_sm_stop(int chk_disable)
 
             /* Set LL state to standby */
             ble_ll_state_set(BLE_LL_STATE_STANDBY);
-
-            /* May need to stop the rfclk */
-#ifdef BLE_XCVR_RFCLK
-            ble_ll_scan_rfclk_chk_stop();
-#endif
         }
         OS_EXIT_CRITICAL(sr);
     }
 
-#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
-    if (scansm->ext_scanning) {
-#ifdef BLE_XCVR_RFCLK
-        ble_ll_sched_rfclk_chk_restart();
-#endif
-        scansm->ext_scanning = 0;
-    }
-#endif
+    /* No need for RF anymore */
+    OS_ENTER_CRITICAL(sr);
+    ble_ll_rfmgmt_scan_changed(false, 0);
+    ble_ll_rfmgmt_release();
+    OS_EXIT_CRITICAL(sr);
 }
 
 static int
@@ -1345,9 +1299,13 @@ ble_ll_scan_sm_start(struct ble_ll_scan_sm *scansm)
     os_mempool_clear(&g_scan_dup_pool);
     TAILQ_INIT(&g_scan_dup_list);
 
-    /* XXX: align to current or next slot???. */
-    /* Schedule start time now */
-    scanp->timing.start_time = os_cputime_get32();
+    /*
+     * First scan window can start when RF is enabled. Add 1 tick since we are
+     * most likely not aligned with ticks so RF may be effectively enabled 1
+     * tick later.
+     */
+    scanp->timing.start_time = ble_ll_rfmgmt_enable_now();
+    ble_ll_rfmgmt_scan_changed(true, scanp->timing.start_time);
 
     if (scanp_next) {
         /* Schedule start time right after first phy */
@@ -1355,8 +1313,8 @@ ble_ll_scan_sm_start(struct ble_ll_scan_sm *scansm)
                                         scanp->timing.window;
     }
 
-    /* Post scanning event to start off the scanning process */
-    ble_ll_event_send(&scansm->scan_sched_ev);
+    /* Start scan at 1st window */
+    os_cputime_timer_start(&scansm->scan_timer, scanp->timing.start_time);
 
     return BLE_ERR_SUCCESS;
 }
@@ -1425,7 +1383,7 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev)
 {
     struct ble_ll_scan_sm *scansm;
     os_sr_t sr;
-    int start_scan;
+    bool start_scan;
     bool inside_window;
     struct ble_ll_scan_params *scanp;
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
@@ -1434,11 +1392,6 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev)
 #endif
     uint32_t next_proc_time;
     uint32_t now;
-#ifdef BLE_XCVR_RFCLK
-    uint32_t xtal_ticks;
-    int xtal_state;
-#endif
-
     /*
      * Get the scanning state machine. If not enabled (this is possible), just
      * leave and do nothing (just make sure timer is stopped).
@@ -1452,6 +1405,8 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev)
     OS_ENTER_CRITICAL(sr);
     if (!scansm->scan_enabled) {
         os_cputime_timer_stop(&scansm->scan_timer);
+        ble_ll_rfmgmt_scan_changed(false, 0);
+        ble_ll_rfmgmt_release();
         OS_EXIT_CRITICAL(sr);
         return;
     }
@@ -1491,17 +1446,21 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev)
 
     /*
      * At this point scanp and scanp_next point to current or closest scan
-     * window on both PHYs (scanp is the closer one).
-     *
-     * Now we need to calculate when next scan proc should happen. If we are
-     * outside window, fire at the start of closest window to start scan. If we
-     * are inside window, fire at the end of window to either disable scan or
-     * switch to next PHY.
+     * window on both PHYs (scanp is the closer one). Make sure RF is enabled
+     * on time.
      */
-    if (!inside_window) {
-        next_proc_time = scanp->timing.start_time;
-    } else {
+    ble_ll_rfmgmt_scan_changed(true, scanp->timing.start_time);
+
+    /*
+     * If we are inside window, next scan proc should happen at the end of
+     * current window to either disable scan or switch to next PHY.
+     * If we are outside window, next scan proc should happen at the time of
+     * closest scan window.
+     */
+    if (inside_window) {
         next_proc_time = scanp->timing.start_time + scanp->timing.window;
+    } else {
+        next_proc_time = scanp->timing.start_time;
     }
 
     /*
@@ -1509,12 +1468,12 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev)
      * scanning event was overlapped in the schedule. In this case all we do
      * is post the scan schedule end event.
      */
-    start_scan = 1;
+    start_scan = inside_window;
     switch (ble_ll_state_get()) {
     case BLE_LL_STATE_ADV:
     case BLE_LL_STATE_CONNECTION:
     case BLE_LL_STATE_SYNC:
-         start_scan = 0;
+         start_scan = false;
          break;
     case BLE_LL_STATE_INITIATING:
         /* Must disable PHY since we will move to a new channel */
@@ -1539,66 +1498,12 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev)
         break;
     }
 
-    if (start_scan && inside_window) {
-#ifdef BLE_XCVR_RFCLK
-        xtal_state = ble_ll_xcvr_rfclk_state();
-        if (xtal_state != BLE_RFCLK_STATE_SETTLED) {
-            if (xtal_state == BLE_RFCLK_STATE_OFF) {
-                xtal_ticks = g_ble_ll_data.ll_xtal_ticks;
-            } else {
-                xtal_ticks = ble_ll_xcvr_rfclk_time_till_settled();
-            }
-
-            /*
-             * Only bother if we have enough time to receive anything
-             * here. The next event time will turn off the clock.
-             */
-            if (scanp->timing.start_time + scanp->timing.window - now <=
-                                                                xtal_ticks) {
-                goto done;
-            }
-
-            /*
-             * If clock off, start clock. Set next event time to now plus
-             * the clock setting time.
-             */
-            if (xtal_state == BLE_RFCLK_STATE_OFF) {
-                ble_ll_xcvr_rfclk_start_now();
-            }
-            next_proc_time = now + xtal_ticks;
-            goto done;
-        }
-#endif
+    if (start_scan) {
         ble_ll_scan_start(scansm, NULL);
-        goto done;
-    }
-
-#ifdef BLE_XCVR_RFCLK
-    if (!inside_window) {
-        /*
-         * We need to wake up before we need to start scanning in order
-         * to make sure the rfclock is on. If we are close to being on,
-         * enable the rfclock. If not, set wakeup time.
-         */
-        if (scanp->timing.start_time - now  <= g_ble_ll_data.ll_xtal_ticks) {
-            /* Start the clock if necessary */
-            if (start_scan) {
-                if (ble_ll_xcvr_rfclk_state() == BLE_RFCLK_STATE_OFF) {
-                    ble_ll_xcvr_rfclk_start_now();
-                    next_proc_time = now + g_ble_ll_data.ll_xtal_ticks;
-                }
-            }
-        } else {
-            next_proc_time = scanp->timing.start_time -
-                             g_ble_ll_data.ll_xtal_ticks;
-            if (start_scan) {
-                ble_ll_scan_rfclk_chk_stop();
-            }
-        }
+    } else {
+        ble_ll_rfmgmt_release();
     }
-#endif
 
-done:
     OS_EXIT_CRITICAL(sr);
     os_cputime_timer_start(&scansm->scan_timer, next_proc_time);
 }
diff --git a/nimble/controller/src/ble_ll_sched.c b/nimble/controller/src/ble_ll_sched.c
index 40a75e8..eef016b 100644
--- a/nimble/controller/src/ble_ll_sched.c
+++ b/nimble/controller/src/ble_ll_sched.c
@@ -28,7 +28,7 @@
 #include "controller/ble_ll_sched.h"
 #include "controller/ble_ll_adv.h"
 #include "controller/ble_ll_scan.h"
-#include "controller/ble_ll_xcvr.h"
+#include "controller/ble_ll_rfmgmt.h"
 #include "controller/ble_ll_trace.h"
 #include "controller/ble_ll_sync.h"
 #include "ble_ll_conn_priv.h"
@@ -36,11 +36,6 @@
 /* XXX: this is temporary. Not sure what I want to do here */
 struct hal_timer g_ble_ll_sched_timer;
 
-#ifdef BLE_XCVR_RFCLK
-/* Settling time of crystal, in ticks */
-uint8_t g_ble_ll_sched_xtal_ticks;
-#endif
-
 uint8_t g_ble_ll_sched_offset_ticks;
 
 #define BLE_LL_SCHED_ADV_WORST_CASE_USECS       \
@@ -274,17 +269,12 @@ ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm)
         entry = start_overlap;
     }
 
-#ifdef BLE_XCVR_RFCLK
     entry = TAILQ_FIRST(&g_ble_ll_sched_q);
     if (entry == sch) {
-        ble_ll_xcvr_rfclk_timer_start(sch->start_time);
+        ble_ll_rfmgmt_sched_changed(sch);
     } else {
         sch = entry;
     }
-#else
-    /* Get first on list */
-    sch = TAILQ_FIRST(&g_ble_ll_sched_q);
-#endif
 
     OS_EXIT_CRITICAL(sr);
 
@@ -532,6 +522,7 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm,
 
     /* 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);
 
@@ -714,6 +705,7 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm,
 
     /* 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);
 
@@ -740,11 +732,7 @@ ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm)
     struct ble_ll_sched_item *entry;
     struct ble_ll_sched_item *next_sch;
     struct ble_ll_sched_item *sch;
-
-#ifdef BLE_XCVR_RFCLK
-    int first;
-    first = 0;
-#endif
+    int first = 0;
 
     /* Get schedule element from connection */
     rc = -1;
@@ -775,9 +763,7 @@ ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm)
     if (!entry) {
         /* Nothing in schedule. Schedule as soon as possible */
         rc = 0;
-#ifdef BLE_XCVR_RFCLK
         first = 1;
-#endif
     } else {
         os_cputime_timer_stop(&g_ble_ll_sched_timer);
         while (1) {
@@ -810,23 +796,18 @@ ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm)
         if (!rc) {
             sch->enqueued = 1;
         }
-#ifdef BLE_XCVR_RFCLK
+
         next_sch = TAILQ_FIRST(&g_ble_ll_sched_q);
         if (next_sch == sch) {
             first = 1;
         } else {
             sch = next_sch;
         }
-#else
-        sch = TAILQ_FIRST(&g_ble_ll_sched_q);
-#endif
     }
 
-#ifdef BLE_XCVR_RFCLK
     if (first) {
-        ble_ll_xcvr_rfclk_timer_start(sch->start_time);
+        ble_ll_rfmgmt_sched_changed(sch);
     }
-#endif
 
     OS_EXIT_CRITICAL(sr);
 
@@ -941,17 +922,12 @@ ble_ll_sched_sync_reschedule(struct ble_ll_sched_item *sch,
         sch->enqueued = 1;
     }
 
-#ifdef BLE_XCVR_RFCLK
     entry = TAILQ_FIRST(&g_ble_ll_sched_q);
     if (entry == sch) {
-        ble_ll_xcvr_rfclk_timer_start(sch->start_time);
+        ble_ll_rfmgmt_sched_changed(sch);
     } else {
         sch = entry;
     }
-#else
-    /* Get first on list */
-    sch = TAILQ_FIRST(&g_ble_ll_sched_q);
-#endif
 
     OS_EXIT_CRITICAL(sr);
 
@@ -1032,17 +1008,12 @@ ble_ll_sched_sync(struct ble_ll_sched_item *sch,
     }
 
 done:
-#ifdef BLE_XCVR_RFCLK
     entry = TAILQ_FIRST(&g_ble_ll_sched_q);
     if (entry == sch) {
-        ble_ll_xcvr_rfclk_timer_start(sch->start_time);
+        ble_ll_rfmgmt_sched_changed(sch);
     } else {
         sch = entry;
     }
-#else
-    /* Get first on list */
-    sch = TAILQ_FIRST(&g_ble_ll_sched_q);
-#endif
 
     OS_EXIT_CRITICAL(sr);
 
@@ -1106,11 +1077,9 @@ ble_ll_sched_adv_new(struct ble_ll_sched_item *sch, ble_ll_sched_adv_new_cb cb,
         cb((struct ble_ll_adv_sm *)orig->cb_arg, adv_start, arg);
     }
 
-#ifdef BLE_XCVR_RFCLK
     if (orig == sch) {
-        ble_ll_xcvr_rfclk_timer_start(sch->start_time);
+        ble_ll_rfmgmt_sched_changed(sch);
     }
-#endif
 
     OS_EXIT_CRITICAL(sr);
 
@@ -1130,9 +1099,7 @@ ble_ll_sched_periodic_adv(struct ble_ll_sched_item *sch, uint32_t *start,
     uint32_t adv_start;
     uint32_t duration;
     struct ble_ll_sched_item *entry;
-#ifdef BLE_XCVR_RFCLK
     struct ble_ll_sched_item *orig = sch;
-#endif
 
     /* Get length of schedule item */
     duration = sch->end_time - sch->start_time;
@@ -1181,11 +1148,9 @@ ble_ll_sched_periodic_adv(struct ble_ll_sched_item *sch, uint32_t *start,
         *start = adv_start;
     }
 
-#ifdef BLE_XCVR_RFCLK
     if (orig == sch) {
-        ble_ll_xcvr_rfclk_timer_start(sch->start_time);
+        ble_ll_rfmgmt_sched_changed(sch);
     }
-#endif
 
     OS_EXIT_CRITICAL(sr);
 
@@ -1308,11 +1273,9 @@ ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t *start,
         sch->end_time = sch->start_time + duration;
         *start = sch->start_time;
 
-#ifdef BLE_XCVR_RFCLK
         if (sch == TAILQ_FIRST(&g_ble_ll_sched_q)) {
-            ble_ll_xcvr_rfclk_timer_start(sch->start_time);
+            ble_ll_rfmgmt_sched_changed(sch);
         }
-#endif
     }
 
     OS_EXIT_CRITICAL(sr);
@@ -1349,6 +1312,8 @@ ble_ll_sched_adv_resched_pdu(struct ble_ll_sched_item *sch)
         sch->enqueued = 1;
     }
 
+    ble_ll_rfmgmt_sched_changed(TAILQ_FIRST(&g_ble_ll_sched_q));
+
     OS_EXIT_CRITICAL(sr);
     os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time);
     return 0;
@@ -1392,6 +1357,7 @@ ble_ll_sched_rmv_elem(struct ble_ll_sched_item *sch)
             if (first) {
                 os_cputime_timer_start(&g_ble_ll_sched_timer, first->start_time);
             }
+            ble_ll_rfmgmt_sched_changed(first);
         }
     }
     OS_EXIT_CRITICAL(sr);
@@ -1432,6 +1398,7 @@ ble_ll_sched_rmv_elem_type(uint8_t type, sched_remove_cb_func remove_cb)
         if (first) {
             os_cputime_timer_start(&g_ble_ll_sched_timer, first->start_time);
         }
+        ble_ll_rfmgmt_sched_changed(first);
     }
 
     OS_EXIT_CRITICAL(sr);
@@ -1548,6 +1515,7 @@ ble_ll_sched_run(void *arg)
         if (sch) {
             os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time);
         }
+        ble_ll_rfmgmt_sched_changed(sch);
     }
 }
 
@@ -1580,64 +1548,6 @@ ble_ll_sched_next_time(uint32_t *next_event_time)
     return rc;
 }
 
-#ifdef BLE_XCVR_RFCLK
-/**
- * Checks to see if we need to restart the cputime timer which starts the
- * rf clock settling.
- *
- * NOTE: Should only be called from the Link Layer task!
- *
- * Context: Link-Layer task.
- *
- */
-void
-ble_ll_sched_rfclk_chk_restart(void)
-{
-    os_sr_t sr;
-    uint8_t ll_state;
-    int32_t time_till_next;
-    uint32_t next_time;
-
-    OS_ENTER_CRITICAL(sr);
-    ll_state = ble_ll_state_get();
-    if (ble_ll_sched_next_time(&next_time)) {
-        /*
-         * If the time until the next event is too close, no need to start
-         * the timer. Leave clock on.
-         */
-        time_till_next = (int32_t)(next_time - os_cputime_get32());
-        if (time_till_next > g_ble_ll_data.ll_xtal_ticks) {
-            /*
-             * XXX stop timer if already scheduled since it could be set for a
-             *     scheduler item which was removed prior to calling this func.
-             *     in such case we need to make sure we are set to proper item.
-             */
-            if (g_ble_ll_data.ll_rfclk_is_sched) {
-                g_ble_ll_data.ll_rfclk_is_sched = 0;
-                os_cputime_timer_stop(&g_ble_ll_data.ll_rfclk_timer);
-            }
-            /* Restart the rfclk timer based on the next scheduled time */
-            ble_ll_xcvr_rfclk_timer_start(next_time);
-
-            /* Only disable the rfclk if doing nothing */
-            if (ll_state == BLE_LL_STATE_STANDBY) {
-                ble_ll_xcvr_rfclk_disable();
-            }
-        }
-    } else {
-        /*
-         * Only stop the timer and rfclk if doing nothing currently. If
-         * in some other state, that state will handle the timer and rfclk
-         */
-        if (ll_state == BLE_LL_STATE_STANDBY) {
-            ble_ll_xcvr_rfclk_stop();
-        }
-    }
-    OS_EXIT_CRITICAL(sr);
-}
-
-#endif
-
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
 /**
  * Called to check if there is place for a planned scan req.
@@ -1784,16 +1694,12 @@ done:
     }
 
     /* Get head of list to restart timer */
-#ifdef BLE_XCVR_RFCLK
     entry = TAILQ_FIRST(&g_ble_ll_sched_q);
     if (entry == sch) {
-        ble_ll_xcvr_rfclk_timer_start(sch->start_time);
+        ble_ll_rfmgmt_sched_changed(sch);
     } else {
         sch = entry;
     }
-#else
-    sch = TAILQ_FIRST(&g_ble_ll_sched_q);
-#endif
 
     OS_EXIT_CRITICAL(sr);
 
@@ -1852,9 +1758,7 @@ done:
     /* Get head of list to restart timer */
     sch = TAILQ_FIRST(&g_ble_ll_sched_q);
 
-#ifdef BLE_XCVR_RFCLK
-    ble_ll_xcvr_rfclk_timer_start(sch->start_time);
-#endif
+    ble_ll_rfmgmt_sched_changed(sch);
 
     OS_EXIT_CRITICAL(sr);
 
diff --git a/nimble/controller/src/ble_ll_sync.c b/nimble/controller/src/ble_ll_sync.c
index f5d22fc..3861075 100644
--- a/nimble/controller/src/ble_ll_sync.c
+++ b/nimble/controller/src/ble_ll_sync.c
@@ -31,6 +31,7 @@
 #include "controller/ble_ll_whitelist.h"
 #include "controller/ble_ll_scan.h"
 #include "controller/ble_ll_resolv.h"
+#include "controller/ble_ll_rfmgmt.h"
 
 #include "nimble/ble.h"
 #include "nimble/hci_common.h"
@@ -201,9 +202,7 @@ ble_ll_sync_sm_clear(struct ble_ll_sync_sm *sm)
         ble_ll_scan_chk_resume();
     }
 
-#ifdef BLE_XCVR_RFCLK
-        ble_ll_sched_rfclk_chk_restart();
-#endif
+    ble_ll_rfmgmt_release();
 
     BLE_LL_ASSERT(sm->sync_ev_end.ev.ev_queued == 0);
     BLE_LL_ASSERT(sm->sch.enqueued == 0);
@@ -990,15 +989,13 @@ ble_ll_sync_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr)
 
     BLE_LL_ASSERT(sm);
 
+    ble_ll_rfmgmt_release();
+
     /* this could happen if sync was cancelled or terminated while pkt_in was
      * already in LL queue, just drop in that case
      */
     if (!sm->flags) {
         ble_ll_scan_chk_resume();
-
-#ifdef BLE_XCVR_RFCLK
-        ble_ll_sched_rfclk_chk_restart();
-#endif
         return;
     }
 
@@ -1044,10 +1041,6 @@ ble_ll_sync_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr)
         /* if chain was scheduled we don't end event yet */
         /* TODO should we check resume only if offset is high? */
         ble_ll_scan_chk_resume();
-
-#ifdef BLE_XCVR_RFCLK
-        ble_ll_sched_rfclk_chk_restart();
-#endif
         return;
     }
 
@@ -1152,6 +1145,8 @@ ble_ll_sync_event_end(struct ble_npl_event *ev)
     sm = ble_npl_event_get_arg(ev);
     BLE_LL_ASSERT(sm);
 
+    ble_ll_rfmgmt_release();
+
     if (sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHING) {
         ble_ll_sync_check_failed(sm);
     }
@@ -1159,10 +1154,6 @@ ble_ll_sync_event_end(struct ble_npl_event *ev)
     /* Check if we need to resume scanning */
     ble_ll_scan_chk_resume();
 
-#ifdef BLE_XCVR_RFCLK
-    ble_ll_sched_rfclk_chk_restart();
-#endif
-
     /* Remove any end events that might be enqueued */
     ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &sm->sync_ev_end);
 
diff --git a/nimble/controller/src/ble_ll_xcvr.c b/nimble/controller/src/ble_ll_xcvr.c
deleted file mode 100644
index d8cdad5..0000000
--- a/nimble/controller/src/ble_ll_xcvr.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include <stdint.h>
-#include <stddef.h>
-#include <assert.h>
-#include <stddef.h>
-#include "syscfg/syscfg.h"
-#include "os/os_cputime.h"
-#include "controller/ble_phy.h"
-#include "controller/ble_ll.h"
-#include "controller/ble_ll_xcvr.h"
-
-#ifdef BLE_XCVR_RFCLK
-int
-ble_ll_xcvr_rfclk_state(void)
-{
-    uint32_t expiry;
-
-    OS_ASSERT_CRITICAL();
-    if (g_ble_ll_data.ll_rfclk_state == BLE_RFCLK_STATE_ON) {
-        expiry = g_ble_ll_data.ll_rfclk_start_time;
-        if ((int32_t)(os_cputime_get32() - expiry) >
-                g_ble_ll_data.ll_xtal_ticks) {
-            g_ble_ll_data.ll_rfclk_state = BLE_RFCLK_STATE_SETTLED;
-        }
-    }
-    return g_ble_ll_data.ll_rfclk_state;
-}
-
-void
-ble_ll_xcvr_rfclk_enable(void)
-{
-    OS_ASSERT_CRITICAL();
-    if (g_ble_ll_data.ll_rfclk_state == BLE_RFCLK_STATE_OFF) {
-        g_ble_ll_data.ll_rfclk_state = BLE_RFCLK_STATE_ON;
-        ble_phy_rfclk_enable();
-    }
-}
-
-void
-ble_ll_xcvr_rfclk_disable(void)
-{
-    OS_ASSERT_CRITICAL();
-    if (g_ble_ll_data.ll_rfclk_state != BLE_RFCLK_STATE_OFF) {
-        ble_phy_rfclk_disable();
-        g_ble_ll_data.ll_rfclk_state = BLE_RFCLK_STATE_OFF;
-    }
-}
-
-void
-ble_ll_xcvr_rfclk_stop(void)
-{
-    OS_ASSERT_CRITICAL();
-    g_ble_ll_data.ll_rfclk_is_sched = 0;
-    os_cputime_timer_stop(&g_ble_ll_data.ll_rfclk_timer);
-    ble_ll_xcvr_rfclk_disable();
-}
-
-uint32_t
-ble_ll_xcvr_rfclk_time_till_settled(void)
-{
-    int32_t dt;
-    uint32_t rc;
-
-    rc = 0;
-    if (g_ble_ll_data.ll_rfclk_state == BLE_RFCLK_STATE_ON) {
-        dt = (int32_t)(os_cputime_get32() - g_ble_ll_data.ll_rfclk_start_time);
-        BLE_LL_ASSERT(dt >= 0);
-        if (dt < g_ble_ll_data.ll_xtal_ticks) {
-            rc = g_ble_ll_data.ll_xtal_ticks - (uint32_t)dt;
-        }
-    }
-
-    return rc;
-}
-
-/**
- * Called when the timer to turn on the RF CLOCK expires. This function checks
- * the state of the clock. If the clock is off, the clock is turned on.
- * Otherwise, we just exit.
- *
- * Context: Interrupt
- *
- * @param arg
- */
-void
-ble_ll_xcvr_rfclk_timer_exp(void *arg)
-{
-    g_ble_ll_data.ll_rfclk_is_sched = 0;
-
-    if (g_ble_ll_data.ll_rfclk_state == BLE_RFCLK_STATE_OFF) {
-        ble_ll_xcvr_rfclk_start_now();
-    }
-}
-
-/**
- * This API is used to turn on the rfclock without setting the cputime timer to
- * start the clock at some later point.
- *
- * NOTE: presumes that the state of the rf clock was checked prior to calling.
- *
- * @param now
- */
-void
-ble_ll_xcvr_rfclk_start_now(void)
-{
-    BLE_LL_ASSERT(g_ble_ll_data.ll_rfclk_state == BLE_RFCLK_STATE_OFF);
-
-    ble_ll_xcvr_rfclk_enable();
-    g_ble_ll_data.ll_rfclk_start_time = os_cputime_get32();
-}
-
-/**
- * Starts the timer that will turn the rf clock on. The 'cputime' is
- * the time at which the clock needs to be settled.
- *
- * @param cputime   Time at which rfclock should be on and settled.
- */
-void
-ble_ll_xcvr_rfclk_timer_start(uint32_t cputime)
-{
-    OS_ASSERT_CRITICAL();
-
-    /*
-     * If we are currently in an advertising event or a connection event,
-     * no need to start the cputime timer
-     */
-    if ((g_ble_ll_data.ll_state == BLE_LL_STATE_ADV) ||
-        (g_ble_ll_data.ll_state == BLE_LL_STATE_CONNECTION)) {
-        return;
-    }
-
-    /* Account for the settling time */
-    cputime -= g_ble_ll_data.ll_xtal_ticks;
-
-    /*
-     * If the timer is on the list, we need to see if its expiry is before
-     * 'cputime'. If the expiry is before, no need to do anything. If it
-     * is after, we need to stop the timer and start at new time.
-     */
-    if (g_ble_ll_data.ll_rfclk_is_sched) {
-        if ((int32_t)(cputime - g_ble_ll_data.ll_rfclk_sched_time) >= 0) {
-            return;
-        }
-        os_cputime_timer_stop(&g_ble_ll_data.ll_rfclk_timer);
-    }
-
-    g_ble_ll_data.ll_rfclk_is_sched = 1;
-    g_ble_ll_data.ll_rfclk_sched_time = cputime;
-    os_cputime_timer_start(&g_ble_ll_data.ll_rfclk_timer, cputime);
-}
-#endif
diff --git a/nimble/drivers/nrf51/src/ble_phy.c b/nimble/drivers/nrf51/src/ble_phy.c
index eef3763..30a0059 100644
--- a/nimble/drivers/nrf51/src/ble_phy.c
+++ b/nimble/drivers/nrf51/src/ble_phy.c
@@ -844,17 +844,6 @@ ble_phy_init(void)
 {
     int rc;
 
-#if !defined(BLE_XCVR_RFCLK)
-    /* BLE wants the HFXO on all the time in this case */
-    ble_phy_rfclk_enable();
-
-    /*
-     * XXX: I do not think we need to wait for settling time here since
-     * we will probably not use the radio for longer than the settling time
-     * and it will only degrade performance. Might want to wait here though.
-     */
-#endif
-
     /* Set phy channel to an invalid channel so first set channel works */
     g_ble_phy_data.phy_chan = BLE_PHY_NUM_CHANS;
 
diff --git a/nimble/drivers/nrf52/src/ble_phy.c b/nimble/drivers/nrf52/src/ble_phy.c
index 2cca6c7..725dac1 100644
--- a/nimble/drivers/nrf52/src/ble_phy.c
+++ b/nimble/drivers/nrf52/src/ble_phy.c
@@ -1375,17 +1375,6 @@ ble_phy_init(void)
 
     g_ble_phy_data.rx_pwr_compensation = 0;
 
-#if !defined(BLE_XCVR_RFCLK)
-    /* BLE wants the HFXO on all the time in this case */
-    ble_phy_rfclk_enable();
-
-    /*
-     * XXX: I do not think we need to wait for settling time here since
-     * we will probably not use the radio for longer than the settling time
-     * and it will only degrade performance. Might want to wait here though.
-     */
-#endif
-
     /* Set phy channel to an invalid channel so first set channel works */
     g_ble_phy_data.phy_chan = BLE_PHY_NUM_CHANS;
 


[mynewt-nimble] 05/09: nimble/ll: Simplify scan proc

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 1d9bc2c3e1852383015d781ee47edb96d5ef0c25
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Mon Dec 9 15:46:10 2019 +0100

    nimble/ll: Simplify scan proc
    
    It's a bit hard to follow how scan proc decides what to scan and when to
    fire next event. This patch makes things, hopfully, easier to follow by
    making flow simpler and adding some comments. This will be also useful
    for upcoming rfclk refactor.
    
    Note that rfclk handling may be a bit broken here (it should not be, but
    did not really check it) but it does not matter since rfclk is going to
    be changed in next patch.
---
 nimble/controller/src/ble_ll_scan.c | 201 +++++++++++++++---------------------
 1 file changed, 85 insertions(+), 116 deletions(-)

diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c
index 0cf43a0..456553f 100644
--- a/nimble/controller/src/ble_ll_scan.c
+++ b/nimble/controller/src/ble_ll_scan.c
@@ -1125,56 +1125,51 @@ ble_ll_scan_get_next_adv_prim_chan(uint8_t chan)
 }
 
 static uint32_t
-ble_ll_scan_get_scan_win(struct ble_ll_scan_params *scanphy, uint32_t cputime)
+ble_ll_scan_move_window_to(struct ble_ll_scan_params *scanp, uint32_t time)
 {
-    /* if past current window, move to next interval */
-    while (CPUTIME_GEQ(cputime - scanphy->timing.start_time,
-                       scanphy->timing.interval)) {
-        scanphy->timing.start_time += scanphy->timing.interval;
+    uint32_t end_time;
 
-        /* update channel if moving to next interval */
-        scanphy->scan_chan =
-                        ble_ll_scan_get_next_adv_prim_chan(scanphy->scan_chan);
+    /*
+     * Move window until given tick is before or inside window and move to next
+     * channel for each skipped interval.
+     */
+
+    end_time = scanp->timing.start_time + scanp->timing.window;
+    while (CPUTIME_GEQ(time, end_time)) {
+        scanp->timing.start_time += scanp->timing.interval;
+        scanp->scan_chan = ble_ll_scan_get_next_adv_prim_chan(scanp->scan_chan);
+        end_time = scanp->timing.start_time + scanp->timing.window;
     }
 
-    return scanphy->timing.start_time;
+    return scanp->timing.start_time;
 }
-/**
- * Called to determine if we are inside or outside the scan window. If we
- * are inside the scan window it means that the device should be receiving
- * on the scan channel.
- *
- * Context: Link Layer
- *
- * @param scansm
- *
- * @return int 0: inside scan window 1: outside scan window
- */
-static int
-ble_ll_scan_window_chk(struct ble_ll_scan_sm *scansm, uint32_t cputime)
+
+static bool
+ble_ll_scan_is_inside_window(struct ble_ll_scan_params *scanp, uint32_t time)
 {
-    struct ble_ll_scan_params *scanphy = scansm->scanp;
+    uint32_t start_time;
     uint32_t dt;
-    uint32_t win_start;
 
-    win_start = ble_ll_scan_get_scan_win(scanphy, cputime);
+    /* Make sure we are checking against closest window */
+    start_time = ble_ll_scan_move_window_to(scanp, time);
 
-    if (scanphy->timing.window == scanphy->timing.interval) {
+    if (scanp->timing.window == scanp->timing.interval) {
         /* always inside window in continuous scan */
-        return 0;
+        return true;
     }
 
-    dt = cputime - win_start;
-    if (dt >= scanphy->timing.window) {
+    if (CPUTIME_LT(time, start_time) ||
+        CPUTIME_GEQ(time, start_time + scanp->timing.window)) {
 #ifdef BLE_XCVR_RFCLK
-        if (dt < (scanphy->timing.interval - g_ble_ll_data.ll_xtal_ticks)) {
+        dt = time - start_time;
+        if (dt < (scanp->timing.interval - g_ble_ll_data.ll_xtal_ticks)) {
             ble_ll_scan_rfclk_chk_stop();
         }
 #endif
-        return 1;
+        return false;
     }
 
-    return 0;
+    return true;
 }
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
 static void
@@ -1368,20 +1363,6 @@ ble_ll_scan_sm_start(struct ble_ll_scan_sm *scansm)
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
 static void
-ble_ll_scan_switch_current_phy(struct ble_ll_scan_sm *scansm)
-{
-    struct ble_ll_scan_params *cur;
-
-    BLE_LL_ASSERT(scansm->scanp_next);
-
-    cur = scansm->scanp;
-    scansm->scanp = scansm->scanp_next;
-    scansm->scanp_next = cur;
-
-    /* PHY is changing in ble_ll_scan_start() */
-}
-
-static void
 ble_ll_aux_scan_rsp_failed(struct ble_ll_scan_sm *scansm)
 {
     if (!scansm->cur_aux_data) {
@@ -1432,35 +1413,6 @@ ble_ll_scan_interrupted_event_cb(struct ble_npl_event *ev)
     ble_ll_scan_chk_resume();
 }
 
-static int
-check_phy_window(struct ble_ll_scan_params *scanphy, uint32_t now, uint32_t *dt,
-                 struct ble_ll_scan_timing *timing)
-{
-    uint32_t win_start;
-
-    win_start = ble_ll_scan_get_scan_win(scanphy, now);
-
-    timing->interval = scanphy->timing.interval;
-
-    /* for continuous scan assume we are always inside window */
-    if (scanphy->timing.window == scanphy->timing.interval) {
-        timing->start_time = win_start + scanphy->timing.interval;
-        return 1;
-    }
-
-    timing->window = scanphy->timing.window;
-
-    /* Check if we are in scan window */
-    *dt = now - win_start;
-    if (*dt < scanphy->timing.window) {
-        timing->start_time = win_start + scanphy->timing.window;
-        return 1;
-    }
-
-    timing->start_time = win_start + scanphy->timing.interval;
-    return 0;
-}
-
 /**
  * Called to process the scanning OS event which was posted to the LL task
  *
@@ -1473,17 +1425,15 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev)
 {
     struct ble_ll_scan_sm *scansm;
     os_sr_t sr;
-    int inside_window;
     int start_scan;
-    uint32_t now;
-    uint32_t dt;
-    struct ble_ll_scan_params *scanphy;
-    struct ble_ll_scan_timing timing;
+    bool inside_window;
+    struct ble_ll_scan_params *scanp;
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
-    uint32_t dt_next;
-    struct ble_ll_scan_timing timing_next;
+    bool inside_window_next;
+    struct ble_ll_scan_params *scanp_next;
 #endif
-
+    uint32_t next_proc_time;
+    uint32_t now;
 #ifdef BLE_XCVR_RFCLK
     uint32_t xtal_ticks;
     int xtal_state;
@@ -1494,7 +1444,10 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev)
      * leave and do nothing (just make sure timer is stopped).
      */
     scansm = (struct ble_ll_scan_sm *)ble_npl_event_get_arg(ev);
-    scanphy = scansm->scanp;
+    scanp = scansm->scanp;
+#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
+    scanp_next = scansm->scanp_next;
+#endif
 
     OS_ENTER_CRITICAL(sr);
     if (!scansm->scan_enabled) {
@@ -1513,33 +1466,45 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev)
 
     now = os_cputime_get32();
 
-    /* check current phy */
-    inside_window = check_phy_window(scanphy, now, &dt, &timing);
-
-    /* timing.start_time is start time for *next* window */
+    inside_window = ble_ll_scan_is_inside_window(scanp, now);
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
-    if (!inside_window) {
-        if (scansm->scanp_next) {
-            /* check next phy */
-            inside_window = check_phy_window(scansm->scanp_next, now, &dt_next,
-                                             &timing_next);
-
-            /* Update current PHY if either next phy is in window or
-             * closest window is for next-PHY
-             */
-            if (inside_window || CPUTIME_LEQ(timing_next.start_time,
-                                             timing.start_time)) {
-                ble_ll_scan_switch_current_phy(scansm);
+    /* Update also next PHY if configured */
+    if (scanp_next) {
+        inside_window_next = ble_ll_scan_is_inside_window(scanp_next, now);
 
-                dt = dt_next;
-                timing = timing_next;
-            }
+        /*
+         * Switch PHY if current PHY is outside window and next PHY is either
+         * inside window or has next window earlier than current PHY.
+         */
+        if (!inside_window &&
+            ((inside_window_next || CPUTIME_LEQ(scanp_next->timing.start_time,
+                                                scanp->timing.start_time)))) {
+            scansm->scanp = scanp_next;
+            scansm->scanp_next = scanp;
+            scanp = scansm->scanp;
+            scanp_next = scansm->scanp_next;
+            inside_window = inside_window_next;
         }
     }
 #endif
 
     /*
+     * At this point scanp and scanp_next point to current or closest scan
+     * window on both PHYs (scanp is the closer one).
+     *
+     * Now we need to calculate when next scan proc should happen. If we are
+     * outside window, fire at the start of closest window to start scan. If we
+     * are inside window, fire at the end of window to either disable scan or
+     * switch to next PHY.
+     */
+    if (!inside_window) {
+        next_proc_time = scanp->timing.start_time;
+    } else {
+        next_proc_time = scanp->timing.start_time + scanp->timing.window;
+    }
+
+    /*
      * If we are not in the standby state it means that the scheduled
      * scanning event was overlapped in the schedule. In this case all we do
      * is post the scan schedule end event.
@@ -1576,7 +1541,7 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev)
 
     if (start_scan && inside_window) {
 #ifdef BLE_XCVR_RFCLK
-            xtal_state = ble_ll_xcvr_rfclk_state();
+        xtal_state = ble_ll_xcvr_rfclk_state();
         if (xtal_state != BLE_RFCLK_STATE_SETTLED) {
             if (xtal_state == BLE_RFCLK_STATE_OFF) {
                 xtal_ticks = g_ble_ll_data.ll_xtal_ticks;
@@ -1588,10 +1553,9 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev)
              * Only bother if we have enough time to receive anything
              * here. The next event time will turn off the clock.
              */
-            if (timing.window != 0) {
-                if ((timing.window - dt) <= xtal_ticks)  {
-                    goto done;
-                }
+            if (scanp->timing.start_time + scanp->timing.window - now <=
+                                                                xtal_ticks) {
+                goto done;
             }
 
             /*
@@ -1601,7 +1565,7 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev)
             if (xtal_state == BLE_RFCLK_STATE_OFF) {
                 ble_ll_xcvr_rfclk_start_now();
             }
-            timing.start_time = now + xtal_ticks;
+            next_proc_time = now + xtal_ticks;
             goto done;
         }
 #endif
@@ -1610,22 +1574,23 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev)
     }
 
 #ifdef BLE_XCVR_RFCLK
-    if (inside_window == 0) {
+    if (!inside_window) {
         /*
          * We need to wake up before we need to start scanning in order
          * to make sure the rfclock is on. If we are close to being on,
          * enable the rfclock. If not, set wakeup time.
          */
-        if (dt >= (timing.interval - g_ble_ll_data.ll_xtal_ticks)) {
+        if (scanp->timing.start_time - now  <= g_ble_ll_data.ll_xtal_ticks) {
             /* Start the clock if necessary */
             if (start_scan) {
                 if (ble_ll_xcvr_rfclk_state() == BLE_RFCLK_STATE_OFF) {
                     ble_ll_xcvr_rfclk_start_now();
-                    timing.start_time = now + g_ble_ll_data.ll_xtal_ticks;
+                    next_proc_time = now + g_ble_ll_data.ll_xtal_ticks;
                 }
             }
         } else {
-            timing.start_time -= g_ble_ll_data.ll_xtal_ticks;
+            next_proc_time = scanp->timing.start_time -
+                             g_ble_ll_data.ll_xtal_ticks;
             if (start_scan) {
                 ble_ll_scan_rfclk_chk_stop();
             }
@@ -1635,7 +1600,7 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev)
 
 done:
     OS_EXIT_CRITICAL(sr);
-    os_cputime_timer_start(&scansm->scan_timer, timing.start_time);
+    os_cputime_timer_start(&scansm->scan_timer, next_proc_time);
 }
 
 /**
@@ -2532,6 +2497,7 @@ ble_ll_scan_chk_resume(void)
 {
     os_sr_t sr;
     struct ble_ll_scan_sm *scansm;
+    uint32_t now;
 
     scansm = &g_ble_ll_scan_sm;
     if (scansm->scan_enabled) {
@@ -2544,8 +2510,9 @@ ble_ll_scan_chk_resume(void)
             return;
         }
 
+        now = os_cputime_get32();
         if (ble_ll_state_get() == BLE_LL_STATE_STANDBY &&
-                    ble_ll_scan_window_chk(scansm, os_cputime_get32()) == 0) {
+            ble_ll_scan_is_inside_window(scansm->scanp, now)) {
             /* Turn on the receiver and set state */
             ble_ll_scan_start(scansm, NULL);
         }
@@ -2597,6 +2564,7 @@ ble_ll_scan_wfr_timer_exp(void)
 #if (BLE_LL_BT5_PHY_SUPPORTED == 1)
     uint8_t phy_mode;
 #endif
+    uint32_t now;
 
     scansm = &g_ble_ll_scan_sm;
 
@@ -2617,7 +2585,8 @@ ble_ll_scan_wfr_timer_exp(void)
          */
         ble_phy_disable();
 
-        if (ble_ll_scan_window_chk(scansm, os_cputime_get32()) == 1) {
+        now = os_cputime_get32();
+        if (!ble_ll_scan_is_inside_window(scansm->scanp, now)) {
             /* Outside the window scan */
             ble_ll_state_set(BLE_LL_STATE_STANDBY);
             return;


[mynewt-nimble] 09/09: nimble/ll: Add missing APIs to native PHY

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 cfaa87053211f7353dcb7f0825289eb33c1d0adc
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Fri Dec 13 16:46:00 2019 +0100

    nimble/ll: Add missing APIs to native PHY
---
 nimble/drivers/native/src/ble_phy.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/nimble/drivers/native/src/ble_phy.c b/nimble/drivers/native/src/ble_phy.c
index 80edd80..f9ab0fc 100644
--- a/nimble/drivers/native/src/ble_phy.c
+++ b/nimble/drivers/native/src/ble_phy.c
@@ -640,3 +640,13 @@ void
 ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs)
 {
 }
+
+void
+ble_phy_rfclk_enable(void)
+{
+}
+
+void
+ble_phy_rfclk_disable(void)
+{
+}


[mynewt-nimble] 01/09: nimble/ll: Remove unused functions

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 e0ddae3dc3c240fcd51751362b1d474961b24285
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Tue Dec 10 18:15:59 2019 +0100

    nimble/ll: Remove unused functions
---
 nimble/controller/include/controller/ble_ll.h |  6 ------
 nimble/controller/src/ble_ll.c                | 23 -----------------------
 nimble/controller/src/ble_ll_adv.c            |  3 ---
 nimble/controller/src/ble_ll_conn.c           |  2 --
 nimble/controller/src/ble_ll_scan.c           |  4 ----
 nimble/controller/src/ble_ll_sched.c          |  1 -
 nimble/controller/src/ble_ll_sync.c           |  4 ----
 7 files changed, 43 deletions(-)

diff --git a/nimble/controller/include/controller/ble_ll.h b/nimble/controller/include/controller/ble_ll.h
index 4514815..a07f8c8 100644
--- a/nimble/controller/include/controller/ble_ll.h
+++ b/nimble/controller/include/controller/ble_ll.h
@@ -537,12 +537,6 @@ int ble_ll_set_public_addr(const uint8_t *addr);
 /* Set random address */
 int ble_ll_set_random_addr(const uint8_t *cmdbuf, uint8_t len, bool hci_adv_ext);
 
-/* Enable wait for response timer */
-void ble_ll_wfr_enable(uint32_t cputime);
-
-/* Disable wait for response timer */
-void ble_ll_wfr_disable(void);
-
 /* Wait for response timer expiration callback */
 void ble_ll_wfr_timer_exp(void *arg);
 
diff --git a/nimble/controller/src/ble_ll.c b/nimble/controller/src/ble_ll.c
index d44a778..68fffda 100644
--- a/nimble/controller/src/ble_ll.c
+++ b/nimble/controller/src/ble_ll.c
@@ -679,28 +679,6 @@ ble_ll_wfr_timer_exp(void *arg)
 }
 
 /**
- * Enable the wait for response timer.
- *
- * Context: Interrupt.
- *
- * @param cputime
- * @param wfr_cb
- * @param arg
- */
-void
-ble_ll_wfr_enable(uint32_t cputime)
-{
-}
-
-/**
- * Disable the wait for response timer
- */
-void
-ble_ll_wfr_disable(void)
-{
-}
-
-/**
  * ll tx pkt in proc
  *
  * Process ACL data packet input from host
@@ -1353,7 +1331,6 @@ ble_ll_reset(void)
 
     /* Stop any wait for response timer */
     OS_ENTER_CRITICAL(sr);
-    ble_ll_wfr_disable();
     ble_ll_sched_stop();
     OS_EXIT_CRITICAL(sr);
 
diff --git a/nimble/controller/src/ble_ll_adv.c b/nimble/controller/src/ble_ll_adv.c
index 136b45e..dd98609 100644
--- a/nimble/controller/src/ble_ll_adv.c
+++ b/nimble/controller/src/ble_ll_adv.c
@@ -1867,7 +1867,6 @@ ble_ll_adv_sm_stop(struct ble_ll_adv_sm *advsm)
         if ((g_ble_ll_cur_adv_sm == advsm) &&
                !(advsm->flags & BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING)) {
             ble_phy_disable();
-            ble_ll_wfr_disable();
             ble_ll_state_set(BLE_LL_STATE_STANDBY);
             g_ble_ll_cur_adv_sm = NULL;
             ble_ll_scan_chk_resume();
@@ -1875,7 +1874,6 @@ ble_ll_adv_sm_stop(struct ble_ll_adv_sm *advsm)
 #else
         if (ble_ll_state_get() == BLE_LL_STATE_ADV) {
             ble_phy_disable();
-            ble_ll_wfr_disable();
             ble_ll_state_set(BLE_LL_STATE_STANDBY);
             g_ble_ll_cur_adv_sm = NULL;
             ble_ll_scan_chk_resume();
@@ -2531,7 +2529,6 @@ ble_ll_adv_sm_stop_periodic(struct ble_ll_adv_sm *advsm)
     if ((g_ble_ll_cur_adv_sm == advsm) &&
             (advsm->flags & BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING)) {
         ble_phy_disable();
-        ble_ll_wfr_disable();
         ble_ll_state_set(BLE_LL_STATE_STANDBY);
         g_ble_ll_cur_adv_sm = NULL;
         ble_ll_scan_chk_resume();
diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c
index 2a98c13..ffb3995 100644
--- a/nimble/controller/src/ble_ll_conn.c
+++ b/nimble/controller/src/ble_ll_conn.c
@@ -375,7 +375,6 @@ static void
 ble_ll_conn_halt(void)
 {
     ble_phy_disable();
-    ble_ll_wfr_disable();
     ble_ll_state_set(BLE_LL_STATE_STANDBY);
     g_ble_ll_conn_cur_sm = NULL;
 }
@@ -3408,7 +3407,6 @@ ble_ll_conn_rx_isr_start(struct ble_mbuf_hdr *rxhdr, uint32_t aa)
      * called at receive end will deal with ending the connection event
      * if needed
      */
-    ble_ll_wfr_disable();
     connsm = g_ble_ll_conn_cur_sm;
     if (connsm) {
         /* Double check access address. Better match connection state machine */
diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c
index 75d674a..27c1033 100644
--- a/nimble/controller/src/ble_ll_scan.c
+++ b/nimble/controller/src/ble_ll_scan.c
@@ -197,7 +197,6 @@ ble_ll_aux_scan_cb(struct ble_ll_sched_item *sch)
      */
     if (lls != BLE_LL_STATE_STANDBY) {
         ble_phy_disable();
-        ble_ll_wfr_disable();
         ble_ll_state_set(BLE_LL_STATE_STANDBY);
     }
 
@@ -1714,9 +1713,6 @@ ble_ll_scan_rx_isr_start(uint8_t pdu_type, uint16_t *rxflags)
 #endif
             }
         }
-
-        /* Disable wfr if running */
-        ble_ll_wfr_disable();
         break;
     case BLE_SCAN_TYPE_PASSIVE:
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
diff --git a/nimble/controller/src/ble_ll_sched.c b/nimble/controller/src/ble_ll_sched.c
index 626f939..40a75e8 100644
--- a/nimble/controller/src/ble_ll_sched.c
+++ b/nimble/controller/src/ble_ll_sched.c
@@ -1482,7 +1482,6 @@ ble_ll_sched_execute_item(struct ble_ll_sched_item *sch)
 
     /* We have to disable the PHY no matter what */
     ble_phy_disable();
-    ble_ll_wfr_disable();
 
     if (lls == BLE_LL_STATE_SCANNING) {
         ble_ll_state_set(BLE_LL_STATE_STANDBY);
diff --git a/nimble/controller/src/ble_ll_sync.c b/nimble/controller/src/ble_ll_sync.c
index f73d90e..f5d22fc 100644
--- a/nimble/controller/src/ble_ll_sync.c
+++ b/nimble/controller/src/ble_ll_sync.c
@@ -196,7 +196,6 @@ ble_ll_sync_sm_clear(struct ble_ll_sync_sm *sm)
 
     if (g_ble_ll_sync_sm_current == sm) {
         ble_phy_disable();
-        ble_ll_wfr_disable();
         ble_ll_state_set(BLE_LL_STATE_STANDBY);
         g_ble_ll_sync_sm_current = NULL;
         ble_ll_scan_chk_resume();
@@ -405,9 +404,6 @@ ble_ll_sync_current_sm_over(void)
     /* Disable the PHY */
     ble_phy_disable();
 
-    /* Disable the wfr timer */
-    ble_ll_wfr_disable();
-
     /* Link-layer is in standby state now */
     ble_ll_state_set(BLE_LL_STATE_STANDBY);
 


[mynewt-nimble] 08/09: nimble/ll: Rename BLE_XTAL_SETTLE_TIME

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 35efdba185ca59b436ecd81a4fb7dd2d26e5fde0
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Thu Dec 12 01:50:43 2019 +0100

    nimble/ll: Rename BLE_XTAL_SETTLE_TIME
    
    With addition of ll_rfmgmt this setting has now more generic meaning so
    let's rename it.
---
 .../controller/include/controller/ble_ll_rfmgmt.h  |  2 +-
 nimble/controller/src/ble_ll_rfmgmt.c              |  4 ++--
 nimble/controller/syscfg.yml                       | 23 +++++++++++++++-------
 3 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/nimble/controller/include/controller/ble_ll_rfmgmt.h b/nimble/controller/include/controller/ble_ll_rfmgmt.h
index da584e5..37b81a8 100644
--- a/nimble/controller/include/controller/ble_ll_rfmgmt.h
+++ b/nimble/controller/include/controller/ble_ll_rfmgmt.h
@@ -26,7 +26,7 @@ extern "C" {
 
 void ble_ll_rfmgmt_init(void);
 
-#if MYNEWT_VAL(BLE_XTAL_SETTLE_TIME) > 0
+#if MYNEWT_VAL(BLE_LL_RFMGMT_ENABLE_TIME) > 0
 
 void ble_ll_rfmgmt_reset(void);
 
diff --git a/nimble/controller/src/ble_ll_rfmgmt.c b/nimble/controller/src/ble_ll_rfmgmt.c
index 58dad7c..3bf5d5f 100644
--- a/nimble/controller/src/ble_ll_rfmgmt.c
+++ b/nimble/controller/src/ble_ll_rfmgmt.c
@@ -28,7 +28,7 @@
 #include "controller/ble_ll_sched.h"
 #include "controller/ble_ll_rfmgmt.h"
 
-#if MYNEWT_VAL(BLE_XTAL_SETTLE_TIME) > 0
+#if MYNEWT_VAL(BLE_LL_RFMGMT_ENABLE_TIME) > 0
 
 enum ble_ll_rfmgmt_state {
     RFMGMT_STATE_OFF = 0,
@@ -215,7 +215,7 @@ ble_ll_rfmgmt_init(void)
     rfmgmt->state = RFMGMT_STATE_OFF;
 
     rfmgmt->ticks_to_enabled =
-            ble_ll_usecs_to_ticks_round_up(MYNEWT_VAL(BLE_XTAL_SETTLE_TIME));
+            ble_ll_usecs_to_ticks_round_up(MYNEWT_VAL(BLE_LL_RFMGMT_ENABLE_TIME));
 
     rfmgmt->timer_scheduled = false;
     os_cputime_timer_init(&rfmgmt->timer, ble_ll_rfmgmt_timer_exp, NULL);
diff --git a/nimble/controller/syscfg.yml b/nimble/controller/syscfg.yml
index 06f08b6..ac87b28 100644
--- a/nimble/controller/syscfg.yml
+++ b/nimble/controller/syscfg.yml
@@ -175,13 +175,18 @@ syscfg.defs:
             material often.
         value: '32'
 
-    # Crystal setting time
-    BLE_XTAL_SETTLE_TIME:
-        description: >
-            The settling time of the high-frequency oscillator. This is
-            used to turn on/off the clock used for the radio (assuming
-            the HW supports this). This value is in microseconds.
-        value: '0'
+    BLE_LL_RFMGMT_ENABLE_TIME:
+        description: >
+            Time required for radio and/or related components to be fully
+            enabled before any request from LL is sent. This value is used
+            by rfmgmt to enable PHY in advance, before request from LL is
+            made. It depends on radio driver selected and may also depend
+            on hardware used:
+            - nrf51 - time required for XTAL to settle
+            - nrf52 - time required for XTAL to settle
+            Value is specified in microseconds. If set to 0, rfmgmt keeps
+            PHY enabled all the time.
+        value: MYNEWT_VAL(BLE_XTAL_SETTLE_TIME)
 
     # Configuration for LL supported features.
     #
@@ -369,6 +374,10 @@ syscfg.defs:
         description: use BLE_LL_DTM instead
         value: 0
         deprecated: 1
+    BLE_XTAL_SETTLE_TIME:
+        description: use BLE_LL_RFMGMT_ENABLE_TIME instead
+        value: 0
+        deprecated: 1
 
 # defunct settings (to be removed eventually)
     BLE_DEVICE:


[mynewt-nimble] 04/09: nimble/ll: Improve scanner PHY toggling

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 37478faaa7fed6d8fb0f55c5f88fa4948a09f00b
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Mon Dec 9 13:54:50 2019 +0100

    nimble/ll: Improve scanner PHY toggling
    
    Instead of toggling indices in scan parameters array we can just have
    two pointers to current and next scan parameters. This makes code more
    compact and easier to read since we avoid extracting data from array
    over and over again. Also checking for configured PHY is simple since
    we just check if pointer is there or not.
    
    Also it should be easier to compile out some code if we support only
    one scan PHY, but this is not addressed in this patch.
---
 nimble/controller/include/controller/ble_ll_scan.h |   6 +-
 nimble/controller/src/ble_ll_scan.c                | 105 +++++++++------------
 2 files changed, 50 insertions(+), 61 deletions(-)

diff --git a/nimble/controller/include/controller/ble_ll_scan.h b/nimble/controller/include/controller/ble_ll_scan.h
index 8bbcc2d..f63c27c 100644
--- a/nimble/controller/include/controller/ble_ll_scan.h
+++ b/nimble/controller/include/controller/ble_ll_scan.h
@@ -68,7 +68,6 @@ extern "C" {
 
 #define PHY_UNCODED                    (0)
 #define PHY_CODED                      (1)
-#define PHY_NOT_CONFIGURED             (0xFF)
 
 #define BLE_LL_EXT_ADV_MODE_NON_CONN    (0x00)
 #define BLE_LL_EXT_ADV_MODE_CONN        (0x01)
@@ -180,8 +179,9 @@ struct ble_ll_scan_sm
     uint8_t ext_scanning;
 #endif
 
-    uint8_t cur_phy;
-    uint8_t next_phy;
+    struct ble_ll_scan_params *scanp;
+    struct ble_ll_scan_params *scanp_next;
+
     uint8_t restart_timer_needed;
     struct ble_ll_aux_data *cur_aux_data;
     struct ble_ll_scan_params phy_data[BLE_LL_SCAN_PHY_NUMBER];
diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c
index 78ab84c..0cf43a0 100644
--- a/nimble/controller/src/ble_ll_scan.c
+++ b/nimble/controller/src/ble_ll_scan.c
@@ -915,8 +915,7 @@ ble_ll_scan_chk_filter_policy(uint8_t pdu_type, uint8_t *adv_addr,
 {
     int use_whitelist;
     int chk_inita;
-    struct ble_ll_scan_params *params =
-                        &g_ble_ll_scan_sm.phy_data[g_ble_ll_scan_sm.cur_phy];
+    struct ble_ll_scan_params *params = g_ble_ll_scan_sm.scanp;
 
     use_whitelist = 0;
     chk_inita = 0;
@@ -975,7 +974,7 @@ static void
 ble_ll_get_chan_to_scan(struct ble_ll_scan_sm *scansm, uint8_t *chan,
                         int *phy)
 {
-    struct ble_ll_scan_params *scanphy = &scansm->phy_data[scansm->cur_phy];
+    struct ble_ll_scan_params *scanphy = scansm->scanp;
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
     struct ble_ll_aux_data *aux_data = scansm->cur_aux_data;
 
@@ -1005,7 +1004,7 @@ static int
 ble_ll_scan_start(struct ble_ll_scan_sm *scansm, struct ble_ll_sched_item *sch)
 {
     int rc;
-    struct ble_ll_scan_params *scanphy = &scansm->phy_data[scansm->cur_phy];
+    struct ble_ll_scan_params *scanphy = scansm->scanp;
     uint8_t scan_chan;
 #if (BLE_LL_BT5_PHY_SUPPORTED == 1)
     uint8_t phy_mode;
@@ -1154,7 +1153,7 @@ ble_ll_scan_get_scan_win(struct ble_ll_scan_params *scanphy, uint32_t cputime)
 static int
 ble_ll_scan_window_chk(struct ble_ll_scan_sm *scansm, uint32_t cputime)
 {
-    struct ble_ll_scan_params *scanphy = &scansm->phy_data[scansm->cur_phy];
+    struct ble_ll_scan_params *scanphy = scansm->scanp;
     uint32_t dt;
     uint32_t win_start;
 
@@ -1317,20 +1316,16 @@ ble_ll_scan_sm_stop(int chk_disable)
 static int
 ble_ll_scan_sm_start(struct ble_ll_scan_sm *scansm)
 {
-    struct ble_ll_scan_params *scanphy_cur;
-    struct ble_ll_scan_params *scanphy_next;
+    struct ble_ll_scan_params *scanp;
+    struct ble_ll_scan_params *scanp_next;
 
     if (!ble_ll_is_valid_own_addr_type(scansm->own_addr_type, g_random_addr)) {
         return BLE_ERR_INV_HCI_CMD_PARMS;
     }
 
-    BLE_LL_ASSERT(scansm->cur_phy != PHY_NOT_CONFIGURED);
-    scanphy_cur = &scansm->phy_data[scansm->cur_phy];
-    if (scansm->next_phy != PHY_NOT_CONFIGURED) {
-        scanphy_next = &scansm->phy_data[scansm->next_phy];
-    } else {
-        scanphy_next = NULL;
-    }
+    BLE_LL_ASSERT(scansm->scanp);
+    scanp = scansm->scanp;
+    scanp_next = scansm->scanp_next;
 
     /* Count # of times started */
     STATS_INC(ble_ll_stats, scan_starts);
@@ -1339,9 +1334,9 @@ ble_ll_scan_sm_start(struct ble_ll_scan_sm *scansm)
     scansm->scan_enabled = 1;
 
     /* Set first advertising channel */
-    scanphy_cur->scan_chan = BLE_PHY_ADV_CHAN_START;
-    if (scanphy_next) {
-        scanphy_next->scan_chan = BLE_PHY_ADV_CHAN_START;
+    scanp->scan_chan = BLE_PHY_ADV_CHAN_START;
+    if (scanp_next) {
+        scanp_next->scan_chan = BLE_PHY_ADV_CHAN_START;
     }
 
     /* Reset scan request backoff parameters to default */
@@ -1357,12 +1352,12 @@ ble_ll_scan_sm_start(struct ble_ll_scan_sm *scansm)
 
     /* XXX: align to current or next slot???. */
     /* Schedule start time now */
-    scanphy_cur->timing.start_time = os_cputime_get32();
+    scanp->timing.start_time = os_cputime_get32();
 
-    if (scanphy_next) {
+    if (scanp_next) {
         /* Schedule start time right after first phy */
-        scanphy_next->timing.start_time = scanphy_cur->timing.start_time +
-                                          scanphy_cur->timing.window;
+        scanp_next->timing.start_time = scanp->timing.start_time +
+                                        scanp->timing.window;
     }
 
     /* Post scanning event to start off the scanning process */
@@ -1375,13 +1370,13 @@ ble_ll_scan_sm_start(struct ble_ll_scan_sm *scansm)
 static void
 ble_ll_scan_switch_current_phy(struct ble_ll_scan_sm *scansm)
 {
-    uint8_t tmp;
+    struct ble_ll_scan_params *cur;
 
-    BLE_LL_ASSERT(scansm->next_phy != PHY_NOT_CONFIGURED);
+    BLE_LL_ASSERT(scansm->scanp_next);
 
-    tmp = scansm->next_phy;
-    scansm->next_phy = scansm->cur_phy;
-    scansm->cur_phy = tmp;
+    cur = scansm->scanp;
+    scansm->scanp = scansm->scanp_next;
+    scansm->scanp_next = cur;
 
     /* PHY is changing in ble_ll_scan_start() */
 }
@@ -1486,7 +1481,6 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev)
     struct ble_ll_scan_timing timing;
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
     uint32_t dt_next;
-    struct ble_ll_scan_params *scanphy_next;
     struct ble_ll_scan_timing timing_next;
 #endif
 
@@ -1500,7 +1494,7 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev)
      * leave and do nothing (just make sure timer is stopped).
      */
     scansm = (struct ble_ll_scan_sm *)ble_npl_event_get_arg(ev);
-    scanphy = &scansm->phy_data[scansm->cur_phy];
+    scanphy = scansm->scanp;
 
     OS_ENTER_CRITICAL(sr);
     if (!scansm->scan_enabled) {
@@ -1526,11 +1520,9 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev)
 
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
     if (!inside_window) {
-        if (scansm->next_phy != PHY_NOT_CONFIGURED) {
-            scanphy_next = &scansm->phy_data[scansm->next_phy];
-
+        if (scansm->scanp_next) {
             /* check next phy */
-            inside_window = check_phy_window(scanphy_next, now, &dt_next,
+            inside_window = check_phy_window(scansm->scanp_next, now, &dt_next,
                                              &timing_next);
 
             /* Update current PHY if either next phy is in window or
@@ -1670,7 +1662,7 @@ ble_ll_scan_rx_isr_start(uint8_t pdu_type, uint16_t *rxflags)
 
     rc = 0;
     scansm = &g_ble_ll_scan_sm;
-    scanphy = &scansm->phy_data[scansm->cur_phy];
+    scanphy = scansm->scanp;
 
     switch (scanphy->scan_type) {
     case BLE_SCAN_TYPE_ACTIVE:
@@ -2235,7 +2227,7 @@ ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok)
 
     /* Get scanning state machine */
     scansm = &g_ble_ll_scan_sm;
-    scanphy = &scansm->phy_data[scansm->cur_phy];
+    scanphy = scansm->scanp;
 
     /*
      * The reason we do something different here (as opposed to failed CRC) is
@@ -3656,8 +3648,8 @@ ble_ll_scan_set_enable(uint8_t enable, uint8_t filter_dups, uint16_t period,
 #if MYNEWT_VAL(BLE_LL_NUM_SCAN_DUP_ADVS)
     scansm->scan_filt_dups = filter_dups;
 #endif
-    scansm->cur_phy = PHY_NOT_CONFIGURED;
-    scansm->next_phy = PHY_NOT_CONFIGURED;
+    scansm->scanp = NULL;
+    scansm->scanp_next = NULL;
 
     for (i = 0; i < BLE_LL_SCAN_PHY_NUMBER; i++) {
         scanphy = &scansm->phy_data[i];
@@ -3673,14 +3665,14 @@ ble_ll_scan_set_enable(uint8_t enable, uint8_t filter_dups, uint16_t period,
         scanphy->scan_filt_policy = scanp->scan_filt_policy;
         scanphy->own_addr_type = scanp->own_addr_type;
 
-        if (scansm->cur_phy == PHY_NOT_CONFIGURED) {
-            scansm->cur_phy = i;
+        if (!scansm->scanp) {
+            scansm->scanp = scanphy;
             /* Take own_addr_type from the first configured PHY.
              * Note: All configured PHYs shall have the same own_addr_type
              */
             scansm->own_addr_type = scanphy->own_addr_type;
         } else {
-            scansm->next_phy = i;
+            scansm->scanp_next = scanphy;
         }
     }
 
@@ -3689,12 +3681,11 @@ ble_ll_scan_set_enable(uint8_t enable, uint8_t filter_dups, uint16_t period,
      * For now be nice to host and just use values based on LE Set Scan
      * Parameters defaults.
      */
-    if (scansm->cur_phy == PHY_NOT_CONFIGURED) {
-        scansm->cur_phy = PHY_UNCODED;
+    if (!scansm->scanp) {
+        scansm->scanp = &scansm->phy_data[PHY_UNCODED];
         scansm->own_addr_type = BLE_ADDR_PUBLIC;
 
-        scanphy = &scansm->phy_data[PHY_UNCODED];
-
+        scanphy = scansm->scanp;
         scanphy->configured = 1;
         scanphy->scan_type = BLE_SCAN_TYPE_PASSIVE;
         scanphy->timing.interval =
@@ -3759,7 +3750,7 @@ ble_ll_scan_can_chg_whitelist(void)
     struct ble_ll_scan_params *params;
 
     scansm = &g_ble_ll_scan_sm;
-    params = &scansm->phy_data[scansm->cur_phy];
+    params = scansm->scanp;
     if (scansm->scan_enabled && (params->scan_filt_policy & 1)) {
         rc = 0;
     } else {
@@ -3782,10 +3773,10 @@ ble_ll_scan_initiator_start(struct hci_create_conn *hcc,
 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
     scansm->ext_scanning = 0;
 #endif
-    scansm->cur_phy = PHY_UNCODED;
-    scansm->next_phy = PHY_NOT_CONFIGURED;
+    scansm->scanp = &scansm->phy_data[PHY_UNCODED];
+    scansm->scanp_next = NULL;
 
-    scanphy = &scansm->phy_data[scansm->cur_phy];
+    scanphy = scansm->scanp;
     scanphy->scan_filt_policy = hcc->filter_policy;
     scanphy->timing.interval = ble_ll_scan_time_hci_to_ticks(hcc->scan_itvl);
     scanphy->timing.window = ble_ll_scan_time_hci_to_ticks(hcc->scan_window);
@@ -3818,8 +3809,8 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc,
 
     scansm = &g_ble_ll_scan_sm;
     scansm->own_addr_type = hcc->own_addr_type;
-    scansm->cur_phy = PHY_NOT_CONFIGURED;
-    scansm->next_phy = PHY_NOT_CONFIGURED;
+    scansm->scanp = NULL;
+    scansm->scanp_next = NULL;
     scansm->ext_scanning = 1;
 
     if (hcc->init_phy_mask & BLE_PHY_MASK_1M) {
@@ -3830,7 +3821,7 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc,
         uncoded->timing.window = ble_ll_scan_time_hci_to_ticks(params->scan_window);
         uncoded->scan_type = BLE_SCAN_TYPE_INITIATE;
         uncoded->scan_filt_policy = hcc->filter_policy;
-        scansm->cur_phy = PHY_UNCODED;
+        scansm->scanp = uncoded;
     }
 
     if (hcc->init_phy_mask & BLE_PHY_MASK_CODED) {
@@ -3841,17 +3832,18 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc,
         coded->timing.window = ble_ll_scan_time_hci_to_ticks(params->scan_window);
         coded->scan_type = BLE_SCAN_TYPE_INITIATE;
         coded->scan_filt_policy = hcc->filter_policy;
-        if (scansm->cur_phy == PHY_NOT_CONFIGURED) {
-            scansm->cur_phy = PHY_CODED;
+        if (scansm->scanp) {
+            scansm->scanp_next = coded;
         } else {
-            scansm->next_phy = PHY_CODED;
+            scansm->scanp = coded;
         }
     }
 
     /* if any of PHYs is configured for continuous scan we alter interval to
      * fit other PHY
      */
-    if (coded->configured && uncoded->configured) {
+    if (scansm->scanp && scansm->scanp_next && coded->configured &&
+        uncoded->configured) {
         if (coded->timing.interval == coded->timing.window) {
             coded->timing.interval += uncoded->timing.window;
         }
@@ -3941,10 +3933,7 @@ ble_ll_scan_get_pdu_data(void)
 int
 ble_ll_scan_whitelist_enabled(void)
 {
-    struct ble_ll_scan_params *params;
-
-    params = &g_ble_ll_scan_sm.phy_data[g_ble_ll_scan_sm.cur_phy];
-    return params->scan_filt_policy & 1;
+    return g_ble_ll_scan_sm.scanp->scan_filt_policy & 1;
 }
 
 static void