• 0
malkauns

Zynq basic interrupt help needed!

Question

I am trying to create an interrupt handler using Zynq.  I am using the Zybo board and am using the Linux kernel from the following link: https://github.com/Xilinx/linux-xlnx.git.  I have searched the Internet and I think I have everything set up properly but my handler never gets called in my driver.  Here is my block design:

block_design.png

... and my interrupts set up in vivado:

GIC.png

My dts file (attached here) contains the following:

ps7_gpio_0: ps7-gpio@e000a000 {
	#gpio-cells = <2>;
	clocks = <&clkc 42>;
	compatible = "xlnx,zynq-gpio-1.0";
	emio-gpio-width = <64>;
	gpio-controller ;
	gpio-mask-high = <0xc0000>;
	gpio-mask-low = <0xfe81>;
	interrupt-parent = <&ps7_scugic_0>;
	interrupts = <0 59 4>;
	reg = <0xe000a000 0x1000>;
} ;

I am trying to hook interrupt 91 on the PS that is triggered from PL using AXI GPIO.  I have subtracted 32 from 91 hence the <0 59 4> in the dts file.   My interrupt_v1_0 IP simply creates a 10ns pulse every second.  I expect to see my interrupt function being called in the driver every second once I load my bitstream and driver but this does not happen.  Can someone please check and tell me what I am doing wrong?  I have attached my driver, dts and code for my interrupt IP here.
 
Thanks.

zynq-zybo.dts

interrupt.vhd

driver.c

Share this post


Link to post
Share on other sites

Recommended Posts

  • 0

Hi malkauns,

I have asked some of our applications engineers about this; they will get back to you here on the Forum.

Thanks,
JColvin

Share this post


Link to post
Share on other sites
  • 0

you are looking at the processing system GPIO controller devicetree node. You should return that to it's original state and make a new axi_gpio device tree node that properly loads the axi_gpio driver. The node should look like:

		axi_gpio_1: gpio@FIXME {
			#gpio-cells = <2>;
			compatible = "xlnx,xps-gpio-1.00.a";
			gpio-controller ;
			interrupt-parent = <&intc>;
			interrupts = <0 29 4>;
			reg = <0xFIXME 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 = <0x1>;
			xlnx,gpio2-width = <0x20>;
			xlnx,interrupt-present = <0x1>;
			xlnx,is-dual = <0x0>;
			xlnx,tri-default = <0xFFFFFFFF>;
			xlnx,tri-default-2 = <0xFFFFFFFF>;
		};

The interrupt ID should be 29, because the first interrupt that gets used when attaching interrupts from the PL is actually interrupt 61, not interrupt 91 (91 is the last one when using all 16 interrupts). You will need to replace the FIXME's with the hexadecimal base address of your GPIO controller. 

FYI, if you use petalinux to generate your linux image then the device tree is generated automatically for you based on your Vivado project... plus you get to use all of Xilinx's great petalinux documentation :). You can find a ZYBO Petalinux 2015.4 project here:

https://github.com/Digilent/petalinux-bsps

It is documented here:

https://github.com/Digilent/petalinux-bsps/wiki/Quick-start-guide

 

 

Share this post


Link to post
Share on other sites
  • 0

Hi, Thanks for replying.  I followed your instructions above but when I run dtc -I dts -O dtb -o devicetree.dtb zynq-zybo.dts I get the following error message:


ERROR (phandle_references): Reference to non-existent node or label "intc"

If I use "-f to force output" I do not see the interrupt listed in /proc/interrupts.  

Please advise.

 

Share this post


Link to post
Share on other sites
  • 0

Hi, I've switched to PetaLinux.  After creating a new project based on Digilent-Zybo-Linux-BD-v2015.4.bsp I have added the node with address 41200000 that you suggested above to the following DTS files:

./build/linux/kernel/download/linux-digilent/arch/arm/boot/dts/zynq-zybo.dts
./build/linux/u-boot/download/u-boot-digilent/arch/arm/dts/zynq-zybo.dts

I didn't know which one was relevant so added to both.  After the build I copied BOOT.BIN and image.ub to the SD card and booted.  However, I am still not able to see anything new listed in /proc/interrupts.  I know I must be missing something.  Please help.  Also how do I get PetaLinux to generate my DTS based on my Vivado project?

Share this post


Link to post
Share on other sites
  • 0

I can see the following 2 interrupts but they always remain zero after loading my bitfile:

 73:          0          0  zynq-gpio  50  btn4
 74:          0          0  zynq-gpio  51  btn5

I guess these are mapped only to the physical buttons.  I also periodically get the following messages after loading my bitfile. Not before:

cdns-i2c e0005000.i2c: timeout waiting on completion

Really need help on this one please!

Edited by malkauns

Share this post


Link to post
Share on other sites
  • 0

sorry for the delay... Glad you switched to petalinux, it will make your life much easier. 

What you need to do is import the .hdf file from your vivado project into the petalinux project you downloaded. This will cause your axi-gpio core to get detected and a device tree node will automatically get created for it by petalinux.

Rather than import the .hdf from the project you have, I would recommend starting with our ZYBO "linux_bd" design and adding in your custom IP. Then you can rebuild the project and export the .hdf from that project. The reason for this is because the linux_bd project has some important features that are required for embedded linux to run properly. It also includes an audio codec controller and video output pipeline that are usable from Linux, but I can walk you through removing them if you don't want them in your design. 

The linux_bd project is found in the ZYBO repo here: https://github.com/Digilent/ZYBO . It was build using Vivado 2015.4. For instructions on opening that project, see this guide:

https://reference.digilentinc.com/learn/software/tutorials/vivado-projects-from-digilent-github/start?redirect=1id=vivado/github

Once you have your hdf file copy it to the petalinux project directory and run the following commands to regenerate BOOT.bin and image.ub :

petalinux-config --get-hw-description=./
(Exit out of the menu that opens)
petalinux-build
petalinux-package --boot --force --fsbl ./images/linux/zynq_fsbl.elf --fpga ./images/linux/linux_bd_wrapper.bit --u-boot -o ./images/linux/BOOT.bin

Finally, copy BOOT.bin and image.ub from the images/linux folder in your petalinux project to your microSD card and you should be able to boot into linux with your gpio controller present.

To learn a lot more about what is going on, I recommend that you read through this guide:

http://www.xilinx.com/support/documentation/sw_manuals/petalinux2015_4/ug1144-petalinux-tools-reference-guide.pdf

Let me know if it works out

Share this post


Link to post
Share on other sites
  • 0

Thanks for all your help so far but now my Zybo gets stuck during boot at:

bootconsole [earlycon0] disabled

For reference these are the commands I am using on Ubuntu 16.04 to build after installing Vivado 2014.4.

sudo apt-get install tofrodos iproute tftpd-hpa gawk gcc git-core make net-tools libncurses5-dev zlib1g-dev libssl-dev flex bison lib32z1 lib32ncurses5 lib32stdc++6 libselinux1
sudo dpkg-reconfigure dash #select No
sudo mkdir /opt/PetaLinux
cd /opt/PetaLinux
download: ./petalinux-v2015.4-final-installer-dec.run and follow instructions to install
cd ~/
git clone https://github.com/Digilent/petalinux-bsps.git
source /opt/Xilinx/SDK/2014.4/settings64.sh
source /opt/Petalinux/petalinux-v2015.4-final/settings.sh
petalinux-create -t project -s ~/petalinux-bsps/releases/Digilent-Zybo-Linux-BD-v2015.4.bsp
cd ~/Digilent-Zybo-Linux-BD-v2015.4
petalinux-config
petalinux-config -c kernel #.. save and exit menu
petalinux-config -c u-boot #.. save and exit menu
petalinux-config -c rootfs #.. save and exit menu
petalinux-build

git clone https://github.com/Digilent/ZYBO.git
cp ~/ZYBO/Projects/linux_bd/sdk/linux_bd_wrapper_hw_platform_0/system.hdf ~/Digilent-Zybo-Linux-BD-v2015.4
cd ~/Digilent-Zybo-Linux-BD-v2015.4
petalinux-config --get-hw-description=./ #exit menu
petalinux-build
petalinux-package --boot --force --fsbl ./images/linux/zynq_fsbl.elf --fpga ./images/linux/linux_bd_wrapper.bit --u-boot -o ./images/linux/BOOT.bin

I have pasted a full Zybo boot log here: http://pastebin.com/T1wXtG4K

Appreciate any response.  Am I using the correct system.hdf file?

Edited by malkauns

Share this post


Link to post
Share on other sites
  • 0

I think I know this one... Your linux kernel is actually still running, just a terminal is not getting created on ttyPS1 (the USB-UART). This is due to a bug in petalinux where PS0 is always indicated as the serial device in the bootargs if it is enabled in the hardware design. This only pops up if you use the new .hdf because linux_bd has recently been updated to enable UART0 over EMIO and connects it to a Pmod connector. The .hdf included with the petalinux bsp has not been updated yet to incorporate this. 

Here is the fix. Open ./Digilent-Zybo-Linux-BD-v2015.4/components/apps/inittab_customisation/Makefile. Replace the "install: $(APP)" section (starting at line 24) with the following:

install: $(APP)
	$(TARGETINST) -a "0:12345:respawn:/sbin/getty 38400 tty0" /etc/inittab
	$(TARGETINST) -a "PS1:2345:respawn:/sbin/getty -L 115200 ttyPS1 vt100" -A "PS1" /etc/inittab

You will also need to make sure that INITTAB_CUSTOMISATION is enabled as an app in the rootfs 

That will force a terminal to get started over USB-UART, while not having to override petalinux's automatically generated bootargs.

Share this post


Link to post
Share on other sites
  • 0

Thanks for the tip.  I would never have known that!  So it boots now (after a few seconds of delay at "bootconsole [earlycon0] disabled") but when I do a cat /proc/interrupts I get the following:

           CPU0       CPU1       
 16:          0          0       GIC  27  gt
 17:          0          0       GIC  43  ttc_clockevent
 18:       4942       2578       GIC  29  twd
 21:         43          0       GIC  39  f8007100.adc
 73:          0          0  zynq-gpio  50  btn4
 74:          0          0  zynq-gpio  51  btn5
141:          8          0       GIC  57  cdns-i2c
142:         75          0       GIC  80  cdns-i2c
144:          0          0       GIC  35  f800c000.ocmc
145:         28          0       GIC  59  xuartps
146:         89          0       GIC  82  xuartps
147:          0          0       GIC  58  e0006000.spi
148:          0          0       GIC  81  e0007000.spi
149:          3          0       GIC  51  e000d000.spi
150:          0          0       GIC  54  eth0
151:         81          0       GIC  56  mmc0
152:          0          0       GIC  45  f8003000.dmac
153:          0          0       GIC  46  f8003000.dmac
154:          0          0       GIC  47  f8003000.dmac
155:          0          0       GIC  48  f8003000.dmac
156:          0          0       GIC  49  f8003000.dmac
157:          0          0       GIC  72  f8003000.dmac
158:          0          0       GIC  73  f8003000.dmac
159:          0          0       GIC  74  f8003000.dmac
160:          0          0       GIC  75  f8003000.dmac
161:          0          0       GIC  40  f8007000.devcfg
167:          0          0       GIC  53  e0002000.usb
168:          0          0       GIC  41  f8005000.watchdog
172:          0          0       GIC  62  xilinx-vdma-controller
173:          0          0       GIC  63  xilinx_vtc
IPI1:          0          0  Timer broadcast interrupts
IPI2:       1151       1039  Rescheduling interrupts
IPI3:          0          0  Function call interrupts
IPI4:         10         40  Single function call interrupts
IPI5:          0          0  CPU stop interrupts
IPI6:          0          0  IRQ work interrupts
IPI7:          0          0  completion interrupts
Err:          0

Aren't any AXI GPIO's with interrupts enabled supposed to be listed here?

Edited by malkauns

Share this post


Link to post
Share on other sites
  • 0

I expect the axi_gpio_hdmi gpio controller to have an interrupt, all others should not (they don't enable interrupts in the vivado block diagram).

I'm not confident on whether or not it should show up there, that will take some research... I glanced at the axi_gpio driver and at first glance it seems to be setting up the interrupt correctly.

Can you post the contents of Digilent-Zybo-Linux-BD-v2015.4/subsystems/linux/configs/device-tree/pl.dtsi to see what device tree nodes are getting generated? Also, an updated boot log would help.

Share this post


Link to post
Share on other sites
  • 0

Try rebuilding your kernel, but first set the "CONFIG_DEBUG_GPIO" KConfig option using "petalinux-config -c kernel". Then repost your boot log.

If the IRQ for the axi_hdmi_gpio IP core is being setup correctly then you should see a message of the form 

"IRQ Base: %d, Pin %d = IRQ %d\n"

 

Share this post


Link to post
Share on other sites
  • 0

After digging around some GPIO drivers and other drivers that register interrupts, I think that what you are seeing might be expected. I'm getting the feeling that GPIO drivers don't register a complete interrupt, but rather some sort of "incomplete" interrupt (my own terminology here, not the kernel's) that requires another driver on top of it to assign some additional functionality to a particular pin's interrupt. I believe this is why you also don't see drivers in /proc/interrupts for the zynq GPIO device, which should always be present. The reasoning for such a system makes sense: A GPIO controller alone signaling an interrupt doesn't mean much to the system until another driver assigns meaning to a particular pin's interrupt.

This also explains why the btn4 and btn5 do show up as interrupts: they leverage the gpio-keys driver. I recommend you try doing the same for your gpio input. With that driver, you can make your interrupt trigger an input event, such as a key press on a keyboard. Then you can write userspace code that responds to the input event.

To do this look at system-top.dts in the subsystems folder of the petalinux project. Add the following node to the gpio-keys node:

my_irpt {
			label = "my_irpt";
			gpios = <&MY_GPIO_LABEL 0 0>;
            /*Additional Input Event Options Here*/
		};

Replace the GPIO label with the axi_gpio label for your axi_gpio core as found in pl.dtsi. I'm not entirely sure that the gpio indexing starts at 0, so it might be <&LABEL 1 0>. For information on how to define different types of input events refer to the gpio-keys documentation.

DISCLAIMER: I just drew a lot of conclusions about the Linux interrupt and gpio sub-systems from about 45 min of clunking around through code. I may have some of this wrong :wacko:

Share this post


Link to post
Share on other sites
  • 0

Sorry for the delay and once again thanks for your help so far.  I ran the following commands and set the GPIO DEBUG option:

petalinux-config -c kernel
petalinux-config --get-hw-description=./
petalinux-build
petalinux-package --boot --force --fsbl ./images/linux/zynq_fsbl.elf --fpga ./images/linux/linux_bd_wrapper.bit --u-boot -o ./images/linux/BOOT.bin

I see "Symbol: DEBUG_GPIO [=y]" in my kernel config but do not get the output you mentioned above.  Here is the latest boot log: http://pastebin.com/xYAiCs6P.  When I add the my_irpt code to system-top.dts this results in the removal of:

73:          0          0  zynq-gpio  50  btn4
74:          0          0  zynq-gpio  51  btn5

from /proc/interrupts and my_irpt is not present.

pl.dtsi: http://pastebin.com/K0W0etC0

system-top.dts: http://pastebin.com/aGnrYAPu

Share this post


Link to post
Share on other sites
  • 0

It looks like you also need to change the kernel log level to see the messages. This is done by adding "debug" to the bootargs. In petalinux, this means you will have to override the automatically generated bootargs. You can do this from petalinux-config (with no '-c' option) in the Kernel  Bootargs menu. Make note of the auto generated bootargs, disable "generate boot args automatically", then set the "user set kernel bootargs" option to be whatever the auto generated bootargs were but with debug appended. For my petalinux project this would make:

 console=ttyPS0,115200 earlyprintk debug

As for your gpio-keys node, the linux,code is required. Try using this instead:


        my_irpt {
            label = "my_irpt";
            gpios = <&axi_gpio_hdmi 0 0>;
            linux,code = <103>; /* up */
        };

Also note I changed the gpio index back to 0. I'm pretty sure that is right.

Edit: A fun side note, if this does work, you will have caused the system to trigger an up-arrow keyboard press event whenever an hdmi monitor is connected.

Share this post


Link to post
Share on other sites
  • 0

Thanks.  So it looks like we've got a little further and can see the following message during boot which corresponds to the address assigned to axi_gpio_hdmi in pl.dtsi:

gpiochip_add: registered GPIOs 901 to 901 on device: /amba_pl/gpio@41230000
IRQ Base: 175, Pin 0 = IRQ 175

I added the my_irtp code to: Digilent-Zybo-Linux-BD-v2015.4/subsystems/linux/configs/device-tree/system-top.dts but there is still no new interrupt under /proc/interrupts.  Am I right in assuming that axi_gpio_hdmi should show up there?

latest boot log: http://pastebin.com/BXqmiDQ3

 

Share this post


Link to post
Share on other sites
  • 0

Looks like our my_irpt node is breaking the gpio-keys driver. My first guess is to try to use a unique linux,code instead of re-using "up". Try this:

my_irpt {
            label = "my_irpt";
            gpios = <&axi_gpio_hdmi 0 0>;
            linux,code = <105>; /* left */
        };

Share this post


Link to post
Share on other sites
  • 0

Does the Xilinx AXI interrupt controller support edge-triggered interrupts? If not, then the interrupt signal may be deasserted by the time the interrupt controller's driver goes to look at the status register.

Most devices use level sensitive interrupts that remain asserted until acknowledged by the interrupt handler to avoid this problem.

 

Share this post


Link to post
Share on other sites
  • 0

Sorry for not getting back sooner.  I got side tracked with other aspects of my project.  The above solution of using a different linux code did not work.  However, cat /proc/interrupts looks like this once I load my driver and before loading my bit file:

           CPU0       CPU1       
 16:          0          0       GIC  27  gt
 17:          0          0       GIC  43  ttc_clockevent
 18:       1009       2507       GIC  29  twd
 21:         43          0       GIC  39  f8007100.adc
 61:          0          0  zynq-gpio  38  int-test
141:          8          0       GIC  57  cdns-i2c
142:          8          0       GIC  80  cdns-i2c
...

I have it hooking (virtual interrupt??) 61 which should hook 29 (61-32).  Once I load my bitfile using: cat design_1_wrapper.bit > /dev/xdevcfg the interrupt counter for int-test does not increment as it should every second.  I think the driver side is correct as it shows up in the interrupts list but something is wrong on the PL side.  Oh, and once I load my bitfile I periodically get these messages:

cdns-i2c e0005000.i2c: timeout waiting on completion
cdns-i2c e0005000.i2c: timeout waiting on completion
cdns-i2c e0005000.i2c: timeout waiting on completion
cdns-i2c e0005000.i2c: timeout waiting on completion

 

Share this post


Link to post
Share on other sites
  • 0

Can you provide the gpio-keys device node so I can see how you setup the int-test interrupt? Also, are you connecting your interrupt_v1_0 core directly to the zynq GPIO controller over emio, or an axi_gpio controller (as pictured in the block diagram of your initial post)? I'm starting to get the feeling that the axi_gpio linux driver isn't compatible with the gpio-keys driver for some reason, so I think the best thing to do would be to connect the output of your IP core directly to the zynq gpio controller over EMIO. This would also protect from any potential interrupt problems such as those that Jamey mentioned.

Share this post


Link to post
Share on other sites
  • 0

Here is my system_top.dts that contains the gpio-keys device node: http://pastebin.com/z8JLPLAC.  My interrupt_v1_0 is connected exactly as shown in the first post.  I did try connecting the pulse signal directly to IRQ_F2P[0:0] on the zynq processing system.  This results in the system pausing while the interrupt is set high from the PL.  I modified my interrupt.vhd slightly:

process(CLK)
        
        variable n : integer := 0;
        variable p : std_logic := '0';
     
    begin

        if rising_edge(CLK) then

            n := n + 1;

            if n = (100000000-1)/2 then
                n := 0;
                p := not p;
            end if;

        end if;

        pulse <= p;

end process;

serial input is halted for 1/2 second at a time.  However the int-test counter in /proc/interrupts still does not increment for any of the cpu's.

Edited by malkauns

Share this post


Link to post
Share on other sites
  • 0

Hi @sbobrowicz,

I am playing with petalinux and the Zybo Board. I downloaded the last linux_bd project from the Digilent Git repo and I upgraded it to Vivado 2016.4.

Then I went through all the steps of UG1144 to run a petalinux system on my Zybo. If I do not modify any settings in the top system configuration menu (that appears after typing petalinux-config) I get the system stalled after "bootconsole [earlycon0] disabled" is printed.

So, after reading what you wrote: "Your linux kernel is actually still running, just a terminal is not getting created on ttyPS1 (the USB-UART). This is due to a bug in petalinux where PS0 is always indicated as the serial device in the bootargs if it is enabled in the hardware design. This only pops up if you use the new .hdf because linux_bd has recently been updated to enable UART0 over EMIO and connects it to a Pmod connector. The .hdf included with the petalinux bsp has not been updated yet to incorporate this."

...I unchecked the "generate boot args automatically" option inside the top system configuration menu and I added "console=ttyPS1,115200 earlyprintk" as a "user set kernel bootargs". Now the boot procedure stalls after printing:

Public key portion is:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC1786RibT8XBySCvTwuulHe7L/aDRhPsOQbQi7kDjI4A4sqiFR21mSEOQeb9LdrI2MCcFgg8ulo0wQswsWIqQtD7wn8VLSNBCJMYb35fe1AE3CviKR4W8QYGJv6ATI4EuY+o9vMvl9hxkNQVwLIEO7yJfQg97Cd7Dl0h7vU+wtPlgnP++YmhOpdOzSXgWIqYO7F4/ARxkOh5OtFYzfiunEme1b5qB07ejXsOCBPmW5oxuHbM4EZOUve0b7F0HmacsNCqQg04queR3PZtzR/Sq26JjS0op3wijdileQLI6cliXd0riFEOBu8WP4IYjHtYC0m4x+NnKQjPaQ2dcvZsGr root@plnx_arm
Fingerprint: md5 85:75:45:a8:93:ee:43:b4:6c:34:68:44:65:72:6a:c2
dropbear.
Starting syslogd/klogd: done
Starting tcf-agent: OK

Could you please help me solve this problem?

Thank you 

Enrico
 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now