cancel
Showing results for 
Search instead for 
Did you mean: 

ADC_Enable in stm32l4xx_hal_adc.c return with HAL_ERROR

deckhard
Associate III

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;

   }

  }

 }

9 REPLIES 9
TDK
Guru

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.

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

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!

TDK
Guru

> 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.

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

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..

TDK
Guru

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.

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

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.

The delay will increase sampling time.

Is there a better solution?

TDK
Guru

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.

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

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.