DMA chaining #12312
Replies: 1 comment 5 replies
-
Mhm, that looks complicated.
(b) DMA0 is programmed to be timed by this DREQ. It transfers one word to the ADC config register that sets CS.START_ONCE
This of course has to happen from a storage location that is fixed, no read increment. The same respective value is written to this ADC register again and again, eliciting the ADC conversion every time. ADC has to be set for One-shot Sample. (c) Another DMA channel (you referred to DMA2, but it might be counted as DMA1) evaluates the DREQ of the ADC and stores the result of the conversion. This may happen in a cyclic manner so that a sufficiently large buffer is written again and again and one only has to poll the DMA writing address in that buffer to extract the values before they get overwritten in the next cycle. If you want all this to happen in an automatic manner, with 200kHz you have to make sure that the PIO, which has its own timer, is running at that frequency. I do not see the need for a third DMA. The parts (a) (b) and (c) may be tested independently. For (c) the ADC may be set to Free-running Sampling. The DMA then should be able to store the values.
It seems you do the transfer from ar1 to ar2 for testing, right? So you can check whether the DMA2 transfer happened? |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Hi all,
For a school project I am using the RP2040 PIO to sample and hold a signal (with externals sample and hold circuits) and then do a ADC convertion using the onboard RP2040's ADC. The iteration, sample and hold + ADC convertion should happens with at a frequency of about 200kHz.
For learning purposes, I would like to implement this using DMA rather than using interupts.
The flow of a single iteration can be summarized in this loosly made flow-chart here below :)

Using this code from J. Bentham, I managed to create the first part of what I want to do (I rely on rp_devices.py).
This first part is to clear any remaining items in the PIO0 RX FIFO
Then I setup the ADC channel with:
Then I initialize the DMAs.
DMA0 is triggered by DREQ_PIO0_RX0 (when I call push() in the PIO program), and trigger the START_ONCE bit of the ADC.
Once the ADC finished with its single convertion, it will trigger DMA2.
DMA2 is triggered by DREQ_ADC, and move the results of the convertion from the ADC FIFO to a buffer array,
adc_buf
.Now I define my PIO program, that will blink the onboard LED, do a
push()
, do a DREQ_PIO0_RX0, trigger the DMA0, which trigger ADC START_ONCE, which will do a ADC_DREQ, that will activate the DMA2 to move the ADC results to the buffer array.Well so far so good, this is the output on the REPL:
And the ADC buffer contains the value of the conversion as it should. (I attach this full code here for easy copy-paste 11_3_PIO_ADC_BUFFER_Q.zip)
Now my objective is to get my two DMAs retriggered in the same order if I call a second time the push() function. By getting inspired by Van Hunter Adams'code, I though that all my problems could be solved by chaining a third DMA (channel2) to DMA1 which would re-trigger DMA0.
There its were I am getting a bit confused.
For debug purpose, rather than trying to retrigger DMA0, I decided to code the DMA2 to have it chained to DMA0 and only move some values between two arrays (
ar1
,ar2
) so I could eye-ball the behaviour. The full code is downloadable here: 11_4_PIO_ADC_BUFFER_DMA2_Q.zip.and reported here below:
What I don't understand is that if I call the
push()
function or I comment it out, the DMA0 will or will not take place. On the other hand, the DMA2 will always transfer the value fromar1
toar2
even if DMA0 was not triggeredWhy is this behaviour happening? Even if it is an unpaced transfer, shouldn't it be chained to DMA0 and happens only when DMA0 takes place? Where could I be wrong?
It is quite of a long post, I hope I managed to convey the problem in a clear way :)
Best,
Martino
Beta Was this translation helpful? Give feedback.
All reactions