SAMD10: What's the best way to USART RX with DMA? - Page 1
Forum section: electronics / general

author: Refrigerator
author_rank: Super Contributor
timestamp: December 05, 2020, 04:24:55 pm
content: I'm trying to get my USART working with DMA and i'm close to done but i've just noticed that there's occasional errors that mess the whole operation up.Currently DMA is set to disable after transfer complete and i've noticed that if data is received before DMA is enabled then some data is skipped once DMA is enabled.This then screws destination address counting completely and my data is no longer aligned.Looks like USART will only receive the first two(?) bytes and will ignore the rest and then DMA transfer will stay pending until it is enabled. So once it's enabled only the RX buffer is transferedIf DMA is enabled before USART receives data everything works fine.Are there better ways to set up DMA to be always enabled and just dump data into memory whenever it arrives or is that bad practice?The other option i see is channel suspend and at first i thought that maybe this would work:QuoteSo does this mean that there will not be any data transfer?

author: enz
author_rank: Regular Contributor
timestamp: December 05, 2020, 05:19:55 pm
content: Here is a very nice description how to receive uart data via DMA:https://github.com/MaJerle/stm32-usart-uart-dma-rx-txSoftware examples are provided, although it is only for STM32.But it should be easy to port this to SAMD devices.I don't know though, if SAMD devices support the dma circular mode which is used here.And it also helps, if the used micro has a uart idle interrupt.If these preqrequisites are met, the solution works very well.

author: voltsandjolts
author_rank: Unknown
timestamp: December 05, 2020, 05:42:15 pm
content: Quote from: enz on December 05, 2020, 05:19:55 pmInteresting.Although he states UART RX DMA must know number of bytes in advance, but this is not true.The STM32 DMA can receive UART characters directly into a (power of two sized) ring buffer continuously.https://www.eevblog.com/forum/microcontrollers/_best_-way-to-load-uart-data-to-ring-buffer-with-stm32hal/

author: Refrigerator
author_rank: Super Contributor
timestamp: December 05, 2020, 05:43:17 pm
content: Quote from: enz on December 05, 2020, 05:19:55 pmIt's a little different with SAMD so i don't think it will be as simple as just porting it over, but at least it might set me on the right track.I think the DMA transfers work in circular mode, which is why my data goes out of alignment, because DMA misses some transfers and the "circle" becomes offset.But i haven't confirmed this yet.

author: Refrigerator
author_rank: Super Contributor
timestamp: December 05, 2020, 05:45:05 pm
content: Quote from: voltsandjolts on December 05, 2020, 05:42:15 pmSAMD10 only has a one byte buffer so i have to grab my data on time otherwise i'll miss the data that comes while buffer is full.In my case i know exactly how much data i'm receiving.

author: ataradov
author_rank: Super Contributor
timestamp: December 05, 2020, 06:16:01 pm
content: DMA and UART RX is hard to manage. DMA needs to know in advance the number of bytes to expect.You can use DMA linked list mode and link two buffers circularly, so that you would get constant receive. But let's say you have two 32-byte buffers, but you only receive 30 bytes. Well, you will be sitting and waiting for the last two bytes to process the data.And the problem with UART is that bytes can get lost occasionally due to errors, so even if you design your protocol to have packets of a fixed size, you can still go out of sync. So you need to add timeouts and stuff like that.UART is a slow enough interface that using interrupt and software handlingAlso, all of that mostly applies to all MCUs out there, not just D10.

author: voltsandjolts
author_rank: Unknown
timestamp: December 05, 2020, 06:21:39 pm
content: Quote from: ataradov on December 05, 2020, 06:16:01 pmThat's not always true, at least with STM32 and perhaps othersThe STM32 DMA can receive UART characters directly into a (power of two sized) ring buffer continuously.https://www.eevblog.com/forum/microcontrollers/_best_-way-to-load-uart-data-to-ring-buffer-with-stm32hal/

author: ataradov
author_rank: Super Contributor
timestamp: December 05, 2020, 06:28:05 pm
content: Quote from: voltsandjolts on December 05, 2020, 06:21:39 pmYou can organize something like this on D10 with DMA and linked list descriptors. Managing that is a bit harder than on STM, since for partial data you would need to get the pointers from the DMA.

author: voltsandjolts
author_rank: Unknown
timestamp: December 05, 2020, 06:47:22 pm
content: Yes, thats the crux of it.If you are able to read the DMA write pointer, in atomic way, while the DMA is active, then you can work out where the RX ring buffer write pointer is at.Then continuous receive to ring buffer is possible.

author: Refrigerator
author_rank: Super Contributor
timestamp: December 05, 2020, 07:25:45 pm
content: So far i think the best way to avoid errors would be to clear RX buffer before enabling DMA.And to occasionally clear the DMA address counter would help as well.Also i included a diagram of what my MCU will be doing, you can see a repeating pattern and how my data will be arriving and leaving.Takes about ~69µs to send one byte at 115200 baud, which, i think, should lend enough time for my DMA to dance around.Total packet size in this "free running mode" is 40 bits, which includes 16 address bits and 24 color bits.Edit: LED TX should be on it's separate PWM row because it's done through DMA.