Hi all,
I have a project which is interfacing an 8 bit micro (6809E) to a pico using PIO state machines and DMA. That bit works, which I know because I'm running code out of the DMA->PIO served memory.
However I have some code that I want to run after each read or write to check for certain conditions and handle them as needed (think embedded registers). To do this I'm using an IRQ that is fired after the DMA has done a transfer. Yes I realize that the code in here has to be short so as not to hang things up.
This *WAS* working but has mysteriously stopped, can anyone spot what the problem may be (code for init and handler for read below).
Cheers.
Phill.
I have a project which is interfacing an 8 bit micro (6809E) to a pico using PIO state machines and DMA. That bit works, which I know because I'm running code out of the DMA->PIO served memory.
However I have some code that I want to run after each read or write to check for certain conditions and handle them as needed (think embedded registers). To do this I'm using an IRQ that is fired after the DMA has done a transfer. Yes I realize that the code in here has to be short so as not to hang things up.
This *WAS* working but has mysteriously stopped, can anyone spot what the problem may be (code for init and handler for read below).
Code:
void __no_inline_not_in_flash_func(ReadDMA_Handler()) { static uint16_t RAddr; // Get the address we just read from RAddr = DMAtoDragon(dma_hw->ch[ReadDMA2].read_addr); ToggleLED(); // If we just read the READ_DATA register, load it with the next byte from // the buffer, note this happens after the data is sent to the SM so is not as // timing critical as it has the E low period to complete. if (D_READ_DATA_REG == RAddr) { if (globalIndex < GLOBUFFSIZE) ReadRegs[D_OS_DATA_REG] = globalData[++globalIndex]; } // Check for a fetch of the reset vector if ((RESET_VEC+1 == RAddr) && (RESET_VEC == last)) { reset_flag = true; } // Record the last address read, to allow detection above to work! if (0xFFFF != RAddr) last = RAddr; lastrw = true; GreenLEDToggle(); // Clear the interrupt request. dma_hw->ints0 = 1u << ReadDMA2; }// Setup read memory DMA chainvoid Setup_Read_DMA(PIO pio, uint8_t StateMachineA, uint8_t StateMachineD){ ReadDMA1 = dma_claim_unused_channel(true); ReadDMA2 = dma_claim_unused_channel(true); dma_channel_config Config; // Setup DMA2, this returns the read byte to the SM's isr. // and is triggered by DMA1 Config=dma_channel_get_default_config(ReadDMA2); // get default config channel_config_set_read_increment(&Config,false); // Don't increment pointers on transfer channel_config_set_write_increment(&Config,false); channel_config_set_transfer_data_size(&Config, DMA_SIZE_8); // 8 bits channel_config_set_chain_to(&Config,ReadDMA1); // Chain to dma 1 when done dma_channel_configure(ReadDMA2, // channe &Config, // Config to apply &(pio->txf[StateMachineD]), // Write address, state machine input queue NULL, // No read aaddress, filled in by ReadDMA1 1, // 1 word at a time false); // don't trigger // Setup dma interrupt handler to run after the byte has been read. dma_channel_set_irq0_enabled(ReadDMA2, true); irq_set_exclusive_handler(DMA_IRQ_0, ReadDMA_Handler); irq_set_enabled(DMA_IRQ_0, true); // Now setup DMA1, this fetches the address for the read from the PIO's OSR. Config=dma_channel_get_default_config(ReadDMA1); // get default config channel_config_set_transfer_data_size(&Config, DMA_SIZE_32); // 32 bits channel_config_set_read_increment(&Config,false); // Don't increment pointers on transfer channel_config_set_write_increment(&Config,false); channel_config_set_dreq(&Config, pio_get_dreq(pio,StateMachineA,false)); // Set data request to StateMachine's drq // Channel size defaults to 32 bits dma_channel_configure(ReadDMA1, // channel &Config, // Config to apply &(dma_hw->ch[ReadDMA2].al3_read_addr_trig), // Write address, trigger address of ReadDMA2 &(pio->rxf[StateMachineA]), // Read aaddress, output queue 1, // 1 word at a time true); // trigger}Phill.
Statistics: Posted by PhillHS — Sun Feb 15, 2026 10:52 pm