I'd like to setup DMA in a way that it writes bytes to GPIO pins 0-7. AFAIK you'd write a little PIO program for that which would actually write out the bytes the DMA transferred. Once the DMA write finishes with the data, I'd immediately like to retrigger it to keep feeding the same sequence of bytes over and over again. AFAIK I can just chain another DMA channel that then gets chained back to the first one. This is the code I came up with, which - unsurprisingly - does not work. I'm good with C++, but the Pico hardware (and low-level microcontroller programming) is relatively new for me. The end goal is a function generator, if context helps. Any help/pointers in the right dir is appreciated
cpp
#include <cstdint>
#include <vector>
#include "hardware/dma.h"
#include "hardware/pio.h"
void setup_pio(PIO pio, uint sm) {
auto program = pio_program_t {
.instructions = pio_program,
.length = sizeof(pio_program),
.origin = -1,
};
auto offset = pio_add_program(pio, &program);
pio_sm_config c = pio_get_default_sm_config();
sm_config_set_out_pins(&c, 0, 8);
pio_sm_init(pio, sm, offset, &c);
pio_sm_set_enabled(pio, sm, true);
}
void setup_dma(PIO pio, int dmaChan0, int dmaChan1, std::vector<std::uint8_t> const& data) {
// Channel 0, which outputs to the PIO, which in turn outputs to the pins
dma_channel_config c = dma_channel_get_default_config(dmaChan0);
channel_config_set_transfer_data_size(&c, DMA_SIZE_8);
channel_config_set_read_increment(&c, true);
channel_config_set_write_increment(&c, false);
// Chain to channel 1 when done
channel_config_set_chain_to(&c, dmaChan1);
dma_channel_configure(dmaChan0, &c, &pio->txf[0], data.data(), data.size(), false);
// Channel 1 just retriggers channel 0
c = dma_channel_get_default_config(dmaChan1);
channel_config_set_chain_to(&c, dmaChan0);
dma_channel_configure(dmaChan1, &c, nullptr, &pio->txf[0], 1, false);
}
// Usage
int main() {
auto dataPoints = std::vector<std::uint8_t> { / ... / };
auto chan0 = dma_claim_unused_channel(true);
auto chan1 = dma_claim_unused_channel(true);
auto pio = pio0;
uint sm = pio_claim_unused_sm(pio, true);
setup_pio(pio, true);
setup_dma(pio, chan0, chan1, dataPoints);
dma_channel_start(chan0);
}