Skip to main content
Visitor II
April 10, 2025
Solved

STM32 Uart Overrun

  • April 10, 2025
  • 2 replies
  • 3835 views

Hello every one .

this is my first post so excuse me if i do something wrong.

I try to establish Uart Asynchronous line between two stm32f303k8 .one of them use basic timer to send 8 byte uint buffer every 200 mili-sec and the other use HAL_UART_Receive_IT first in the "/* USER CODE BEGIN 2 */"

and circularly recall it again in HAL_UART_RxCpltCallback.

So my problem is that after the first reception i get overrun error and when i enable overrun in the CubeMX i see that after the first reception the first byte are the last byte of the previous message and all other bytes are shifted right .

**I attached image of   my  UART configuration (same for both of them)

Sender variables :

uint8_t m_tx_buffer[8] = {0};
uint8_t flag = 0;

 

 Sender while(1): 

 if (flag == 1)
 {
 flag = 0;
 HAL_UART_Transmit_IT(&huart1, m_tx_buffer, sizeof(m_tx_buffer));
 m_tx_buffer[5] ++;
 }

 

Receiver variables : 

volatile uint8_t s_rx_buffer[8] = {0};
uint8_t s_tx_buffer[8] = {0};
uint8_t flag = 0;

 

Receiver Callback :

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
 while(HAL_UART_GetState(huart) == HAL_UART_STATE_BUSY);
 memset(s_rx_buffer, 0, sizeof(s_rx_buffer));
 HAL_UART_Receive_IT(huart, s_rx_buffer, sizeof(s_rx_buffer));
}

 

I basically try everything, and it is not working. I try to move to DMA and i try to change the word length of the Uart I try to use slowing the sending of messages and try to see other's post on the internet. and i really not understanding how to fix that.


Source code formatting applied

    This topic has been closed for replies.
    Best answer by yairyamin

    thanks a lot i decide to change the Uart-rx to circular mode and the Tx remain in normal mode and it is fix the problem!!

    2 replies

    Super User
    April 10, 2025

    Welcome to the forum.

    For best results, please see: How to write your question to maximize your chances to find a solution.

    In particular: How to insert source code.

     


    @yairyamin wrote:

    I try to establish Uart Asynchronous line between two stm32f303k8


    It's best not to try to do both ends of the link at once - that gives you too many unknowns:

    https://community.st.com/t5/others-hardware-and-software/uart-comunication/m-p/768126/highlight/true#M30687

     

    A UART overrun indicates that you didn't retrieve previous received data before new data arrived.

    Probably, this means that your sender was sending before the receiver was ready.

    You haven't shown the part of your code where you get the receiver ready to receive

     

    PS:

    Having blocking delays within an interrupt handler is rarely a Good Thing:

    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    {
     while(HAL_UART_GetState(huart) == HAL_UART_STATE_BUSY);

     

    Please show the complete code for both sender & receiver.

    yairyaminAuthor
    Visitor II
    April 10, 2025

    thanks for the reply . what do you mean by "You haven't shown the part of your code where you get the receiver ready to receive

    do i need to add some steps in  HAL_UART_RxCpltCallback to make sure that the receiver ready to receive ?

     

    *** i Attached the code of both of them here 

     

    Super User
    April 10, 2025

    @yairyamin wrote:

    what do you mean by "You haven't shown the part of your code where you get the receiver ready to receive


    Thanks for the full listing - it's here:

     /* USER CODE BEGIN 2 */
     //HAL_TIM_Base_Start_IT(&htim6);
     for(int i=0; i<8; i++)
     {
     s_tx_buffer[i] = 0x02;
     }
    
     HAL_UART_Receive_IT(&huart1, s_rx_buffer, sizeof(s_rx_buffer));
     /* USER CODE END 2 */
    
     /* Infinite loop */

    So that initial HAL_UART_Receive_IT is what gets the receiver ready to receive.

    When that receive completes - ie, after filling the buffer - the interrupt will be generated, and the handler will be called.

    Thus, the handler is only called when the reception is all done - so this is not needed in the handler:

    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    {
     while(HAL_UART_GetState(huart) == HAL_UART_STATE_BUSY);

    By definition, when the handler is called,  the UART is not busy - it has finished the reception!

     

    Note that you don't need to manually code a for loop to fill a buffer - there's a standard C library function for that:

    memset( s_tx_buffer, 0, sizeof(s_tx_buffer) );

    https://en.cppreference.com/w/cpp/string/byte/memset

    Graduate II
    April 10, 2025

    For reception I recommend using DMA and a circular buffer.

    Super User
    April 10, 2025

    Don't you think that might be a bit advanced for a beginner?

    I'd suggest interrupts & a circular buffer first ...

    Graduate II
    April 10, 2025

    @Andrew Neil wrote:

    Don't you think that might be a bit advanced for a beginner?

    I'd suggest interrupts & a circular buffer first ...


    When I was a beginner with STM32 MCUs setting up the DMA was a bit tricky, but it saved me a lot of headaches with missing UART RX data. Linear buffer with DMA is simpler. If the TS is a beginner with MCUs in general I recommend interrupts first. But even interrupts can be tricky for a beginner.