Repository: incubator-mynewt-core
Updated Branches:
  refs/heads/develop 3c3ca3f3e -> f35d5d193


MYNEWT-538 Add RTC timer to hal timers for nordic

There are two changes to the code. One was a bug fix where we need
to call the timer callback if we are within 3 ticks of a timer
expiration if the timer is an RTC timer. The other change was just
a modification of the code when checking for a timer that is too
far in the future.


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/f35d5d19
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/f35d5d19
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/f35d5d19

Branch: refs/heads/develop
Commit: f35d5d1936adeacc9ec24c1d91ac0fb2d7c7c096
Parents: 3c3ca3f
Author: William San Filippo <[email protected]>
Authored: Wed Jan 18 16:04:02 2017 -0800
Committer: William San Filippo <[email protected]>
Committed: Wed Jan 18 16:05:47 2017 -0800

----------------------------------------------------------------------
 hw/mcu/nordic/nrf51xxx/src/hal_timer.c | 57 ++++++++++++++++-------------
 hw/mcu/nordic/nrf52xxx/src/hal_timer.c | 54 +++++++++++++++------------
 2 files changed, 63 insertions(+), 48 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f35d5d19/hw/mcu/nordic/nrf51xxx/src/hal_timer.c
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/nrf51xxx/src/hal_timer.c 
b/hw/mcu/nordic/nrf51xxx/src/hal_timer.c
index ab6a437..1776406 100644
--- a/hw/mcu/nordic/nrf51xxx/src/hal_timer.c
+++ b/hw/mcu/nordic/nrf51xxx/src/hal_timer.c
@@ -154,7 +154,7 @@ nrf_timer_set_ocmp(struct nrf51_hal_timer *bsptimer, 
uint32_t expiry)
 {
     int32_t delta_t;
     uint16_t expiry16;
-    uint32_t expiry24;
+    uint32_t cntr;
     uint32_t temp;
     NRF_TIMER_Type *hwtimer;
     NRF_RTC_Type *rtctimer;
@@ -188,32 +188,33 @@ nrf_timer_set_ocmp(struct nrf51_hal_timer *bsptimer, 
uint32_t expiry)
             /* Nothing to do; wait for overflow interrupt to set ocmp */
         }
     } else if (bsptimer->tmr_rtc) {
-        /* The RTC is a 24-bit counter so we need to check them first */
         rtctimer = (NRF_RTC_Type *)bsptimer->tmr_reg;
         rtctimer->INTENCLR = NRF_TIMER_INT_MASK(NRF_RTC_TIMER_CC_INT);
-        temp = expiry & 0xff000000;
-        delta_t = (int32_t)(temp - bsptimer->tmr_cntr);
-        if (delta_t < 0) {
-            goto set_ocmp_late;
-        } else if (delta_t == 0) {
-            /* Check if we might miss the timer */
-            expiry24 = expiry & 0x00ffffff;
-
-            /*
-             * The nrf documentation states that you must set the output
-             * compare to 2 greater than the counter to guarntee an interrupt.
-             * Since the counter can tick once while we check, we make sure
-             * it is greater than 2.
-             */
-            if ((expiry <= (rtctimer->COUNTER+2)) || rtctimer->EVENTS_OVRFLW) {
-                goto set_ocmp_late;
+        temp = bsptimer->tmr_cntr;
+        cntr = rtctimer->COUNTER;
+        if (rtctimer->EVENTS_OVRFLW) {
+            temp += (1UL << 24);
+            cntr = rtctimer->COUNTER;
+        }
+        temp |= cntr;
+        delta_t = (int32_t)(expiry - temp);
+
+        /*
+         * The nrf documentation states that you must set the output
+         * compare to 2 greater than the counter to guarantee an interrupt.
+         * Since the counter can tick once while we check, we make sure
+         * it is greater than 2.
+         */
+        if (delta_t < 3) {
+            NVIC_SetPendingIRQ(bsptimer->tmr_irq_num);
+        } else  {
+            if (delta_t < (1UL << 24)) {
+                rtctimer->CC[NRF_RTC_TIMER_CC_INT] = expiry & 0x00ffffff;
+            } else {
+                /* CC too far ahead. Just make sure we set compare far ahead */
+                rtctimer->CC[NRF_RTC_TIMER_CC_INT] = cntr + (1UL << 23);
             }
-
-            /* Set the output compare and enable interrupt */
-            rtctimer->CC[NRF_RTC_TIMER_CC_INT] = expiry24;
             rtctimer->INTENSET = NRF_TIMER_INT_MASK(NRF_RTC_TIMER_CC_INT);
-        } else {
-            /* Nothing to do; wait for overflow interrupt to set ocmp */
         }
     } else {
         /* Disable ocmp interrupt */
@@ -309,6 +310,7 @@ hal_timer_read_bsptimer(struct nrf51_hal_timer *bsptimer)
 static void
 hal_timer_chk_queue(struct nrf51_hal_timer *bsptimer)
 {
+    int32_t delta;
     uint32_t tcntr;
     uint32_t ctx;
     struct hal_timer *timer;
@@ -316,12 +318,17 @@ hal_timer_chk_queue(struct nrf51_hal_timer *bsptimer)
     /* disable interrupts */
     __HAL_DISABLE_INTERRUPTS(ctx);
     while ((timer = TAILQ_FIRST(&bsptimer->hal_timer_q)) != NULL) {
-        if (bsptimer->tmr_16bit || bsptimer->tmr_rtc) {
+        if (bsptimer->tmr_16bit) {
+            tcntr = hal_timer_read_bsptimer(bsptimer);
+            delta = 0;
+        } else if (bsptimer->tmr_rtc) {
             tcntr = hal_timer_read_bsptimer(bsptimer);
+            delta = -3;
         } else {
             tcntr = nrf_read_timer_cntr(bsptimer->tmr_reg);
+            delta = 0;
         }
-        if ((int32_t)(tcntr - timer->expiry) >= 0) {
+        if ((int32_t)(tcntr - timer->expiry) >= delta) {
             TAILQ_REMOVE(&bsptimer->hal_timer_q, timer, link);
             timer->link.tqe_prev = NULL;
             timer->cb_func(timer->cb_arg);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f35d5d19/hw/mcu/nordic/nrf52xxx/src/hal_timer.c
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/nrf52xxx/src/hal_timer.c 
b/hw/mcu/nordic/nrf52xxx/src/hal_timer.c
index d556f2c..dacf7de 100644
--- a/hw/mcu/nordic/nrf52xxx/src/hal_timer.c
+++ b/hw/mcu/nordic/nrf52xxx/src/hal_timer.c
@@ -147,38 +147,39 @@ static void
 nrf_timer_set_ocmp(struct nrf52_hal_timer *bsptimer, uint32_t expiry)
 {
     int32_t delta_t;
-    uint32_t expiry24;
     uint32_t temp;
+    uint32_t cntr;
     NRF_TIMER_Type *hwtimer;
     NRF_RTC_Type *rtctimer;
 
     if (bsptimer->tmr_rtc) {
-        /* The RTC is a 24-bit counter so we need to check them first */
         rtctimer = (NRF_RTC_Type *)bsptimer->tmr_reg;
         rtctimer->INTENCLR = NRF_TIMER_INT_MASK(NRF_RTC_TIMER_CC_INT);
-        temp = expiry & 0xff000000;
-        delta_t = (int32_t)(temp - bsptimer->tmr_cntr);
-        if (delta_t < 0) {
+        temp = bsptimer->tmr_cntr;
+        cntr = rtctimer->COUNTER;
+        if (rtctimer->EVENTS_OVRFLW) {
+            temp += (1UL << 24);
+            cntr = rtctimer->COUNTER;
+        }
+        temp |= cntr;
+        delta_t = (int32_t)(expiry - temp);
+
+        /*
+         * The nrf documentation states that you must set the output
+         * compare to 2 greater than the counter to guarantee an interrupt.
+         * Since the counter can tick once while we check, we make sure
+         * it is greater than 2.
+         */
+        if (delta_t < 3) {
             NVIC_SetPendingIRQ(bsptimer->tmr_irq_num);
-        } else if (delta_t == 0) {
-            /* Check if we might miss the timer */
-            expiry24 = expiry & 0x00ffffff;
-
-            /*
-             * The nrf documentation states that you must set the output
-             * compare to 2 greater than the counter to guarntee an interrupt.
-             * Since the counter can tick once while we check, we make sure
-             * it is greater than 2.
-             */
-            if ((expiry <= (rtctimer->COUNTER+2)) || rtctimer->EVENTS_OVRFLW) {
-                NVIC_SetPendingIRQ(bsptimer->tmr_irq_num);
+        } else  {
+            if (delta_t < (1UL << 24)) {
+                rtctimer->CC[NRF_RTC_TIMER_CC_INT] = expiry & 0x00ffffff;
+            } else {
+                /* CC too far ahead. Just make sure we set compare far ahead */
+                rtctimer->CC[NRF_RTC_TIMER_CC_INT] = cntr + (1UL << 23);
             }
-
-            /* Set the output compare and enable interrupt */
-            rtctimer->CC[NRF_RTC_TIMER_CC_INT] = expiry24;
             rtctimer->INTENSET = NRF_TIMER_INT_MASK(NRF_RTC_TIMER_CC_INT);
-        } else {
-            /* Nothing to do; wait for overflow interrupt to set ocmp */
         }
     } else {
         hwtimer = bsptimer->tmr_reg;
@@ -251,6 +252,7 @@ hal_timer_read_bsptimer(struct nrf52_hal_timer *bsptimer)
 static void
 hal_timer_chk_queue(struct nrf52_hal_timer *bsptimer)
 {
+    int32_t delta;
     uint32_t tcntr;
     uint32_t ctx;
     struct hal_timer *timer;
@@ -260,10 +262,16 @@ hal_timer_chk_queue(struct nrf52_hal_timer *bsptimer)
     while ((timer = TAILQ_FIRST(&bsptimer->hal_timer_q)) != NULL) {
         if (bsptimer->tmr_rtc) {
             tcntr = hal_timer_read_bsptimer(bsptimer);
+            /*
+             * If we are within 3 ticks of RTC, we wont be able to set compare.
+             * Thus, we have to service this timer early.
+             */
+            delta = -3;
         } else {
             tcntr = nrf_read_timer_cntr(bsptimer->tmr_reg);
+            delta = 0;
         }
-        if ((int32_t)(tcntr - timer->expiry) >= 0) {
+        if ((int32_t)(tcntr - timer->expiry) >= delta) {
             TAILQ_REMOVE(&bsptimer->hal_timer_q, timer, link);
             timer->link.tqe_prev = NULL;
             timer->cb_func(timer->cb_arg);

Reply via email to