2021-11-27 02:22 PM
Hi,
I use STM32Cube_FW_WB_V1.12.1 on a STM32WB55, with generated init code and HAL functions.
I have setup a circular DMA for RX of UART1 and use HAL_UART_Transmit() when I need to send data.
I'm communicating with a device (GPS module) that can be configured at two different baud rates, so I have written code to try to talk to it alternatively at both baud rates until it responds something that the UART understands.
The problem is that upon raising a Frame Error on RX, HAL_UART_IRQHandler calls HAL_DMA_Abort_IT which in turn calls UART_DMAAbortOnError, which is implemented as below :
/**
* @brief DMA UART communication abort callback, when initiated by HAL services on Error
* (To be called at end of DMA Abort procedure following error occurrence).
* @param hdma DMA handle.
* @retval None
*/
static void UART_DMAAbortOnError(DMA_HandleTypeDef *hdma)
{
UART_HandleTypeDef *huart = (UART_HandleTypeDef *)(hdma->Parent);
huart->RxXferCount = 0U;
huart->TxXferCount = 0U;
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered error callback*/
huart->ErrorCallback(huart);
#else
/*Call legacy weak error callback*/
HAL_UART_ErrorCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
}
As you can see, TxXferCount is set to zero, evn though the original error only concerns RX...
And when this happens while HAL_UART_Transmit is ongoing, specifically in this snippet of that function :
while (huart->TxXferCount > 0U)
{
if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
{
return HAL_TIMEOUT;
}
if (pdata8bits == NULL)
{
huart->Instance->TDR = (uint16_t)(*pdata16bits & 0x01FFU);
pdata16bits++;
}
else
{
huart->Instance->TDR = (uint8_t)(*pdata8bits & 0xFFU);
pdata8bits++;
}
huart->TxXferCount--;
}
the result is TxXferCount going to zero just before being decremented, so it wraps around to 65536 (TxXferCount is volatile).
This obviously leads to a very wrong result of having about 1/3rd of the RAM of my chip transmitted.
This bug looks like a HAL bug to me.
The behavior I would have though normal here would have been to only reset the RxXferCount when the error concerns only RX.
Best,
Nicolas