Hi all
I managed to implement SPI mode 0 slave on my rp2040 via PIO and DMA, and it copies the data flawlessly. However, I get a Heisenbug error, where when I step through my code, it does wht its suppoed to but when it runs on its own, it skips values and doesn't do it.
the above is my irq handler, and the below is my code for pio and dma
and with this my spi slave works perfectly
However with thiswhen I step through it it manages tto get my date array perfectly, but when I run it normally it completely bypasses creating a char array. Can anyone offer any insights as to what I am doing wrong to get this Heisenbug?
Kind regards
I managed to implement SPI mode 0 slave on my rp2040 via PIO and DMA, and it copies the data flawlessly. However, I get a Heisenbug error, where when I step through my code, it does wht its suppoed to but when it runs on its own, it skips values and doesn't do it.
Code:
PRIVATE void myIRQHandler(uint gpio, uint32_t events) { if(events & GPIO_IRQ_EDGE_FALL) { dma_init(); // Set up DMA to transfer data from PIO to memory when CSN goes low, indicating the start of an SPI transaction uint32_t status = save_and_disable_interrupts(); // Disable interrupts to ensure atomic access to shared resources csn_high = true; // Set flag to indicate that CSN is active (low) restore_interrupts(status); // Restore previous interrupt state } if(events & GPIO_IRQ_EDGE_RISE) { dma_channel_unclaim(pio_spi.dma_chan); // Unclaim the DMA channel to free it up for future use when CSN goes high, indicating the end of an SPI transaction uint32_t status = save_and_disable_interrupts(); csn_high = false; // Set flag to indicate that CSN is high (inactive) restore_interrupts(status); // Restore previous interrupt state }}Code:
PUBLIC void pio_dma_setup(void){ pio_spi.pio = pio0; uint offset = pio_add_program(pio_spi.pio, &clocked_input_program); pio_spi.sm = pio_claim_unused_sm(pio_spi.pio, true); clocked_input_program_init(pio_spi.pio, pio_spi.sm, offset,PICO_DEFAULT_SPI_RX_PIN,PICO_DEFAULT_SPI_CSN_PIN ); pio_spi.dma_chan = dma_claim_unused_channel(true); pio_spi.pio_dma_chan_config = dma_channel_get_default_config(pio_spi.dma_chan); //Tranfers 8-bits at a time channel_config_set_transfer_data_size(&pio_spi.pio_dma_chan_config, DMA_SIZE_8); //sets the size of each DMA transfer to 32 bits channel_config_set_read_increment(&pio_spi.pio_dma_chan_config, false); //Disabled when reading from peripheral, as the source address is fixed channel_config_set_write_increment(&pio_spi.pio_dma_chan_config, true); channel_config_set_dreq(&pio_spi.pio_dma_chan_config, DREQ_PIO0_RX0); //Configures the DMA channel to be triggered by the PIO's RX FIFO for the specific state machine. This means that a DMA transfer will occur whenever there is data in the RX FIFO of the PIO state machine, allowing for efficient data handling without CPU intervention.}PRIVATE void dma_init(void){ dma_channel_configure( pio_spi.dma_chan, &pio_spi.pio_dma_chan_config, give_array_address(), // Destination address where data is written to memory &(pio_spi.pio->rxf[0]), // Destination address in memory where data is read from the PIO's RX FIFO BUF_LEN, // Number of transfers (bytes) to perform true); //start immediately // dma_channel_wait_for_finish_blocking(pio_spi.dma_chan); // Waits for the DMA transfer to complete before proceeding. This ensures that all data has been transferred from the PIO's RX FIFO to the data buffer in memory before any further processing is done.}However with this
Code:
PUBLIC uint8_t* give_array_address(){ return myQueue.buffer; // return the current position in the buffer}Code:
PRIVATE void get_date(const char *in, char *date){ memset(date,0,sizeof(date)); const char *date_ptr = in; while(*date_ptr) { if (*date_ptr == '/') { date[0] = *( date_ptr - 2); // Get the first digit of the day date[1] = *(date_ptr - 1); // Get the second digit of the day date[2] = *( date_ptr ); // Get the first / date[3] = *( date_ptr + 1); // Get the first digit of the month date[4] = *( date_ptr + 2); // Get the second digit of the month date[5] = *( date_ptr + 3); // Get the second / date[6] = *( date_ptr + 4); // Get the first digit of the year date[7] = *( date_ptr + 5); // Get the second digit of the year date[8] = '\0'; // Null-terminate the string break; // Exit the loop after extracting the date // Validate the date format (DD/MM/YY) } date_ptr++; // Found the first '/', now look for the second '/' }} Kind regards
Statistics: Posted by Maaz1 — Wed Mar 04, 2026 3:18 pm — Replies 1 — Views 103