2021-07-30 08:09 AM
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)
Solved! Go to Solution.
2021-08-09 06:36 AM
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:
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);
__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
2021-08-02 03:07 AM
Hello @Wolfgang Pupp
Thanks for your post,
Could you please share more details about the Part number used?
Khouloud
2021-08-02 03:57 AM
It's an STM32H730VBH (TFBGA100 Package) (also added info in main post)
2021-08-09 06:36 AM
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:
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);
__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