diff options
author | Vic Yang <victoryang@chromium.org> | 2013-05-08 02:43:59 +0800 |
---|---|---|
committer | ChromeBot <chrome-bot@google.com> | 2013-05-07 20:59:47 -0700 |
commit | 235e6e1d0d713ddad79fa77d6982c006378053cd (patch) | |
tree | b4bb3c44f4f7a23ae4a37f268bcbe3c4e5eed135 | |
parent | 0fe217c745406dd562d875ee845a73f8783339b8 (diff) | |
download | chrome-ec-235e6e1d0d713ddad79fa77d6982c006378053cd.tar.gz |
stm32f: Set ADC single read timeout
If an ADC read fails and EOC bit is somehow never set, we will be stuck
in the read function holding mutex lock forever, which is really bad.
Let's set a timeout for this.
BUG=chrome-os-partner:18997
TEST=Boot Spring. Check ADC works.
BRANCH=spring
Change-Id: I19b108326f34f380497606fe92eabfaf0a778bb4
Signed-off-by: Vic Yang <victoryang@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/50338
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r-- | chip/stm32/adc.c | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/chip/stm32/adc.c b/chip/stm32/adc.c index 99b014ef29..d65ffed2c0 100644 --- a/chip/stm32/adc.c +++ b/chip/stm32/adc.c @@ -14,6 +14,8 @@ #include "timer.h" #include "util.h" +#define ADC_SINGLE_READ_TIMEOUT 3000 /* 3 ms */ + struct mutex adc_lock; static int watchdog_ain_id; @@ -170,6 +172,7 @@ int adc_read_channel(enum adc_channel ch) const struct adc_t *adc = adc_channels + ch; int value; int restore_watchdog = 0; + timestamp_t deadline; if (!adc_powered()) return EC_ERROR_UNKNOWN; @@ -190,15 +193,21 @@ int adc_read_channel(enum adc_channel ch) STM32_ADC_CR2 |= (1 << 0); /* ADON */ /* Wait for EOC bit set */ - while (!adc_conversion_ended()) - ; - value = STM32_ADC_DR & ADC_READ_MAX; + deadline.val = get_time().val + ADC_SINGLE_READ_TIMEOUT; + value = ADC_READ_ERROR; + do { + if (adc_conversion_ended()) { + value = STM32_ADC_DR & ADC_READ_MAX; + break; + } + } while (!timestamp_expired(deadline, NULL)); if (restore_watchdog) adc_enable_watchdog_no_lock(); mutex_unlock(&adc_lock); - return value * adc->factor_mul / adc->factor_div + adc->shift; + return (value == ADC_READ_ERROR) ? ADC_READ_ERROR : + value * adc->factor_mul / adc->factor_div + adc->shift; } int adc_read_all_channels(int *data) |