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 2016/07/08 21:20:34 UTC

[47/50] [abbrv] incubator-mynewt-core git commit: MYNEWT-313: Low power modifications

MYNEWT-313: Low power modifications

There were a number of changes with this commit:
1) Porting the nrf51 code which uses an RTC timer for the OS timer tick to
the nrf52. The nrf52 used to use a higher power timer for its os tick.
2) Changing OS_TICKS_PER_SEC on the nrf51 and nrf52 to 128 (from 1000).
3) Modified blinky as it was doing a os_time_delay(1000) instead of os_time_delay(OS_TICKS_PER_SEC).


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

Branch: refs/heads/master
Commit: 9b008aa849eea2f6dae5f44cc1d523add450b887
Parents: 127d425
Author: William San Filippo <wi...@runtime.io>
Authored: Tue Jul 5 14:59:42 2016 -0700
Committer: William San Filippo <wi...@runtime.io>
Committed: Tue Jul 5 15:02:17 2016 -0700

----------------------------------------------------------------------
 apps/blinky/src/main.c                         |   4 +-
 hw/bsp/bmd300eval/pkg.yml                      |   2 +-
 hw/bsp/nrf51dk/pkg.yml                         |   4 +-
 hw/bsp/nrf52dk/pkg.yml                         |   2 +-
 hw/mcu/nordic/nrf51xxx/include/mcu/cortex_m0.h |   4 +-
 hw/mcu/nordic/nrf52xxx/include/mcu/cortex_m4.h |   6 +-
 hw/mcu/nordic/nrf52xxx/src/hal_os_tick.c       | 179 ++++++++++++++++++--
 7 files changed, 174 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9b008aa8/apps/blinky/src/main.c
----------------------------------------------------------------------
diff --git a/apps/blinky/src/main.c b/apps/blinky/src/main.c
index 3d4ff9e..24d0311 100755
--- a/apps/blinky/src/main.c
+++ b/apps/blinky/src/main.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,
@@ -89,7 +89,7 @@ task1_handler(void *arg)
         ++g_task1_loops;
 
         /* Wait one second */
-        os_time_delay(1000);
+        os_time_delay(OS_TICKS_PER_SEC);
 
         /* Toggle the LED */
         hal_gpio_toggle(g_led_pin);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9b008aa8/hw/bsp/bmd300eval/pkg.yml
----------------------------------------------------------------------
diff --git a/hw/bsp/bmd300eval/pkg.yml b/hw/bsp/bmd300eval/pkg.yml
index ccaf641..60d88ff 100644
--- a/hw/bsp/bmd300eval/pkg.yml
+++ b/hw/bsp/bmd300eval/pkg.yml
@@ -32,7 +32,7 @@ pkg.linkerscript: "bmd300eval.ld"
 pkg.linkerscript.bootloader.OVERWRITE: "boot-bmd300eval.ld"
 pkg.downloadscript: bmd300eval_download.sh
 pkg.debugscript: bmd300eval_debug.sh
-pkg.cflags: -DNRF52
+pkg.cflags: -DNRF52 -DBSP_HAS_32768_XTAL
 pkg.deps:
     - hw/mcu/nordic/nrf52xxx
     - libs/baselibc

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9b008aa8/hw/bsp/nrf51dk/pkg.yml
----------------------------------------------------------------------
diff --git a/hw/bsp/nrf51dk/pkg.yml b/hw/bsp/nrf51dk/pkg.yml
index 60fb6e6..4a1a93b 100644
--- a/hw/bsp/nrf51dk/pkg.yml
+++ b/hw/bsp/nrf51dk/pkg.yml
@@ -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,
@@ -32,7 +32,7 @@ pkg.linkerscript: "nrf51dk.ld"
 pkg.linkerscript.bootloader.OVERWRITE: "boot-nrf51dk.ld"
 pkg.downloadscript: nrf51dk_download.sh
 pkg.debugscript: nrf51dk_debug.sh
-pkg.cflags: -DNRF51
+pkg.cflags: -DNRF51 -DBSP_HAS_32768_XTAL
 pkg.deps:
     - hw/mcu/nordic/nrf51xxx
     - libs/baselibc

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9b008aa8/hw/bsp/nrf52dk/pkg.yml
----------------------------------------------------------------------
diff --git a/hw/bsp/nrf52dk/pkg.yml b/hw/bsp/nrf52dk/pkg.yml
index 617cea7..d350e70 100644
--- a/hw/bsp/nrf52dk/pkg.yml
+++ b/hw/bsp/nrf52dk/pkg.yml
@@ -32,7 +32,7 @@ pkg.linkerscript: "nrf52dk.ld"
 pkg.linkerscript.bootloader.OVERWRITE: "boot-nrf52dk.ld"
 pkg.downloadscript: nrf52dk_download.sh
 pkg.debugscript: nrf52dk_debug.sh
-pkg.cflags: -DNRF52
+pkg.cflags: -DNRF52 -DBSP_HAS_32768_XTAL
 pkg.deps:
     - hw/mcu/nordic/nrf52xxx
     - libs/baselibc

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9b008aa8/hw/mcu/nordic/nrf51xxx/include/mcu/cortex_m0.h
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/nrf51xxx/include/mcu/cortex_m0.h b/hw/mcu/nordic/nrf51xxx/include/mcu/cortex_m0.h
index b8c91a9..3ae4253 100644
--- a/hw/mcu/nordic/nrf51xxx/include/mcu/cortex_m0.h
+++ b/hw/mcu/nordic/nrf51xxx/include/mcu/cortex_m0.h
@@ -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,
@@ -27,6 +27,6 @@
  * clocked at 32768Hz. The tick frequency is chosen such that it divides
  * cleanly into 32768 to avoid a systemic bias in the actual tick frequency.
  */
-#define OS_TICKS_PER_SEC    (1024)
+#define OS_TICKS_PER_SEC    (128)
 
 #endif /* __MCU_CORTEX_M0_H__ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9b008aa8/hw/mcu/nordic/nrf52xxx/include/mcu/cortex_m4.h
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/nrf52xxx/include/mcu/cortex_m4.h b/hw/mcu/nordic/nrf52xxx/include/mcu/cortex_m4.h
index d7661c7..bb1c14e 100644
--- a/hw/mcu/nordic/nrf52xxx/include/mcu/cortex_m4.h
+++ b/hw/mcu/nordic/nrf52xxx/include/mcu/cortex_m4.h
@@ -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,
@@ -22,6 +22,10 @@
 
 #include "mcu/nrf52.h"
 
+#if defined(BSP_HAS_32768_XTAL)
+#define OS_TICKS_PER_SEC    (128)
+#else
 #define OS_TICKS_PER_SEC    (1000)
+#endif
 
 #endif /* __MCU_CORTEX_M4_H__ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9b008aa8/hw/mcu/nordic/nrf52xxx/src/hal_os_tick.c
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/nrf52xxx/src/hal_os_tick.c b/hw/mcu/nordic/nrf52xxx/src/hal_os_tick.c
index ba3f0b3..454d2a1 100644
--- a/hw/mcu/nordic/nrf52xxx/src/hal_os_tick.c
+++ b/hw/mcu/nordic/nrf52xxx/src/hal_os_tick.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,
@@ -22,16 +22,58 @@
 #include <mcu/nrf52_bitfields.h>
 #include <bsp/cmsis_nvic.h>
 
+#if defined(BSP_HAS_32768_XTAL)
+#define RTC_FREQ            32768       /* in Hz */
+#define OS_TICK_TIMER       NRF_RTC1
+#define OS_TICK_IRQ         RTC1_IRQn
+#define OS_TICK_CMPREG      3   /* generate timer interrupt */
+#define OS_TICK_PRESCALER   1   /* prescaler to generate timer freq */
+#define TIMER_LT(__t1, __t2)    ((((__t1) - (__t2)) & 0xffffff) > 0x800000)
+#define RTC_COMPARE_INT_MASK(ccreg) (1UL << ((ccreg) + 16))
+#else
 #define OS_TICK_TIMER       NRF_TIMER1
 #define OS_TICK_IRQ         TIMER1_IRQn
 #define OS_TICK_CMPREG      0   /* generate timer interrupt */
 #define OS_TICK_COUNTER     1   /* capture current timer value */
 #define OS_TICK_PRESCALER   4   /* prescaler to generate 1MHz timer freq */
 #define TIMER_LT(__t1, __t2)    ((int32_t)((__t1) - (__t2)) < 0)
+#endif
+
+struct hal_os_tick
+{
+    int ticks_per_ostick;
+    os_time_t max_idle_ticks;
+    uint32_t lastocmp;
+};
+
+struct hal_os_tick g_hal_os_tick;
+
+/*
+ * Implement (x - y) where the range of both 'x' and 'y' is limited to 24-bits.
+ *
+ * For example:
+ *
+ * sub24(0, 0xffffff) = 1
+ * sub24(0xffffff, 0xfffffe) = 1
+ * sub24(0xffffff, 0) = -1
+ * sub24(0x7fffff, 0) = 8388607
+ * sub24(0x800000, 0) = -8388608
+ */
+static inline int
+sub24(uint32_t x, uint32_t y)
+{
+    int result;
+
+    assert(x <= 0xffffff);
+    assert(y <= 0xffffff);
 
-static int timer_ticks_per_ostick;
-static os_time_t nrf52_max_idle_ticks;
-static uint32_t lastocmp;
+    result = x - y;
+    if (result & 0x800000) {
+        return (result | 0xff800000);
+    } else {
+        return (result & 0x007fffff);
+    }
+}
 
 static inline uint32_t
 nrf52_os_tick_counter(void)
@@ -42,11 +84,15 @@ nrf52_os_tick_counter(void)
      */
     OS_ASSERT_CRITICAL();
 
+#if defined(BSP_HAS_32768_XTAL)
+    return OS_TICK_TIMER->COUNTER;
+#else
     /*
      * Capture the current timer value and return it.
      */
     OS_TICK_TIMER->TASKS_CAPTURE[OS_TICK_COUNTER] = 1;
     return (OS_TICK_TIMER->CC[OS_TICK_COUNTER]);
+#endif
 }
 
 static inline void
@@ -56,12 +102,33 @@ nrf52_os_tick_set_ocmp(uint32_t ocmp)
 
     OS_ASSERT_CRITICAL();
     while (1) {
+#if defined(BSP_HAS_32768_XTAL)
+        int delta;
+
+        ocmp &= 0xffffff;
+        OS_TICK_TIMER->CC[OS_TICK_CMPREG] = ocmp;
+        counter = nrf52_os_tick_counter();
+        /*
+         * From nRF52 Product specification
+         *
+         * - If Counter is 'N' writing (N) or (N + 1) to CC register
+         *   may not trigger a compare event.
+         *
+         * - If Counter is 'N' writing (N + 2) to CC register is guaranteed
+         *   to trigger a compare event at 'N + 2'.
+         */
+        delta = sub24(ocmp, counter);
+        if (delta > 2) {
+            break;
+        }
+#else
         OS_TICK_TIMER->CC[OS_TICK_CMPREG] = ocmp;
         counter = nrf52_os_tick_counter();
         if (TIMER_LT(counter, ocmp)) {
             break;
         }
-        ocmp += timer_ticks_per_ostick;
+#endif
+        ocmp += g_hal_os_tick.ticks_per_ostick;
     }
 }
 
@@ -74,21 +141,35 @@ nrf52_timer_handler(void)
 
     OS_ENTER_CRITICAL(sr);
 
-    /*
-     * Calculate elapsed ticks and advance OS time.
-     */
+    /* Calculate elapsed ticks and advance OS time. */
+#if defined(BSP_HAS_32768_XTAL)
+    int delta;
+
     counter = nrf52_os_tick_counter();
-    ticks = (counter - lastocmp) / timer_ticks_per_ostick;
+    delta = sub24(counter, g_hal_os_tick.lastocmp);
+    ticks = delta / g_hal_os_tick.ticks_per_ostick;
     os_time_advance(ticks);
 
     /* Clear timer interrupt */
     OS_TICK_TIMER->EVENTS_COMPARE[OS_TICK_CMPREG] = 0;
 
     /* Update the time associated with the most recent tick */
-    lastocmp += ticks * timer_ticks_per_ostick;
+    g_hal_os_tick.lastocmp = (g_hal_os_tick.lastocmp +
+        (ticks * g_hal_os_tick.ticks_per_ostick)) & 0xffffff;
+#else
+    counter = nrf52_os_tick_counter();
+    ticks = (counter - g_hal_os_tick.lastocmp) / g_hal_os_tick.ticks_per_ostick;
+    os_time_advance(ticks);
+
+    /* Clear timer interrupt */
+    OS_TICK_TIMER->EVENTS_COMPARE[OS_TICK_CMPREG] = 0;
+
+    /* Update the time associated with the most recent tick */
+    g_hal_os_tick.lastocmp += ticks * g_hal_os_tick.ticks_per_ostick;
+#endif
 
     /* Update the output compare to interrupt at the next tick */
-    nrf52_os_tick_set_ocmp(lastocmp + timer_ticks_per_ostick);
+    nrf52_os_tick_set_ocmp(g_hal_os_tick.lastocmp + g_hal_os_tick.ticks_per_ostick);
 
     OS_EXIT_CRITICAL(sr);
 }
@@ -104,10 +185,10 @@ os_tick_idle(os_time_t ticks)
         /*
          * Enter tickless regime during long idle durations.
          */
-        if (ticks > nrf52_max_idle_ticks) {
-            ticks = nrf52_max_idle_ticks;
+        if (ticks > g_hal_os_tick.max_idle_ticks) {
+            ticks = g_hal_os_tick.max_idle_ticks;
         }
-        ocmp = lastocmp + ticks * timer_ticks_per_ostick;
+        ocmp = g_hal_os_tick.lastocmp + (ticks*g_hal_os_tick.ticks_per_ostick);
         nrf52_os_tick_set_ocmp(ocmp);
     }
 
@@ -123,18 +204,79 @@ os_tick_idle(os_time_t ticks)
     }
 }
 
+#if defined(BSP_HAS_32768_XTAL)
+void
+os_tick_init(uint32_t os_ticks_per_sec, int prio)
+{
+    uint32_t sr;
+    uint32_t mask;
+
+    assert(RTC_FREQ % os_ticks_per_sec == 0);
+
+    g_hal_os_tick.lastocmp = 0;
+    g_hal_os_tick.ticks_per_ostick = RTC_FREQ / os_ticks_per_sec;
+
+    /*
+     * The maximum number of OS ticks allowed to elapse during idle is
+     * limited to 1/4th the number of timer ticks before the 24-bit counter
+     * rolls over.
+     */
+    g_hal_os_tick.max_idle_ticks = (1UL << 22) / g_hal_os_tick.ticks_per_ostick;
+
+    /* Turn on the LFCLK */
+    NRF_CLOCK->TASKS_LFCLKSTOP = 1;
+    NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
+    NRF_CLOCK->LFCLKSRC = CLOCK_LFCLKSRC_SRC_Xtal;
+    NRF_CLOCK->TASKS_LFCLKSTART = 1;
+
+    /* Wait here till started! */
+    mask = CLOCK_LFCLKSTAT_STATE_Msk | CLOCK_LFCLKSTAT_SRC_Xtal;
+    while (1) {
+        if (NRF_CLOCK->EVENTS_LFCLKSTARTED) {
+            if ((NRF_CLOCK->LFCLKSTAT & mask) == mask) {
+                break;
+            }
+        }
+    }
+
+    /* disable interrupts */
+    OS_ENTER_CRITICAL(sr);
+
+    /* Set isr in vector table and enable interrupt */
+    NVIC_SetPriority(OS_TICK_IRQ, prio);
+    NVIC_SetVector(OS_TICK_IRQ, (uint32_t)nrf52_timer_handler);
+    NVIC_EnableIRQ(OS_TICK_IRQ);
+
+    /*
+     * Program the OS_TICK_TIMER to operate at 32KHz and trigger an output
+     * compare interrupt at a rate of 'os_ticks_per_sec'.
+     */
+    OS_TICK_TIMER->TASKS_STOP = 1;
+    OS_TICK_TIMER->TASKS_CLEAR = 1;
+
+    OS_TICK_TIMER->EVTENCLR = 0xffffffff;
+    OS_TICK_TIMER->INTENCLR = 0xffffffff;
+    OS_TICK_TIMER->INTENSET = RTC_COMPARE_INT_MASK(OS_TICK_CMPREG);
+
+    OS_TICK_TIMER->EVENTS_COMPARE[OS_TICK_CMPREG] = 0;
+    OS_TICK_TIMER->CC[OS_TICK_CMPREG] = g_hal_os_tick.ticks_per_ostick;
+
+    OS_TICK_TIMER->TASKS_START = 1;
+
+    OS_EXIT_CRITICAL(sr);
+}
+#else
 void
 os_tick_init(uint32_t os_ticks_per_sec, int prio)
 {
-    lastocmp = 0;
-    timer_ticks_per_ostick = 1000000 / os_ticks_per_sec;
+    g_hal_os_tick.ticks_per_ostick = 1000000 / os_ticks_per_sec;
 
     /*
      * The maximum number of timer ticks allowed to elapse during idle is
      * limited to 1/4th the number of timer ticks before the 32-bit counter
      * rolls over.
      */
-    nrf52_max_idle_ticks = (1UL << 30) / timer_ticks_per_ostick;
+    g_hal_os_tick.max_idle_ticks = (1UL << 30) / g_hal_os_tick.ticks_per_ostick;
 
     /*
      * Program OS_TICK_TIMER to operate at 1MHz and trigger an output
@@ -146,7 +288,7 @@ os_tick_init(uint32_t os_ticks_per_sec, int prio)
     OS_TICK_TIMER->BITMODE = TIMER_BITMODE_BITMODE_32Bit;
     OS_TICK_TIMER->PRESCALER = OS_TICK_PRESCALER;
 
-    OS_TICK_TIMER->CC[OS_TICK_CMPREG] = timer_ticks_per_ostick;
+    OS_TICK_TIMER->CC[OS_TICK_CMPREG] = g_hal_os_tick.ticks_per_ostick;
     OS_TICK_TIMER->INTENSET = TIMER_COMPARE_INT_MASK(OS_TICK_CMPREG);
     OS_TICK_TIMER->EVENTS_COMPARE[OS_TICK_CMPREG] = 0;
 
@@ -156,3 +298,4 @@ os_tick_init(uint32_t os_ticks_per_sec, int prio)
 
     OS_TICK_TIMER->TASKS_START = 1;     /* start the os tick timer */
 }
+#endif