cancel
Showing results for 
Search instead for 
Did you mean: 

On RX Framing error, UART_DMAAbortOnError can corrupts ongoing TX transfer resulting in 65536 bytes transfered. HAL bug ?

NSAUG.1
Associate III

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

0 REPLIES 0