cancel
Showing results for 
Search instead for 
Did you mean: 

Syncing USART/DMA RX

petereckstrand9
Associate II
Posted on May 20, 2013 at 22:38

I am using a STM32F407 and have set it up for using USART with DMA. 

I have some problems with the RX part. What is the best way to sync the enabling of the RX DMA with the remote transmitter? 

If I enable it in the middle of a transmission, only part of the message will fill the buffer and I will get the TC interrupt during transmission of next message. 

Or if I enable it when the transmitter is idle but some garbage is clocked in, for instance a break symbol when the transmitter is reset, I will get one byte offset in my buffer and the interrupt will fire too early.

What is the best way to tackle this? 

#usart-dma #stm32f4-dma-usart
3 REPLIES 3
Posted on May 20, 2013 at 22:59

I would be tempted to turn the thing on it's head, use a circular DMA buffer, pull content via HT/TC, and have a timeout, along with a protocol that was robust to resynching. ie had some preamble and structure.

I'd imagine you could set up the DMA transfer ahead of time, and then engage USART_DMACmd(USARTx, USART_DMAReq_Rx, ENABLE); when RXNE was clear, or wait for the first byte via an RXNE interrupt and then light off the remainder.

Can you describe the protocol interaction that elicits the received data?

From: frank bolatoli / peter eckstrand

Posted: Monday, May 20, 2013 10:38 PM

Subject: Syncing USART/DMA RX

I am using a STM32F407 and have set it up for using USART with DMA. 

I have some problems with the RX part. What is the best way to sync the enabling of the RX DMA with the remote transmitter? 

If I enable it in the middle of a transmission, only part of the message will fill the buffer and I will get the TC interrupt during transmission of next message. 

Or if I enable it when the transmitter is idle but some garbage is clocked in, for instance a break symbol when the transmitter is reset, I will get one byte offset in my buffer and the interrupt will fire too early.

What is the best way to tackle this? 
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
petereckstrand9
Associate II
Posted on May 20, 2013 at 23:41

Thank you Clive.

It is a Master-slave link in which the master sends a request and the slave sends a response.

The syncronization on the master side is easier as it enables the RX dma when the TX has finished. 

Your solution is fine, but I think there are a chance of delays before a complete request could be assembled. Let's say some garbage data has arrived first. Part of a message will be pulled in with HT/TC, and the remaining part will start to be transferred by DMA to the receive buffer but it may be too few bytes to trigger a HT/TC. We then have to wait till the next request transmission. Or is it possible to use the timeout to examine the buffer to see if we have a complete message?

jpeacock2399
Associate II
Posted on May 21, 2013 at 21:43

One solution would be to buffer everything on RX into a circular buffer, and then look for framing characters around your response.  That guarantees you receive an entire message.

If there's no framing then it gets complicated.  Set up a circular buffer with room for two messages and let it run constantly.  At the end of TX look at where the RX NDTR register is.  That's your frame mark for the start of the incoming message.  You'll have to adjust for buffer wrap.

Since you don't have a clean RX you can't count on the TC interrupt.  You'll have to use timers to periodically poll the RX NDTR to determine if your message has arrived.  If you know the length and transmission rate you should be able to get close to when it should finish before polling.

Another solution (for point to point) is to simply use the hardware handshaking pins between the two ports.  Assert RTS when you are ready to receive, deassert when the message arrives.  Tie the RTS to the CTS on the other side, and vice versa.  The USART does the flow control in hardware.  USART TX will automatically stall until the other side is ready to receive.

The clean solution is to tie the serial RX input to a timer capture pin.  Set up the timer to reset whenver a capture occurs.  Load the timer with twice the maximum time between characters in the message.  When the timer overflows that's an inter-message idle gap that frames your message.  The Modbus serial protocol in binary mode works this way to frame messages.  I use it for high speed RS-485 RX DMA with variable length messages.  But it requires a hardware change, allocating a timer that supports capture reset (I use TIM9).

  Jack Peacock