You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by we...@apache.org on 2017/03/16 16:59:43 UTC

[3/3] incubator-mynewt-core git commit: Checking in almost working code. Not quite there yet.

Checking in almost working code. Not quite there yet.


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/6db66772
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/6db66772
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/6db66772

Branch: refs/heads/nrf_cputime
Commit: 6db66772cf077f1ac3cf84148bec47453e9b208c
Parents: 94a59a3
Author: William San Filippo <wi...@runtime.io>
Authored: Thu Mar 16 09:48:28 2017 -0700
Committer: William San Filippo <wi...@runtime.io>
Committed: Thu Mar 16 09:48:28 2017 -0700

----------------------------------------------------------------------
 apps/bletest/src/main.c                         |   2 +-
 hw/drivers/nimble/nrf52/include/ble/xcvr.h      |  22 +++
 hw/drivers/nimble/nrf52/src/ble_phy.c           |  17 ++
 .../controller/include/controller/ble_ll.h      |  25 ++-
 .../include/controller/ble_ll_sched.h           |   5 +
 .../controller/include/controller/ble_ll_xcvr.h |  48 +++++
 .../controller/include/controller/ble_phy.h     |  10 +
 net/nimble/controller/src/ble_ll.c              |  30 +++
 net/nimble/controller/src/ble_ll_adv.c          |  24 +++
 net/nimble/controller/src/ble_ll_conn.c         |   4 +
 net/nimble/controller/src/ble_ll_scan.c         | 129 ++++++++++++-
 net/nimble/controller/src/ble_ll_sched.c        | 106 +++++++++++
 net/nimble/controller/src/ble_ll_xcvr.c         | 183 +++++++++++++++++++
 net/nimble/controller/syscfg.yml                |   8 +
 net/nimble/host/src/ble_hs_hci_evt.c            |   9 +-
 net/nimble/syscfg.yml                           |   2 +-
 16 files changed, 612 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6db66772/apps/bletest/src/main.c
----------------------------------------------------------------------
diff --git a/apps/bletest/src/main.c b/apps/bletest/src/main.c
index e2519eb..efb3fd4 100755
--- a/apps/bletest/src/main.c
+++ b/apps/bletest/src/main.c
@@ -172,7 +172,7 @@ bletest_multi_adv_instances[BLETEST_CFG_ADV_TEST_INSTANCES] = {
 #define BLETEST_CFG_MAX_CE_LEN          (BLETEST_CFG_CONN_ITVL)
 #define BLETEST_CFG_CONN_PEER_ADDR_TYPE (BLE_HCI_CONN_PEER_ADDR_PUBLIC)
 #define BLETEST_CFG_CONN_OWN_ADDR_TYPE  (BLE_HCI_ADV_OWN_ADDR_PUBLIC)
-#define BLETEST_CFG_CONCURRENT_CONNS    (1)
+#define BLETEST_CFG_CONCURRENT_CONNS    (8)
 
 /* Test packet config */
 #define BLETEST_CFG_RAND_PKT_SIZE       (1)

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6db66772/hw/drivers/nimble/nrf52/include/ble/xcvr.h
----------------------------------------------------------------------
diff --git a/hw/drivers/nimble/nrf52/include/ble/xcvr.h b/hw/drivers/nimble/nrf52/include/ble/xcvr.h
index effe81d..45d2739 100644
--- a/hw/drivers/nimble/nrf52/include/ble/xcvr.h
+++ b/hw/drivers/nimble/nrf52/include/ble/xcvr.h
@@ -24,8 +24,30 @@
 extern "C" {
 #endif
 
+/*
+ * WWW: Need to think about this. Does this definition need to be in xcvr.h?
+ * 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
+
 /* Transceiver specific definitions */
 #if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+
+/* We will turn on/off rf clock */
+#if MYNEWT_VAL(BLE_XTAL_SETTLE_TIME) != 0
+#define BLE_XCVR_RFCLK
+#endif
+
 /*
  * NOTE: we have to account for the RTC output compare issue, which is why
  * this number is much larger when using the 32.768 crystal for cputime. We

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6db66772/hw/drivers/nimble/nrf52/src/ble_phy.c
----------------------------------------------------------------------
diff --git a/hw/drivers/nimble/nrf52/src/ble_phy.c b/hw/drivers/nimble/nrf52/src/ble_phy.c
index 410e0dc..a3254ca 100644
--- a/hw/drivers/nimble/nrf52/src/ble_phy.c
+++ b/hw/drivers/nimble/nrf52/src/ble_phy.c
@@ -794,6 +794,8 @@ int
 ble_phy_init(void)
 {
     int rc;
+
+#if !defined(BLE_XCVR_RFCLK)
     uint32_t os_tmo;
 
     /* Make sure HFXO is started */
@@ -808,6 +810,7 @@ ble_phy_init(void)
             return BLE_PHY_ERR_INIT;
         }
     }
+#endif
 
     /* Set phy channel to an invalid channel so first set channel works */
     g_ble_phy_data.phy_chan = BLE_PHY_NUM_CHANS;
@@ -1498,3 +1501,17 @@ ble_phy_resolv_list_disable(void)
     g_ble_phy_data.phy_privacy = 0;
 }
 #endif
+
+#ifdef BLE_XCVR_RFCLK
+void
+ble_phy_rfclk_enable(void)
+{
+    NRF_CLOCK->TASKS_HFCLKSTART = 1;
+}
+
+void
+ble_phy_rfclk_disable(void)
+{
+    NRF_CLOCK->TASKS_HFCLKSTOP = 1;
+}
+#endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6db66772/net/nimble/controller/include/controller/ble_ll.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll.h b/net/nimble/controller/include/controller/ble_ll.h
index d46f722..cdb170f 100644
--- a/net/nimble/controller/include/controller/ble_ll.h
+++ b/net/nimble/controller/include/controller/ble_ll.h
@@ -22,8 +22,10 @@
 
 #include "stats/stats.h"
 #include "os/os_eventq.h"
+#include "os/os_callout.h"
 #include "os/os_cputime.h"
 #include "nimble/nimble_opt.h"
+#include "controller/ble_phy.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -61,11 +63,22 @@ struct ble_ll_obj
 
     /* Number of ACL data packets supported */
     uint8_t ll_num_acl_pkts;
+
+#ifdef BLE_XCVR_RFCLK
+    uint8_t ll_rfclk_state;
+    uint16_t ll_xtal_ticks;
+#else
     uint8_t _pad;
+    uint16_t _pad16;
+#endif
 
     /* ACL data packet size */
     uint16_t ll_acl_pkt_size;
-    uint16_t _pad16;
+
+#ifdef BLE_XCVR_RFCLK
+    uint32_t ll_rfclk_start_time;
+    struct hal_timer ll_rfclk_timer;
+#endif
 
     /* Task event queue */
     struct os_eventq ll_evq;
@@ -382,6 +395,11 @@ int ble_ll_rand_data_get(uint8_t *buf, uint8_t len);
 void ble_ll_rand_prand_get(uint8_t *prand);
 int ble_ll_rand_start(void);
 
+/* Clock management */
+#ifdef BLE_XCVR_RFCLK
+void ble_ll_rfclk_start(uint32_t cputime);
+#endif
+
 /*
  * XXX: temporary LL debug log. Will get removed once we transition to real
  * log
@@ -408,6 +426,11 @@ int ble_ll_rand_start(void);
 #define BLE_LL_LOG_ID_ADV_TXBEG         (50)
 #define BLE_LL_LOG_ID_ADV_TXDONE        (60)
 #define BLE_LL_LOG_ID_SCHED             (80)
+#define BLE_LL_LOG_ID_RFCLK_START       (90)
+#define BLE_LL_LOG_ID_RFCLK_ENABLE      (91)
+#define BLE_LL_LOG_ID_RFCLK_STOP        (95)
+#define BLE_LL_LOG_ID_RFCLK_SCHED_DIS   (96)
+#define BLE_LL_LOG_ID_RFCLK_SCAN_DIS    (97)
 
 #ifdef BLE_LL_LOG
 void ble_ll_log(uint8_t id, uint8_t arg8, uint16_t arg16, uint32_t arg32);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6db66772/net/nimble/controller/include/controller/ble_ll_sched.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_sched.h b/net/nimble/controller/include/controller/ble_ll_sched.h
index bf3bc6d..d2321b7 100644
--- a/net/nimble/controller/include/controller/ble_ll_sched.h
+++ b/net/nimble/controller/include/controller/ble_ll_sched.h
@@ -149,6 +149,11 @@ int ble_ll_sched_next_time(uint32_t *next_event_time);
 /* 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
+
 #ifdef __cplusplus
 }
 #endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6db66772/net/nimble/controller/include/controller/ble_ll_xcvr.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_xcvr.h b/net/nimble/controller/include/controller/ble_ll_xcvr.h
new file mode 100644
index 0000000..0ede701
--- /dev/null
+++ b/net/nimble/controller/include/controller/ble_ll_xcvr.h
@@ -0,0 +1,48 @@
+/*
+ * 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(uint32_t cputime);
+void ble_ll_xcvr_rfclk_start_now(uint32_t now);
+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);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_LL_ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6db66772/net/nimble/controller/include/controller/ble_phy.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_phy.h b/net/nimble/controller/include/controller/ble_phy.h
index f300a13..e2b83e3 100644
--- a/net/nimble/controller/include/controller/ble_phy.h
+++ b/net/nimble/controller/include/controller/ble_phy.h
@@ -20,6 +20,8 @@
 #ifndef H_BLE_PHY_
 #define H_BLE_PHY_
 
+#include "ble/xcvr.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -129,6 +131,14 @@ void ble_phy_wfr_enable(uint32_t wfr_usecs);
 #define ble_phy_stop_usec_timer()
 #endif
 
+#ifdef BLE_XCVR_RFCLK
+/* Starts rf clock */
+void ble_phy_rfclk_enable(void);
+
+/* Stops rf clock */
+void ble_phy_rfclk_disable(void);
+#endif
+
 /*
  * Used to restart reception on same channel after wfr timer expiration or
  * frame received.

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6db66772/net/nimble/controller/src/ble_ll.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll.c b/net/nimble/controller/src/ble_ll.c
index 0d1fa07..1a06d4e 100644
--- a/net/nimble/controller/src/ble_ll.c
+++ b/net/nimble/controller/src/ble_ll.c
@@ -39,6 +39,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 "ble_ll_conn_priv.h"
 
 /* XXX:
@@ -224,6 +225,15 @@ ble_ll_log(uint8_t id, uint8_t arg8, uint16_t arg16, uint32_t arg32)
     os_sr_t sr;
     struct ble_ll_log *le;
 
+    /* WWW */
+    if ((id >= 90) || (id == 10) || (id == 20)) {
+        goto good;
+    } else {
+        return;
+    }
+good:
+    /* WWW */
+
     OS_ENTER_CRITICAL(sr);
     le = &g_ble_ll_log[g_ble_ll_log_index];
     le->cputime = os_cputime_get32();
@@ -1181,6 +1191,11 @@ ble_ll_reset(void)
     /* Set state to standby */
     ble_ll_state_set(BLE_LL_STATE_STANDBY);
 
+#ifdef BLE_XCVR_RFCLK
+    /* Stops rf clock and rfclock timer */
+    ble_ll_xcvr_rfclk_stop();
+#endif
+
     /* Reset our random address */
     memset(g_random_addr, 0, BLE_DEV_ADDR_LEN);
 
@@ -1225,11 +1240,26 @@ ble_ll_init(void)
 {
     int rc;
     uint8_t features;
+#ifdef BLE_XCVR_RFCLK
+    uint32_t xtal_ticks;
+#endif
     struct ble_ll_obj *lldata;
 
     /* Ensure this function only gets called by sysinit. */
     SYSINIT_ASSERT_ACTIVE();
 
+#ifdef BLE_XCVR_RFCLK
+    /* Settling time of crystal, in ticks */
+    xtal_ticks = MYNEWT_VAL(BLE_XTAL_SETTLE_TIME);
+    assert(xtal_ticks != 0);
+    g_ble_ll_data.ll_xtal_ticks = os_cputime_usecs_to_ticks(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
+
     /* Get pointer to global data object */
     lldata = &g_ble_ll_data;
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6db66772/net/nimble/controller/src/ble_ll_adv.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_adv.c b/net/nimble/controller/src/ble_ll_adv.c
index dd27336..b478922 100644
--- a/net/nimble/controller/src/ble_ll_adv.c
+++ b/net/nimble/controller/src/ble_ll_adv.c
@@ -746,6 +746,10 @@ ble_ll_adv_sm_stop(struct ble_ll_adv_sm *advsm)
             ble_ll_wfr_disable();
             ble_ll_state_set(BLE_LL_STATE_STANDBY);
             g_ble_ll_cur_adv_sm = NULL;
+            ble_ll_scan_chk_resume();
+#ifdef BLE_XCVR_RFCLK
+            ble_ll_sched_rfclk_chk_restart();
+#endif
         }
 #else
         if (ble_ll_state_get() == BLE_LL_STATE_ADV) {
@@ -753,6 +757,12 @@ ble_ll_adv_sm_stop(struct ble_ll_adv_sm *advsm)
             ble_ll_wfr_disable();
             ble_ll_state_set(BLE_LL_STATE_STANDBY);
             g_ble_ll_cur_adv_sm = NULL;
+            ble_ll_scan_chk_resume();
+#ifdef BLE_XCVR_RFCLK
+            /* WWW */
+            ble_ll_log(201,0,0,0);
+            ble_ll_sched_rfclk_chk_restart();
+#endif
         }
 #endif
         OS_EXIT_CRITICAL(sr);
@@ -1508,6 +1518,11 @@ ble_ll_adv_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
+
         /* This event is over. Set adv channel to first one */
         advsm->adv_chan = ble_ll_adv_first_chan(advsm);
 
@@ -1600,6 +1615,14 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm)
     /* Schedule advertising transmit */
     ble_ll_adv_set_sched(advsm);
 
+    /* WWW: Need to look at direct advertising (HD) to see if I messed up
+     * the resched pdu call.
+     *
+     * For xcvr clock, we only need to worry when we schedule new adv
+     * event. We want to make sure we dont turn off the clock if we are
+     * not done with the advertising event. Think about this.
+     */
+
     /*
      * In the unlikely event we cant reschedule this, just post a done
      * event and we will reschedule the next advertising event
@@ -1607,6 +1630,7 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm)
     if (resched_pdu) {
         rc = ble_ll_sched_adv_resched_pdu(&advsm->adv_sch);
     } else {
+        /* Reschedule advertising event */
         rc = ble_ll_sched_adv_reschedule(&advsm->adv_sch, &start_time,
                                          max_delay_ticks);
         if (!rc) {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6db66772/net/nimble/controller/src/ble_ll_conn.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_conn.c b/net/nimble/controller/src/ble_ll_conn.c
index 1f4ab8b..253e96e 100644
--- a/net/nimble/controller/src/ble_ll_conn.c
+++ b/net/nimble/controller/src/ble_ll_conn.c
@@ -2049,6 +2049,10 @@ ble_ll_conn_event_end(struct os_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
+
     /* If we have transmitted the terminate IND successfully, we are done */
     if ((connsm->csmflags.cfbit.terminate_ind_txd) ||
         (connsm->csmflags.cfbit.terminate_ind_rxd)) {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6db66772/net/nimble/controller/src/ble_ll_scan.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_scan.c b/net/nimble/controller/src/ble_ll_scan.c
index 306b8cc..5b81219 100644
--- a/net/nimble/controller/src/ble_ll_scan.c
+++ b/net/nimble/controller/src/ble_ll_scan.c
@@ -37,6 +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 "hal/hal_gpio.h"
 
 /*
@@ -618,6 +619,37 @@ ble_ll_scan_start(struct ble_ll_scan_sm *scansm, uint8_t chan)
     }
 }
 
+#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_log(BLE_LL_LOG_ID_RFCLK_SCAN_DIS, g_ble_ll_data.ll_rfclk_state,0,0);
+        ble_ll_xcvr_rfclk_disable();
+    }
+    OS_EXIT_CRITICAL(sr);
+}
+#endif
+
 /**
  * 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
@@ -635,6 +667,7 @@ ble_ll_scan_window_chk(struct ble_ll_scan_sm *scansm, uint32_t cputime)
     int rc;
     uint8_t chan;
     uint32_t itvl;
+    uint32_t dt;
     uint32_t win_start;
 
     itvl = os_cputime_usecs_to_ticks(scansm->scan_itvl * BLE_HCI_SCAN_ITVL);
@@ -651,7 +684,13 @@ ble_ll_scan_window_chk(struct ble_ll_scan_sm *scansm, uint32_t cputime)
     rc = 0;
     if (scansm->scan_window != scansm->scan_itvl) {
         itvl = os_cputime_usecs_to_ticks(scansm->scan_window * BLE_HCI_SCAN_ITVL);
-        if ((cputime - win_start) >= itvl) {
+        dt = cputime - win_start;
+        if (dt >= itvl) {
+#ifdef BLE_XCVR_RFCLK
+            if (dt < (scansm->scan_itvl - g_ble_ll_data.ll_xtal_ticks)) {
+                ble_ll_scan_rfclk_chk_stop();
+            }
+#endif
             rc = 1;
         }
     }
@@ -694,6 +733,11 @@ 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);
     }
@@ -763,6 +807,9 @@ ble_ll_scan_event_proc(struct os_event *ev)
     uint32_t win_start;
     uint32_t scan_itvl;
     uint32_t next_event_time;
+#ifdef BLE_XCVR_RFCLK
+    uint32_t xtal_ticks;
+#endif
     struct ble_ll_scan_sm *scansm;
 
     /*
@@ -792,12 +839,19 @@ ble_ll_scan_event_proc(struct os_event *ev)
     dt = now - win_start;
     scansm->scan_chan = chan;
     scansm->scan_win_start_time = win_start;
+    if (scansm->scan_window != scansm->scan_itvl) {
+        win = os_cputime_usecs_to_ticks(scansm->scan_window * BLE_HCI_SCAN_ITVL);
+    } else {
+        win = 0;
+    }
 
     /* Determine on/off state based on scan window */
     rxstate = 1;
     next_event_time = win_start + scan_itvl;
-    if (scansm->scan_window != scansm->scan_itvl) {
-        win = os_cputime_usecs_to_ticks(scansm->scan_window * BLE_HCI_SCAN_ITVL);
+
+    OS_ENTER_CRITICAL(sr);
+
+    if (win != 0) {
         if (dt >= win) {
             rxstate = 0;
         } else {
@@ -805,7 +859,6 @@ ble_ll_scan_event_proc(struct os_event *ev)
         }
     }
 
-    OS_ENTER_CRITICAL(sr);
     /*
      * 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
@@ -821,6 +874,9 @@ ble_ll_scan_event_proc(struct os_event *ev)
     case BLE_LL_STATE_SCANNING:
         /* Must disable PHY since we will move to a new channel */
         ble_phy_disable();
+        if (!rxstate) {
+            ble_ll_state_set(BLE_LL_STATE_STANDBY);
+        }
         break;
     case BLE_LL_STATE_STANDBY:
         break;
@@ -828,11 +884,72 @@ ble_ll_scan_event_proc(struct os_event *ev)
         assert(0);
         break;
     }
+
+#ifdef BLE_XCVR_RFCLK
+    if (rxstate == 0) {
+        /*
+         * 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 >= (scan_itvl - 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(now);
+                    next_event_time = now + g_ble_ll_data.ll_xtal_ticks;
+                }
+            }
+        } else {
+            next_event_time -= g_ble_ll_data.ll_xtal_ticks;
+            if (start_scan) {
+                ble_ll_scan_rfclk_chk_stop();
+            }
+        }
+    }
+#endif
+
     if (start_scan && rxstate) {
+#ifdef BLE_XCVR_RFCLK
+        /* NOTE: reuse rxstate */
+        rxstate = ble_ll_xcvr_rfclk_state();
+        if (rxstate != BLE_RFCLK_STATE_SETTLED) {
+            if (rxstate == 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 (win != 0) {
+                if ((win - dt) <= xtal_ticks)  {
+                    goto rfclk_not_settled;
+                }
+            }
+
+            /* WWW: This should just be an enable. No need to start
+               cputimer here! */
+            /*
+             * If clock off, start clock. Set next event time to now plus
+             * the clock setting time.
+             */
+            if (rxstate == BLE_RFCLK_STATE_OFF) {
+                ble_ll_xcvr_rfclk_start(now);
+            }
+            next_event_time = now + xtal_ticks;
+            goto rfclk_not_settled;
+        }
+#endif
         ble_ll_scan_start(scansm, scansm->scan_chan);
     }
-    OS_EXIT_CRITICAL(sr);
 
+#ifdef BLE_XCVR_RFCLK
+rfclk_not_settled:
+#endif
+    OS_EXIT_CRITICAL(sr);
     os_cputime_timer_start(&scansm->scan_timer, next_event_time);
 }
 
@@ -1484,7 +1601,7 @@ ble_ll_scan_init(void)
     scansm->scan_itvl = BLE_HCI_SCAN_ITVL_DEF;
     scansm->scan_window = BLE_HCI_SCAN_WINDOW_DEF;
 
-    /* Initialize connection supervision timer */
+    /* Initialize scanning timer */
     os_cputime_timer_init(&scansm->scan_timer, ble_ll_scan_timer_cb, scansm);
 
     /* Get a scan request mbuf (packet header) and attach to state machine */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6db66772/net/nimble/controller/src/ble_ll_sched.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_sched.c b/net/nimble/controller/src/ble_ll_sched.c
index 2c18e0c..b5109dd 100644
--- a/net/nimble/controller/src/ble_ll_sched.c
+++ b/net/nimble/controller/src/ble_ll_sched.c
@@ -28,11 +28,17 @@
 #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 "ble_ll_conn_priv.h"
 
 /* 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
+
 #if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
 uint8_t g_ble_ll_sched_offset_ticks;
 #endif
@@ -253,8 +259,17 @@ 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_rfclk_start(sch->start_time);
+    } else {
+        sch = entry;
+    }
+#else
     /* Get first on list */
     sch = TAILQ_FIRST(&g_ble_ll_sched_q);
+#endif
 
     OS_EXIT_CRITICAL(sr);
 
@@ -450,6 +465,15 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm,
     return rc;
 }
 
+/**
+ * Schedules a slave connection for the first time.
+ *
+ * Context: Link Layer
+ *
+ * @param connsm
+ *
+ * @return int
+ */
 int
 ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm)
 {
@@ -459,6 +483,11 @@ ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm)
     struct ble_ll_sched_item *next_sch;
     struct ble_ll_sched_item *sch;
 
+#ifdef BLE_XCVR_RFCLK
+    int first;
+    first = 0;
+#endif
+
     /* Get schedule element from connection */
     rc = -1;
     sch = &connsm->conn_sch;
@@ -494,6 +523,9 @@ 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) {
@@ -526,9 +558,24 @@ 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_rfclk_start(sch->start_time);
+    }
+#endif
+
     OS_EXIT_CRITICAL(sr);
 
     os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time);
@@ -590,6 +637,12 @@ ble_ll_sched_adv_new(struct ble_ll_sched_item *sch)
 
     ble_ll_adv_scheduled((struct ble_ll_adv_sm *)orig->cb_arg, adv_start);
 
+#ifdef BLE_XCVR_RFCLK
+    if (orig == sch) {
+        ble_ll_rfclk_start(sch->start_time);
+    }
+#endif
+
     OS_EXIT_CRITICAL(sr);
 
     os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time);
@@ -708,6 +761,12 @@ 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_rfclk_start(sch->start_time);
+        }
+#endif
     }
 
     OS_EXIT_CRITICAL(sr);
@@ -899,6 +958,53 @@ ble_ll_sched_next_time(uint32_t *next_event_time)
     return rc;
 }
 
+#ifdef BLE_XCVR_RFCLK
+void
+ble_ll_sched_rfclk_chk_restart(void)
+{
+    int stop;
+    os_sr_t sr;
+    uint8_t ll_state;
+    int32_t time_till_next;
+    uint32_t next_time;
+
+    stop = 0;
+    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 and leave the clock on
+         */
+        time_till_next = (int32_t)(next_time - os_cputime_get32());
+        if (time_till_next > g_ble_ll_data.ll_xtal_ticks) {
+            /* Stop the clock */
+            stop = 1;
+
+            /*
+             * Restart the timer as long as not advertising or in connection
+             * event
+             */
+            if (!((ll_state == BLE_LL_STATE_ADV) ||
+                  (ll_state == BLE_LL_STATE_CONNECTION))) {
+                ble_ll_xcvr_rfclk_start(next_time - g_ble_ll_data.ll_xtal_ticks);
+            }
+        }
+    } else {
+        stop = 1;
+    }
+
+    if (stop && (ll_state == BLE_LL_STATE_STANDBY)) {
+        ble_ll_log(BLE_LL_LOG_ID_RFCLK_SCHED_DIS, g_ble_ll_data.ll_rfclk_state,
+                   0, 0);
+        ble_ll_xcvr_rfclk_disable();
+    }
+    OS_EXIT_CRITICAL(sr);
+}
+
+#endif
+
+
 /**
  * Stop the scheduler
  *

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6db66772/net/nimble/controller/src/ble_ll_xcvr.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_xcvr.c b/net/nimble/controller/src/ble_ll_xcvr.c
new file mode 100644
index 0000000..43a2e49
--- /dev/null
+++ b/net/nimble/controller/src/ble_ll_xcvr.c
@@ -0,0 +1,183 @@
+/*
+ * 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 <assert.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"
+
+#if 0
+#include <string.h>
+#include "sysinit/sysinit.h"
+#include "os/os.h"
+#include "stats/stats.h"
+#include "bsp/bsp.h"
+#include "nimble/ble.h"
+#include "nimble/nimble_opt.h"
+#include "nimble/hci_common.h"
+#include "nimble/ble_hci_trans.h"
+#include "controller/ble_hw.h"
+#include "controller/ble_ll_adv.h"
+#include "controller/ble_ll_sched.h"
+#include "controller/ble_ll_scan.h"
+#include "controller/ble_ll_hci.h"
+#include "controller/ble_ll_whitelist.h"
+#include "controller/ble_ll_resolv.h"
+#include "ble_ll_conn_priv.h"
+#endif
+
+#ifdef BLE_XCVR_RFCLK
+int
+ble_ll_xcvr_rfclk_state(void)
+{
+    uint32_t expiry;
+
+    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;
+}
+
+/**
+ * Start the rf clock timer running at the specified cputime. The cputime
+ * is when the clock should start; it will be settled after xtal ticks have
+ * expired.
+ *
+ * If the clock is ON or SETTLED there is no need to start the timer. If the
+ * clock is OFF the timer might be set for some time in the future. If it is,
+ * we will reset the time if 'cputime' is earlier than the expiry time.
+ *
+ * @param cputime
+ */
+void
+ble_ll_xcvr_rfclk_start(uint32_t cputime)
+{
+    if (g_ble_ll_data.ll_rfclk_state == BLE_RFCLK_STATE_OFF) {
+
+        /*
+         * 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_timer.link.tqe_prev != NULL) {
+            if ((int32_t)(cputime - g_ble_ll_data.ll_rfclk_timer.expiry) >= 0) {
+                return;
+            }
+            os_cputime_timer_stop(&g_ble_ll_data.ll_rfclk_timer);
+        }
+        os_cputime_timer_start(&g_ble_ll_data.ll_rfclk_timer, cputime);
+        ble_ll_log(BLE_LL_LOG_ID_RFCLK_START, g_ble_ll_data.ll_rfclk_state, 0,
+                   g_ble_ll_data.ll_rfclk_timer.expiry);
+    }
+}
+
+void
+ble_ll_xcvr_rfclk_enable(void)
+{
+    g_ble_ll_data.ll_rfclk_state = BLE_RFCLK_STATE_ON;
+    ble_phy_rfclk_enable();
+}
+
+void
+ble_ll_xcvr_rfclk_disable(void)
+{
+    ble_phy_rfclk_disable();
+    g_ble_ll_data.ll_rfclk_state = BLE_RFCLK_STATE_OFF;
+}
+
+void
+ble_ll_xcvr_rfclk_stop(void)
+{
+    ble_ll_log(BLE_LL_LOG_ID_RFCLK_STOP, g_ble_ll_data.ll_rfclk_state, 0,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);
+        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
+ *
+ * Context: Interrupt
+ *
+ * @param arg
+ */
+void
+ble_ll_xcvr_rfclk_timer_exp(void *arg)
+{
+    if (g_ble_ll_data.ll_rfclk_state == BLE_RFCLK_STATE_OFF) {
+        ble_ll_xcvr_rfclk_enable();
+        g_ble_ll_data.ll_rfclk_start_time = g_ble_ll_data.ll_rfclk_timer.expiry;
+        ble_ll_log(BLE_LL_LOG_ID_RFCLK_ENABLE, g_ble_ll_data.ll_rfclk_state, 0,
+                   g_ble_ll_data.ll_rfclk_start_time);
+    }
+}
+
+/**
+ * This API is used to turn on the rfclock without setting the cputimer timer
+ * to start the clock at some later point.
+ *
+ * @param now
+ */
+void
+ble_ll_xcvr_rfclk_start_now(uint32_t now)
+{
+    ble_ll_xcvr_rfclk_enable();
+    g_ble_ll_data.ll_rfclk_start_time = now;
+    ble_ll_log(BLE_LL_LOG_ID_RFCLK_ENABLE, g_ble_ll_data.ll_rfclk_state, 0,
+               g_ble_ll_data.ll_rfclk_start_time);
+}
+
+/* WWW: This is really confusing. This is called when we add something
+ * to schedule at the start. We want to stop the current cputime timer
+ * for the clock and restart it at the new time.
+ *
+ */
+void
+ble_ll_rfclk_start(uint32_t cputime)
+{
+    /* If we are currently doing something, no need to start the clock */
+    if (g_ble_ll_data.ll_state == BLE_LL_STATE_STANDBY) {
+        ble_ll_xcvr_rfclk_start(cputime - g_ble_ll_data.ll_xtal_ticks);
+    }
+}
+#endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6db66772/net/nimble/controller/syscfg.yml
----------------------------------------------------------------------
diff --git a/net/nimble/controller/syscfg.yml b/net/nimble/controller/syscfg.yml
index 357decc..569010f 100644
--- a/net/nimble/controller/syscfg.yml
+++ b/net/nimble/controller/syscfg.yml
@@ -137,6 +137,14 @@ 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'
+
     # Configuration for LL supported features.
     #
     # There are a total 8 features that the LL can support. These can be found

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6db66772/net/nimble/host/src/ble_hs_hci_evt.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_hci_evt.c b/net/nimble/host/src/ble_hs_hci_evt.c
index a2d7a52..664df7b 100644
--- a/net/nimble/host/src/ble_hs_hci_evt.c
+++ b/net/nimble/host/src/ble_hs_hci_evt.c
@@ -6,7 +6,7 @@
  * 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,
@@ -622,15 +622,18 @@ ble_hs_hci_evt_acl_process(struct os_mbuf *om)
         goto err;
     }
 
+    /* WWW*/
+#if 0
 #if (BLETEST_THROUGHPUT_TEST == 0)
     BLE_HS_LOG(DEBUG, "ble_hs_hci_evt_acl_process(): conn_handle=%u pb=%x "
                       "len=%u data=",
-               BLE_HCI_DATA_HANDLE(hci_hdr.hdh_handle_pb_bc), 
-               BLE_HCI_DATA_PB(hci_hdr.hdh_handle_pb_bc), 
+               BLE_HCI_DATA_HANDLE(hci_hdr.hdh_handle_pb_bc),
+               BLE_HCI_DATA_PB(hci_hdr.hdh_handle_pb_bc),
                hci_hdr.hdh_len);
     ble_hs_log_mbuf(om);
     BLE_HS_LOG(DEBUG, "\n");
 #endif
+#endif  /* WWW */
 
     if (hci_hdr.hdh_len != OS_MBUF_PKTHDR(om)->omp_len) {
         rc = BLE_HS_EBADDATA;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6db66772/net/nimble/syscfg.yml
----------------------------------------------------------------------
diff --git a/net/nimble/syscfg.yml b/net/nimble/syscfg.yml
index f44da01..1f0aaf4 100644
--- a/net/nimble/syscfg.yml
+++ b/net/nimble/syscfg.yml
@@ -35,7 +35,7 @@ syscfg.defs:
 
     BLE_MAX_CONNECTIONS:
         description: 'The maximum number of concurrent connections.'
-        value: 1
+        value: 8
     BLE_WHITELIST:
         description: 'TBD'
         value: 1