Skip to main content
Visitor II
October 15, 2020
Question

ADC_Enable in stm32l4xx_hal_adc.c return with HAL_ERROR

  • October 15, 2020
  • 8 replies
  • 3134 views

Hi

When calling HAL_ADC_Start, ADC_Enable returns with error due to timeout.

The timeout set by the HAL is 2ms (ADC_ENABLE_TIMEOUT)

I'm using the STM32L496 with MSI @1Mhz.

I'm using the HAL with FreeRTOS, and there are several tasks running.

There is more than 1 task using the ADC but on different ports (ADC1/ADC2/ADC3) and different channels.

Once in a while during one of the measurements the timeout occurs.

Increasing the timeout solved the issue.

Any idea why this is happening.

Obviously a task context switch happens, prolonging the time this function is out of context thus making it reach the timeout.

These are the relevant lines of code:

  /* Enable the ADC peripheral */

  LL_ADC_Enable(hadc->Instance);

  /* Wait for ADC effectively enabled */

  tickstart = HAL_GetTick();

  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)

   {

    /* 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;

   }

  }

 }

    This topic has been closed for replies.

    8 replies

    Super User
    October 15, 2020

    If a context switch happens, takes >2ms, and returns just prior to the timeout check, it is going to timeout. It will do so before __HAL_ADC_GET_FLAG(hadc, ADC_FLAG_RDY) is checked again.

    If you need to delay 4 ADC clock cycles, seems like there is a better solution for how to handle this. Just a 1ms hard delay should solve it.

    deckhardAuthor
    Visitor II
    October 18, 2020

    The delay will increase sampling time.

    Is there a better solution?

    deckhardAuthor
    Visitor II
    October 15, 2020

    Your suggestion is to add HAL_Delay(1) before calling HAL_ADC_Start?

    Or to change the HAL code and placing it before

     __HAL_ADC_GET_FLAG(hadc, ADC_FLAG_RDY) is checked ?

    Thanks!

    Super User
    October 15, 2020

    > Your suggestion is to add HAL_Delay(1) before calling HAL_ADC_Start?

    Place the delay after calibration but before enabling the ADC. I assume that's right before the code you posted. Since this will take more than 4 ADC ticks, the workaround you're using is no longer needed and the timeout problem is avoided.

    deckhardAuthor
    Visitor II
    October 15, 2020

    Where exactly ?

    The calibration is done in HAL_ADC_Init right?

    The problem is that I allways call HAL_ADC_Start with every sampling I do, thus calling ADC_Enable each time.

    Adding a 1 ms delay will increase the sampling time..

    Super User
    October 16, 2020

    Hmm, calibration is a separate step, by HAL_ADCEx_Calibration_Start. It's not done in HAL_ADC_Init. If you're not calibrating, I'm not sure what the issue is. Perhaps separate threads are trying to use the same ADC, although I know you said that isn't the case.

    deckhardAuthor
    Visitor II
    October 16, 2020

    Yea sure I call HAL_ADCEx_Calibration_Start right before HAL_ADC_Start.

    So I should place the delay in between?

    As I said, It will increase the sampling time...isn't there a better solution in your opinion?

    I understand that just increasing the timeout is not good enough because eventually a higher priority thread can always starve the ADC sampling thread causing it to timeout.

    Super User
    October 18, 2020

    The code you posted is within HAL, so I understand why it can't be changed. It's unfortunate they've put that workaround in there. You can ignore my advice about adding a delay.

    I also see that the ADC_ENABLE_TIMEOUT value is hard-coded to 2ms within HAL.

    One solution would be to prevent task switching during the call to HAL_ADC_Start. Not ideal, but it seems like it would prevent the issue. Could be wrong.

    deckhardAuthor
    Visitor II
    October 18, 2020

    Looks like increasing ADC_ENABLE_TIMEOUT is the better solution isn’t it?

    I don’t like changing Hal code but what about deleting that timeout workaround they’ve put there?

    What could be the implications of doing that?

    thanks again.