Coroutine blocked in interrupt.wait()

Hello Guys,
I’m using PYNQ V3.0.1 on a custom board based on ZCU104 with image built by following the docs of PYNQ. And it works well.
Then I got video signal input to PL(display to screen through DVI) and there is an IP which generate interrupt signal per frame. The interrupt signal connected to axi_intc(intc) and then to PS IRQ_F2P(pl_ps_irq0). Interrupt configs are:



The test code and it’s output is:

#import user packages and modules
import time
import threading
from pynq import Overlay, PL, allocate
print("start script")

PL.reset()
print("PL reset done")
fpga = Overlay('/home/xilinx/jupyter_notebooks/wrap_up.bit', ignore_version = True)
print("load fpga bit file done")
time.sleep(0.1)

#create full handle
ops_handle = {}

prod_create(fpga, ops_handle)

prod_video_enable(ops_handle)

prod_video_start(ops_handle)

print("ready")
#here I can see video output on my screen

start script
ready

hist_obj = ops_handle[NAME_HIST]
intr = hist_obj.dev.irq
type(intr)

pynq.interrupt.Interrupt

import asyncio
#import logging
#logging.getLogger("asyncio").setLevel(logging.INFO)
class my_thread(threading.Thread):
    def __init__(self, intr, func, name='my-thread'):
        super(my_thread, self).__init__(name=name)
        self.intr = intr
        self.func = func

        self.stop_event = threading.Event()
        self.stop_event.clear()

    def run(self):
        self.func(self.stop_event, self.intr)

def al_func(stop_event, intr):
    global flag
    flag = False
    async def irq_test(stop_event, intr):
        global flag
        cnt = 0
        start = time.time()
        print("irq_test started")
        while not stop_event.is_set():
            print("irq_test continue?", (not stop_event.is_set()))
            #await asyncio.sleep(1)
            await intr.wait()
            cnt = cnt + 1
            flag = True
            print("cnt:", cnt)
        print("irq_test stopped")
        stop = time.time()
        gap = stop - start
        fps = cnt / gap
        print(gap, cnt, fps)
        
    async def work2(stop_event):
        global flag
        cnt2 = 0
        while not stop_event.is_set():
            await asyncio.sleep(0.001)
            if flag:
                cnt2 = cnt2 + 1
                flag = False
        print("work2 cnt:", cnt2)
        
    async def all_work(stop_event, intr):
        results = await asyncio.gather(*(irq_test(stop_event, intr), work2(stop_event)))
        return results
    
    asyncio.run(all_work(stop_event, intr))
    #asyncio.run(irq_test(stop_event, intr), debug=True)
    print("finished")
althd = my_thread(intr, al_func)
stp = althd.stop_event
althd.start()

irq_test started
irq_test continue? True
cnt: 1
irq_test continue? True
cnt: 2
irq_test continue? True
cnt: 3
irq_test continue? True
cnt: 4
irq_test continue? True
cnt: 5
irq_test continue? True
cnt: 6
irq_test continue? True
cnt: 7
irq_test continue? True
cnt: 8
irq_test continue? True
cnt: 9
irq_test continue? True
cnt: 10
irq_test continue? True
cnt: 11
irq_test continue? True
cnt: 12
irq_test continue? True
cnt: 13
irq_test continue? True
cnt: 14
irq_test continue? True
cnt: 15
irq_test continue? True
cnt: 16
irq_test continue? True
cnt: 17
irq_test continue? True
cnt: 18
irq_test continue? True
cnt: 19
irq_test continue? True
cnt: 20
irq_test continue? True
cnt: 21
irq_test continue? True
cnt: 22
irq_test continue? True
cnt: 23
irq_test continue? True
cnt: 24
irq_test continue? True
cnt: 25
irq_test continue? True
cnt: 26
irq_test continue? True
cnt: 27
irq_test continue? True
cnt: 28
irq_test continue? True
cnt: 29
irq_test continue? True
cnt: 30
irq_test continue? True
cnt: 31
irq_test continue? True
cnt: 32
irq_test continue? True
cnt: 33
irq_test continue? True
cnt: 34
irq_test continue? True
cnt: 35
irq_test continue? True
cnt: 36
irq_test continue? True
cnt: 37
irq_test continue? True
cnt: 38
irq_test continue? True
cnt: 39
irq_test continue? True
cnt: 40
irq_test continue? True
cnt: 41
irq_test continue? True
cnt: 42
irq_test continue? True
cnt: 43
irq_test continue? True
cnt: 44
irq_test continue? True
cnt: 45
irq_test continue? True
cnt: 46
irq_test continue? True
cnt: 47
irq_test continue? True
cnt: 48
irq_test continue? True
cnt: 49
irq_test continue? True
cnt: 50
irq_test continue? True
cnt: 51
irq_test continue? True
cnt: 52
irq_test continue? True
cnt: 53
irq_test continue? True
cnt: 54
irq_test continue? True
cnt: 55
irq_test continue? True
cnt: 56
irq_test continue? True
cnt: 57
irq_test continue? True
cnt: 58
irq_test continue? True
cnt: 59
irq_test continue? True
cnt: 60
irq_test continue? True
cnt: 61
irq_test continue? True
cnt: 62
irq_test continue? True
cnt: 63
irq_test continue? True
cnt: 64
irq_test continue? True
cnt: 65
irq_test continue? True
cnt: 66
irq_test continue? True
cnt: 67
irq_test continue? True
cnt: 68
irq_test continue? True
cnt: 69
irq_test continue? True
cnt: 70
irq_test continue? True
cnt: 71
irq_test continue? True

stp.set()

cnt: 72
irq_test continue? True
cnt: 73
irq_test continue? True
work2 cnt: 73

So the irq_test() cannot be stopped because it was blocked in await intr.wait() after the coroutine work2() was finished. And if I replaced intr.wait() with asyncio.sleep(1), then irq_test() could be finished.
If I run irq_test() itself in asyncio.run(), it was also blocked there.
I tried to open debug mode of asyncio by transferring debug=True in asyncio.run(), it does no help, I cannot see any info printed.
I’m curious about why interrupt.wait() would be blocked in this scenario. Would anyone do me a favor? Thanks.

1 Like

I found that using asyncio.Event instead of global variable flag will block the intr.wait() from the very first. Any ideas?