STMicroelectronics / stm32h7xx_hal_driver

Provides the STM32Cube MCU Component "hal_driver" of the STM32H7 series.
BSD 3-Clause "New" or "Revised" License
97 stars 41 forks source link

UART HAL driver - handle RX overrun condition #17

Closed pavel-a closed 1 year ago

pavel-a commented 2 years ago

It looks like receive overrun is not checked and not dismissed in HAL_UART_Receive(). RX data overrun would totally block the program, unless overrun is disabled (in Cube, as "advanced feature").

RX data ready is tested by UART_WaitOnFlagUntilTimeout https://github.com/STMicroelectronics/stm32h7xx_hal_driver/blob/3ba4eb3e14ec1d407c05f5af5665e0eae789bd0b/Src/stm32h7xx_hal_uart.c#L1258

which just spins until RXNE flag is set - but overrun and other errors prevent it from being set.

KORKAD commented 2 years ago

Hello @pavel-a ,

The UART errors aren't hundled when using blocking transfer mode and it is recommanded to use non blocking mode to avoid such kind of issues.

Here below the description from HAL UART driver:

(#) There are two mode of transfer:
   (+) Blocking mode: The communication is performed in polling mode.
       The HAL status of all data processing is returned by the same function
       after finishing transfer.
   (+) Non-Blocking mode: The communication is performed using Interrupts
       or DMA, These API's return the HAL status.
       The end of the data processing will be indicated through the
       dedicated UART IRQ when using Interrupt mode or the DMA IRQ when
       using DMA mode.
       The HAL_UART_TxCpltCallback(), HAL_UART_RxCpltCallback() user callbacks
       will be executed respectively at the end of the transmit or Receive process
       The HAL_UART_ErrorCallback()user callback will be executed when a communication error is detected
(#) Blocking mode API's are :
    (+) HAL_UART_Transmit()
    (+) HAL_UART_Receive()
(#) Non-Blocking mode API's with Interrupt are :
    (+) HAL_UART_Transmit_IT()
    (+) HAL_UART_Receive_IT()
    (+) HAL_UART_IRQHandler()
(#) Non-Blocking mode API's with DMA are :
    (+) HAL_UART_Transmit_DMA()
    (+) HAL_UART_Receive_DMA()
    (+) HAL_UART_DMAPause()
    (+) HAL_UART_DMAResume()
    (+) HAL_UART_DMAStop()
(#) A set of Transfer Complete Callbacks are provided in Non_Blocking mode:
    (+) HAL_UART_TxHalfCpltCallback()
    (+) HAL_UART_TxCpltCallback()
    (+) HAL_UART_RxHalfCpltCallback()
    (+) HAL_UART_RxCpltCallback()
    (+) HAL_UART_ErrorCallback()
(#) Non-Blocking mode transfers could be aborted using Abort API's :
    (+) HAL_UART_Abort()
    (+) HAL_UART_AbortTransmit()
    (+) HAL_UART_AbortReceive()
    (+) HAL_UART_Abort_IT()
    (+) HAL_UART_AbortTransmit_IT()
    (+) HAL_UART_AbortReceive_IT()     

.....

(#) In Non-Blocking mode transfers, possible errors are split into 2 categories.
    Errors are handled as follows :
   (+) Error is considered as Recoverable and non blocking : Transfer could go till end, but error severity is
       to be evaluated by user : this concerns Frame Error, Parity Error or Noise Error
       in Interrupt mode reception .
       Received character is then retrieved and stored in Rx buffer, Error code is set to allow user
       to identify error type, and HAL_UART_ErrorCallback() user callback is executed.
       Transfer is kept ongoing on UART side.
       If user wants to abort it, Abort services should be called by user.
   (+) Error is considered as Blocking : Transfer could not be completed properly and is aborted.
       This concerns Overrun Error In Interrupt mode reception and all errors in DMA mode.
       Error code is set to allow user to identify error type, and HAL_UART_ErrorCallback()
       user callback is executed.
stefanct commented 1 year ago

The same problem exists in the L4 driver too. As a minimal fix it would suffice to check and clear the ORE flag in HAL_UARTEx_ReceiveToIdle() and UART_WaitOnFlagUntilTimeout() and return HAL_ERROR. This is clearly an issue for many people (there is at least a dozen of reports around the internet that are most likely caused by this very bug that date back to at least 2016) and there is not the slightest hint in the documentation that this could happen.

I was in hope that this gets fixed after this issue has been triaged over a year ago. Can you please give us a progress report? Will it be fixed in the next release and is it tracked for other families (e.g., L4)?

ASELSTM commented 1 year ago

Hi @pavel-a, @stefanct,

The fix is now available as part of the latest release of the stm32h7xx_hal_driver.

Please allow me thus to close this thread.

With regards,