summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2015-01-02 09:41:34 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-01-03 17:13:18 +0000
commitc268f2eee300bb56adcf8ff942325469a936a5d6 (patch)
tree750d5897d40849569948932f04ed5876ee4fa512
parent1f55eea80994538350588eb27dce0ee791144e2e (diff)
downloadchrome-ec-c268f2eee300bb56adcf8ff942325469a936a5d6.tar.gz
zinger: maintain a 64-bit time counter
Keep track of the high 32-bit of the microsecond time counter to avoid rollback issues. Just activate the timer "update" interrupt (aka UIE) and increment the high word on every update interrupt. Also disable STOP mode when we are going to roll-over during sleep to avoid missing the event. Given that's only happening every hour, we should not waste too much power. Signed-off-by: Vincent Palatin <vpalatin@chromium.org> BRANCH=samus BUG=chrome-os-partner:34159 TEST=patch the code to set the initial TIM2 value to 0xFC000000, wait for 67s, see the counter rolling and the high word incrementing, then verify that Zinger is still functional. Change-Id: I3a2f8fc09104d8ac75c581b2abcbcef99344def7 Reviewed-on: https://chromium-review.googlesource.com/238220 Trybot-Ready: Vincent Palatin <vpalatin@chromium.org> Tested-by: Vincent Palatin <vpalatin@chromium.org> Reviewed-by: Alec Berg <alecaberg@chromium.org> Commit-Queue: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--board/zinger/hardware.c5
-rw-r--r--board/zinger/runtime.c28
2 files changed, 23 insertions, 10 deletions
diff --git a/board/zinger/hardware.c b/board/zinger/hardware.c
index 54a92aaccd..1713ca342e 100644
--- a/board/zinger/hardware.c
+++ b/board/zinger/hardware.c
@@ -146,11 +146,12 @@ static void timers_init(void)
/* TIM2 is a 32-bit free running counter with 1Mhz frequency */
STM32_TIM_CR2(2) = 0x0000;
STM32_TIM32_ARR(2) = 0xFFFFFFFF;
- STM32_TIM32_CNT(2) = 0;
STM32_TIM_PSC(2) = CPU_CLOCK / 1000000 - 1;
STM32_TIM_EGR(2) = 0x0001; /* Reload the pre-scaler */
STM32_TIM_CR1(2) = 1;
- STM32_TIM_DIER(2) = 0;
+ STM32_TIM32_CNT(2) = 0x00000000;
+ STM32_TIM_SR(2) = 0; /* Clear pending interrupts */
+ STM32_TIM_DIER(2) = 1; /* Overflow interrupt */
task_enable_irq(STM32_IRQ_TIM2);
}
diff --git a/board/zinger/runtime.c b/board/zinger/runtime.c
index 186480f3e9..9d644e763a 100644
--- a/board/zinger/runtime.c
+++ b/board/zinger/runtime.c
@@ -17,12 +17,15 @@
volatile uint32_t last_event;
uint32_t sleep_mask;
+/* High word of the 64-bit timestamp counter */
+static volatile uint32_t clksrc_high;
+
timestamp_t get_time(void)
{
timestamp_t t;
t.le.lo = STM32_TIM32_CNT(2);
- t.le.hi = 0;
+ t.le.hi = clksrc_high;
return t;
}
@@ -62,9 +65,18 @@ uint32_t task_set_event(task_id_t tskid, uint32_t event, int wait)
void tim2_interrupt(void)
{
- STM32_TIM_DIER(2) = 0; /* disable match interrupt */
+ uint32_t stat = STM32_TIM_SR(2);
+
+ if (stat & 2) { /* Event match */
+ /* disable match interrupt but keep update interrupt */
+ STM32_TIM_DIER(2) = 1;
+ last_event = TASK_EVENT_TIMER;
+ }
+ if (stat & 1) /* Counter overflow */
+ clksrc_high++;
+
+ STM32_TIM_SR(2) = ~stat & 3; /* clear interrupt flags */
task_clear_pending_irq(STM32_IRQ_TIM2);
- last_event = TASK_EVENT_TIMER;
}
DECLARE_IRQ(STM32_IRQ_TIM2, tim2_interrupt, 1);
@@ -115,6 +127,7 @@ void runtime_init(void)
*/
#define STOP_MODE_LATENCY 300 /* us */
#define SET_RTC_MATCH_DELAY 200 /* us */
+#define MAX_LATENCY (STOP_MODE_LATENCY + SET_RTC_MATCH_DELAY)
uint32_t task_wait_event(int timeout_us)
{
@@ -140,16 +153,15 @@ uint32_t task_wait_event(int timeout_us)
/* set timeout on timer */
if (timeout_us < 0) {
asm volatile ("wfi");
- } else if (timeout_us <=
- (STOP_MODE_LATENCY + SET_RTC_MATCH_DELAY) ||
+ } else if (timeout_us <= MAX_LATENCY ||
+ t1.le.lo - timeout_us > t1.le.lo + MAX_LATENCY ||
!DEEP_SLEEP_ALLOWED) {
STM32_TIM32_CCR1(2) = STM32_TIM32_CNT(2) + timeout_us;
- STM32_TIM_SR(2) = 0; /* clear match flag */
- STM32_TIM_DIER(2) = 2; /* match interrupt */
+ STM32_TIM_DIER(2) = 3; /* match interrupt and UIE */
asm volatile("wfi");
- STM32_TIM_DIER(2) = 0; /* disable match interrupt */
+ STM32_TIM_DIER(2) = 1; /* disable match, keep UIE */
} else {
t0 = get_time();