You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2018/11/21 22:47:33 UTC

[mynewt-nimble] 01/06: host: Divide startup into two stages

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

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

commit 71f95c45b4d51dd954b40c684b6e1c914a497d96
Author: Christopher Collins <cc...@apache.org>
AuthorDate: Wed Oct 3 17:34:56 2018 -0700

    host: Divide startup into two stages
    
    Prior to this commit: host startup was done in a single stage by an
    event on the default event queue.  This creates a problem if the
    application wishes to run the host in a different event queue (i.e., not
    the default task).  The typical init sequence looks like this:
    
    1. Sysinit (start event enqueued to default event queue).
    2. Application configures host, possible changing the host event queue.
    3. Host start event runs in the default task.
    
    The problem is that the start event in step three determines that the
    host task is the currently running task.  This is always the default
    task, which is incorrect if the user reconfigured the event queue.
    
    Now: host startup is divided into two stages.  The first stage simply
    enqueues a second event on the host event queue.  The startup sequence
    now looks like this:
    
    1. Sysinit (start event enqueued to default event queue).
    2. Application configures host, possible changing the host event queue.
    3. Stage 1 start event runs in the default task (stage 2 event enqueued
    to host task).
    4. Stage 2 start event runs in the host task.
---
 nimble/host/include/host/ble_hs.h |  8 ++++--
 nimble/host/src/ble_hs.c          | 55 ++++++++++++++++++++++++++++++++-------
 2 files changed, 51 insertions(+), 12 deletions(-)

diff --git a/nimble/host/include/host/ble_hs.h b/nimble/host/include/host/ble_hs.h
index 192fdef..82d7ff5 100644
--- a/nimble/host/include/host/ble_hs.h
+++ b/nimble/host/include/host/ble_hs.h
@@ -301,7 +301,9 @@ int ble_hs_synced(void);
  * commands.  This function must be called before any other host functionality
  * is used, but it must be called after both the host and controller are
  * initialized.  Typically, the host-parent-task calls this function at the top
- * of its task routine.
+ * of its task routine.  This function must only be called in the host parent
+ * task.  A safe alternative for starting the stack from any task is to call
+ * `ble_hs_sched_start()`.
  *
  * If the host fails to synchronize with the controller (if the controller is
  * not fully booted, for example), the host will attempt to resynchronize every
@@ -319,7 +321,9 @@ int ble_hs_start(void);
  * configure the host package in the meantime.
  *
  * If auto-start is disabled, the application should use this function to start
- * the BLE stack.
+ * the BLE stack.  This function can be called at any time as long as the host
+ * is stopped.  When the host successfully starts, the application is notified
+ * via the ble_hs_cfg.sync_cb callback.
  */
 void ble_hs_sched_start(void);
 
diff --git a/nimble/host/src/ble_hs.c b/nimble/host/src/ble_hs.c
index 1718c98..edfd88f 100644
--- a/nimble/host/src/ble_hs.c
+++ b/nimble/host/src/ble_hs.c
@@ -38,7 +38,8 @@
 static void ble_hs_event_rx_hci_ev(struct ble_npl_event *ev);
 static void ble_hs_event_tx_notify(struct ble_npl_event *ev);
 static void ble_hs_event_reset(struct ble_npl_event *ev);
-static void ble_hs_event_start(struct ble_npl_event *ev);
+static void ble_hs_event_start_stage1(struct ble_npl_event *ev);
+static void ble_hs_event_start_stage2(struct ble_npl_event *ev);
 static void ble_hs_timer_sched(int32_t ticks_from_now);
 
 struct os_mempool ble_hs_hci_ev_pool;
@@ -52,7 +53,8 @@ static struct ble_npl_event ble_hs_ev_tx_notifications;
 /** OS event - triggers a full reset. */
 static struct ble_npl_event ble_hs_ev_reset;
 
-static struct ble_npl_event ble_hs_ev_start;
+static struct ble_npl_event ble_hs_ev_start_stage1;
+static struct ble_npl_event ble_hs_ev_start_stage2;
 
 uint8_t ble_hs_sync_state;
 static int ble_hs_reset_reason;
@@ -455,15 +457,22 @@ ble_hs_timer_resched(void)
      */
     ble_hs_timer_reset(0);
 }
- 
+
+static void
+ble_hs_sched_start_stage2(void)
+{
+    ble_npl_eventq_put((struct ble_npl_eventq *)ble_hs_evq_get(),
+                       &ble_hs_ev_start_stage2);
+}
+
 void
 ble_hs_sched_start(void)
 {
 #ifdef MYNEWT
     ble_npl_eventq_put((struct ble_npl_eventq *)os_eventq_dflt_get(),
-                       &ble_hs_ev_start);
+                       &ble_hs_ev_start_stage1);
 #else
-    ble_npl_eventq_put(nimble_port_get_dflt_eventq(), &ble_hs_ev_start);
+    ble_npl_eventq_put(nimble_port_get_dflt_eventq(), &ble_hs_ev_start_stage1);
 #endif
 }
 
@@ -504,8 +513,30 @@ ble_hs_event_reset(struct ble_npl_event *ev)
     ble_hs_reset();
 }
 
+/**
+ * Implements the first half of the start process.  This just enqueues another
+ * event on the host parent task's event queue.
+ *
+ * Starting is done in two stages to allow the application time to configure
+ * the event queue to use after system initialization but before the host
+ * starts.
+ */
+static void
+ble_hs_event_start_stage1(struct ble_npl_event *ev)
+{
+    ble_hs_sched_start_stage2();
+}
+
+/**
+ * Implements the second half of the start process.  This actually starts the
+ * host.
+ *
+ * Starting is done in two stages to allow the application time to configure
+ * the event queue to use after system initialization but before the host
+ * starts.
+ */
 static void
-ble_hs_event_start(struct ble_npl_event *ev)
+ble_hs_event_start_stage2(struct ble_npl_event *ev)
 {
     int rc;
 
@@ -651,9 +682,13 @@ ble_hs_init(void)
      */
     ble_hs_reset_reason = 0;
 
-    ble_npl_event_init(&ble_hs_ev_tx_notifications, ble_hs_event_tx_notify, NULL);
+    ble_npl_event_init(&ble_hs_ev_tx_notifications, ble_hs_event_tx_notify,
+                       NULL);
     ble_npl_event_init(&ble_hs_ev_reset, ble_hs_event_reset, NULL);
-    ble_npl_event_init(&ble_hs_ev_start, ble_hs_event_start, NULL);
+    ble_npl_event_init(&ble_hs_ev_start_stage1, ble_hs_event_start_stage1,
+                       NULL);
+    ble_npl_event_init(&ble_hs_ev_start_stage2, ble_hs_event_start_stage2,
+                       NULL);
 
 #if BLE_MONITOR
     rc = ble_monitor_init();
@@ -712,9 +747,9 @@ ble_hs_init(void)
 #if MYNEWT_VAL(BLE_HS_AUTO_START)
 #ifdef MYNEWT
     ble_npl_eventq_put((struct ble_npl_eventq *)os_eventq_dflt_get(),
-                       &ble_hs_ev_start);
+                       &ble_hs_ev_start_stage1);
 #else
-    ble_npl_eventq_put(nimble_port_get_dflt_eventq(), &ble_hs_ev_start);
+    ble_npl_eventq_put(nimble_port_get_dflt_eventq(), &ble_hs_ev_start_stage1);
 #endif
 #endif