cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 Uart Overrun

yairyamin
Associate

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

11 REPLIES 11

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.

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.

For reception I recommend using DMA and a circular buffer.

Kudo posts if you have the same problem and kudo replies if the solution works.
Click "Accept as Solution" if a reply solved your problem. If no solution was posted please answer with your own.

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

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

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.

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 

 


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

Kudo posts if you have the same problem and kudo replies if the solution works.
Click "Accept as Solution" if a reply solved your problem. If no solution was posted please answer with your own.

@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

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.

thanks for the advice i remove the while in HAL_UART_RxCpltCallback

 

but i not see any changes 

i attached some screenshots 


@yairyamin wrote:

i not see any changes 


The trouble is, you have no synchronisation between your sender and your receiver.

When you start your receiver, you have no idea where that happens relative to what the sender is sending

So you might catch the start of a transmission (if you're very lucky), but most likely will start somewhere in the middle of a transmission.

Having started out-of-sync, you have no way to get back into sync.

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.

@Andrew Neil wrote:

@yairyamin wrote:

i not see any changes 


The trouble is, you have no synchronisation between your sender and your receiver.

When you start your receiver, you have no idea where that happens relative to what the sender is sending

So you might catch the start of a transmission (if you're very lucky), but most likely will start somewhere in the middle of a transmission.

Having started out-of-sync, you have no way to get back into sync.


Exactly. I wrote about this before:
https://community.st.com/t5/stm32-mcus-boards-and-hardware/extra-character-in-uart-rx-buffer/m-p/777243/highlight/true#M24441

There several ways to achieve synchronization:

1) Timing based. Bytes within a packet have a maximum allowed delay between them and packets have a minimum required delay between them.
By using a receive timeout function you can detect if a packet is received. Most MCUs have some type of interrupt for this.
Can be combined with DMA to write it to a buffer.
You can use a circular buffer to constantly receive data.
2) Software flow control or delimiter based. Use some type of delimiter character. If this character is in the data it needs to be escaped.
If the escape character is in the data it needs to be escaped too. Receiving requires a finite state machine to detect start and end of messages.
Can be combined with DMA to write it to a buffer. You can use a circular buffer to constantly receive data.
3) Hardware flow control using extra datalines. RS232 has signals for this (CTS/RTS). I never used this.

It is also recommended to use some type of crc to check the integrity of the packet.
Kudo posts if you have the same problem and kudo replies if the solution works.
Click "Accept as Solution" if a reply solved your problem. If no solution was posted please answer with your own.