How to access XDMA BAR0 in Petalinux?

599 Views Asked by At

I have a block design and hardware configuration with a Zynq processor running Petalinux. I furthermore have an XDMA IP configured as a memory-mapped endpoint. I have configured BAR0 and BAR2 in the PCI BARs tab.

I am trying to write a simple program/app for petalinux that sets the correct configuration values in BAR0 for the host to read. I am, however, not sure where BAR0 is located nor how to write to it. How do I find the pointer to BAR0 in Petalinux?

1

There are 1 best solutions below

0
On BEST ANSWER

When you export the .xsa file you will have the BAR0 address defined in the register space of your PS. Furthermore you can decompile the device tree to check that the xilinx-xdma IP has the correct BAR registers:

./build/tmp/work/..../usr/bin/dtc -I dtb -O dts images/linux/system.dtb  > system.dts

vi system.dts

There you should find something like this (I have omitted some fields for clarity):

                axi-pcie@B0200000{
                        #address-cells = <0x03>;
                        #interrupt-cells = <0x01>;
                        #size-cells = <0x02>;
                        compatible = "xlnx,xdma-host-3.00";
                        device_type = "pci";
                        interrupt-names = "misc\0msi0\0msi1";
                        ranges = <0x2000000 0x00 0xb0200000 0x00 0xb0200000 0x00 0x100000>;
                        reg = <0x05 0x00 0x00 0x20000000>;
                        phandle = <0xab>;

The important info is in the ranges property. This info is parsed at boot time by linux to know where the BAR0 is.

We also know that the driver will be xdma-host-3.00 that drives the PCI low level communication (source), checks if the link is up and handles the MSI interrupts.

From here you have countless opportunities depending on which device you have attached to the PCIe bus. If there is an NVMe disk, for instance, the Xilinx drivers for the NVMe will use the PCIe drivers to talk to the end-point.

However, if you want to have access to the BAR registers for a special or custom end-point you can use the pci_uio_generic driver, which maps the PCIe resources on a generic user space IO device.

There is some documentation here or in the DPDK library.

The basic idea, however, is that once you have bound the driver to the PCIe device, you'll find a new uio device under

/sys/class/uio/uio<dev_num>/device/resource0

And if you mmap such resource, you'll have a virtual memory address pointing directly into the BAR0 of your PCIe device.