adafruit / Adafruit_ZeroDMA

DMA helper/wrapped for ATSAMD21 such as Arduino Zero & Feather M0
MIT License
58 stars 23 forks source link

[Question/Feature Request] Query current source address? #16

Closed modmatic closed 4 years ago

modmatic commented 4 years ago

Is it possible to use this library to get the current source address mid-transfer (for writes, with source address incrementing)? For instance, kicking off a block DMA write of 100 bytes, I'd like to be able to understand at any point in time how far along the DMA controller is in this particular block. I'd be happy to submit a PR if I could only narrow down what register would contain this value. I tried checking the descriptor's SRCADDR (and BTCNT, to try to derive it) to no avail as they seem static for a given block. I also checked the corresponding values in the writeback descriptor, which remained zero. There's got to be something I'm missing. The DMA controller is keeping track of this somehow. Thoughts?

ladyada commented 4 years ago

we've never seen any way to get this info - you can sometimes set where the IRQ gets triggered on a DMA controller - perhaps there's one for halfway-thru?

modmatic commented 4 years ago

@ladyada Ah ok, bummer. In my case, knowing halfway won't help much. Gonna try a different approach. Thanks anyway!

For the curious:

I have a buffer that I'm using DMA to send over the SPI bus. I subsequently need to clear the buffer to prepare it for further use, but I'd like to do the clearing in parallel with the DMA job. If I could know which DMA address is being read from while the job is running, I can keep the erasure from outpacing the DMA job.

Instead, I've had success with using two buffers, and swapping them just after starting the DMA job. Then I can prepare (erase) the new buffer for use while the last one is being processed by the DMA job. It achieves the same efficiency I was going for but requires more RAM (which I can afford on a SAMD51).

PaintYourDragon commented 4 years ago

Have you looked in the writeback descriptor list? I have no idea if the info would be there, just speculating.

modmatic commented 4 years ago

@PaintYourDragon I haven’t looked at the entire set of values on the write back descriptor. The ones I thought would have the info were zero, but I’ll update this thread if I ever find anything useful.

PaintYourDragon commented 4 years ago

A couple kludgey ideas here, if nothing else has borne fruit yet…

If you don’t need atomic precision on the progress counter and just a few updates would suffice (e.g. 0, 20, 40, 60, 80, 100%)…one thought would be to use a set of linked descriptors, alternating between “update some progress counter” and “move some data.” e.g. first descriptor would move a value of 0 to a progress variable, second descriptor would move N bytes from source to dest, second descriptor would move a value of N to progress, third descriptor would move N bytes from (source+N) to (dest+N), fourth would move a value of N*2 to progress, and so forth. Super kludgey (and would introduce small but probably insignificant delays into the DMA transfer overall). Each descriptor is…16 bytes I think? Not impractical or overbearing, if it’s like a dozen linked descriptors.

Other thought would be some house of cards built around the Event System peripheral, which I BARELY understand, but you can see an example of its use in Adafruit_SPITFT.cpp (in Adafruit-GFX-Library). Each DMA beat transfer can generate an event, and those events can be routed to one of the Timer/Counter peripherals…which would also need to be configured. But IN THEORY this might then provide a DMA progress counter. That would be pretty cool but also could easily sink several days into datasheets, errata and headaches with no guarantee of success.

PaintYourDragon commented 4 years ago

Also: Adafruit_SPITFT uses the two-alternating-DMA-buffers approach, each sized for one scanline. It’s a pretty bog-standard way of doing these things and two scanlines isn’t too much to ask. Might be least painful just to stick with what works.

modmatic commented 4 years ago

Hey @PaintYourDragon, thanks for all your input! I’ve moved past this with the double-buffer approach but these are some great ideas to keep in mind if this pops up again.