cancel
Showing results for 
Search instead for 
Did you mean: 

UART in full duplex missing bytes

machinist
Associate III

Hello,

I have an application where I transfer data to and from a PC with a FT232R and a UART. There is data beeing transfered back and foth constantly and asynchrone to another, so it is sending and receiveing at any random time and simultaneously. Sending and receiving is done by interrupt and use the same interrupt (checking in the interrupt which flag is active). I noticed that there was something wrong and toggled a pin each time the UART reived a byte. The problem is that it occaseonly misses some single bytes. This is when there are several hundred bytes transmitted to the STM32 at the maximum rate without delay between the bytes. Generally the UART is supposed to be fullduplex. The interrupt routine is shorter than a byte. So maybe the sending and receiving on the same interrupt is causing this.

I wondered now if it is possible to send the bytes not by interrupt but by using a DMA with a DMA finished interrupt while receiving the bytes with the UART interrupt? It seems strange as the USRT interrupt is the second highes priority with the highes only active for very short times (much less than one byte length). So it should fire after the other one is done. But the byte is missed completely.

So how is the "normal" way to acheive sending and receiving at high rates over the full duplex UART (I got FIFOs for both directions)? I thought it was quite straight forward.

Edit: Is it possible to use two DMA for transmitting and receiving at the same time on the UART?

8 REPLIES 8
Guenael Cadier
ST Employee

Dear @machinist​ 

Yes UART transfer could be used for simultaneously send/receive data to/from your PC.

HAL UART API using DMA are :

  • HAL_UART_Transmit_DMA()
  • HAL_UART_Receive_DMA()

I don't know what STM32 serie you are using, but there are some HAL UART examples that show this behavior.

Please try to have a look at Examples\UART\UART_HyperTerminal_DMA or Examples\UART\UART_TwoBoards_ComDMA examples, if available in your STM32Cube FW package.

Regards

Which STM32? What baudrate, what system clock?

> Sending and receiving is done by interrupt and use the same interrupt (checking in the interrupt which flag is active).

Show your code, together with the pin toggling you mentioned.

JW

machinist
Associate III

Thanks for the answers. It is working now using the TX DMA and a RX interrupt. Even at maximum byterates there are no misses.

it is some time ago you posted this,but i am running in the same issue. 

Were you receiving and sending single bytes in the continuous incoming stream, or were you able to buffer a couple of bytes and then send them with the dma transfer?

Could you share some of the code in the interrupt handler and tx function?

There are several approaches to DMA, you need to send from a long-term global buffer as the DMA can span many milliseconds.

I would stage to a buffer, if there is currently no active transaction you can light off that data immediately, if there is an active transaction, leave and let the completion call-back light off the next available block of data.

Managing as a ring buffer might be the most efficient, splitting the wrapping cases into two transactions.

Implementation is STM32 device/family specific, and not stated. The Cube repo's should have UART DMA examples for EVAL or DISCO boards, review.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

My code looks similar to the code in this post.

When I tx in main() , sometimes a byte is lost, the same as machinist posts in this thread, He mentioned that when he transmits in DMA mode, he had no problem. How can that be? 

The thing I can think of is that the dma doesn't generate the buffer transfer interrupt, but only the transfer complete interrupt. Could that cause issues when the rx interrupt is handled at the same time?

My uart interrupt handler, first handles the rx interrupt, and then checks with an if statement too if there is something to transmit, but that seems not to be done, but it also doesn't generate a new interrupt that handles the next tx. Perhaps the dma handles this better?

>> ..he had no problem. How can that be? 

That he had a different problem and not yours? You're projecting on to a three year old post here.

And you've not establish the cause, just matched a symptom.

Is it really failing to transmit the data? Are you getting any under/over flow errors?

Is it the RECEIVING end that's broken?

Can you use a Logic Analyzer, triggered by the observed failure, that shows the STM32 is not sending the correct data?

Using two stop bits might improve the ability to see the inter-symbol gap and resynchronize the byte frames on the wire.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

we put another rs485 monitor device on the line (from docklight) and that one is also reporting a missing byte

I converted my tx routine to use dma now, and the missing byte occurs there too

i don't see the breakpoint of one of the error flags being set: USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE when the byte is missing

I am lost, I might have to use two uarts: one for receiving , one for transmitting. 

Is the STM32F405 chip not working correctly, did I make a mistake in software? Are interrupts handled wrong?