Problems setting PIO Data Direction register

Hi, my first time here.
I have been fighting this problem 2 weeks, and have asked on Altera and ARM DS-5 forums, no luck.

I am working with a Terasic DE0-Nano-SoC board, mostly in Linux, and am working in DS-5 Community Edition 17.1.

I have created some PIO peripheral registers in Qsys / Platform Designer, connected to some well tested firmware, containing registers;
I have 2 output only PIOs, which are working fine.
I am also trying to both read and write from a bidirectional Qsys PIO,
and my change direction commands seem to be being ignored.
Perhaps I am not generating the Data Direction Register address correctly ?
Can you help ?
This data register PIO is bidirectional :

The bidirectional data PIO that can read readonly registers in my firmware,
but if I write data to read-write registers, and then read it back, it is always 0.
Tracing with SignalTap shows no data being output from the PIO on write.

Below is the crucial code, I am hoping someone can see where I am going wrong.
Is it the address calculation for the Data Direction register ?

This is for the Data register (which works for the output only PIOs) :
h2p_lw_pio_d_addr=virtual_base + ( ( unsigned long )( ALT_LWFPGASLVS_OFST + PIO_D_BASE ) & ( unsigned long)( HW_REGS_MASK ) );

Is this right for the Data Direction register ?
h2p_lw_pio_d_dirn = virtual_base + ( ( unsigned long )( ALT_LWFPGASLVS_OFST + PIO_D_BASE + 1 ) & ( unsigned long)( HW_REGS_MASK ) );

I am setting this as :
Write :
Set Data :
Data = strtol(argv[4], &strptr, 10); // Data to write
*(uint32_t *)h2p_lw_pio_d_addr = Data;
Output it :
*(uint32_t *)h2p_lw_pio_d_dirn = 0xff ; // All PIO Data bits set to output (write)

Set Input :
*(uint32_t *)h2p_lw_pio_d_dirn = 0x00 ; // All PIO Data bits set to input (read)
Read :
SkelData_read = *(uint32_t *)h2p_lw_pio_d_addr;

Any ideas what I am doing wrong ?
Cheers,
Beau

I have had a reply on the Altera Forumn, that has given me the answer :

[QUOTE=austin944;234454] Try it like this:
h2p_lw_pio_d_dirn = virtual_base + ( ( unsigned long )( ALT_LWFPGASLVS_OFST + PIO_D_BASE + 4 ) & ( unsigned long)( HW_REGS_MASK ) );

I understand the 1 vs 4 is due to word or byte addressing.

Working nicely now, able to read and write the registers in my own firmware, from C in Linux, via the SoC PIOs.
Time to add the rest of my firmware …

Beau Webber

1 Like