cancel
Showing results for 
Search instead for 
Did you mean: 

UART DMA check if a byte received

Raider E
Associate III
Posted on April 12, 2017 at 02:50

Hi All,

Which flag in the UART DMA can be checked to indicate that I received a new byte. I also would like to check the DMA of my UART while its receiving, and if I receive a special character say '\r',I want to start processing the received buffer and reset dma. I am using the HAL library. Is it possible to do something like RxQuarterCplt instead of HAL_UART_RxHalfCpltCallback?

Many thanks

7 REPLIES 7
Posted on April 12, 2017 at 03:40

No, but you could colour the buffer and check occasionally. ie USART reads as 16-bit half-word, high order bits zero, you mark the word(s) you've already taken.

Check the Address Pointer

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on April 12, 2017 at 05:29

The DMA controller has a register called NDTR. This register holds the outstanding transfer count.

If you set up a DMA transfer of 1000 bytes, NDTR will start at 1000 and get decremented on each transfer.

If you want to see if something came in, keep track of the value of NDTR, and poll it periodically to see if it has changed. It will also give you an idea of where in your buffer to look for \r characters.

Andrei

Alan Chambers
Associate II
Posted on April 12, 2017 at 05:48

I do this with a recurring timer. The DMA RX buffer is circular and generates no interrupts. I poll NDTR every millisecond or so, compare NDTR to its previous value, and deal with any new bytes. Timing is not critical, so I use a software timer based on SysTick, but a TIM interrupt could do the same.

I would decouple the processing from the receiving. I always pass the bytes asynchronously to a simple state machine which reconstructs packets from the byte stream. In your case, this means accumulating bytes in a buffer until you see a line end (reset the buffer if it fills up), and then parsing the line. I would try to avoid doing this work in an ISR.

Posted on April 12, 2017 at 06:52

Thank you all for the ideas you've given.

Ill try continuously polling the NDTR and see if this can solve my problem. I'll be back in touch and see what worked for me.

Posted on April 12, 2017 at 13:25

I am polling the NDTR now with a freertos thread every 1ms and can see its value changing. Now i am if I am continuously transmitting (polling) different commands from the uart port, the connected device will transmit back different responses with various lengths and these all are terminated with \r. So if I 

decouple the processing from the receiving how can I know that reply 1 belongs to command 1 and reply 2 belongs to command 2? the device might for example not respond for command 1 and respond for command 2. in such case, response from command 2 will be assumed as reponse to command 1. there is no way to tell, am I correct?. I was doing something trivial, which I would like to avoid, is after every transmission I wait using vtaskdelay before i process the buffer and that works just fine. But this is not ideal and no one likes delays even if they are non blocking. Vtaskdealy is a non blocking delay it allows other threads to run. So I like the idea of watching the NDTR but can not figure out a sensible way to make use of it.

Posted on April 12, 2017 at 18:44

You have now problem with the general application logic and this has nothing to do with the original subject.

What would you do if you would have only simple polled Tx, and then polled Rx, in a plain no-OS application, how would you handle the behaviour of the connected device?

JW

Posted on April 12, 2017 at 18:53

There is a

https://community.st.com/0D50X00009XkhAxSAJ

with reading NDTR and then reading from the buffer, namely, that - contrary to documentation - NDTR is decremented *before* the transfer happens. Now many users won't notice as there is usually enough program to do between reading NDTR and reading the actual data from memory, but in cases of high optimization this might bite. I know of no simple solution to this problem, as it involves latencies on the AHB/ABP bridge, arbitration within DMA and then latencies on the target AHB/memory.

Also note that there are two distinct DMA implementations in the STM32s, a rather complex one in 'F2/'F4/'F7 and a simpler one in the rest, and they may behave slightly differently in this regard. My experience is with 'F4 only.

JW