mbed

Fork of mbed-dev by mbed official

Revision:
163:74e0ce7f98e8
Parent:
160:d5399cc887bb
Child:
165:e614a9f1c9e2
diff -r e13f6fdb2ac4 -r 74e0ce7f98e8 targets/TARGET_NORDIC/TARGET_NRF5/us_ticker.c
--- a/targets/TARGET_NORDIC/TARGET_NRF5/us_ticker.c	Wed Apr 12 16:21:43 2017 +0100
+++ b/targets/TARGET_NORDIC/TARGET_NRF5/us_ticker.c	Fri Apr 28 14:04:18 2017 +0100
@@ -42,6 +42,7 @@
 #include "nrf_drv_common.h"
 #include "nrf_drv_config.h"
 #include "lp_ticker_api.h"
+#include "mbed_critical.h"
 
 
 //------------------------------------------------------------------------------
@@ -52,12 +53,25 @@
 bool              m_common_rtc_enabled = false;
 uint32_t volatile m_common_rtc_overflows = 0;
 
+__STATIC_INLINE void rtc_ovf_event_check(void)
+{
+    if (nrf_rtc_event_pending(COMMON_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW)) {
+        nrf_rtc_event_clear(COMMON_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW);
+        // Don't disable this event. It shall occur periodically.
+
+        ++m_common_rtc_overflows;
+    }
+}
+
 #if defined(TARGET_MCU_NRF51822)
 void common_rtc_irq_handler(void)
 #else
 void COMMON_RTC_IRQ_HANDLER(void)
 #endif
 {
+
+    rtc_ovf_event_check();
+
     if (nrf_rtc_event_pending(COMMON_RTC_INSTANCE, US_TICKER_EVENT)) {
         us_ticker_irq_handler();
     }
@@ -69,12 +83,6 @@
     }
 #endif
 
-    if (nrf_rtc_event_pending(COMMON_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW)) {
-        nrf_rtc_event_clear(COMMON_RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW);
-        // Don't disable this event. It shall occur periodically.
-
-        ++m_common_rtc_overflows;
-    }
 }
 
 #if (defined (__ICCARM__)) && defined(TARGET_MCU_NRF51822)//IAR
@@ -142,13 +150,37 @@
     m_common_rtc_enabled = true;
 }
 
+__STATIC_INLINE void rtc_ovf_event_safe_check(void)
+{
+    core_util_critical_section_enter();
+
+    rtc_ovf_event_check();
+
+    core_util_critical_section_exit();
+}
+
+
 uint32_t common_rtc_32bit_ticks_get(void)
 {
-    uint32_t ticks = nrf_rtc_counter_get(COMMON_RTC_INSTANCE);
-    // The counter used for time measurements is less than 32 bit wide,
-    // so its value is complemented with the number of registered overflows
-    // of the counter.
-    ticks += (m_common_rtc_overflows << RTC_COUNTER_BITS);
+    uint32_t ticks;
+    uint32_t prev_overflows;
+
+    do {
+        prev_overflows = m_common_rtc_overflows;
+
+        ticks = nrf_rtc_counter_get(COMMON_RTC_INSTANCE);
+        // The counter used for time measurements is less than 32 bit wide,
+        // so its value is complemented with the number of registered overflows
+        // of the counter.
+        ticks += (m_common_rtc_overflows << RTC_COUNTER_BITS);
+
+        // Check in case that OVF occurred during execution of a RTC handler (apply if call was from RTC handler)
+        // m_common_rtc_overflows might been updated in this call.
+        rtc_ovf_event_safe_check();
+
+        // If call was made from a low priority level m_common_rtc_overflows might have been updated in RTC handler.
+    } while (m_common_rtc_overflows != prev_overflows);
+
     return ticks;
 }
 
@@ -185,6 +217,8 @@
     uint32_t compare_value =
         (uint32_t)CEIL_DIV((timestamp64) * RTC_INPUT_FREQ, 1000000);
 
+
+    core_util_critical_section_enter();
     // The COMPARE event occurs when the value in compare register is N and
     // the counter value changes from N-1 to N. Therefore, the minimal safe
     // difference between the compare value to be set and the current counter
@@ -197,6 +231,8 @@
 
     nrf_rtc_cc_set(COMMON_RTC_INSTANCE, cc_channel, RTC_WRAP(compare_value));
     nrf_rtc_event_enable(COMMON_RTC_INSTANCE, int_mask);
+
+    core_util_critical_section_exit();
 }
 //------------------------------------------------------------------------------