From 235e6e1d0d713ddad79fa77d6982c006378053cd Mon Sep 17 00:00:00 2001 From: Vic Yang Date: Wed, 8 May 2013 02:43:59 +0800 Subject: [PATCH] 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 Reviewed-on: https://gerrit.chromium.org/gerrit/50338 Reviewed-by: Vincent Palatin --- chip/stm32/adc.c | 17 +++++++++++++---- 1 file 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)