summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlec Berg <alecaberg@chromium.org>2014-10-31 09:20:46 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-11-18 05:20:46 +0000
commit7e7e82f2c1855a46f4cba2d4f08e4f8c2e842a5c (patch)
treef9129e383b9b83b3f70a090dd6b468f01cc58465
parentd64324ad4d2211f9326dbaaed873c66c390f6f5b (diff)
downloadchrome-ec-7e7e82f2c1855a46f4cba2d4f08e4f8c2e842a5c.tar.gz
zinger: fix task_wait_event() to only exit on event received
Fix task_wait_event() so that it only wakes when an event is received or on timeout. Currently it wakes up on any interrupt, which can cause subtle timing issues with PD communication. BUG=none BRANCH=samus TEST=load onto samus, see it negotiate for 20V a few times Change-Id: Ia1268a1ac902433433949269d779ef11403eeae3 Signed-off-by: Alec Berg <alecaberg@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/226811 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--board/zinger/runtime.c72
1 files changed, 45 insertions, 27 deletions
diff --git a/board/zinger/runtime.c b/board/zinger/runtime.c
index 407daa5c54..d07139dbaf 100644
--- a/board/zinger/runtime.c
+++ b/board/zinger/runtime.c
@@ -117,10 +117,12 @@ void runtime_init(void)
uint32_t task_wait_event(int timeout_us)
{
uint32_t evt;
- timestamp_t t0;
+ timestamp_t t0, t1;
uint32_t rtc0, rtc0ss, rtc1, rtc1ss;
int rtc_diff;
+ t1.val = get_time().val + timeout_us;
+
asm volatile("cpsid i");
/* the event already happened */
if (last_event || !timeout_us) {
@@ -131,42 +133,58 @@ uint32_t task_wait_event(int timeout_us)
return evt;
}
- /* set timeout on timer */
- if (timeout_us < 0) {
- asm volatile ("wfi");
- } else if (timeout_us <= (STOP_MODE_LATENCY + SET_RTC_MATCH_DELAY)) {
- 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 */
+ /* loop until an event is triggered */
+ while (1) {
+ /* set timeout on timer */
+ if (timeout_us < 0) {
+ asm volatile ("wfi");
+ } else if (timeout_us <=
+ (STOP_MODE_LATENCY + SET_RTC_MATCH_DELAY)) {
+ 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 */
- asm volatile("wfi");
+ asm volatile("wfi");
- STM32_TIM_DIER(2) = 0; /* disable match interrupt */
- } else {
- t0 = get_time();
+ STM32_TIM_DIER(2) = 0; /* disable match interrupt */
+ } else {
+ t0 = get_time();
- /* set deep sleep bit */
- CPU_SCB_SYSCTRL |= 0x4;
+ /* set deep sleep bit */
+ CPU_SCB_SYSCTRL |= 0x4;
- set_rtc_alarm(0, timeout_us - STOP_MODE_LATENCY,
- &rtc0, &rtc0ss);
+ set_rtc_alarm(0, timeout_us - STOP_MODE_LATENCY,
+ &rtc0, &rtc0ss);
- asm volatile("wfi");
+ asm volatile("wfi");
- CPU_SCB_SYSCTRL &= ~0x4;
+ CPU_SCB_SYSCTRL &= ~0x4;
- config_hispeed_clock();
+ config_hispeed_clock();
- /* fast forward timer according to RTC counter */
- reset_rtc_alarm(&rtc1, &rtc1ss);
- rtc_diff = get_rtc_diff(rtc0, rtc0ss, rtc1, rtc1ss);
- t0.val = t0.val + rtc_diff;
- force_time(t0);
- }
+ /* fast forward timer according to RTC counter */
+ reset_rtc_alarm(&rtc1, &rtc1ss);
+ rtc_diff = get_rtc_diff(rtc0, rtc0ss, rtc1, rtc1ss);
+ t0.val = t0.val + rtc_diff;
+ force_time(t0);
+ }
- asm volatile("cpsie i ; isb");
+ asm volatile("cpsie i ; isb");
+ /* note: interrupt that woke us up will run here */
- /* note: interrupt that woke us up will run here */
+ t0 = get_time();
+ /* check for timeout if timeout was set */
+ if (timeout_us >= 0 && t0.val >= t1.val)
+ last_event = TASK_EVENT_TIMER;
+ /* break from loop when event has triggered */
+ if (last_event)
+ break;
+ /* recalculate timeout if timeout was set */
+ if (timeout_us >= 0)
+ timeout_us = t1.val - t0.val;
+
+ asm volatile("cpsid i");
+ }
evt = last_event;
last_event = 0;