From ff7be31f264c359b6f11fcc2cec8489dfe4905bd Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Wed, 16 Jun 2021 23:44:52 +0200 Subject: [PATCH] stm32/adc: Allow using ADC12 and ADC3 for H7. * Modify common functions in adc.c to accept ADC handle. * Most external channels are connected to ADC12 which is used by default. * For ADCAll (internal channels) ADC3 is used instead. * Issue #4435 is possibly related (at least partially fixed). --- ports/stm32/adc.c | 68 ++++++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 28 deletions(-) diff --git a/ports/stm32/adc.c b/ports/stm32/adc.c index 5fa22d7c78..6f709e9098 100644 --- a/ports/stm32/adc.c +++ b/ports/stm32/adc.c @@ -51,16 +51,9 @@ /// val = adc.read_core_vref() # read MCU VREF /* ADC defintions */ - -#if defined(STM32H7) -#define ADCx (ADC3) -#define PIN_ADC_MASK PIN_ADC3 -#define pin_adc_table pin_adc3 -#else #define ADCx (ADC1) #define PIN_ADC_MASK PIN_ADC1 #define pin_adc_table pin_adc1 -#endif #define ADCx_CLK_ENABLE __HAL_RCC_ADC1_CLK_ENABLE @@ -142,7 +135,7 @@ defined(STM32F746xx) || defined(STM32F765xx) || \ defined(STM32F767xx) || defined(STM32F769xx) #define VBAT_DIV (4) -#elif defined(STM32H743xx) +#elif defined(STM32H743xx) || defined(STM32H747xx) #define VBAT_DIV (4) #elif defined(STM32L432xx) || \ defined(STM32L451xx) || defined(STM32L452xx) || \ @@ -214,12 +207,12 @@ STATIC bool is_adcx_channel(int channel) { #endif } -STATIC void adc_wait_for_eoc_or_timeout(int32_t timeout) { +STATIC void adc_wait_for_eoc_or_timeout(ADC_HandleTypeDef *adcHandle, int32_t timeout) { uint32_t tickstart = HAL_GetTick(); #if defined(STM32F4) || defined(STM32F7) - while ((ADCx->SR & ADC_FLAG_EOC) != ADC_FLAG_EOC) { + while ((adcHandle->Instance->SR & ADC_FLAG_EOC) != ADC_FLAG_EOC) { #elif defined(STM32F0) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) - while (READ_BIT(ADCx->ISR, ADC_FLAG_EOC) != ADC_FLAG_EOC) { + while (READ_BIT(adcHandle->Instance->ISR, ADC_FLAG_EOC) != ADC_FLAG_EOC) { #else #error Unsupported processor #endif @@ -229,11 +222,15 @@ STATIC void adc_wait_for_eoc_or_timeout(int32_t timeout) { } } -STATIC void adcx_clock_enable(void) { +STATIC void adcx_clock_enable(ADC_HandleTypeDef *adch) { #if defined(STM32F0) || defined(STM32F4) || defined(STM32F7) ADCx_CLK_ENABLE(); #elif defined(STM32H7) - __HAL_RCC_ADC3_CLK_ENABLE(); + if (adch->Instance == ADC3) { + __HAL_RCC_ADC3_CLK_ENABLE(); + } else { + __HAL_RCC_ADC12_CLK_ENABLE(); + } __HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_CLKP); #elif defined(STM32L4) || defined(STM32WB) if (__HAL_RCC_GET_ADC_SOURCE() == RCC_ADCCLKSOURCE_NONE) { @@ -246,9 +243,8 @@ STATIC void adcx_clock_enable(void) { } STATIC void adcx_init_periph(ADC_HandleTypeDef *adch, uint32_t resolution) { - adcx_clock_enable(); + adcx_clock_enable(adch); - adch->Instance = ADCx; adch->Init.Resolution = resolution; adch->Init.ContinuousConvMode = DISABLE; adch->Init.DiscontinuousConvMode = DISABLE; @@ -308,6 +304,7 @@ STATIC void adc_init_single(pyb_obj_adc_t *adc_obj) { mp_hal_pin_config(pin, MP_HAL_PIN_MODE_ADC, MP_HAL_PIN_PULL_NONE, 0); } + adc_obj->handle.Instance = ADCx; adcx_init_periph(&adc_obj->handle, ADC_RESOLUTION_12B); #if defined(STM32L4) && defined(ADC_DUALMODE_REGSIMULT_INJECSIMULT) @@ -335,7 +332,11 @@ STATIC void adc_config_channel(ADC_HandleTypeDef *adc_handle, uint32_t channel) #if defined(STM32F0) sConfig.SamplingTime = ADC_SAMPLETIME_55CYCLES_5; #elif defined(STM32F4) || defined(STM32F7) - sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES; + if (__HAL_ADC_IS_CHANNEL_INTERNAL(channel)) { + sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES; + } else { + sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES; + } #elif defined(STM32H7) if (__HAL_ADC_IS_CHANNEL_INTERNAL(channel)) { sConfig.SamplingTime = ADC_SAMPLETIME_810CYCLES_5; @@ -370,8 +371,8 @@ STATIC void adc_config_channel(ADC_HandleTypeDef *adc_handle, uint32_t channel) STATIC uint32_t adc_read_channel(ADC_HandleTypeDef *adcHandle) { HAL_ADC_Start(adcHandle); - adc_wait_for_eoc_or_timeout(EOC_TIMEOUT); - uint32_t value = ADCx->DR; + adc_wait_for_eoc_or_timeout(adcHandle, EOC_TIMEOUT); + uint32_t value = adcHandle->Instance->DR; HAL_ADC_Stop(adcHandle); return value; } @@ -529,19 +530,19 @@ STATIC mp_obj_t adc_read_timed(mp_obj_t self_in, mp_obj_t buf_in, mp_obj_t freq_ } else { // for subsequent samples we can just set the "start sample" bit #if defined(STM32F4) || defined(STM32F7) - ADCx->CR2 |= (uint32_t)ADC_CR2_SWSTART; + self->handle.Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART; #elif defined(STM32F0) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) - SET_BIT(ADCx->CR, ADC_CR_ADSTART); + SET_BIT(self->handle.Instance->CR, ADC_CR_ADSTART); #else #error Unsupported processor #endif } // wait for sample to complete - adc_wait_for_eoc_or_timeout(EOC_TIMEOUT); + adc_wait_for_eoc_or_timeout(&self->handle, EOC_TIMEOUT); // read value - uint value = ADCx->DR; + uint value = self->handle.Instance->DR; // store value in buffer if (typesize == 1) { @@ -608,9 +609,9 @@ STATIC mp_obj_t adc_read_timed_multi(mp_obj_t adc_array_in, mp_obj_t buf_array_i adc_config_channel(&adc0->handle, adc0->channel); HAL_ADC_Start(&adc0->handle); // Wait for sample to complete and discard - adc_wait_for_eoc_or_timeout(EOC_TIMEOUT); + adc_wait_for_eoc_or_timeout(&adc0->handle, EOC_TIMEOUT); // Read (and discard) value - uint value = ADCx->DR; + uint value = adc0->handle.Instance->DR; // Ensure first sample is on a timer tick __HAL_TIM_CLEAR_FLAG(tim, TIM_FLAG_UPDATE); @@ -639,17 +640,17 @@ STATIC mp_obj_t adc_read_timed_multi(mp_obj_t adc_array_in, mp_obj_t buf_array_i // for the first sample we need to turn the ADC on // ADC is started: set the "start sample" bit #if defined(STM32F4) || defined(STM32F7) - ADCx->CR2 |= (uint32_t)ADC_CR2_SWSTART; + adc->handle.Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART; #elif defined(STM32F0) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) - SET_BIT(ADCx->CR, ADC_CR_ADSTART); + SET_BIT(adc->handle.Instance->CR, ADC_CR_ADSTART); #else #error Unsupported processor #endif // wait for sample to complete - adc_wait_for_eoc_or_timeout(EOC_TIMEOUT); + adc_wait_for_eoc_or_timeout(&adc->handle, EOC_TIMEOUT); // read value - value = ADCx->DR; + value = adc->handle.Instance->DR; // store values in buffer if (typesize == 1) { @@ -723,13 +724,24 @@ void adc_init_all(pyb_adc_all_obj_t *adc_all, uint32_t resolution, uint32_t en_m if (en_mask & (1 << channel)) { // Channels 0-16 correspond to real pins. Configure the GPIO pin in // ADC mode. + #if defined(STM32H7) + const pin_obj_t *pin = pin_adc3[channel]; + #else const pin_obj_t *pin = pin_adc_table[channel]; + #endif if (pin) { mp_hal_pin_config(pin, MP_HAL_PIN_MODE_ADC, MP_HAL_PIN_PULL_NONE, 0); } } } + #if defined(STM32H7) + // On the H7 the internal channels are connected to ADC3. To read internal channels + // with ADCAll, ADC3 must be used here, and ADC12 is used to read the GPIO channels. + adc_all->handle.Instance = ADC3; + #else + adc_all->handle.Instance = ADCx; + #endif adcx_init_periph(&adc_all->handle, resolution); }