summaryrefslogtreecommitdiff
path: root/chip
diff options
context:
space:
mode:
authorVic Yang <victoryang@chromium.org>2013-05-08 02:43:59 +0800
committerChromeBot <chrome-bot@google.com>2013-05-07 20:59:47 -0700
commit235e6e1d0d713ddad79fa77d6982c006378053cd (patch)
treeb4bb3c44f4f7a23ae4a37f268bcbe3c4e5eed135 /chip
parent0fe217c745406dd562d875ee845a73f8783339b8 (diff)
downloadchrome-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>
Diffstat (limited to 'chip')
-rw-r--r--chip/stm32/adc.c17
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)