Skip to main content
Graduate
November 7, 2025
Question

UART3 overrun interrupt

  • November 7, 2025
  • 4 replies
  • 727 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.

    This topic has been closed for replies.

    4 replies

    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.

    GTanovaAuthor
    Graduate
    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?  

    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.

     

    Graduate
    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.

    GTanovaAuthor
    Graduate
    November 10, 2025

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

    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

     

     

    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 @Bermingham  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.