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等軟硬件開發,另外分享生活中的趣事以及感悟。目的是建立一個平臺記錄學習過的知識,並分享出來自認爲有用的與感興趣的道友相互交流進步。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章