cancel
Showing results for 
Search instead for 
Did you mean: 

HAL UART Overrun causes it to never receive data again in normal and interrupt modes

EGi
Associate III

HAL_UART_Receive and HAL_UART_Receive_IT contain a bug. To reproduce (I use STM32L412KB nucleo 32 for this):

  • Connect a terminal emulator to the ST-LINK as serial port.
  • Configure that serial port in CubeIDE if default not chosen.
  • Use for example the following code:
  • HAL_StatusTypeDef uhst = HAL_UART_Receive (&huart2, uart_buffer, 1, 1);
  • if (uhst == HAL_OK) { /* store the single byte in a larger buffer */ }

If one runs the code, there seems to be no issue.

Put a breakpoint in the function that stores the UART data.

Type 1 char in the terminal: the debugger kicks in. The debugger stops the core but not the UART. Type a number of chars in the terminal, enough to cause UART overrun condition.

Resume the software from the breakpoint. Whatever you type from now in the terminal emulator, HAL will never report UART data available.

The easiest solution is to put a receiver timeout and when it happens call

__HAL_UART_CLEAR_OREFLAG(&huart2);

but this isn't a clean way. HAL implemenation should clear the overrun bit when set and return an error condition.

The same behavior occurs in real-time, if an UART overrun event triggers.

The correct behavior would be HAL to report (overrun) error while this bit is set in the UART status and clear it afterwards.

3 REPLIES 3
_alaBaster
Associate III

Hi @EGi,

I seem to be having a similar issue as You described few years back, that is:
- I cant read a second byte on UART2 with interrupt after a first. Interrupt seems disabled even though I am calling HAL_UART_Receive _IT

My issue is described here:
only 1 byte RS485 received on STM32L051 - STMicroelectronics Community

Could you remember how and if you found a solution to that?

Cheers

If you wrote your HAL_UART_Receive _IT like that link, then of course you're going to have issues. That code doesn't check the HAL status. You need to check HAL status to see if it returned HAL_BUSY.

If it does return HAL_BUSY, well that means the interrupt was not enabled and you'll never get another interrupt, ever.

You need to set a flag, exit the callback. In the main while loop check the flag and enable the UART interrupt again.

 

 

 

 

 

Tips and Tricks with TimerCallback https://www.youtube.com/@eebykarl
If you find my solution useful, please click the Accept as Solution so others see the solution.

HI @Karl Yamashita 

 good point on checking the return value of HAL_UART_Receive_IT.


What would you suggest to be doing in case of HAL_BUSY?

 

My issue was anyway sort of HW related and the basic code without HAL_BUSY check in first approximation works.

Cheers