cancel
Showing results for 
Search instead for 
Did you mean: 

How to use ADC with DMA on the STM32H7S78-DK

VPguy
Associate

Hi everyone,

I am currently trying to use the ADC with DMA on my STM32H7S78-DK. To do so, I am following this guide: https://community.st.com/t5/stm32-mcus/stm32h7r-s-how-to-configure-an-adc-dma-transfer-in-circular-mode/ta-p/737149

I've made little changes to the code compared to the guide. I am attaching my project.

 

The problem is that the program ends up in the Error_Handler() when the HAL_ADC_Start_DMA() (or the HAL_ADCEx_Calibration_Start()) function is executed.

During the execution of the HAL_ADC_Start_DMA(), the ADC_Enable() function returns HAL_ERROR:

      /* Enable the ADC peripheral */
      tmp_hal_status = ADC_Enable(hadc);

      /* Start conversion if ADC is effectively enabled */
      if (tmp_hal_status == HAL_OK)

Inside the ADC_Enable() function, the execution lead to this part (ADC_ENABLE_TIMEOUT limit reached):

      if ((HAL_GetTick() - tickstart) > ADC_ENABLE_TIMEOUT)
      {
        /* New check to avoid false timeout detection in case of preemption */
        if (__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_RDY) == 0UL)
        {
          /* Update ADC state machine to error */
          SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);

          /* Set ADC error code to ADC peripheral internal error */
          SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);

          return HAL_ERROR;
        }
      }

I am a bit new to STM32H7S programming and I don't understand why the ADC can't enable.

Do you have any idea ?

2 REPLIES 2
TDK
Super User

Debug the program. When it ends up in Error_Handler, show the stack trace.

 

Actually, step through HAL_ADCEx_Calibration_Start and find out the reason it's returning an error instead of HAL_OK.

If you feel a post has answered your question, please click "Accept as Solution".

How do I do to get the stack trace in STM32CubeIDE?

 

I put some breakpoints in HAL_ADCEx_Calibration_Start and the problem comes from the call to ADC_Enable.

Inside this loop, the program does not enter the first if and ends up in the second one after a certain time:

    while (__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_RDY) == 0UL)
    {
      /*  If ADEN bit is set less than 4 ADC clock cycles after the ADCAL bit
          has been cleared (after a calibration), ADEN bit is reset by the
          calibration logic.
          The workaround is to continue setting ADEN until ADRDY is becomes 1.
          Additionally, ADC_ENABLE_TIMEOUT is defined to encompass this
          4 ADC clock cycle duration */
      /* Note: Test of ADC enabled required due to hardware constraint to     */
      /*       not enable ADC if already enabled.                             */
      if (LL_ADC_IsEnabled(hadc->Instance) == 0UL)
      {
        LL_ADC_Enable(hadc->Instance);
      }

      if ((HAL_GetTick() - tickstart) > ADC_ENABLE_TIMEOUT)
      {
        /* New check to avoid false timeout detection in case of preemption */
        if (__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_RDY) == 0UL)
        {
          /* Update ADC state machine to error */
          SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);

          /* Set ADC error code to ADC peripheral internal error */
          SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);

          return HAL_ERROR;
        }
      }
    }

 Feel free to ask me for more details, I'm not sure if that's clear.