drivers: adc: stm32: Add function to enable ADC consistently

Use a wrapper for LL_ADC_Enable that also waits for ADRDY if required
by the SoC to make sure it's properly enabled everywhere this is done.

Signed-off-by: Alexander Mihajlovic <a@abxy.se>
This commit is contained in:
Alexander Mihajlovic 2022-01-03 18:45:58 +01:00 committed by Anas Nashif
commit e521c7d49e

View file

@ -407,6 +407,44 @@ static void adc_stm32_oversampling(ADC_TypeDef *adc, uint8_t ratio, uint32_t shi
} }
#endif /* CONFIG_SOC_SERIES_STM32xxx */ #endif /* CONFIG_SOC_SERIES_STM32xxx */
/*
* Enable ADC peripheral, and wait until ready if required by SOC.
*/
static int adc_stm32_enable(ADC_TypeDef *adc)
{
if (LL_ADC_IsEnabled(adc) == 1UL) {
return 0;
}
LL_ADC_Enable(adc);
#if defined(CONFIG_SOC_SERIES_STM32L4X) || \
defined(CONFIG_SOC_SERIES_STM32L5X) || \
defined(CONFIG_SOC_SERIES_STM32WBX) || \
defined(CONFIG_SOC_SERIES_STM32G0X) || \
defined(CONFIG_SOC_SERIES_STM32G4X) || \
defined(CONFIG_SOC_SERIES_STM32H7X) || \
defined(CONFIG_SOC_SERIES_STM32WLX)
/*
* Enabling ADC modules in L4, WB, G0 and G4 series may fail if they are
* still not stabilized, this will wait for a short time to ensure ADC
* modules are properly enabled.
*/
uint32_t count_timeout = 0;
while (LL_ADC_IsActiveFlag_ADRDY(adc) == 0) {
if (LL_ADC_IsEnabled(adc) == 0UL) {
LL_ADC_Enable(adc);
count_timeout++;
if (count_timeout == 10) {
return -ETIMEDOUT;
}
}
}
#endif
return 0;
}
static int start_read(const struct device *dev, static int start_read(const struct device *dev,
const struct adc_sequence *sequence) const struct adc_sequence *sequence)
{ {
@ -513,9 +551,7 @@ static int start_read(const struct device *dev,
while (LL_ADC_IsEnabled(adc) == 1UL) { while (LL_ADC_IsEnabled(adc) == 1UL) {
} }
LL_ADC_SetResolution(adc, resolution); LL_ADC_SetResolution(adc, resolution);
LL_ADC_Enable(adc); adc_stm32_enable(adc);
while (LL_ADC_IsActiveFlag_ADRDY(adc) != 1UL) {
}
#elif !defined(CONFIG_SOC_SERIES_STM32F1X) && \ #elif !defined(CONFIG_SOC_SERIES_STM32F1X) && \
!defined(STM32F3X_ADC_V2_5) !defined(STM32F3X_ADC_V2_5)
LL_ADC_SetResolution(adc, resolution); LL_ADC_SetResolution(adc, resolution);
@ -530,7 +566,8 @@ static int start_read(const struct device *dev,
LL_ADC_Disable(adc); LL_ADC_Disable(adc);
while (LL_ADC_IsEnabled(adc) == 1UL) { while (LL_ADC_IsEnabled(adc) == 1UL) {
} }
#endif /* CONFIG_SOC_SERIES_STM32L0X */ #endif
#if defined(CONFIG_SOC_SERIES_STM32G0X) || \ #if defined(CONFIG_SOC_SERIES_STM32G0X) || \
defined(CONFIG_SOC_SERIES_STM32G4X) || \ defined(CONFIG_SOC_SERIES_STM32G4X) || \
defined(CONFIG_SOC_SERIES_STM32H7X) || \ defined(CONFIG_SOC_SERIES_STM32H7X) || \
@ -580,11 +617,11 @@ static int start_read(const struct device *dev,
#endif /* CONFIG_SOC_SERIES_STM32H7X */ #endif /* CONFIG_SOC_SERIES_STM32H7X */
default: default:
LOG_ERR("Invalid oversampling"); LOG_ERR("Invalid oversampling");
LL_ADC_Enable(adc); adc_stm32_enable(adc);
return -EINVAL; return -EINVAL;
} }
/* re-enable ADC after changing the OVS */ /* re-enable ADC after changing the OVS */
LL_ADC_Enable(adc); adc_stm32_enable(adc);
#else #else
if (sequence->oversampling) { if (sequence->oversampling) {
LOG_ERR("Oversampling not supported"); LOG_ERR("Oversampling not supported");
@ -606,7 +643,7 @@ static int start_read(const struct device *dev,
} }
adc_stm32_calib(dev); adc_stm32_calib(dev);
/* re-enable ADC after calibration */ /* re-enable ADC after calibration */
LL_ADC_Enable(adc); adc_stm32_enable(adc);
#else #else
LOG_ERR("Calibration not supported"); LOG_ERR("Calibration not supported");
return -ENOTSUP; return -ENOTSUP;
@ -628,7 +665,7 @@ static int start_read(const struct device *dev,
#elif defined(CONFIG_SOC_SERIES_STM32F1X) #elif defined(CONFIG_SOC_SERIES_STM32F1X)
LL_ADC_EnableIT_EOS(adc); LL_ADC_EnableIT_EOS(adc);
#elif defined(STM32F3X_ADC_V2_5) #elif defined(STM32F3X_ADC_V2_5)
LL_ADC_Enable(adc); adc_stm32_enable(adc);
LL_ADC_EnableIT_EOS(adc); LL_ADC_EnableIT_EOS(adc);
#else #else
LL_ADC_EnableIT_EOCS(adc); LL_ADC_EnableIT_EOCS(adc);
@ -975,32 +1012,10 @@ static int adc_stm32_init(const struct device *dev)
} }
#endif #endif
LL_ADC_Enable(adc); err = adc_stm32_enable(adc);
if (err < 0) {
#if defined(CONFIG_SOC_SERIES_STM32L4X) || \ return err;
defined(CONFIG_SOC_SERIES_STM32L5X) || \
defined(CONFIG_SOC_SERIES_STM32WBX) || \
defined(CONFIG_SOC_SERIES_STM32G0X) || \
defined(CONFIG_SOC_SERIES_STM32G4X) || \
defined(CONFIG_SOC_SERIES_STM32H7X) || \
defined(CONFIG_SOC_SERIES_STM32WLX)
/*
* Enabling ADC modules in L4, WB, G0 and G4 series may fail if they are
* still not stabilized, this will wait for a short time to ensure ADC
* modules are properly enabled.
*/
uint32_t countTimeout = 0;
while (LL_ADC_IsActiveFlag_ADRDY(adc) == 0) {
if (LL_ADC_IsEnabled(adc) == 0UL) {
LL_ADC_Enable(adc);
countTimeout++;
if (countTimeout == 10) {
return -ETIMEDOUT;
}
}
} }
#endif
config->irq_cfg_func(); config->irq_cfg_func();