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