Hi all,
I have a pio state machine which will provide addresses to be looked up by DMA and returned to it. But it only seems to be triggering once
PIO code :
PIO init code :
Code For Setup_Read_DMA
I suspect that I've missed something subtle in the DMA or PIO initialization that's causing this to fail, I know that the IRQ handler is getting called once as the green led on my board comes on and stays on (checked with a scope). I also have a logic analyser on the data and select lines and they show no activity either.
If I comment out the "pull block" everything runs freely, but obviously no valid data is returned.
Can anyone spot what I've missed?
Cheers.
Phill.
I have a pio state machine which will provide addresses to be looked up by DMA and returned to it. But it only seems to be triggering once
PIO code :
Code:
// Pins are common and used by all state machines..define public PIN_RW 0.define public PIN_E 1.define public PIN_A0 2.define public PIN_SEL1 26.define public NO_SEL_PINS 3// Bit patterns used to select one of the 3 LVC245 buffer chips..define NOTHING 0b111.define ADDRESS_LOW 0b011.define ADDRESS_HIGH 0b101.define DATA 0b110/************************************************************************************************** Read code, handles reads from pico - > 6809. Wait for a transition of E 0->1 First R/W is tested, if it is a write then spin until the end of the cycle doing nothing If it is a read...... Address is latched from 6809 bus A14..A0 R/W bits is inserted in b15 Top bits of of arm address inserted from reg X which is setup by the C code. This will trigger an autopush, whe then block waiting for DMA to fill the OSR. This is then passed to ReadDMA1 (see C code), which puts this address in the source address for ReadDMA2, which fetches the byte from the Memory[] array and pushes it to the isr, the code below then pulls this and outputs it on the 6809's data bus until just after E falls. ISR is 32 bits and shifts right, and is autopushed. OSR is 8 bits and shifts right. **************************************************************************************************/ .program get_addr_read.side_set 3 optget_addr_read_start: wait 0 GPIO PIN_E ; ensure SM starts at beginning of a bus cycle wait 1 GPIO PIN_E side ADDRESS_LOW ; wait for E clock 0 -> 1 jmp PIN read_is_read ; this is a read, process it// This is a write, spin until end of bus cycle, write state machine will handle wait 0 GPIO PIN_E ; wait for end of cycle jmp get_addr_read_start ; loop againread_is_read:get_addr: nop [1] nop [1] in PINS 8 ; read address A0-A7 nop [1] side ADDRESS_HIGH ; slelect A8-A15 nop [1] nop [1] set y 1 [1] in PINS 7 ; read address A8-A14 in x 17 ; get MSW of address from X register// This should autopush here pull block ; wait for and get data from DMA chain out PINS 8 side DATA ; output Data mov osr, ~NULL out PINDIRS 8 ; Set direction = out wait 0 GPIO PIN_E ; wait for E->0 nop [1] nop [1] nop [1] mov osr, NULL ; set direction = in out PINDIRS 8 side ADDRESS_LOW jmp get_addr_read_start ; loop for next address% c-sdk {// this is a raw helper function for use by the user which sets up the GPIO output, and configures the SM to output on a particular pinvoid get_addr_read_init(PIO pio, uint sm, uint offset) { pio_sm_config c = get_addr_read_program_get_default_config(offset); sm_config_set_jmp_pin (&c, PIN_RW); sm_config_set_in_pins(&c, PIN_A0); sm_config_set_in_pin_count(&c, 8); sm_config_set_out_pins(&c, PIN_A0, 8); sm_config_set_sideset(&c, 4, true, false); sm_config_set_sideset_pins(&c, PIN_SEL1); sm_config_set_in_shift(&c, true, true, 32); pio_sm_set_consecutive_pindirs (pio, sm, PIN_SEL1, 3, true); sm_config_set_out_shift(&c, true, false, 8); sm_config_set_clkdiv(&c, 1); pio_sm_init(pio, sm, offset, &c);}%}Code:
static void SetPIO_x(PIO pio, uint8_t StateMachine, uint32_t XValue){ printf("setting state machine %d X to %lx\n",StateMachine,XValue); pio_sm_put_blocking(pio,StateMachine, XValue); pio_sm_exec_wait_blocking(pio, StateMachine, pio_encode_pull(false,false)); pio_sm_exec_wait_blocking(pio, StateMachine, pio_encode_mov(pio_x,pio_osr));}in my main program...... SMOffset = pio_add_program(pio, &get_addr_read_program); get_addr_read_init(pio, SMC_READ, SMOffset); pio_sm_clear_fifos(pio, SMC_READ); pio_sm_set_enabled(pio, SMC_READ, true); // Setup upper word of address for DMA SetPIO_x(pio,SMC_READ, (uint32_t)ReadRAM >> 15); // Initialize DMA for 6809 bus read and writes Setup_Read_DMA(SMC_READ);Code:
void ReadDMA_Handler() { // In here we'll check for reads from registers and set flags for mainline code to dispatch them. //printf("%lx=[%02x]\n",dma_hw->ch[ReadDMA2].al3_read_addr_trig,*(uint8_t *)(dma_hw->ch[ReadDMA2].al3_read_addr_trig)); // Clear the interrupt request. GreenLEDToggle(); dma_hw->ints0 = 1u << ReadDMA2; }// Setup read memory DMA chainvoid Setup_Read_DMA(uint8_t StateMachine){ 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 pointer on transfer channel_config_set_transfer_data_size(&Config, DMA_SIZE_8); // 8 bits dma_channel_set_transfer_count(ReadDMA2, 1, false); // 1 byte at a time don't retrigger dma_channel_set_write_addr(ReadDMA2, &(pio->txf[StateMachine]),false); // send the data to the state machine's isr channel_config_set_chain_to(&Config,ReadDMA1); // Chain to dma 1 when done dma_channel_set_config(ReadDMA2, &Config, false); // set config for dma2, don't trigger 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_read_increment(&Config,false); // Don't increment pointer on transfer channel_config_set_dreq(&Config, pio_get_dreq(pio,StateMachine,false)); // Set data request to StateMachine's drq // Channel size defaults to 32 bits dma_channel_set_transfer_count(ReadDMA1, 1, false); // 1 dword at a time don't retrigger dma_channel_set_read_addr(ReadDMA1, &(pio->rxf[StateMachine]),false); // Read output queue of state machine dma_channel_set_write_addr(ReadDMA1,&(dma_hw->ch[ReadDMA2].al3_read_addr_trig),false); // Write to dma2's read address register, don't trigger now dma_channel_set_config(ReadDMA1, &Config, true); // set config for dma1, trigger}If I comment out the "pull block" everything runs freely, but obviously no valid data is returned.
Can anyone spot what I've missed?
Cheers.
Phill.
Statistics: Posted by PhillHS — Wed Feb 04, 2026 3:53 pm — Replies 0 — Views 37