mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Revision:
188:bcfe06ba3d64
Parent:
187:0387e8f68319
Child:
189:f392fc9709a3
--- a/hal/mbed_ticker_api.c	Thu Sep 06 13:40:20 2018 +0100
+++ b/hal/mbed_ticker_api.c	Thu Nov 08 11:46:34 2018 +0000
@@ -17,7 +17,7 @@
 #include <stddef.h>
 #include "hal/ticker_api.h"
 #include "platform/mbed_critical.h"
-#include "mbed_assert.h"
+#include "platform/mbed_assert.h"
 
 static void schedule_interrupt(const ticker_data_t *const ticker);
 static void update_present_time(const ticker_data_t *const ticker);
@@ -32,6 +32,9 @@
     if (ticker->queue->initialized) {
         return;
     }
+    if (ticker->queue->suspended) {
+        return;
+    }
 
     ticker->interface->init();
 
@@ -44,7 +47,7 @@
 
     uint8_t frequency_shifts = 0;
     for (uint8_t i = 31; i > 0; --i) {
-        if ((1 << i) == frequency) {
+        if ((1U << i) == frequency) {
             frequency_shifts = i;
             break;
         }
@@ -70,6 +73,7 @@
     ticker->queue->max_delta_us = max_delta_us;
     ticker->queue->present_time = 0;
     ticker->queue->dispatching = false;
+    ticker->queue->suspended = false;
     ticker->queue->initialized = true;
 
     update_present_time(ticker);
@@ -121,6 +125,9 @@
 static void update_present_time(const ticker_data_t *const ticker)
 {
     ticker_event_queue_t *queue = ticker->queue;
+    if (queue->suspended) {
+        return;
+    }
     uint32_t ticker_time = ticker->interface->read();
     if (ticker_time == ticker->queue->tick_last_read) {
         // No work to do
@@ -165,9 +172,9 @@
 }
 
 /**
- * Given the absolute timestamp compute the hal tick timestamp.
+ * Given the absolute timestamp compute the hal tick timestamp rounded up.
  */
-static timestamp_t compute_tick(const ticker_data_t *const ticker, us_timestamp_t timestamp)
+static timestamp_t compute_tick_round_up(const ticker_data_t *const ticker, us_timestamp_t timestamp)
 {
     ticker_event_queue_t *queue = ticker->queue;
     us_timestamp_t delta_us = timestamp - queue->present_time;
@@ -186,14 +193,14 @@
         } else if (0 != queue->frequency_shifts) {
             // Optimized frequencies divisible by 2
 
-            delta = (delta_us << ticker->queue->frequency_shifts) / 1000000;
+            delta = ((delta_us << ticker->queue->frequency_shifts) + 1000000 - 1) / 1000000;
             if (delta > ticker->queue->max_delta) {
                 delta = ticker->queue->max_delta;
             }
         } else {
             // General case
 
-            delta = delta_us * queue->frequency / 1000000;
+            delta = (delta_us * queue->frequency + 1000000 - 1) / 1000000;
             if (delta > ticker->queue->max_delta) {
                 delta = ticker->queue->max_delta;
             }
@@ -230,7 +237,7 @@
 static void schedule_interrupt(const ticker_data_t *const ticker)
 {
     ticker_event_queue_t *queue = ticker->queue;
-    if (ticker->queue->dispatching) {
+    if (queue->suspended || ticker->queue->dispatching) {
         // Don't schedule the next interrupt until dispatching is
         // finished. This prevents repeated calls to interface->set_interrupt
         return;
@@ -249,14 +256,11 @@
             return;
         }
 
-        timestamp_t match_tick = compute_tick(ticker, match_time);
-        // The time has been checked to be future, but it could still round
-        // to the last tick as a result of us to ticks conversion
-        if (match_tick == queue->tick_last_read) {
-            // Match time has already expired so fire immediately
-            ticker->interface->fire_interrupt();
-            return;
-        }
+        timestamp_t match_tick = compute_tick_round_up(ticker, match_time);
+
+        // The same tick should never occur since match_tick is rounded up.
+        // If the same tick is returned scheduling will not work correctly.
+        MBED_ASSERT(match_tick != queue->tick_last_read);
 
         ticker->interface->set_interrupt(match_tick);
         timestamp_t cur_tick = ticker->interface->read();
@@ -285,6 +289,10 @@
     core_util_critical_section_enter();
 
     ticker->interface->clear_interrupt();
+    if (ticker->queue->suspended) {
+        core_util_critical_section_exit();
+        return;
+    }
 
     /* Go through all the pending TimerEvents */
     ticker->queue->dispatching = true;
@@ -430,3 +438,29 @@
 
     return ret;
 }
+
+void ticker_suspend(const ticker_data_t *const ticker)
+{
+    core_util_critical_section_enter();
+
+    ticker->queue->suspended = true;
+
+    core_util_critical_section_exit();
+}
+
+void ticker_resume(const ticker_data_t *const ticker)
+{
+    core_util_critical_section_enter();
+
+    ticker->queue->suspended = false;
+    if (ticker->queue->initialized) {
+        ticker->queue->tick_last_read = ticker->interface->read();
+
+        update_present_time(ticker);
+        schedule_interrupt(ticker);
+    } else {
+        initialize(ticker);
+    }
+
+    core_util_critical_section_exit();
+}