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

SDK • restarting a DMA that reads from a PIO fed FIFO

$
0
0
I've got some PIO code that counts bits in an incoming bit stream; and for every 8 clock transitions; it pushes the count into a FIFO; which then fills up a DMA buffer. Once the buffer is full, an IRQ is called - which then processes the data. Currently this is a simple printf().

I am struggling to 1) re-start the DMA after the read. It hangs. And 2) to run this in the background/non-blocking - I need to call dma_channel_wait_for_finish_blocking().

The full code is at https://github.com/dirkx/pdm-experiment ... receiver.c

I've got it working for sending data DMA-FIFO->Sending works (https://github.com/dirkx/pdm-experiment ... 7/sender.c -- but am struggling to get it to work for receiving.

The pertinent lines of code are:

Code:

uint32_t buffer_rx[32] __attribute__((aligned(256)));void init_pdm_receiver(int pin_dat, int pin_clk, uint64_t sampleBitRate) {    pio = pio1;    offset = pio_add_program(pio, &receiver_program);    sm = pio_claim_unused_sm(pio, true);    receiver_program_init(pio, sm, offset, pin_dat, pin_clk, sampleBitRate);    irq_add_shared_handler(dma_get_irq_num(DMA_IRQ_TO_USE), dma_irq_handler, DMA_IRQ_PRIORITY);    irq_set_enabled(dma_get_irq_num(DMA_IRQ_TO_USE), true);    dma_channel_config config_rx;    dma_channel_rx = dma_claim_unused_channel(true);    config_rx = dma_channel_get_default_config(dma_channel_rx);    channel_config_set_transfer_data_size(&config_rx, DMA_SIZE_32);    channel_config_set_read_increment(&config_rx, false); // do not increment; FIFO    channel_config_set_write_increment(&config_rx, true);     // Wire DMA to FIFO    channel_config_set_dreq(&config_rx, pio_get_dreq(pio, sm, false /* is rx */));    dma_channel_configure(dma_channel_rx,  &config_rx, buffer_rx,  // write addr(io_rw_8*)&pio->rxf[sm], // read addrsizeof(buffer_rx) / sizeof(*buffer_rx), // -- number of transactionstrue // dma started    );    if (0 /* does not make a difference*) channel_config_set_ring(        &config_rx,         true, // Apply to write addresses.        7 // bits for wrap around; buffer is 256 bytes; 32 transfer     );     dma_irqn_set_channel_enabled(DMA_IRQ_TO_USE, dma_channel_rx, true);    pio_sm_set_enabled(pio, sm, true);}
With the IRQ handler:

Code:

static void dma_irq_handler() {    dma_irqn_acknowledge_channel(DMA_IRQ_TO_USE, dma_channel_rx);        printf("dma_rx complete\n");      // Reset DMA process for next block from PIO FIFO  // dma_channel_set_write_addr(dma_channel_rx,buffer_rx,true);  dma_channel_hw_addr(dma_channel_rx)->al2_write_addr_trig = (uintptr_t) buffer_rx;}
This works once if call dma_channel_wait_for_finish_blocking(dma_channel_rx); . How does one restart the FIFO/DMA process at this point - and how do you initially start it fully in the background. dma_channel_start() does not seem to be right.

Any and all suggestions appreciated. As to the context - it is a Pulse Density Microphone simulator (Sender) and a a receiver.

Statistics: Posted by dirkx — Sat Sep 13, 2025 10:34 pm



Viewing all articles
Browse latest Browse all 8013

Trending Articles