2012-01-24 08:15 AM
Hi All,
I would like to use DMA to service a UART that I am implementing (RX and TX). My project has 2 bi-directional data ports (including the UART) which have different data rates (up to 512kbps). I have to use hardware flow control on the UART (both RX and TX). Is this possible with the DMA method? I have read through AN3109 and looked at the attached example code, but all examples have the hardware flow control set to ''..._NONE''. Thanks in advance, Charlie #dma #uart-flow-control #usart2012-01-24 09:59 AM
It's an easy enough flag to enable, have you evaluated it, or flow control in a polled USART?
The DMA is paced by the RXNE/TXE flags on the USART, so if the USART stops sending/receiving the DMA will stall. The servicing of the USART is likely to be far more aggressive than a polled/interrupt solution. You'd have to check when the CTS/RTS pins are sampled. Also check the errata, at least one of the CTS/RTS pairs conflicts with a CAN controller, at least on the F103.2012-01-24 10:48 AM
Hey Clive,
Thanks for the reply. I'm in the design stage for the section of the project so no in depth evaluation yet. It is the F103 part that I'm using so I'll check the Errata - thanks for the tip! I am running an OS which is fairly busy doing other stuff so I could do with using the DMA to lighten the load. If I am TXing then it looks OK. I enable hardware flow control on TX and the USART stops transmitting when the far end asserts nRTS (my nCTS). I guess this would then stall the DMA process and prevent overflow (although I need to ensure my firmware stops writing to the USART DMA TX area). For receive however it looks to me that the RXNE flag is set by the hardware and cleared by DMA. What I need to happen is when the DMA read buffer is full, my nRTS pin asserts to prevent further data transmission from the data source (by asserting their nCTS pin). Am I correct in understanding that: if the DMA memory area is full, then it will not read from the USART receive register, meaning that nRTS output would assert? If so then that is all I need! Thanks for your help, Charlie2012-01-24 11:10 AM
I've use DMA on USARTS, I'm not particularly fond of ST's implementation, I'd much rather have seen a USART with it's own FIFO.
It depends on how you implement receive DMA, if the DMA buffer is consumed it won't be servicing the USART, RXNE will not get cleared. Now presumably you're thinking about using a circular DMA buffer, in which case you'll need to manage the flow in software, perhaps at the TC/HT interrupts. You can't tie the USART1 RX DMA into the USART2 TX DMA and have the hardware throttle them based on current fill levels. They act independently, if you say you have 10 bytes to send they had better be there already. If I were forwarding full duplex between two ports, I'd probably have a list of buffers, and use regular DMA (ie non circular) to fill them, and at the TC interupt enqueue them to transmit, if the transmit was idle I'd fire of the DMA for the transmit, or let the transmit TC interrupt rack it up next, and free the current. Pick a size and quantity of buffers to meet your anticipated needs, or resources.2012-01-25 05:39 AM
Thanks for your thoughts. The data stream passing through my device has to be inspected by a process. The code for the process already exists so I have got to force it through the process 1 byte at a time... I`ll take another look at my design with your suggestions in mind to fine tune it.
Although DMA is nice, I agree with you on the comment about the separate USART FIFO. Other micros I`ve used have this facility and it is simpler to handle than DMA.2012-01-28 03:41 AM
I tend not to use the libraries supplied by ST except as examples from which to derive my code, but my primary reference is always the reference manual.
I played around with hardware flow control with DMA for RS232 reception at the ST end. What I found on my STM32F103 was that nRTS would pulse for every character that was received even though the DMA was taking the received data byte out of the USART on the next available bus cycle! I considered so much activity on nRTS to be a ''bad thing'' so instead I arranged for a half-complete interrupt on my (circular, repeating) DMA-into-receive-buffer and asserted nRTS manually on that interrupt if the buffer was at least half-full, clearing nRTS when reading from the buffer emptied it to less than half-full. I know this wastes half the memory I allocated to my RS232 receive buffer. But I do not know the innerds of the other end (a commercial module). It might (for example) choose to process an interrupt on every change in its nCTS but do everything else by DMA, and I do not want to overwhelm it with interrupts. Using this technique, I have not seen problems driving the USART up to 1843200 bps. The STM32F2xx and 4xx might be different. I have not yet played with them. - Danish2012-01-30 10:25 AM
Interesting technique Danish. That sounds like it would work for my application. I would also need to implement a DMA timeout as the data I am receiving is not always a constant stream so sometimes the buffer may not reach the half full stage. I know this can be done using a timer is slave reset mode on the RX pin of the USART.
I have had to use ``seemingly wasteful`` CTS procedures/buffers before when joining to some Windows boxes as they tended to take a few bytes to acknowledge the hardware flow control. I found that I had to assert nCTS and keep buffering the incoming bytes until Windows reacts to the signal. I guess this approach would give the same results?