Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 8013

SDK • Re: Timer triggered DMA to PIO

$
0
0
I see that the code is set up to do ring mode, so it looks like you are expecting this to run continuously. There are two problems:

1) There's no way on RP2040 to get an infinite transfer count. Your 256 will only run once through the array. For some purposes,0xffffffff is near enough to infinity, but in this case 2^32/25.6kHz is only about two days, and I'd not be happy with something that died after that amount of time. The simplest way to fix it is as @alistairpatrick suggests - set up two DMA channels with identical configuration, each as you have now but with the chain-to fields set to point at each other. You then start one of them, and each time one finishes the other one will be started and you've got an infinite duration.

2) Your buffer "steps" isn't aligned, and ring mode requires the buffer addresses to be aligned. Easiest is to just declare the buffer __attribute__ ((aligned(256*4))). That's potentially wasteful of RAM, but probably not a big deal with this 1Kbyte buffer.

Alternatively you can fix both problems with a slightly different DMA setup. Configure one channel for just a single pass through the buffer (ie. not using ring mode, so the buffer doesn't need to be aligned), then configure a second channel to do a 1-word DMA (without increment) from a spare variable holding the buffer address into the al3_read_addr_trig register of the first channel. First channel is configured to chain to the second one, second channel should NOT be set to chain as the _trig alias of the register does that for you and with the right timing. This again gives you infinite transfers, but without the buffer alignment requirement. Swings and roundabouts to the two approaches, but I generally prefer this one.

Other notes:

Your PIO program is currently 3 instructions, only needs to be one: the PULL can be deleted if you enable auto-pull in the configuration, and the JMP isn't needed as you already have .wrap_target/.wrap set up to do that. This is beneficial both for code saving (if you are planning to use the rest of the PIO for something else, running out of instructions is a key problem), but also for the program itself - executing the OUT instruction every cycle rather than every 3 cycles will give you less jitter.

Alternatively, you could look at implementing PWM in the PIO. One PWM per PIO SM is easy, but that only gets you 8 channels using all the PIO resource on the chip. Two PWMs per SM isn't too hard - use X for the counter, Y as a temporary register for doing comparisons, and ISR/OSR to hold the two durations. Tricky bit is balancing the delays in all the paths so the loop time is always constant. So that should get you 16 channels.

But it's not clear what you are needing that's causing you to go to this trouble - the hardware PWM certainly supports some kinds of phase shift, so are you needing something special?

Statistics: Posted by arg001 — Tue Mar 12, 2024 10:38 am



Viewing all articles
Browse latest Browse all 8013

Trending Articles