Skip to main content
Explorer
March 1, 2025
Question

HAL_ADC_PollForConversion gets stuck

  • March 1, 2025
  • 7 replies
  • 2639 views

I'm writing software that involves reading a single ADC value from my STM32H7R3V8H6, however it is getting stuck in HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);.

If i switch the delay to a smaller value it runs through but it still returns a timeout.

while (1)
 {
		HAL_ADC_Start(&hadc1);
		HAL_ADC_PollForConversion(&hadc1, 100);
		adc1Data = HAL_ADC_GetValue(&hadc1);
		HAL_ADC_Stop(&hadc1);
		//readT(&engine, 0);
		//readP(&engine, 0);
 /* USER CODE END WHILE */

 /* USER CODE BEGIN 3 */
 }

static void MX_ADC1_Init(void)
{

 /* USER CODE BEGIN ADC1_Init 0 */

 /* USER CODE END ADC1_Init 0 */

 ADC_MultiModeTypeDef multimode = {0};
 ADC_ChannelConfTypeDef sConfig = {0};

 /* USER CODE BEGIN ADC1_Init 1 */

 /* USER CODE END ADC1_Init 1 */

 /** Common config
 */
 hadc1.Instance = ADC1;
 hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
 hadc1.Init.Resolution = ADC_RESOLUTION_12B;
 hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
 hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
 hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
 hadc1.Init.LowPowerAutoWait = DISABLE;
 hadc1.Init.ContinuousConvMode = DISABLE;
 hadc1.Init.NbrOfConversion = 1;
 hadc1.Init.DiscontinuousConvMode = DISABLE;
 hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
 hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
 hadc1.Init.SamplingMode = ADC_SAMPLING_MODE_NORMAL;
 hadc1.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR;
 hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
 hadc1.Init.OversamplingMode = DISABLE;
 if (HAL_ADC_Init(&hadc1) != HAL_OK)
 {
 Error_Handler();
 }

 /** Configure the ADC multi-mode
 */
 multimode.Mode = ADC_MODE_INDEPENDENT;
 if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
 {
 Error_Handler();
 }

 /** Configure Regular Channel
 */
 sConfig.Channel = ADC_CHANNEL_0;
 sConfig.Rank = ADC_REGULAR_RANK_1;
 sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
 sConfig.SingleDiff = ADC_SINGLE_ENDED;
 sConfig.OffsetNumber = ADC_OFFSET_NONE;
 sConfig.Offset = 0;
 sConfig.OffsetSign = ADC_OFFSET_SIGN_NEGATIVE;
 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN ADC1_Init 2 */

 /* USER CODE END ADC1_Init 2 */

}
    This topic has been closed for replies.

    7 replies

    Graduate II
    March 1, 2025

    HAL_MAX_DELAY = 49.7 Days! 

    So if you wait for almost 50 days, the function will eventually return.

    Typically 100ms is more than enough for a timeout.

     

    How do you know if it return a timeout? You're not checking the return value.

    HAL_StatusTypeDef hal_status = HAL_ADC_PollForConversion(&hadc1, 100);
    	if(hal_status == HAL_ERROR)
    	{
    		// error handler
    	}
    	else if(hal_status == HAL_TIMEOUT)
    	{
    		// timeout handler
    	}
    	// get adc value

     

    dfsheaAuthor
    Explorer
    March 1, 2025

    Hm, 50 days is a bit much to see if it times out, so I reduced the delay to 100ms and added a return variable and confirmed that it is indeed returning HAL_TIMEOUT. 

     

    I also did some digging and found where in the function it's getting stuck:

     tickstart = HAL_GetTick();
    
     /* Wait until End of unitary conversion or sequence conversions flag is raised */
     while ((hadc->Instance->ISR & tmp_Flag_End) == 0UL)
     {
     /* Check if timeout is disabled (set to infinite wait) */
     if (Timeout != HAL_MAX_DELAY)
     {
     if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0UL))
     {
     /* New check to avoid false timeout detection in case of preemption */
     if ((hadc->Instance->ISR & tmp_Flag_End) == 0UL)
     {
     /* Update ADC state machine to timeout */
     SET_BIT(hadc->State, HAL_ADC_STATE_TIMEOUT);
    
     /* Process unlocked */
     __HAL_UNLOCK(hadc);
    
     return HAL_TIMEOUT;
     }
     }
     }
     }

    dfshea_0-1740800326794.png

     

    Graduate II
    March 4, 2025

    What's your definition of stuck? Because if you return a timeout, then how can it be stuck?

    Technical Moderator
    March 4, 2025

    Hello @dfshea 

    Did you confirm an ADC calibration before starting the conversion please? 

    Did you check to compare your implementation with the example below?

     Projects/NUCLEO-H7S3L8/Examples/ADC/ADC_SingleConversion_TriggerSW

    dfsheaAuthor
    Explorer
    March 4, 2025

    @Saket_Om, I forgot to do the calibration, I wasn't sure if it was necessary or not. However I just tried doing the calibration and it gets stuck there as well. It gets stuck in this loop:

    while (LL_ADC_IsCalibrationOnGoing(hadc->Instance) != 0UL)
     {
     wait_loop_index++;
     if (wait_loop_index >= ADC_CALIBRATION_TIMEOUT)
     {
     /* Update ADC state machine to error */
     ADC_STATE_CLR_SET(hadc->State,
     HAL_ADC_STATE_BUSY_INTERNAL,
     HAL_ADC_STATE_ERROR_INTERNAL);
    
     /* Process unlocked */
     __HAL_UNLOCK(hadc);
    
     return HAL_ERROR;
     }
     }
    Graduate
    March 4, 2025

    Where is the code that enables the ADC peripheral clock?

    Are your ADC configuration registers all zeroes? 

    dfsheaAuthor
    Explorer
    March 4, 2025

    @Chris21 It's this code here right? (I could be wrong, this was autogenerated)

    static void MX_ADC1_Init(void)
    {
    
     /* USER CODE BEGIN ADC1_Init 0 */
    
     /* USER CODE END ADC1_Init 0 */
    
     ADC_MultiModeTypeDef multimode = {0};
     ADC_ChannelConfTypeDef sConfig = {0};
    
     /* USER CODE BEGIN ADC1_Init 1 */
    
     /* USER CODE END ADC1_Init 1 */
    
     /** Common config
     */
     hadc1.Instance = ADC1;
     hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
     hadc1.Init.Resolution = ADC_RESOLUTION_12B;
     hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
     hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
     hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
     hadc1.Init.LowPowerAutoWait = DISABLE;
     hadc1.Init.ContinuousConvMode = DISABLE;
     hadc1.Init.NbrOfConversion = 1;
     hadc1.Init.DiscontinuousConvMode = DISABLE;
     hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
     hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
     hadc1.Init.SamplingMode = ADC_SAMPLING_MODE_NORMAL;
     hadc1.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR;
     hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
     hadc1.Init.OversamplingMode = DISABLE;
     if (HAL_ADC_Init(&hadc1) != HAL_OK)
     {
     Error_Handler();
     }
    
     /** Configure the ADC multi-mode
     */
     multimode.Mode = ADC_MODE_INDEPENDENT;
     if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
     {
     Error_Handler();
     }
    
     /** Configure Regular Channel
     */
     sConfig.Channel = ADC_CHANNEL_0;
     sConfig.Rank = ADC_REGULAR_RANK_1;
     sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5;
     sConfig.SingleDiff = ADC_SINGLE_ENDED;
     sConfig.OffsetNumber = ADC_OFFSET_NONE;
     sConfig.Offset = 0;
     sConfig.OffsetSign = ADC_OFFSET_SIGN_NEGATIVE;
     if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
     {
     Error_Handler();
     }
     /* USER CODE BEGIN ADC1_Init 2 */
    
     /* USER CODE END ADC1_Init 2 */
    
    }
    Graduate II
    March 4, 2025

    The ADC clock is enable from calling  MX_ADC1_Init>HAL_ADC_Init>HAL_ADC_MspInit

    Graduate
    March 4, 2025

    Somewhere you need something like:

     


    /* Peripheral clock enable */
    __HAL_RCC_ADC_CLK_ENABLE();

     

    Also GPIO pins configured for analog mode.

    dfsheaAuthor
    Explorer
    March 4, 2025

    I confirmed the pins are in analog mode. And this may be a foolish question but when I try to call __HAL_RCC_ADC_CLK_ENABLE() it says there is an undefined reference to it. Is there another HAL library I need to include in the main.c file? Thank you again for your help!

    Graduate
    March 4, 2025

    Looks like the H7 is a bit different as far as the ADC Clock, it's set in RCC domain 3 kernel clock configuration register (RCC_D3CCIPR):

    Chris21_0-1741127127185.png

     

    Chris21_1-1741127166620.png