I've been investigating the different options for interacting with the PL from the PS running Linux and have been having some issues with interrupts using userspace I/O (uio). I'm wondering if someone can help. The board is a Zedboard, and I am using the Xilinx Linux kernel version 4.6.
The fabric design is quite simple, as you can see in the block diagram*, with an interrupt from the gpio block connected to the Zedboard buttons. This works when running a bare machine application (the interrupt fires). It also works when I specify the device as a GPIO device in the device-tree:
I can enable the interrupt by setting the 'edge' value in/sys/class/gpio/and can see the interrupts counted in/proc/interrupts, corresponding to button presses:
To use uio, I change the compatible property in the device tree node to:compatible = "generic-uio";. I then (having rebooted) load the uio and uio_pdrv_genirq.ko modules (the latter with the parameterof_id="generic-uio"). The device/dev/uio0is created as expected and I can interact with the fabric via an mmap'ed memory pointer in a user space program - I can see the value change depending on which of the five buttons is pressed. So far so good!
I can see that the interrupt is created and that the GIC knows about it, via some debugging in the GIC code and also it is listed in/proc/interrupts:
But the interrupt never seems to be fire, or at least is never acknowledged. The count in/proc/interruptsnever increments and if put some debug statements into theuio_read()function in the driver it shows that the read never picks up an interrupt. My user space test code is very simple (edited highlights, error checking etc. removed):
... int fd; ssize_t value = 0; int count = 1;
fd = open("/dev/uio0", O_RDWR);
while(1) { value = write(fd, &count, sizeof(count)); value = read(fd, &count, sizeof(count));
if (value == sizeof(value)) { printf("interrupt!\n"); } } ...
The read blocks as expected but never unblocks when the buttons are pressed (and the interrupt supposedly fires).
So my questions are... does anything different have to be done at the Fabric design level (i.e. in Vivado) for an PL-PS interrupt to work with UIO? Is there anything I may have missed on the Linux side?
Question
sg4036
I've been investigating the different options for interacting with the PL from the PS running Linux and have been having some issues with interrupts using userspace I/O (uio). I'm wondering if someone can help. The board is a Zedboard, and I am using the Xilinx Linux kernel version 4.6.
The fabric design is quite simple, as you can see in the block diagram*, with an interrupt from the gpio block connected to the Zedboard buttons. This works when running a bare machine application (the interrupt fires). It also works when I specify the device as a GPIO device in the device-tree:
--snip--
axi_gpio_0: gpio@41200000 {
#gpio-cells = <2>;
#interrupt-cells = <2>;
compatible = "xlnx,xps-gpio-1.00.a";
gpio-controller ;
interrupt-controller ;
interrupt-parent = <&intc>;
interrupts = <0 29 4>;
reg = <0x41200000 0x10000>;
xlnx,all-inputs = <0x1>;
xlnx,all-inputs-2 = <0x0>;
xlnx,all-outputs = <0x0>;
xlnx,all-outputs-2 = <0x0>;
xlnx,dout-default = <0x00000000>;
xlnx,dout-default-2 = <0x00000000>;
xlnx,gpio-width = <0x5>;
xlnx,gpio2-width = <0x20>;
xlnx,interrupt-present = <0x1>;
xlnx,is-dual = <0x0>;
xlnx,tri-default = <0xFFFFFFFF>;
xlnx,tri-default-2 = <0xFFFFFFFF>;
};
--snip--
I can enable the interrupt by setting the 'edge' value in /sys/class/gpio/ and can see the interrupts counted in /proc/interrupts, corresponding to button presses:
root@target:/sys/class/gpio# echo 901 > export
root@target:/sys/class/gpio# cd gpio901
root@target:/sys/class/gpio/gpio901# echo rising > edge
[ 304.116780] xgpio_irq_unmask: Enable 0 irq, irq_enable_mask 0x0
<<press button a few times>>
root@target:/sys/class/gpio/gpio901# cat /proc/interrupts
CPU0 CPU1
...
165: 7 0 xgpio 0 Edge gpiolib
...
To use uio, I change the compatible property in the device tree node to: compatible = "generic-uio"; . I then (having rebooted) load the uio and uio_pdrv_genirq.ko modules (the latter with the parameter of_id="generic-uio"). The device /dev/uio0 is created as expected and I can interact with the fabric via an mmap'ed memory pointer in a user space program - I can see the value change depending on which of the five buttons is pressed. So far so good!
I can see that the interrupt is created and that the GIC knows about it, via some debugging in the GIC code and also it is listed in /proc/interrupts:
root@target:~# cat /proc/interrupts
...
164: 0 0 GIC-0 61 Level gpio
...
But the interrupt never seems to be fire, or at least is never acknowledged. The count in /proc/interrupts never increments and if put some debug statements into the uio_read() function in the driver it shows that the read never picks up an interrupt. My user space test code is very simple (edited highlights, error checking etc. removed):
...
int fd;
ssize_t value = 0;
int count = 1;
fd = open("/dev/uio0", O_RDWR);
while(1) {
value = write(fd, &count, sizeof(count));
value = read(fd, &count, sizeof(count));
if (value == sizeof(value)) {
printf("interrupt!\n");
}
}
...
The read blocks as expected but never unblocks when the buttons are pressed (and the interrupt supposedly fires).
So my questions are... does anything different have to be done at the Fabric design level (i.e. in Vivado) for an PL-PS interrupt to work with UIO? Is there anything I may have missed on the Linux side?
Any suggestions gratefully received.
* design from: https://embeddedcentric.com/interrupts/
Link to comment
Share on other sites
13 answers to this question
Recommended Posts
Archived
This topic is now archived and is closed to further replies.