cancel
Showing results for 
Search instead for 
Did you mean: 

H7/CubeMX critical bugs with LL and ADC3

Wolfgang Pupp
Associate III

ADC3 is broken when using the LL interface.

1) This is because it gets initialized with invalid resolution bits:

CubeMX currently generates:

   ADC_InitStruct.Resolution  = LL_ADC_RESOLUTION_12B;

   ADC_InitStruct.LowPowerMode = LL_ADC_LP_MODE_NONE;

   LL_ADC_Init(ADC3, &ADC_InitStruct);

But this needs to be:

  ADC_InitStruct.Resolution  = __LL_ADC12_RESOLUTION_TO_ADC3(LL_ADC_RESOLUTION_12B);

This results in bogus values.

2) Initialization delay is broken:

   uint32_t wait_loop_index;

   wait_loop_index = ((LL_ADC_DELAY_INTERNAL_REGUL_STAB_US * (SystemCoreClock / (100000 * 2))) / 10);

   while (wait_loop_index != 0) {

      wait_loop_index--;

   }

This is because the whole wait loop is doing exactly nothing and there is no reason for the compiler to not optimize it out. This can be easily fixed by declaring the loop index as "volatile uint32_t wait_loop_index;".

Also note that this tends to block SIGNIFICANTLY longer than intended; with execution from RAM@550MHz I get ~110µs delay instead of 10µs (pipeline to blame?). Delay precision can be fixed by stuffing the loop body with NOPs, but thats kinda wasting instruction memory. IMO the nicest fix would be to turn the DWT block on, use the cycle counter for the delay and restore it to previous state after (maybe a "LL_Usleep(uint32_t usec)" also useable elsewhere?).

Workaround:

Manually fix these every time after generating code...

Affected:

STMCubeMX 6.3.0

STMCubeIDE 1.7.0

Both with HAL: STM32 H7 1.9.0

On: STM32H730 (TFBGA100 Package)

1 ACCEPTED SOLUTION

Accepted Solutions

Hello @Wolfgang Pupp​ ,

Thank you for providing more details, it helped me a lot to determine the problem.

You're absolutely right, for both issues reported! Issues appear only for LL project and not HAL, in fact:

  • For the first one, which is the missing Resolution Conversion for ADC3, so the expected LL code, as you already mentioned, should be :
ADC_InitStruct.Resolution = __LL_ADC12_RESOLUTION_TO_ADC3(__ADC_RESOLUTION__);

This problem does not occur for HAL project, as the resolution conversion will be automatically done through :

#elif defined(ADC_VER_V5_V90)
    if (hadc->Instance == ADC3)
    {
      tmpCFGR  = (ADC_CFGR_CONTINUOUS((uint32_t)hadc->Init.ContinuousConvMode)         |
                  hadc->Init.Overrun                                                     |
                  hadc->Init.DataAlign                                                   |
                  ((__LL_ADC12_RESOLUTION_TO_ADC3(hadc->Init.Resolution)  & (ADC_CFGR_RES_1 | ADC_CFGR_RES_0)) << 1UL)                                                   |
                  ADC_CFGR_REG_DISCONTINUOUS((uint32_t)hadc->Init.DiscontinuousConvMode));
    }
    else
    {
      tmpCFGR  = (ADC_CFGR_CONTINUOUS((uint32_t)hadc->Init.ContinuousConvMode)          |
                  hadc->Init.Overrun                                                    |
                  hadc->Init.Resolution                                                 |
                  ADC_CFGR_REG_DISCONTINUOUS((uint32_t)hadc->Init.DiscontinuousConvMode));
    }
 
#else
 
    if ((HAL_GetREVID() > REV_ID_Y) && (ADC_RESOLUTION_8B == hadc->Init.Resolution))
    {
      /* for STM32H7 silicon rev.B and above , ADC_CFGR_RES value for 8bits resolution is : b111 */
      tmpCFGR  = (ADC_CFGR_CONTINUOUS((uint32_t)hadc->Init.ContinuousConvMode)          |
                  hadc->Init.Overrun                                                    |
                  hadc->Init.Resolution | (ADC_CFGR_RES_1 | ADC_CFGR_RES_0)                |
                  ADC_CFGR_REG_DISCONTINUOUS((uint32_t)hadc->Init.DiscontinuousConvMode));
    }
    else
    {
 
      tmpCFGR  = (ADC_CFGR_CONTINUOUS((uint32_t)hadc->Init.ContinuousConvMode)          |
                  hadc->Init.Overrun                                                    |
                  hadc->Init.Resolution                                                 |
                  ADC_CFGR_REG_DISCONTINUOUS((uint32_t)hadc->Init.DiscontinuousConvMode));
    }

with

/* Update Configuration Register CFGR */
      MODIFY_REG(hadc->Instance->CFGR, ADC3_CFGR_FIELDS_1, tmpCFGR);
  • For the second one, yes, if the optimization will be done, so the regulator stabilization will not be completed, to avoid the optimization, the expected LL code should be:
 __IO uint32_t wait_loop_index;
  wait_loop_index = ((LL_ADC_DELAY_INTERNAL_REGUL_STAB_US * (SystemCoreClock / (100000 * 2))) / 10);
  while(wait_loop_index != 0)
  {
    wait_loop_index--;
  }

Also this problem does not occur with HAL project as the wait_loop_index was defined from the beginning as volatile in HAL_ADC_Init function.

Many thanks for bringing these issues to our attention, they will be fixed.

Khouloud

View solution in original post

3 REPLIES 3
Khouloud ZEMMELI
ST Employee

Hello @Wolfgang Pupp​ 

Thanks for your post,

Could you please share more details about the Part number used?

Khouloud

Wolfgang Pupp
Associate III

It's an STM32H730VBH (TFBGA100 Package) (also added info in main post)

Hello @Wolfgang Pupp​ ,

Thank you for providing more details, it helped me a lot to determine the problem.

You're absolutely right, for both issues reported! Issues appear only for LL project and not HAL, in fact:

  • For the first one, which is the missing Resolution Conversion for ADC3, so the expected LL code, as you already mentioned, should be :
ADC_InitStruct.Resolution = __LL_ADC12_RESOLUTION_TO_ADC3(__ADC_RESOLUTION__);

This problem does not occur for HAL project, as the resolution conversion will be automatically done through :

#elif defined(ADC_VER_V5_V90)
    if (hadc->Instance == ADC3)
    {
      tmpCFGR  = (ADC_CFGR_CONTINUOUS((uint32_t)hadc->Init.ContinuousConvMode)         |
                  hadc->Init.Overrun                                                     |
                  hadc->Init.DataAlign                                                   |
                  ((__LL_ADC12_RESOLUTION_TO_ADC3(hadc->Init.Resolution)  & (ADC_CFGR_RES_1 | ADC_CFGR_RES_0)) << 1UL)                                                   |
                  ADC_CFGR_REG_DISCONTINUOUS((uint32_t)hadc->Init.DiscontinuousConvMode));
    }
    else
    {
      tmpCFGR  = (ADC_CFGR_CONTINUOUS((uint32_t)hadc->Init.ContinuousConvMode)          |
                  hadc->Init.Overrun                                                    |
                  hadc->Init.Resolution                                                 |
                  ADC_CFGR_REG_DISCONTINUOUS((uint32_t)hadc->Init.DiscontinuousConvMode));
    }
 
#else
 
    if ((HAL_GetREVID() > REV_ID_Y) && (ADC_RESOLUTION_8B == hadc->Init.Resolution))
    {
      /* for STM32H7 silicon rev.B and above , ADC_CFGR_RES value for 8bits resolution is : b111 */
      tmpCFGR  = (ADC_CFGR_CONTINUOUS((uint32_t)hadc->Init.ContinuousConvMode)          |
                  hadc->Init.Overrun                                                    |
                  hadc->Init.Resolution | (ADC_CFGR_RES_1 | ADC_CFGR_RES_0)                |
                  ADC_CFGR_REG_DISCONTINUOUS((uint32_t)hadc->Init.DiscontinuousConvMode));
    }
    else
    {
 
      tmpCFGR  = (ADC_CFGR_CONTINUOUS((uint32_t)hadc->Init.ContinuousConvMode)          |
                  hadc->Init.Overrun                                                    |
                  hadc->Init.Resolution                                                 |
                  ADC_CFGR_REG_DISCONTINUOUS((uint32_t)hadc->Init.DiscontinuousConvMode));
    }

with

/* Update Configuration Register CFGR */
      MODIFY_REG(hadc->Instance->CFGR, ADC3_CFGR_FIELDS_1, tmpCFGR);
  • For the second one, yes, if the optimization will be done, so the regulator stabilization will not be completed, to avoid the optimization, the expected LL code should be:
 __IO uint32_t wait_loop_index;
  wait_loop_index = ((LL_ADC_DELAY_INTERNAL_REGUL_STAB_US * (SystemCoreClock / (100000 * 2))) / 10);
  while(wait_loop_index != 0)
  {
    wait_loop_index--;
  }

Also this problem does not occur with HAL project as the wait_loop_index was defined from the beginning as volatile in HAL_ADC_Init function.

Many thanks for bringing these issues to our attention, they will be fixed.

Khouloud