I'm struggling to implement DMA chaining on the LPC824 and beginning to wonder if what I'm trying to do is possible at all on the LPC824.
For a start, I already have a working DMA based UART implementation that writes received bytes to a ring buffer using a ping-pong transfer descriptor approach (USART0 -> DMA channel 0).
Now what I'm trying to do is to implement a timeout if no byte was received for a certain time (let's say 300µs). So only after the timeout happened after the last byte received I get an interrupt which wakes the CPU from sleep to check received bytes.
My idea was to write a new value to the MRT0 interval register (with the force load flag set) each time a byte is received by a 2nd DMA channel chained to the UART receive DMA transfer. As chaining only seems to work when the transfer descriptor is exhausted, I swapped the channels, I.e. I'm using channel 0 (the UART RX dma channel) to write the new MRT0.INTVAL value and then chain to another channel (channel 9 in my current prototype) that is used to handle the UART receive ring buffer which was done by channel 0 before.
To make a long story short, I got this working to some degree but each time the chained channel (9) is triggered, it doesn't write a single byte as expected, but instead copies the same byte to the whole ring buffer until the transfer descriptor is exhausted.
I'm starting to wonder if it's actually possible to create a single transfer request by chaining.
I set up the channels as described in the manual (i.e. HWTRIGEN=1, TRIGPOL=0, TRIGTYPE=0) but as far as I can tell, the TRIG flag in CTLSTAT9 stays high and causes a permanent transfer from the UART RX register until the descriptor is exhausted. So while the manual warns about that this can happen for level triggering, the edge triggering used here doesn't seem to make any difference at all.
Actually, the whole concept of TRIG flags and HW triggers vs. DMA requests seems somewhat weird and is not properly described in the manual. As is the concept of having to clear the TRIG flags at RELOAD.
It's a bit frustrating that something as simple as linking two DMA channels seems to be a minefield of vaguely described flags and requires such a complex setup which isn't even working as expected in the end.
In a nutshell: is there a way to link ("chain") from a DMA channel triggered by peripheral DMA request (UART receive) to a 2nd channel in a way that each end of transfer on the 1st channel actually only triggers a single transfer on the chained channel instead of causing permanent transfers until the descriptor of the chained channel is exhausted?
Hi Volker Oth
Have a great day,
TIC
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Thanks for the fast reply. I'm unsure though how changing the DMA priority would improve the situation.
The 2nd (chained to) channel is of course already called after the 1st (chained from) has finished. After all, this is the idea of chaining. So changing the priority can't actually make any difference at all.
What puzzles me is that I need to set up the chained channel as edge triggered (i.e. one trigger -> one transfer) but the behavior is the same as it would be level triggered. If there is really no option to configure the chaining in a way to only trigger a single request, it's IMHO useless for almost any imaginable use case.
Anyway, I guess I have to go with interrupts for the receive case. Not very elegant, but my only other choice with this severe limitation of the chaining implementation would be to set up N transfer descriptors for a receive buffer of N bytes which would be somewhat insane.