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

General • PIO State machine / DMA interaction, only triggering once.

$
0
0
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 :

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);}%}
PIO init code :

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 For Setup_Read_DMA

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}
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.

Statistics: Posted by PhillHS — Wed Feb 04, 2026 3:53 pm — Replies 0 — Views 37



Viewing all articles
Browse latest Browse all 7503

Trending Articles