2024-09-25 08:39 AM
STM32Cube FW_H7 V1.11.2
I previously posted an issue related to incorrect selection of the internal ADC paths on STM32H7 series (specifically I am using STM32H750). To work around the issue, I manually call LL_ADC_SetCommonPathInternalChAdd() as needed to enable the desired internal channel.
I discovered that calling this function immediately before a conversion can cause the ADC polling function to block waiting for the IRQ (See the relevant while loop excerpt below). It seems the IRQ flag is never raised and the Timeout value = 0xFFFFFFFF and so the timeout mechanism never triggers to exit the while loop.
HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef *hadc, uint32_t Timeout)
{
...
/* 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;
}
}
}
}
...
}
In the above case, ISR = 0x0000100B and tmp_Flag_End = 4, but the ISR bit 4 is never raised. Additionally, Timeout = 0xFFFFFFFF and, therefore, since it equals HAL_MAX_DELAY, the Timeout block is never entered and cannot break out of the while loop.
This issue happens intermittently. I suppose there is a race condition related to running the ADC clock asynchronously with a very fast CPU clock and changing the internal channel paths. I am running 240MHz CPU clock with 20 MHz (80/4 MHz) asynchronous ADC clock. I do not see this issue if I avoid changing the internal paths immediately before a conversion, or if I insert a delay (HAL_Delay(1)) after changing the internal path.
I noticed another forum post stating that the VBAT coin cell can be drained faster if the internal VBAT ADC path is left connected, so to reduce VBAT consumption I am enabling/disabling the internal VBAT path on demand. This means that I will always have a chance of blocking the firmware while waiting for VBAT conversion.
Can this issue be fixed in CubeMX FW? I have a use case where I need to enable/disable the internal path repeatedly at run time, but I prefer not to inject a blocking delay in the code base if it can be avoided.