Skip to main content
Associate III
November 7, 2025
Question

UART3 overrun interrupt

  • November 7, 2025
  • 4 replies
  • 729 views

Hello,

It is the first time I am using STM32 and migrating my code from texas instruments controller using USART3. I want to receive data and then transmit data of different sizes. I get a problem that I see appears often but in my case I cannot see why it appears. I want to use USART on port C, PC4 = Tx and PC5 = Rx. I have a partner sending data via uart and I can see the data is on the Rx line but somehow it does not come to the buffer. I get to the interrupt handler and then Error callback. I am using the receive to Idle with interrupts when data is received. The first expected data is 10 bytes, my rx buffer is 1024 big and my rx buffer is defined , not NULL. I call the function for receive directly after my partner device is on and I have got the reply this device is on. The partner device is making 10 attempts to send the same data and without answer is shutting down. It starts sending shortly after it is on. 
My uart onfiguration is as follows:

 
 
handleUart3.Instance = USART3;
handleUart3.Init.BaudRate = 115200;
handleUart3.Init.WordLength = UART_WORDLENGTH_8B;
handleUart3.Init.StopBits = UART_STOPBITS_1;
handleUart3.Init.Parity = UART_PARITY_NONE;
handleUart3.Init.Mode = UART_MODE_TX_RX;
handleUart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
handleUart3.Init.OverSampling = UART_OVERSAMPLING_16;
handleUart3.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
handleUart3.Init.ClockPrescaler = UART_PRESCALER_DIV1;
handleUart3.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&handleUart3) != HAL_OK)
{
 Error_Handler();
}

if (HAL_UARTEx_SetTxFifoThreshold(&handleUart3, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
 Error_Handler();
}

if (HAL_UARTEx_SetRxFifoThreshold(&handleUart3, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
 Error_Handler();
}

if (HAL_UARTEx_DisableFifoMode(&handleUart3) != HAL_OK)
{
 Error_Handler();
}

HAL_NVIC_SetPriority(USART3_IRQn, 3, 0);
HAL_NVIC_EnableIRQ(USART3_IRQn);
__HAL_UART_CLEAR_FEFLAG(&handleUart3);
__HAL_UART_CLEAR_NEFLAG(&handleUart3);
__HAL_UART_CLEAR_OREFLAG(&handleUart3);

 


Then all I do is call the receive function and wait for interrupts

uint8 *uartRxBuf; // pointing to a buffer that is created for this communication handler, uint8 * const buffPtr
HAL_UARTEx_ReceiveToIdle_IT(handleUart3, uartRxBuf, 1024);

Then the code somes here 

void USART3_IRQHandler(void)
{
 HAL_UART_IRQHandler(&handleUart3);
}


and eventually HAL_UART_ErrorCallback()

Do you have any tips how to debug more and what can go wrong?


Edited to apply source code formatting - please see How to insert source code for future reference.

4 replies

TDK
Super User
November 7, 2025

After 10 bytes, the 1024 byte buffer isn't even half full so not callbacks are triggered. Same thing after 100 bytes (10 tries).

If you want to handle each burst of data, consider using HAL_UARTEx_ReceiveToIdle_IT instead and using the HAL_UARTEx_RxEventCallback callback to process things on the idle/HT/TC interrupts.

If HAL_UART_ErrorCallback gets called, look at the flags in the uart handle to understand why.

"If you feel a post has answered your question, please click ""Accept as Solution""."
GTanovaAuthor
Associate III
November 7, 2025

Sorry, I did not get it. I am using this same function already. I have the Rx extended callback as well but the code never gets there. Only the error callback gets reached. I can see the USART_ISR_ORE and USART_CR1_RXNEIE_RXFNEIE are set in the handler. 
I clear the interrupts before calling the receive function like this:

 if (isr & USART_ISR_FE) __HAL_UART_CLEAR_FEFLAG(&handleUart3);
 if (isr & USART_ISR_NE) __HAL_UART_CLEAR_NEFLAG(&handleUart3);
 if (isr & USART_ISR_ORE) __HAL_UART_CLEAR_OREFLAG(&handleUart3);
 if (isr & (USART_ISR_RXNE_RXFNE)) (void)&handleUart3.Instance->RDR;

 

Technical Moderator
November 7, 2025

Hello @GTanova 

What is the flag that trigger the error callback and what is the error code you are getting?  

"To give better visibility on the answered topics, please click on ""Accept as Solution"" on the reply which solved your issue or answered your question.Saket_Om"
Pavel A.
Super User
November 7, 2025

Yes the RX overrun error is notorious. It can occur when the other side sends while you're initializing the UART and something gets received before you begin reading. Just clear it ASAP and keep running.

 

gbm
Principal
November 7, 2025

Actually RX overrun lies in the very nature of HAL.

I wrote firmware for hundreds of MCU devices with UART communication. HAL UART stuff isn't suitable for anything  - it has no right to work for any slave device, so for me it is not usable. I believe the concept of enabling reception more than once is simply ill. The only thing really needed for data reception is "byte received" callback with no need/requirement of enabling reception in it or anywhere else. I believe HAL2 should introduce this alternate (and, at least for me - the only reliable) model of UART reception.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice
GTanovaAuthor
Associate III
November 10, 2025

Thank you for the answer. Is there a HAL2 library? if so where can I find it?

Guenael Cadier
ST Employee
November 10, 2025

hi @GTanova 

HAL_UARTEx_ReceiveToIdle_IT(handleUart3, uartRxBuf, 1024);

should behave as follows :
- if 10 bytes are received, and a "pause" (i.e. Idle event) occurs on the rx line, then reception stops and HAL_UARTEx_RxEventCallback callback is called with nb of received data in parameter.

- if the transmitter starts again sending data to your device, and your want to receive those data, you need to restart a new reception process by calling again HAL_UARTEx_ReceiveToIdle_IT();

In order to get rid of sync issues between transmitter and receiver, you could clear error flags, just before calling ReceptionToIdle API. Please also make sure that time needed for execution of HAL_UARTEx_RxEventCallback callback is not too long, as it could lead to overrun error in an it based process.
You could also have a look to HAL_UARTEx_ReceiveToIdle_DMA() API, with a circular buffer that could be interesting for endless reception loop.
An example is available in U5 FW package here.
Regards

 

 

Pavel A.
Super User
November 10, 2025

@Guenael Cadier IMHO in HAL2 ST could add a new function similar to "continuous receiver" in the Microsoft's WDF.

This functionality already exists in HAL_UART_Receive_DMA() with circular buffer mode, but is badly lacking in simple interrupt mode. As noted by @unknown  it can yield data byte-by byte, or (with FIFO) by small bursts. It should use RTO instead of "idle" event whenever possible.  It should run continuously, without disabling U(S)ART interrupts, until stopped by user. If overrun occurs, call the error handler, clear and continue.