From e521c7d49e0141d2d8d96b6f83e44cedefb363a4 Mon Sep 17 00:00:00 2001
From: Alexander Mihajlovic
Date: Mon, 3 Jan 2022 18:45:58 +0100
Subject: [PATCH] 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
---
drivers/adc/adc_stm32.c | 81 ++++++++++++++++++++++++-----------------
1 file changed, 48 insertions(+), 33 deletions(-)
diff --git a/drivers/adc/adc_stm32.c b/drivers/adc/adc_stm32.c
index 471d91b49e2..ac311460e9b 100644
--- a/drivers/adc/adc_stm32.c
+++ b/drivers/adc/adc_stm32.c
@@ -407,6 +407,44 @@ static void adc_stm32_oversampling(ADC_TypeDef *adc, uint8_t ratio, uint32_t shi
}
#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,
const struct adc_sequence *sequence)
{
@@ -513,9 +551,7 @@ static int start_read(const struct device *dev,
while (LL_ADC_IsEnabled(adc) == 1UL) {
}
LL_ADC_SetResolution(adc, resolution);
- LL_ADC_Enable(adc);
- while (LL_ADC_IsActiveFlag_ADRDY(adc) != 1UL) {
- }
+ adc_stm32_enable(adc);
#elif !defined(CONFIG_SOC_SERIES_STM32F1X) && \
!defined(STM32F3X_ADC_V2_5)
LL_ADC_SetResolution(adc, resolution);
@@ -530,7 +566,8 @@ static int start_read(const struct device *dev,
LL_ADC_Disable(adc);
while (LL_ADC_IsEnabled(adc) == 1UL) {
}
-#endif /* CONFIG_SOC_SERIES_STM32L0X */
+#endif
+
#if defined(CONFIG_SOC_SERIES_STM32G0X) || \
defined(CONFIG_SOC_SERIES_STM32G4X) || \
defined(CONFIG_SOC_SERIES_STM32H7X) || \
@@ -580,11 +617,11 @@ static int start_read(const struct device *dev,
#endif /* CONFIG_SOC_SERIES_STM32H7X */
default:
LOG_ERR("Invalid oversampling");
- LL_ADC_Enable(adc);
+ adc_stm32_enable(adc);
return -EINVAL;
}
/* re-enable ADC after changing the OVS */
- LL_ADC_Enable(adc);
+ adc_stm32_enable(adc);
#else
if (sequence->oversampling) {
LOG_ERR("Oversampling not supported");
@@ -606,7 +643,7 @@ static int start_read(const struct device *dev,
}
adc_stm32_calib(dev);
/* re-enable ADC after calibration */
- LL_ADC_Enable(adc);
+ adc_stm32_enable(adc);
#else
LOG_ERR("Calibration not supported");
return -ENOTSUP;
@@ -628,7 +665,7 @@ static int start_read(const struct device *dev,
#elif defined(CONFIG_SOC_SERIES_STM32F1X)
LL_ADC_EnableIT_EOS(adc);
#elif defined(STM32F3X_ADC_V2_5)
- LL_ADC_Enable(adc);
+ adc_stm32_enable(adc);
LL_ADC_EnableIT_EOS(adc);
#else
LL_ADC_EnableIT_EOCS(adc);
@@ -975,32 +1012,10 @@ static int adc_stm32_init(const struct device *dev)
}
#endif
- 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 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;
- }
- }
+ err = adc_stm32_enable(adc);
+ if (err < 0) {
+ return err;
}
-#endif
config->irq_cfg_func();