Ultra96 PYNQ入门之三——中断与协程

不合理的地方欢迎批评指正!!!

源代码链接:Ultra96-PYNQ_A-simple-summary

1 协程入门

个人感觉这个博主讲的挺全面的,想全面了解协程的小伙伴,可以移步如下链接

  1. asyncio 学习笔记:基本用法
  2. asyncio 学习笔记:调用定时函数
  3. asyncio 学习笔记:并发执行 Task
  4. asyncio 学习笔记:产生异步结果
  5. asyncio 学习笔记:控制组合式 Coroutines
  6. asyncio 学习笔记:同步原语
  7. asyncio 学习笔记:使用抽象类 Protocol 实现异步 I/O

如不想全面性了解协程这个东西,可以看下我的简练的总结,可以看懂如下的实验,只不过没法进一步个性化设计。

  • 在线程中创建一个协程循环start_loop = asyncio.get_event_loop()
  • 完成协程直至返回return_value = start_loop.run_until_complete(button_led())
  • 协程中等待await button_inter.wait_for_value_async(1),等待属于异步操作,并不占用CPU。可以创建多个协程,相应多个中断,这个会在后面提及。

注:目前个人感觉协程这个东西,和裸机开发中的中断还是有区别的,属于软件调度的中断?效率不咋高,所以千万不要在1秒内相应上千个中断,否则你会发现中断执行的时间还没有中断触发的时间延迟长呢。

2 PYNQ的中断使用

2.1 硬件设计

很简单的一个设计,可以在Vivado中的TCL控制台通过如下命令,进行快速重建

source 3.axi_gpio_interrupt.tcl

在这里插入图片描述

  • button用于检测中断
  • led用于显示中断的情况

button、led均用口袋仪器仿真

中断控制器这里,仅实验了默认的高电平中断,小伙伴可以尝试边沿中断,来进行实验
在这里插入图片描述

2.2 中断的使用

2.2.1 一个不恰当的例子

软件代码如下

import time
from pynq import Overlay
import asyncio

gpio_inter_design = Overlay("./data/3.AXI_GPIO_Interrupt.bit")

button_inter = gpio_inter_design.axi_gpio_0.Input( parent=gpio_inter_design.axi_gpio_0.channel1, 
													start=0, stop=1 )
led = gpio_inter_design.axi_gpio_0.Output( parent=gpio_inter_design.axi_gpio_0.channel2, 
											start=0, stop=1 )

async def button_led():
    for i in range(10):
        start = time.time()
        await button_inter.wait_for_value_async(1)
        led.toggle()
        end = time.time()
        
        print("中断的周期 :{}s".format(end -start))
    

start_loop = asyncio.get_event_loop()
return_value = start_loop.run_until_complete(button_led())

button利用信号发生器模拟,1Hz、1.8V、5%的脉冲波
在这里插入图片描述

实验的结果惨不忍睹

中断的周期 :0.6854667663574219s
中断的周期 :6.651878356933594e-05s
中断的周期 :5.888938903808594e-05s
中断的周期 :5.817413330078125e-05s
中断的周期 :5.888938903808594e-05s
中断的周期 :5.745887756347656e-05s
中断的周期 :5.745887756347656e-05s
中断的周期 :5.793571472167969e-05s
中断的周期 :5.817413330078125e-05s
中断的周期 :5.8650970458984375e-05s

分析原因
中断控制器采用了默认的高电平中断,即使中断之后清除中断,由于是高电平触发,中断控制器仍然定义发生了中断。

2.2.2 恰当的操作

  • 软件代码如下
	import time
	from pynq import Overlay
	import asyncio
	
	gpio_inter_design = Overlay("./data/3.AXI_GPIO_Interrupt.bit")
	
	button_inter = gpio_inter_design.axi_gpio_0.Input( parent=gpio_inter_design.axi_gpio_0.channel1, 
														start=0, stop=1 )
	led = gpio_inter_design.axi_gpio_0.Output( parent=gpio_inter_design.axi_gpio_0.channel2, 
												start=0, stop=1 )
	
	async def button_led():
	    for i in range(10):
	        start = time.time()
	        await button_inter.wait_for_value_async(1)
	        led.toggle()
	        await asyncio.sleep(0.05)
	        end = time.time()
	        
	        print("中断的周期 :{}s".format(end -start))
	    
	
	start_loop = asyncio.get_event_loop()
	return_value = start_loop.run_until_complete(button_led())

使用await asyncio.sleep(0.05)跳过高电平脉冲时间,即可正确的产生中断。

  • 软件输出
中断的周期 :0.1248316764831543s
中断的周期 :0.9994022846221924s
中断的周期 :0.9997074604034424s
中断的周期 :0.9996352195739746s
中断的周期 :0.999701738357544s
中断的周期 :0.9996013641357422s
中断的周期 :0.9996085166931152s
中断的周期 :1.0001087188720703s
中断的周期 :0.9996082782745361s
中断的周期 :0.9993538856506348s

同样button利用信号发生器模拟,1Hz、1.8V、5%的脉冲波,逻辑分析仪测试结果如下
在这里插入图片描述

这里仅演示了单高电平触发的中断,尝试利用协程实现多中断,充分利用CPU。



原创不易,严禁剽窃!

在这里插入图片描述

欢迎大家关注我创建的微信公众号——小白仓库
原创经验资料分享:包含但不仅限于FPGA、ARM、RISC-V、Linux、LabVIEW等软硬件开发,另外分享生活中的趣事以及感悟。目的是建立一个平台记录学习过的知识,并分享出来自认为有用的与感兴趣的道友相互交流进步。

猜你喜欢

转载自blog.csdn.net/qq_35712169/article/details/106247110
96