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: 
Explorer
Explorer
8,238 Views
Registered: ‎04-18-2017

Custom Hardware with UIO

Jump to solution

Hello,

 

Yet another similar post about UIO and petalinux. I have a custom ip which simply writes the 8 LEDS from the zedboard. And as outputs it reads the values from the switches and also generates a pulse with a push button. This is in a custom AXI-IP rather than using the AXI-GPIO. So, on the slv_reg0 I receive the value for the LEDS and on slv_reg1 I write the values from the switches on every rising edge of the axi_clk. The pulse generated from the PB is connected to IRQ_F2P[0:0]. This works fine in a standalone application coded in SDK with the auto generated functions to read and write the custom IP plus it reacts to the interrupt.

 

custom_ip.png

Just in case, I am using vivado and petalinux 2017.3.

 

Now I am eager to replicate the behavior on linux with the UIO. Therefore, this are the steps that I am following:

 

1. Create a new petalinux project

petalinux-create --type project --template zynq --name custom_ip

2. Get the custom hardware generated with vivado/sdk

petalinux-config --get-hw-description=/home/ariel/Documents/vivado_prjts/custom_ip/custom_ip.sdk

3. Configure the kernel with

CONFIG_UIO=y 
CONFIG_UIO_PDRV_GENIRQ=y

4. Build the project so it autogenerates the files needed

petalinux-build

5. Edit  <plnx_proj_root>/project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi so it looks like this:

/include/ "system-conf.dtsi"
/ {
    user_io@43c00000{
    compatible = "custom_ip,generic-uio,ui_pdrv";
    status = "okay";
	interrupt-parent = <&intc>;
	interrupts = <0 29 4>;
	reg = <0x43c00000 0x10000>;
    };
};

I extracted the values form interrupt-parent, interrupts and reg from  <plnx_proj_root>/components/plnx_workspace/device-tree/device-tree-generation/pl.dtsi. Also, the user_io@43c00000 is from pl.dtsi

 

6. Following some similar posts, they recommend edit <plnx_proj_root>/components/plnx_workspace/device-tree/device-tree-generation/system-conf.dtsi so it looks like this:

chosen {
bootargs = "console=ttyPS0,115200 earlyprintk uio_pdrv_genirq.of_id=generic-uio";
};

But I have seen that this is autogenerated. Therefore, after petalinux-build, the uio_pdrv_genirq.of_id=generic-uio part is removed. One suggestion was to edit <plnx_proj_root>/components/plnx_workspace/device-tree/device-tree-generation/system-top.dts but this is also autogenerated and therefore modified.

 

On this, I noticed that <plnx_proj_root>/project-spec/meta-user/recipes-dt does not exist.

 

$ ls <plnx_proj_root>/project-spec/meta-user/
conf  COPYING.MIT  README  recipes-apps  recipes-bsp  recipes-core  recipes-kernel

 

7. Build the project with my changes with petalinux-build

8. Package it:

petalinux-package --boot --format BIN --fsbl ./images/linux/zynq_fsbl.elf --fpga ./images/linux/design_1_wrapper.bit --u-boot --force

9. Copy <plnx_proj_root>/images/linux/* to the BOOT partition of the SD.

 

When linux boots, in /dev I do not see /dev/uio, but if I can read the switches and write the LEDS with:

 

devmem 0x41200000 32 0x000000ff   --To write to the LEDS

devmem 0x41210004                 --To read the switches.

The issue is as /dev/uio is missing, i will not be able to follow this guide to write a C application to include it later on petalinux.

 

The question is what step should I modify, add or remove to have /dev/uio 'created' so I can access it in a C code via the UIO?

 

Thank you for the help

1 Solution

Accepted Solutions
Xilinx Employee
Xilinx Employee
11,296 Views
Registered: ‎09-22-2015

Re: Custom Hardware with UIO

Jump to solution

We have seen an issue with generic-uio in previous versions of petalinux where eventhough you select it as a [Y], it would still not come up in /dev/. Please try this workaround. One thing to remember here is all changes to recipes-dt will be overwritten except for the file system-user.dtsi. You need to use this file only to add changes to device-tree.

 

How to enable UIO drivers so that it comes up after Linux bootup. 

Description

I have enabled the UIO drivers in the kernel config, but after Linux boots up I try

 

ls /dev/uio*

ls: /dev/uio*: No such file or directory

 

There are no devices listed under /dev

What should I do to make these come up after kernel boots.

 

Solution

  1. In the kernel config make the following changes to the kernel config menu for the User space I/O platform driver.

 

 

 

 

 

  1. In the device tree add the compatible string "generic-uio" for the gpio devices as well as add uio_pdrv_genirq.of_id=generic-uio to the kernel boot args.

 

 This should be added to system-user.dtsi inside

/{

chosen {

        bootargs = "earlycon=cdns,mmio,0xFF000000,115200n8 uio_pdrv_genirq.of_id=generic-uio";

        };

};

 

 

&axi_gpio_0 {

        compatible =  "generic-uio";

        };

&axi_gpio_1  {

        compatible =  "generic-uio";

        };      

 

 Build Linux and boot it up. Once you boot it up you should see the uio nodes after you ls into the /dev directory.

 

 

------------------------------------------------------------------------------------------------------------------------
Please mark an answer "Accept as solution" if a post has the solution to your issue.
------------------------------------------------------------------------------------------------------------------------
13 Replies
Xilinx Employee
Xilinx Employee
8,204 Views
Registered: ‎09-22-2015

Re: Custom Hardware with UIO

Jump to solution
Check your modules.dep under /lib/modules/. See if uio_pdrv_genirq exists as loadable module and load it using insmod <path-to-module>.
Check status of module using lsmod. See if nodes are created in /dev
------------------------------------------------------------------------------------------------------------------------
Please mark an answer "Accept as solution" if a post has the solution to your issue.
------------------------------------------------------------------------------------------------------------------------
0 Kudos
Explorer
Explorer
8,187 Views
Registered: ‎04-18-2017

Re: Custom Hardware with UIO

Jump to solution

Hello @akshayva,

 

I cannot see anything with uio in modules.dep:

 

 

root@custom_ip:~# cat /lib/modules/4.9.0-xilinx-v2017.3/modules.dep
kernel/crypto/echainiv.ko:
kernel/crypto/hmac.ko:
kernel/crypto/sha256_generic.ko:
kernel/crypto/drbg.ko:
kernel/crypto/jitterentropy_rng.ko:
kernel/drivers/usb/gadget/function/usb_f_ss_lb.ko: kernel/drivers/usb/gadget/libcomposite.ko
kernel/drivers/usb/gadget/function/usb_f_mass_storage.ko: kernel/drivers/usb/gadget/libcomposite.ko
kernel/drivers/usb/gadget/legacy/g_zero.ko: kernel/drivers/usb/gadget/libcomposite.ko
kernel/drivers/usb/gadget/libcomposite.ko:
kernel/drivers/virtio/virtio.ko:
kernel/drivers/virtio/virtio_ring.ko:
kernel/drivers/remoteproc/remoteproc.ko: kernel/drivers/virtio/virtio.ko kernel/drivers/virtio/virtio_ring.ko
kernel/drivers/remoteproc/zynq_remoteproc.ko: kernel/drivers/remoteproc/remoteproc.ko kernel/drivers/virtio/virtio.ko kernel/drivers/virtio/virtio_ring.ko
kernel/drivers/rpmsg/rpmsg_core.ko:
kernel/drivers/rpmsg/virtio_rpmsg_bus.ko: kernel/drivers/rpmsg/rpmsg_core.ko kernel/drivers/virtio/virtio.ko kernel/drivers/virtio/virtio_ring.ko
kernel/net/802/p8022.ko: kernel/net/llc/llc.ko
kernel/net/802/psnap.ko: kernel/net/llc/llc.ko
kernel/net/802/stp.ko: kernel/net/llc/llc.ko
kernel/net/ipv4/ipip.ko:
kernel/net/8021q/8021q.ko:
kernel/net/llc/llc.ko:
kernel/net/bridge/bridge.ko: kernel/net/802/stp.ko kernel/net/llc/llc.ko
root@custom_ip:~# cat /lib/modules/4.9.0-xilinx-v2017.3/modules.dep | grep uio
root@custom_ip:~#

 

What about step6? Is it correct?

 

In step 3, should they be =y or =m? I had it with =y. I switched to =m and now this is what I got:

 

 

root@custom_ip:~# cat /lib/modules/4.9.0-xilinx-v2017.3/modules.dep
kernel/crypto/echainiv.ko:
kernel/crypto/hmac.ko:
kernel/crypto/sha256_generic.ko:
kernel/crypto/drbg.ko:
kernel/crypto/jitterentropy_rng.ko:
kernel/drivers/usb/gadget/function/usb_f_ss_lb.ko: kernel/drivers/usb/gadget/libcomposite.ko
kernel/drivers/usb/gadget/function/usb_f_mass_storage.ko: kernel/drivers/usb/gadget/libcomposite.ko
kernel/drivers/usb/gadget/legacy/g_zero.ko: kernel/drivers/usb/gadget/libcomposite.ko
kernel/drivers/usb/gadget/libcomposite.ko:
kernel/drivers/usb/serial/usbserial.ko:
kernel/drivers/usb/serial/ftdi_sio.ko: kernel/drivers/usb/serial/usbserial.ko
kernel/drivers/virtio/virtio.ko:
kernel/drivers/virtio/virtio_ring.ko:
kernel/drivers/uio/uio.ko:
kernel/drivers/uio/uio_pdrv_genirq.ko: kernel/drivers/uio/uio.ko
kernel/drivers/uio/uio_dmem_genirq.ko: kernel/drivers/uio/uio.ko
kernel/drivers/uio/uio_xilinx_apm.ko: kernel/drivers/uio/uio.ko
kernel/drivers/remoteproc/remoteproc.ko: kernel/drivers/virtio/virtio.ko kernel/drivers/virtio/virtio_ring.ko
kernel/drivers/remoteproc/zynq_remoteproc.ko: kernel/drivers/remoteproc/remoteproc.ko kernel/drivers/virtio/virtio.ko kernel/drivers/virtio/virtio_ring.ko
kernel/drivers/rpmsg/rpmsg_core.ko:
kernel/drivers/rpmsg/virtio_rpmsg_bus.ko: kernel/drivers/rpmsg/rpmsg_core.ko kernel/drivers/virtio/virtio.ko kernel/drivers/virtio/virtio_ring.ko
kernel/net/802/p8022.ko: kernel/net/llc/llc.ko
kernel/net/802/psnap.ko: kernel/net/llc/llc.ko
kernel/net/802/stp.ko: kernel/net/llc/llc.ko
kernel/net/ipv4/ipip.ko:
kernel/net/8021q/8021q.ko:
kernel/net/llc/llc.ko:
kernel/net/bridge/bridge.ko: kernel/net/802/stp.ko kernel/net/llc/llc.ko
root@custom_ip:~# cat /lib/modules/4.9.0-xilinx-v2017.3/modules.dep | grep uio
kernel/drivers/uio/uio.ko:
kernel/drivers/uio/uio_pdrv_genirq.ko: kernel/drivers/uio/uio.ko
kernel/drivers/uio/uio_dmem_genirq.ko: kernel/drivers/uio/uio.ko
kernel/drivers/uio/uio_xilinx_apm.ko: kernel/drivers/uio/uio.ko

I loaded it with insmod but I still cannot see /dev/uio but it shows with lsmod:

root@custom_ip:/lib/modules/4.9.0-xilinx-v2017.3/kernel/drivers/uio# lsmod
    Not tainted
uio_pdrv_genirq 2754 0 - Live 0xbf01c000
uio 7190 1 uio_pdrv_genirq, Live 0xbf000000

Thanks for the help!

 

EDIT1:

I saw in another post that I should also edit pl.dtsi and add to compatible generic-uio. Should I?

/ {
	amba_pl: amba_pl {
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "simple-bus";
		ranges ;
		custom_ip_0: custom_ip@43c00000 {
			compatible = "xlnx,custom-ip-1.0 generic-uio";
			interrupt-parent = <&intc>;
			interrupts = <0 29 4>;
			reg = <0x43c00000 0x10000>;
			xlnx,s00-axi-addr-width = <0x4>;
			xlnx,s00-axi-data-width = <0x20>;
		};
	};
};
0 Kudos
Xilinx Employee
Xilinx Employee
11,297 Views
Registered: ‎09-22-2015

Re: Custom Hardware with UIO

Jump to solution

We have seen an issue with generic-uio in previous versions of petalinux where eventhough you select it as a [Y], it would still not come up in /dev/. Please try this workaround. One thing to remember here is all changes to recipes-dt will be overwritten except for the file system-user.dtsi. You need to use this file only to add changes to device-tree.

 

How to enable UIO drivers so that it comes up after Linux bootup. 

Description

I have enabled the UIO drivers in the kernel config, but after Linux boots up I try

 

ls /dev/uio*

ls: /dev/uio*: No such file or directory

 

There are no devices listed under /dev

What should I do to make these come up after kernel boots.

 

Solution

  1. In the kernel config make the following changes to the kernel config menu for the User space I/O platform driver.

 

 

 

 

 

  1. In the device tree add the compatible string "generic-uio" for the gpio devices as well as add uio_pdrv_genirq.of_id=generic-uio to the kernel boot args.

 

 This should be added to system-user.dtsi inside

/{

chosen {

        bootargs = "earlycon=cdns,mmio,0xFF000000,115200n8 uio_pdrv_genirq.of_id=generic-uio";

        };

};

 

 

&axi_gpio_0 {

        compatible =  "generic-uio";

        };

&axi_gpio_1  {

        compatible =  "generic-uio";

        };      

 

 Build Linux and boot it up. Once you boot it up you should see the uio nodes after you ls into the /dev directory.

 

 

------------------------------------------------------------------------------------------------------------------------
Please mark an answer "Accept as solution" if a post has the solution to your issue.
------------------------------------------------------------------------------------------------------------------------
Explorer
Explorer
8,170 Views
Registered: ‎04-18-2017

Re: Custom Hardware with UIO

Jump to solution

I just came to post this. I edited the system-user.dtsi (as stated in ug1144) adding the bootargs for uio plus the compatible for my custom_ip and that was it. It works now.

I have one more thing.....what if I want to user another kernel, for example ubuntu (as suggested here) so I can have apt-get for example and also have to possibility to store changes in the sd card on the second partition (rootfs)?

0 Kudos
Xilinx Employee
Xilinx Employee
8,157 Views
Registered: ‎09-22-2015

Re: Custom Hardware with UIO

Jump to solution

I 'm not sure about whether that is possible. But here are some options:

1. Use the smart package manager instead that comes with Yocto and part of petalinux. To enable this, please add:

│ Location: │
│ -> Filesystem Packages │
│ -> devel │
│ -> python │
│ (1) -> python-smartpm

 

2. Follow steps on this wiki-xilinx page which talks about Ubuntu on ZYNQ but its fairly old.(http://www.wiki.xilinx.com/Ubuntu+on+Zynq)

 

 

------------------------------------------------------------------------------------------------------------------------
Please mark an answer "Accept as solution" if a post has the solution to your issue.
------------------------------------------------------------------------------------------------------------------------
0 Kudos
Explorer
Explorer
8,140 Views
Registered: ‎04-18-2017

Re: Custom Hardware with UIO

Jump to solution

Hello @akshayva,

 

Other thing...I have been following this guide on how to write the UIO C code but it is general. My question is, if I have a custom AXI-IP with 4 32 bit register. How do I write to register N and read from register M?

 

Thanks again for the help!

 

EDIT 1: Perhaps to make it more clear, this is what I do in a standalone code in SDK in the interrup handler:

	u32 leds;
	leds = CUSTOM_IP_mReadReg(CUSTOM_IP_BASEADDR, CUSTOM_IP_S00_AXI_SLV_REG1_OFFSET);	// Read from the IP.
	CUSTOM_IP_mWriteReg(CUSTOM_IP_BASEADDR + CUSTOM_IP_S00_AXI_SLV_REG0_OFFSET, 0, leds);	// Write to the IP.
0 Kudos
Xilinx Employee
Xilinx Employee
8,117 Views
Registered: ‎09-22-2015

Re: Custom Hardware with UIO

Jump to solution

/dev/uioX is used to access the address space of the card. Just use mmap() to access registers or RAM locations of your card.

Please refer to this document for more information on how to use UIO. It is using mmap() on the /dev/uioX device file.

https://www.kernel.org/doc/html/v4.12/driver-api/uio-howto.html

 

------------------------------------------------------------------------------------------------------------------------
Please mark an answer "Accept as solution" if a post has the solution to your issue.
------------------------------------------------------------------------------------------------------------------------
0 Kudos
Xilinx Employee
Xilinx Employee
8,116 Views
Registered: ‎09-22-2015

Re: Custom Hardware with UIO

Jump to solution
Using linux kernel driver will give you a standard interface to the Custom IP and you should be able to use the same attributes as any other UIO device for AXI Custom IP. All you need to do is map on the device file and access register.
------------------------------------------------------------------------------------------------------------------------
Please mark an answer "Accept as solution" if a post has the solution to your issue.
------------------------------------------------------------------------------------------------------------------------
0 Kudos
Highlighted
Explorer
Explorer
8,095 Views
Registered: ‎04-18-2017

Re: Custom Hardware with UIO

Jump to solution

Thank you @akshayva for the help. I managed to read and write to different register in my custom ip:

 

This is my (auto-generated) pl.dtsi:

/ {
	amba_pl: amba_pl {
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "simple-bus";
		ranges ;
		custom_ip_0: custom_ip@43c00000 {
			compatible = "xlnx,custom-ip-1.0";
			interrupt-parent = <&intc>;
			interrupts = <0 29 4>;
			reg = <0x43c00000 0x10000>;
			xlnx,s00-axi-addr-width = <0x4>;
			xlnx,s00-axi-data-width = <0x20>;
		};
	};
};

The system-user.dtsi:

/include/ "system-conf.dtsi"
/ {
};

/ {
	model = "Zynq Zed Development Board";
	compatible = "xlnx,zynq-zed", "xlnx,zynq-7000";

	usb_phy0: phy0@e0002000 {
		compatible = "ulpi-phy";
		#phy-cells = <0>;
		reg = <0xe0002000 0x1000>;
		view-port = <0x0170>;
		drv-vbus;
	};
};

&clkc {
	ps-clk-frequency = <33333333>;
};

/ {
chosen {
    bootargs = "console=ttyPS0,115200 earlyprintk uio_pdrv_genirq.of_id=generic-uio";
    };

amba_pl: amba_pl {
		custom_ip_0: custom_ip@43c00000 {
			compatible = "generic-uio";
			interrupt-parent = <&intc>;
			interrupts = <0 29 1>;
	    };
	};
};

&usb0 {
	dr_mode = "host";
	usb-phy = <&usb_phy0>;
};

And the C code:

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <poll.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <sys/mman.h>


#define CUSTOM_IP_MAP_SIZE                  0x10000
#define CUSTOM_IP_BASEADDR	                0x43C00000
#define CUSTOM_IP_S00_AXI_SLV_REG0_OFFSET   0
#define CUSTOM_IP_S00_AXI_SLV_REG1_OFFSET   4
#define CUSTOM_IP_S00_AXI_SLV_REG2_OFFSET   8
#define CUSTOM_IP_S00_AXI_SLV_REG3_OFFSET   12

int main(void)
{
    uint32_t leds=0x0;
    int fd = open("/dev/uio0", O_RDWR);
    void *ptr;

    if (fd < 0) {
        perror("open");
        exit(EXIT_FAILURE);
    }
    ptr = mmap(NULL, CUSTOM_IP_MAP_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);

    while (1) {
        uint32_t info = 1; /* unmask */

        ssize_t nb = write(fd, &info, sizeof(info));
        if (nb < sizeof(info)) {
            perror("write");
            close(fd);
            exit(EXIT_FAILURE);
        }

        struct pollfd fds = {
            .fd = fd,
            .events = POLLIN,
        };

        int ret = poll(&fds, 1, -1);
        if (ret >= 1) {
            nb = read(fd, &info, sizeof(info));
            if (nb == sizeof(info)) {
                /* Do something in response to the interrupt. */
                printf("Interrupt #%u!\n", info);
                leds = *((unsigned *)(ptr + CUSTOM_IP_S00_AXI_SLV_REG1_OFFSET));    //Read from the IP (slv_reg1).
                printf("Switches: %d\n", leds);
                *((unsigned *)(ptr + CUSTOM_IP_S00_AXI_SLV_REG0_OFFSET)) = leds;    //Write to the IP (slv_reg0).
                printf("Wrote to leds\n");
            }
        } else {
            perror("poll()");
            close(fd);
            exit(EXIT_FAILURE);
        }
    }

    close(fd);
    exit(EXIT_SUCCESS);
}

Hopefully it helps someone with the same doubts.

0 Kudos
Scholar ronnywebers
Scholar
4,608 Views
Registered: ‎10-10-2014

Re: Custom Hardware with UIO

Jump to solution

@aripod, regarding the dtsi entry :

 

chosen {
bootargs = "console=ttyPS0,115200 earlyprintk uio_pdrv_genirq.of_id=generic-uio";
};

 

fyi : you can set manual bootargs in the config menu (at least in my Petalinux 2017.2). Not sure which is the best method : the system-user.dtsi or the bootargs in the config menu (never tried this last one)

** kudo if the answer was helpful. Accept as solution if your question is answered **
0 Kudos
4,042 Views
Registered: ‎06-12-2018

Re: Custom Hardware with UIO

Jump to solution

 Passing the argument in the config -c kernel. Doesnt let the uio show up in dev.

system-user.dtsi file should look like this.

 

/include/ "system-conf.dtsi"
/ {
};

/{

chosen {

bootargs = "earlycon=cdns,mmio,0xFF000000,115200n8 uio_pdrv_genirq.of_id=generic-uio";

};

};

 

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

0 Kudos
Visitor hanni_xu
Visitor
2,985 Views
Registered: ‎05-03-2018

Re: Custom Hardware with UIO

Jump to solution

hi,your code is very useful for me,but I don't understand one line:

int ret = poll(&fds, 1, -1);

what does it do ? and why?

0 Kudos
Explorer
Explorer
2,171 Views
Registered: ‎04-18-2017

Re: Custom Hardware with UIO

Jump to solution

That waits for the interrupt to happen

0 Kudos