How to enable Interrupt when overlay(download=False)

So I’m fresh here but I already used PYNQ for a period. It’s really amazing and provides us various possibilities.
Now the problem is when I instant the interrupt with ol=Overlay(‘system.bit’,download=False), it turns out like this:

from pynq import Overlay, GPIO, Interrupt,UioController
import asyncio
import time
intr_inst = Interrupt('axi_intc_0/intr')
ValueError                                Traceback (most recent call last)
<ipython-input-1-5a03c77529e4> in <module>()
      3 import time
      4 ol=Overlay('system.bit',download=False)
----> 5 intc_ip=ol.axi_intc_0
      6 intr_inst = Interrupt('axi_intc_0/intr')

/usr/local/lib/python3.6/dist-packages/pynq/ in __getattr__(self, key)
    335         """
    336    #     if self.is_loaded():
--> 337         return getattr(self._ip_map, key)
    338    #     else:
    339    #         raise RuntimeError("Overlay not currently loaded")

/usr/local/lib/python3.6/dist-packages/pynq/ in __getattr__(self, key)
    735         elif key in self._description['ip']:
    736             ipdescription = self._description['ip'][key]
--> 737             driver = ipdescription['driver'](ipdescription)
    738             setattr(self, key, driver)
    739             return driver

/usr/local/lib/python3.6/dist-packages/pynq/ in __init__(self, description)
    600             self._gpio = {}
    601         for interrupt, details in self._interrupts.items():
--> 602             setattr(self, interrupt, Interrupt(details['fullpath']))
    603         for gpio, entry in self._gpio.items():
    604             gpio_number = GPIO.get_gpio_pin(entry['index'])

/usr/local/lib/python3.6/dist-packages/pynq/ in __init__(self, pinname)
     91         """
     92         if pinname not in PL.interrupt_pins:
---> 93             raise ValueError("No Pin of name {} found".format(pinname))
     95         parentname = PL.interrupt_pins[pinname]['controller']

ValueError: No Pin of name axi_intc_0/intr found

Considering I run the ADI RF board(ADRV9009) on the ZCU102, my environment is built in petalinux2019 with meta-adi and PYNQ2.4. Then I drive the board with ADI kernel driver and program with PYNQ. That results that I only can boot the system with bitstream inside boot.bin while ADI’s kernel doesn’t support FPGA Mange and the RF board kernel driver would crash if I download the bitstream in PYNQ. The bitstream can be downloaded and control the FPGA well by the PYNQ but I’ll lose control of the RF board after that.

Thus, so far I always boot with the wanted bitstream and use Overlay the same bitstream with download=‘False’. IPs in FPGA, like GPIO, MMIO, and DMA, can be controlled well with this procedure till now. The interrupt instance shows errors like the above and I guess it results from I didn’t load bitstream into PL server.
Before I overlay anything, I’ve checked the interrupt can be found under “/proc/interrupt” and “/sys/class/uio/uio4/name”. I’ve tested it with the same bitstream downloaded with overlay, the interrupt can work well while RF board goes down as expected. In the hardware design, the interrupt signal generated from my IP, connects to the AXI Interrupt Controller. Then the AXI Interrupt Controller connects to ps interrupt pin, just like the example in Zynq PS7 Interrupts.

I’ve also tried the method in the thread Minimal simple Interrupt handling with UIO device in Pynq but I got

controller = UioController("/dev/uio4")
event = asyncio.Event()
async def interrupt_test():
   while True:
       controller.add_event(event, 0) # Number is a dummy variable
       await event
       print("Interrupt Triggered")

loop = asyncio.get_event_loop()
TypeError                                 Traceback (most recent call last)
<ipython-input-15-93a1fd13b234> in <module>()
     10 loop = asyncio.get_event_loop()
---> 11 loop.run_until_complete(interrupt_test())

/usr/lib/python3.6/asyncio/ in run_until_complete(self, future)
    466             raise RuntimeError('Event loop stopped before Future completed.')
--> 468         return future.result()
    470     def stop(self):

<ipython-input-15-93a1fd13b234> in interrupt_test()
      5        event.clear()
      6        controller.add_event(event, 0) # Number is a dummy variable
----> 7        await controller
      8        print("Interrupt Triggered")

TypeError: object UioController can't be used in 'await' expression

So, is there any suggestion to allow me instant the interrupt like usual or another way to let me apply the interrupt within PYNQ?

Hi @Jesse_CP,

Are you using an interrupt controller to drive your interrupt? In this version of PYNQ you cannot connect the interrupts directly to the IRQ pin on the PS.

See discussion here


1 Like

Thanks for your reply Mario.

Yes, I use the AXI interrupter controller to drive my interrupt. I do not connect the interrupt directly from my IP to PS IRQ pin.

Here’s the screenshot of my design. The orange line connects to my IP.


Are you sure this is aligned?
[petalinux2019] [PYNQ2.4]?
Sound far beyond aligned Image.


Yes, you are correct. Seems Petalinux2019 should go with PYNQ2.5. But since the way I built it is adding the PYNQ dtsi to my petalinux project and customizing the rootfs from PYNQ image. Everything goes fine so far. I’ve tested each function provided by PYNQ, including the interrupt.

I’ll rebuild it with PYNQ2.5, but I don’t think this will solve the problem that how to use the interrupt class without downloading the bitstream. The bitstream is already loaded while booting. The GPIO, MMIO, and DMA classes from PYNQ are all can be applied with this procedure.

The reason I overlay with download=False is ADI kernel driver would crash if download the bitstream into FPGA. There are ADI interface IPs in the bitstream from boot.bin.
If ignored the ADI board supporting, then the Linux I built currently works totally well with PYNQ.

But still thank you for pointing out that.

I wonder if the ILA on the irq pin is causing a problem.

Can you also share the ip_dict for the interrupt controller?

The problem is happening in this line PYNQ/ at v2.4 · Xilinx/PYNQ · GitHub, so the pin is not being parsed properly for some reason.

1 Like

According to my experience last night that connected the GPIO to AXI Interrupt Controller while ILA all the irq wires, seems ILA wouldn’t cause interrupt working improperly.

But just in case, I removed the ILA and use the GPIO signal to imitate the interrupt signal. The problem remains.

Here’s the screenshot of the design currently and ADI interfaces are included. This hardware design has been verified that interrupt works well if overlay(download=True).

Here’s the result of ip_dict with download True and False.

With the download=True like the below screen, interrupt works well.

1 Like

What about PL.interrupt_pins for download=True and download=False?

1 Like

Here’s download=True.

And download=False.

I’ve also tried to load a bitstreamA with download=True into a Zedboard with image built through PYNQ official procedure. Then load a bitstreamB with downlaod=False. I found that the PL information, like ip_dict, still remained the status as bitstreamA. Rather than OL information already changed into bitstreamB.

Besides after some digging into PYNQ source code, seems pl only called in function download() and is_loaded() in overlay, and PL server updates after that. Perhaps that can explain why I can’t get pl information to renew when download=False?

You can try to do

PL.interrupt_pins = ol.interrupt_pins

before accessing to the interrupt controller. (intc_ip=ol.axi_intc_0)

I don’t know if there’s going to be something else that could fail. This is an very old version of PYNQ (4 releases old) and support is limited.


1 Like

Unfortunately, it doesn’t work, but that’s a good idea. I’ll try to do something to pl server and the idea might help. Seeing whether I can pass the information to pl without really downloading bitstream.

Right now, I’m trying to make interrupt with UioController and manually write the AXI Interrupt Controller with mmio. I consider this may be the easiest way since I only need one interrupt pin in fpga. I assume that as long as the AXI interrupt Controller is settled and handled correctly, like writing certain stuff into the IP address. I can get the interrupt through the UIO.

I’ll share the result if there’s any progress.
If there’s any suggestion, like which certain version could do that, please tell me.
I really appreciate all the suggestions you gave.

You can try the device reset as indicated here

If there’s any suggestion, like which certain version could do that, please tell me.

I always suggest the latest version of PYNQ

1 Like


Wait, I guess @marioruiz have a point here.
JTAG could possibly had a higher priority than the software stack.
Try remove ILA and give it a try really not that much of work.


No, as I mentioned in the above comment, the problems remain whether the ILA exists or not.
In that comment, I’ve verified that interrupt works well with ILA. But just in case, I still removed the ILA and replaced my IP with AXI GPIO to imitate the interrupt signal. It’s still unable to use interrupt class while overlay(downlaod=False).


OK this is clear, how is the IRQ trigger edge or level?

If level trigger and the GPIO response is very slow I encountered some ARM system will crash.


Your suggestions are sincerely appreciated. Though there’s no Device attribute in PYNQ2.4, I do PL.reset(ol.parser) instead. It works!
Pl server can now update the information without downloading the bitstream.

Thanks for briansune’s effort as well. Mine is level trigger, but so far I hadn’t met the ARM crash problem you mentioned. I’ll keep that in mind.

1 Like


Lesson learnt, the AXI interrupt does not include first time reset cycle.
Instead of good reason behind using level trigger, edge trigger is always preferred.


1 Like