Skip to content

Commit bdcef28

Browse files
committed
drivers/adc: stm32: workaround for L462xE errata 2.5.2 and stuck reads
According to the ST Errata sheet ES0389 - Rev 5, section 2.5.2, the workaround to the issue of "Wrong ADC result if conversion done late after calibration or previous conversion" is to perform two consecutive ADC conversions. We found also that the same objective is achieved enabling and disabling it at every read. Moreover, this approach solves another issue found on several STM32L462VE samples, where the reads were stuck, giving always the same wrong value, that was 0 or the last calibration value. Additional clearing of ADRDY flag has been added to avoid finding it already set before next enabling. Signed-off-by: Giancarlo Stasi <[email protected]>
1 parent a87a5ea commit bdcef28

File tree

1 file changed

+53
-29
lines changed

1 file changed

+53
-29
lines changed

drivers/adc/adc_stm32.c

Lines changed: 53 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -502,15 +502,61 @@ static void adc_stm32_isr(const struct device *dev)
502502
LOG_DBG("ISR triggered.");
503503
}
504504

505+
static int adc_stm32_enable_and_wait_stabilisation(ADC_TypeDef *adc)
506+
{
507+
#if defined(CONFIG_SOC_SERIES_STM32L4X) || \
508+
defined(CONFIG_SOC_SERIES_STM32L5X) || \
509+
defined(CONFIG_SOC_SERIES_STM32WBX) || \
510+
defined(CONFIG_SOC_SERIES_STM32G0X) || \
511+
defined(CONFIG_SOC_SERIES_STM32G4X) || \
512+
defined(CONFIG_SOC_SERIES_STM32H7X) || \
513+
defined(CONFIG_SOC_SERIES_STM32WLX)
514+
/*
515+
* Enabling ADC modules in L4, WB, G0 and G4 series may fail if they are
516+
* still not stabilized, this will wait for a short time to ensure ADC
517+
* modules are properly enabled.
518+
*/
519+
uint32_t countTimeout = 0;
520+
521+
do {
522+
if (LL_ADC_IsEnabled(adc) == 0UL) {
523+
LL_ADC_Enable(adc);
524+
}
525+
countTimeout++;
526+
if (countTimeout == 10) {
527+
return -ETIMEDOUT;
528+
}
529+
} while (LL_ADC_IsActiveFlag_ADRDY(adc) == 0);
530+
LL_ADC_ClearFlag_ADRDY(adc);
531+
#else
532+
if (LL_ADC_IsEnabled(adc) == 0UL) {
533+
LL_ADC_Enable(adc);
534+
}
535+
#endif
536+
return 0;
537+
}
538+
505539
static int adc_stm32_read(const struct device *dev,
506540
const struct adc_sequence *sequence)
507541
{
508542
struct adc_stm32_data *data = dev->data;
509-
int error;
543+
const struct adc_stm32_cfg *config = dev->config;
544+
ADC_TypeDef *adc = (ADC_TypeDef *)config->base;
545+
int error = 0;
510546

511-
adc_context_lock(&data->ctx, false, NULL);
512-
error = start_read(dev, sequence);
513-
adc_context_release(&data->ctx, error);
547+
if (LL_ADC_IsEnabled(adc) == 0) {
548+
error = adc_stm32_enable_and_wait_stabilisation(adc);
549+
}
550+
551+
if (error == 0) {
552+
adc_context_lock(&data->ctx, false, NULL);
553+
error = start_read(dev, sequence);
554+
adc_context_release(&data->ctx, error);
555+
}
556+
557+
if (LL_ADC_IsEnabled(adc)) {
558+
LL_ADC_Disable(adc);
559+
}
514560

515561
return error;
516562
}
@@ -796,32 +842,10 @@ static int adc_stm32_init(const struct device *dev)
796842
}
797843
#endif
798844

799-
LL_ADC_Enable(adc);
800-
801-
#if defined(CONFIG_SOC_SERIES_STM32L4X) || \
802-
defined(CONFIG_SOC_SERIES_STM32L5X) || \
803-
defined(CONFIG_SOC_SERIES_STM32WBX) || \
804-
defined(CONFIG_SOC_SERIES_STM32G0X) || \
805-
defined(CONFIG_SOC_SERIES_STM32G4X) || \
806-
defined(CONFIG_SOC_SERIES_STM32H7X) || \
807-
defined(CONFIG_SOC_SERIES_STM32WLX)
808-
/*
809-
* Enabling ADC modules in L4, WB, G0 and G4 series may fail if they are
810-
* still not stabilized, this will wait for a short time to ensure ADC
811-
* modules are properly enabled.
812-
*/
813-
uint32_t countTimeout = 0;
814-
815-
while (LL_ADC_IsActiveFlag_ADRDY(adc) == 0) {
816-
if (LL_ADC_IsEnabled(adc) == 0UL) {
817-
LL_ADC_Enable(adc);
818-
countTimeout++;
819-
if (countTimeout == 10) {
820-
return -ETIMEDOUT;
821-
}
822-
}
845+
err = adc_stm32_enable_and_wait_stabilisation(adc);
846+
if (err < 0) {
847+
return err;
823848
}
824-
#endif
825849

826850
config->irq_cfg_func();
827851

0 commit comments

Comments
 (0)