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)