UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Observer ishahak
Observer
4,855 Views
Registered: ‎01-31-2018

How to access AXI registers under Petalinux?

Jump to solution

I'm a software guy, working on Zynq UltraZed + IOCC board from Avnet.

I got a hardware declaration (HDF) file from an FPGA developer, and created a petalinux project using the following technique:

 

  • First, I've put the HDF file into a folder called "hdf". I unzipped the '.bit' file out of it into the same folder, because for some reason it was necessary.
  • Then I did the following:

cd <place for project>

petalinux-create --type project --template zynqMP --name <petalinux-proj>

cd <petalinux-proj>

mkdir hw_platform

cp <my-hdf-folder>/*.hdf hw_platform/uz_petalinux_hw.hdf
cp <my-hdf-folder>/*.bit hw_platform/system_wrapper.bit

petalinux-config --oldconfig --get-hw-description=./hw_platform

petalinux-build

petalinux-package --boot --fsbl images/linux/zynqmp_fsbl.elf --fpga hw_platform/system_wrapper.bit --uboot --force

 

After that, I've got BOOT.BIN and image.ub to put into the SD card, and rootfs.cpio file as the rootfs, which I was setting as NFS mount.

 

My plnx-aarch64-system.dts shows these lines:

   amba_pl@0 {
      #address-cells = <0x2>;
      #size-cells = <0x2>;
      compatible = "simple-bus";
      ranges;

      axi2regs@80002000 {
         compatible = "xlnx,axi2regs-1.1";
         reg = <0x0 0x80002000 0x0 0x1000>;
         xlnx,s00-axi-addr-width = <0xb>;
         xlnx,s00-axi-data-width = <0x20>;
      };

 

I was trying to use the python script described here to read the registers at 0x80002000, but these addresses seem to be non  accessible through /dev/mem.

 

Under my petalinux project folder, I see the following structure:

tree ./project-spec/hw-description/drivers
└── axi2regs_v1_0
    ├── data
    │   ├── axi2regs.mdd
    │   └── axi2regs.tcl
    └── src
        ├── axi2regs.c
        ├── axi2regs.h
        ├── axi2regs_selftest.c
        └── Makefile

 

The header file contains this:

* C-style signature:
* u32 AXI2REGS_mReadReg(u32 BaseAddress, unsigned RegOffset)

 

Questions:

  1. Does it mean that my linux build contains a driver for accessing the registers? Is there a way to verify that by looking under /sys/class?
  2. Is it possible to use something similar to /dev/mem to access the AXI registers?
  3. In the Vivado SDK, if I create an application project of type Linux, how can I setup the project to allow me to use the AXI2REGS_mReadReg API? I didn't find any clear tutorial for doing that.

 

I'll be very thankful for getting some answer...

 

 

Tags (3)
0 Kudos
1 Solution

Accepted Solutions
Highlighted
Observer ishahak
Observer
5,731 Views
Registered: ‎01-31-2018

Re: How to access AXI registers under Petalinux?

Jump to solution

Well it took me two weeks to find the solution:

 

Had to add clk_ignore_unused to the bootargs variable...

Without that, accessing the memory of the AXI was causing the machine to hang up, trying to read an answer from a non-clocked device.

 

I'll add that it is possible to use the /dev/mem and mmap, but it is better to use the generic-uio driver, as it is safer and accessible to non-root users.

 

To do that:

Find system-user.dtsi and add the following to its end, making sure to put the name for your own IP:

&axi2regs_0 {
   compatible = "generic-uio";
};

 

Also add your bootargs variable with this: uio_pdrv_genirq.of_id="generic-uio"

 

And also do "petalinux-config -c kernel" and go to "device drivers">"Userspace...", and there turn "Userspace io platform" into "*" by pressing "y".

 

So now you should have the generic-uio driver active and connected to your IP. To verify that, look under /sys/class/uio/uio0/maps/map0.


You can then install uioctl by Bryan Newbold and test the registers, for example you can read the first register using

./uioctl /dev/uio0 0x0

 

(to compile the uioctl tool, use the cross compiler found in your petalinux installation, e.g. 

/opt/plnx/tools/linux-i386/aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc)

 

And BTW, do not expect the memory addresses of AXI registers to appear under /proc/iomem, as it is not there.

 

So I've put here some of the many things that I have learned while struggling to get my board talking to me :)

-Itay

Tags (3)
4 Replies
Scholar vanmierlo
Scholar
4,826 Views
Registered: ‎06-10-2008

Re: How to access AXI registers under Petalinux?

Jump to solution

As suggested by the thread you mentioned, first try to verify with U-boot that you can access the registers (using md) without an OS.

Then try devmem on the linux command line.

There is no known linux kernel driver compatible with "xlnx,axi2regs-1.1".

0 Kudos
Observer ishahak
Observer
4,802 Views
Registered: ‎01-31-2018

Re: How to access AXI registers under Petalinux?

Jump to solution

Hi @vanmierlo,

 

Thank you so much for taking the time to respond!

Indeed, 'md 0x80002000' reads the registers correctly, allowing me to see the expected data.

However, devmem in Linux is failing, probably due to inaccessible memory:

 

# devmem 0x80002000

[   49.832660] INFO: rcu_sched detected stalls on CPUs/tasks:

[   49.838058]  2-...: (0 ticks this GP) idle=98d/140000000000000/0 softirq=449/449 fqs=2626

... 

 

Of course, there is no generic 'xlmx,axi2regs-1.1' driver. But isn't the above mentioned content of './project-spec/hw-description/drivers' mean that a driver was generated automatically for it?

Is it possible to manually edit the 'compatible' line, and put there a name of a generic linux driver?

 

I'll appreciate some help please.

0 Kudos
Highlighted
Observer ishahak
Observer
5,732 Views
Registered: ‎01-31-2018

Re: How to access AXI registers under Petalinux?

Jump to solution

Well it took me two weeks to find the solution:

 

Had to add clk_ignore_unused to the bootargs variable...

Without that, accessing the memory of the AXI was causing the machine to hang up, trying to read an answer from a non-clocked device.

 

I'll add that it is possible to use the /dev/mem and mmap, but it is better to use the generic-uio driver, as it is safer and accessible to non-root users.

 

To do that:

Find system-user.dtsi and add the following to its end, making sure to put the name for your own IP:

&axi2regs_0 {
   compatible = "generic-uio";
};

 

Also add your bootargs variable with this: uio_pdrv_genirq.of_id="generic-uio"

 

And also do "petalinux-config -c kernel" and go to "device drivers">"Userspace...", and there turn "Userspace io platform" into "*" by pressing "y".

 

So now you should have the generic-uio driver active and connected to your IP. To verify that, look under /sys/class/uio/uio0/maps/map0.


You can then install uioctl by Bryan Newbold and test the registers, for example you can read the first register using

./uioctl /dev/uio0 0x0

 

(to compile the uioctl tool, use the cross compiler found in your petalinux installation, e.g. 

/opt/plnx/tools/linux-i386/aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc)

 

And BTW, do not expect the memory addresses of AXI registers to appear under /proc/iomem, as it is not there.

 

So I've put here some of the many things that I have learned while struggling to get my board talking to me :)

-Itay

Tags (3)
Visitor roberttout
Visitor
1,950 Views
Registered: ‎04-23-2015

Re: How to access AXI registers under Petalinux?

Jump to solution

I had the same problem and spent a week trying to figure out whether it was a hardware or software problem. After a great deal of research i discovered the following fascinating comment in UG585…pdf:

‘Register APER_CLK_CTRL (0xF800012C)
These clocks must be enabled if you want to read from the peripheral register space.’

Bits[19:18] of register 0xF800012C are the I2C1 and I2C0 ports respectively. The default value of these bits == 1 (as documented in UG585). However, when i read this register bits[19:18] were zero. ‘Linux’ must have resets them – presumably on the grounds that the devices were not specified in the DTB and are therefore not used. The idea (i suppose) is to reduce the power by some small amount (having a lot of clocks wagging their tails unnecessarily can get expensive, so this was not necessarily the wrong decision – just a sand trap for young players who live between the virtual and physical world).

I set bits [19:18] in register 0xF800012C with the obvious code:

memoryFD = open(“/dev/mem”, O_RDWR);

u32P = mmap(0, 0x20, PROT_READ | PROT_WRITE, MAP_SHARED, memoryFD, (off_t)0xF8000000);
u32P[0x12C/4] = u32P[0x12C/4] | 0xC0000; //*[19:18] = 2'b11, enable I2c0 and I2C1 clocks
munmap((void*)u32P, 0x20);

and was then able to read the I2C registers using:

u32P = mmap(0, 0x20, PROT_READ | PROT_WRITE, MAP_SHARED, memoryFD, (off_t)0xE0004000); //I2C#0
for (ii=0; ii < 11; ii++) printf(“0x%08X\n”, u32P[ii];    
munmap((void*)u32P, 0x20);

and a similar set of statements for I2C1 at 0xE0005000.

*note the cautious assignment rather than ‘u32P[0x12C/4] |= 0xC0000;’ - probably irrelevant on the ARM.

The resulting registers had the POR values as expected, and now I can presumably drive the I2C’s from user space code.

Tags (3)