drivers/adc: stm32: do not disable the ADC if resolution is unchanged

In case the resolution is already correct (probably the common use
case), do nothing instead of disabling the ADC.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
Aurelien Jarno 2022-06-01 23:30:10 +02:00 committed by Fabio Baltieri
parent 897554bd39
commit c57a41c5d2

View file

@ -344,6 +344,20 @@ static void adc_stm32_calib(const struct device *dev)
}
#endif
/*
* Disable ADC peripheral, and wait until it is disabled
*/
static inline void adc_stm32_disable(ADC_TypeDef *adc)
{
if (LL_ADC_IsEnabled(adc) != 1UL) {
return;
}
LL_ADC_Disable(adc);
while (LL_ADC_IsEnabled(adc) == 1UL) {
}
}
#if defined(CONFIG_SOC_SERIES_STM32G0X) || \
defined(CONFIG_SOC_SERIES_STM32G4X) || \
defined(CONFIG_SOC_SERIES_STM32H7X) || \
@ -369,6 +383,48 @@ static void adc_stm32_calib(const struct device *dev)
};
#endif /* ! ADC_VER_V5_V90 */
/*
* Function to configure the oversampling scope. It is basically a wrapper over
* LL_ADC_SetOverSamplingScope() which in addition stops the ADC if needed.
*/
static void adc_stm32_oversampling_scope(ADC_TypeDef *adc, uint32_t ovs_scope)
{
#if defined(CONFIG_SOC_SERIES_STM32L0X) || \
defined(CONFIG_SOC_SERIES_STM32WLX)
/*
* setting OVS bits is conditioned to ADC state: ADC must be disabled
* or enabled without conversion on going : disable it, it will stop
*/
if (LL_ADC_GetOverSamplingScope(adc) == ovs_scope) {
return;
}
adc_stm32_disable(adc);
#endif
LL_ADC_SetOverSamplingScope(adc, ovs_scope);
}
/*
* Function to configure the oversampling ratio and shift. It is basically a
* wrapper over LL_ADC_SetOverSamplingRatioShift() which in addition stops the
* ADC if needed.
*/
static void adc_stm32_oversampling_ratioshift(ADC_TypeDef *adc, uint32_t ratio, uint32_t shift)
{
#if defined(CONFIG_SOC_SERIES_STM32L0X) || \
defined(CONFIG_SOC_SERIES_STM32WLX)
/*
* setting OVS bits is conditioned to ADC state: ADC must be disabled
* or enabled without conversion on going : disable it, it will stop
*/
if ((LL_ADC_GetOverSamplingRatio(adc) == ratio)
&& (LL_ADC_GetOverSamplingShift(adc) == shift)) {
return;
}
adc_stm32_disable(adc);
#endif
LL_ADC_ConfigOverSamplingRatioShift(adc, ratio, shift);
}
/*
* Function to configure the oversampling ratio and shit using stm32 LL
* ratio is directly the sequence->oversampling (a 2^n value)
@ -376,7 +432,7 @@ static void adc_stm32_calib(const struct device *dev)
*/
static void adc_stm32_oversampling(ADC_TypeDef *adc, uint8_t ratio, uint32_t shift)
{
LL_ADC_SetOverSamplingScope(adc, LL_ADC_OVS_GRP_REGULAR_CONTINUED);
adc_stm32_oversampling_scope(adc, LL_ADC_OVS_GRP_REGULAR_CONTINUED);
#if defined(CONFIG_SOC_SERIES_STM32H7X)
/*
* Set bits manually to circumvent bug in LL Libraries
@ -396,13 +452,13 @@ static void adc_stm32_oversampling(ADC_TypeDef *adc, uint8_t ratio, uint32_t shi
#elif defined(CONFIG_SOC_SERIES_STM32U5X)
if (adc == ADC1) {
/* the LL function expects a value from 1 to 1024 */
LL_ADC_ConfigOverSamplingRatioShift(adc, (1 << ratio), shift);
adc_stm32_oversampling_ratioshift(adc, (1 << ratio), shift);
} else {
/* the LL function expects a value LL_ADC_OVS_RATIO_x */
LL_ADC_ConfigOverSamplingRatioShift(adc, stm32_adc_ratio_table[ratio], shift);
adc_stm32_oversampling_ratioshift(adc, stm32_adc_ratio_table[ratio], shift);
}
#else /* CONFIG_SOC_SERIES_STM32H7X */
LL_ADC_ConfigOverSamplingRatioShift(adc, stm32_adc_ratio_table[ratio], shift);
adc_stm32_oversampling_ratioshift(adc, stm32_adc_ratio_table[ratio], shift);
#endif /* CONFIG_SOC_SERIES_STM32H7X */
}
#endif /* CONFIG_SOC_SERIES_STM32xxx */
@ -450,20 +506,6 @@ static int adc_stm32_enable(ADC_TypeDef *adc)
return 0;
}
/*
* Disable ADC peripheral, and wait until it is disabled
*/
static inline void adc_stm32_disable(ADC_TypeDef *adc)
{
if (LL_ADC_IsEnabled(adc) != 1UL) {
return;
}
LL_ADC_Disable(adc);
while (LL_ADC_IsEnabled(adc) == 1UL) {
}
}
static int start_read(const struct device *dev,
const struct adc_sequence *sequence)
{
@ -560,26 +602,19 @@ static int start_read(const struct device *dev,
#if defined(CONFIG_SOC_SERIES_STM32G0X) || \
defined(CONFIG_SOC_SERIES_STM32WLX)
/*
* Writing ADC_CFGR1 register while ADEN bit is set
* resets RES[1:0] bitfield. We need to disable and enable adc.
*/
adc_stm32_disable(adc);
LL_ADC_SetResolution(adc, resolution);
if (LL_ADC_GetResolution(adc) != resolution) {
/*
* Writing ADC_CFGR1 register while ADEN bit is set
* resets RES[1:0] bitfield. We need to disable and enable adc.
*/
adc_stm32_disable(adc);
LL_ADC_SetResolution(adc, resolution);
}
#elif !defined(CONFIG_SOC_SERIES_STM32F1X) && \
!defined(STM32F3X_ADC_V2_5)
LL_ADC_SetResolution(adc, resolution);
#endif
#if defined(CONFIG_SOC_SERIES_STM32L0X) || \
defined(CONFIG_SOC_SERIES_STM32WLX)
/*
* setting OVS bits is conditioned to ADC state: ADC must be disabled
* or enabled without conversion on going : disable it, it will stop
*/
adc_stm32_disable(adc);
#endif
#if defined(CONFIG_SOC_SERIES_STM32G0X) || \
defined(CONFIG_SOC_SERIES_STM32G4X) || \
defined(CONFIG_SOC_SERIES_STM32H7X) || \
@ -592,7 +627,7 @@ static int start_read(const struct device *dev,
switch (sequence->oversampling) {
case 0:
LL_ADC_SetOverSamplingScope(adc, LL_ADC_OVS_DISABLE);
adc_stm32_oversampling_scope(adc, LL_ADC_OVS_DISABLE);
break;
case 1:
adc_stm32_oversampling(adc, 1, LL_ADC_OVS_SHIFT_RIGHT_1);