Ultra96 PYNQ入門之一——PS端控制MIO與EMIO
不合理的地方歡迎批評指正!!!
源代碼鏈接:Ultra96-PYNQ_A-simple-summary
1 PYNQ GPIO模塊
注:這部分是進行簡單分析相應的重要函數,如嫌囉嗦,可以直接轉到2小節。
本小節與Ultra96-V2板卡的PL部分無關,直接使用PS控制GPIO作爲示例
進行下面之前,需要導入GPIO模塊
from pynq import GPIO
1.1 get_gpio_base
獲取gpio號的基地址,PYNQ的源代碼是使用Linux’s GPIO Sysfs API來獲取對應的基地址的。
gpio_base = GPIO.get_gpio_base()
print("Ultra96-V2 gpio_base is {}".format(gpio_base))
下面是對應的Linux Sysfs部分
xilinx@pynq:~$ cd /sys/class/gpio/
xilinx@pynq:/sys/class/gpio$ tree
.
├── export
├── gpiochip338 -> ../../devices/platform/amba/ff0a0000.gpio/gpio/gpiochip338
└── unexport
1.2 get_gpio_base_path
獲取gpio設備在Linux Sysfs的路徑
gpio_base_path = GPIO.get_gpio_base_path()
print("Ultra96-V2 gpio_base_path is {}".format(gpio_base_path))
1.3 get_gpio_npins
獲取這個gpio控制器,最多可控制多少個引腳
gpio_npins = GPIO.get_gpio_npins()
print("Ultra96-V2 gpio_npins is {}".format(gpio_npins))
Ultra96-V2 gpio_npins is 174
從數據手冊可以獲取這個數值的含義,相信你只要上過小學,就可以知道這個174是MIO+EMIO的數量
1.4 get_gpio_pin
這個可以獲取Linux Sysfs GPIO的引腳號,可用於後續的初始化。
def get_gpio_pin(gpio_user_index, target_label=None):
if target_label is not None:
GPIO_OFFSET = 0
else:
GPIO_OFFSET = GPIO._GPIO_MIN_USER_PIN
return (GPIO.get_gpio_base(target_label) + GPIO_OFFSET +
gpio_user_index)
通過源碼可知如使用MIO部分的GPIO,則不建議使用此API。
1.5 init
初始化部分必須慎重對待。區分開MIO與EMIO,EMIO在MIO之外加上相應的偏移。
def __init__(self, gpio_index, direction):
"""Return a new GPIO object.
Parameters
----------
gpio_index : int
The index of the GPIO using Linux's GPIO Sysfs API.
direction : 'str'
Input/output direction of the GPIO.
"""
1.5.1 PS MIO
gpio_index = GPIO.get_gpio_base() + MIO編號
1.5.2 PS EMIO
gpio_index = GPIO.get_gpio_base() + GPIO.get_gpio_pin(gpio_user_index = EMIO編號)
1.6 其他
這部分API不用多說,很簡單明瞭。
read(self)
write(self, value)
release(self)
- …
2 PS MIO的使用
2.1 嘗試控制LED?
經過上面的講解,假設你看中了Ultra96-V2的一個PS MIO連接的LED,想要試驗一下,控制這個LED,找點成就感,在此我遺憾的告訴你,你將碰一鼻子灰…。
如果執行如下操作
led1 = GPIO(gpio_base + 19, 'out')
則會出現設備資源繁忙,無法訪問的錯誤,如下所示
OSError Traceback (most recent call last)
OSError: [Errno 16] Device or resource busy
During handling of the above exception, another exception occurred:
OSError Traceback (most recent call last)
<ipython-input-5-22b01faa7ec5> in <module>()
----> 1 led1 = GPIO(gpio_base + 19, 'out')
/usr/local/lib/python3.6/dist-packages/pynq/gpio.py in __init__(self, gpio_index, direction)
192
193 if not self._impl or not self._impl.is_exported():
--> 194 self._impl = _GPIO(gpio_index, direction)
195 _gpio_map[gpio_index] = self._impl
196
/usr/local/lib/python3.6/dist-packages/pynq/gpio.py in __init__(self, gpio_index, direction)
77 if not os.path.exists(self.path):
78 with open('/sys/class/gpio/export', 'w') as f:
---> 79 f.write(str(self.index))
80
81 with open(self.path + 'direction', 'w') as f:
OSError: [Errno 16] Device or resource busy
根本原因是,Ultra96-V2的PYNQ鏡像,已經在設備樹中將該GPIO資源分配給LED了,如果再通過GPIO模塊對該資源進行訪問,則肯定會出現設備資源繁忙錯誤報告。
Ultra96-V2的設備樹中的LED如下所示
xilinx@pynq:/sys/class/gpio$ cd /sys/class/leds/
xilinx@pynq:/sys/class/leds$ tree
.
├── ds2 -> ../../devices/platform/leds/leds/ds2
├── ds3 -> ../../devices/platform/leds/leds/ds3
├── ds4 -> ../../devices/platform/leds/leds/ds4
├── ds5 -> ../../devices/platform/leds/leds/ds5
├── mmc0:: -> ../../devices/platform/amba/ff160000.mmc/leds/mmc0::
├── mmc1:: -> ../../devices/platform/amba/ff170000.mmc/leds/mmc1::
└── vbus_det -> ../../devices/platform/leds/leds/vbus_det
7 directories, 0 files
進入相應目錄,可以使用root寫入brightness來控制相應LED的亮滅。具體如何通過Python來控制這些,會在文章最後進行簡單提及的。
xilinx@pynq:/sys/class/leds/ds3$ cat brightness
0
xilinx@pynq:/sys/class/leds/ds3$ su
Password:
root@pynq:/sys/class/leds/ds3# tree
.
├── brightness
├── device -> ../../../leds
├── max_brightness
├── power
│ ├── autosuspend_delay_ms
│ ├── control
│ ├── runtime_active_time
│ ├── runtime_status
│ └── runtime_suspended_time
├── subsystem -> ../../../../../class/leds
├── trigger
└── uevent
3 directories, 9 files
root@pynq:/sys/class/leds/ds3# echo 1 > brightness
root@pynq:/sys/class/leds/ds3# cat brightness
1
root@pynq:/sys/class/leds/ds3#
2.2 控制GPIO
既然LED設備資源無法訪問,訪問那些沒有在設備樹分配相應功能的GPIO資源了。
這裏僅使用MIO36_PS_GPIO1_0輸出示例使用方法。
如果嘗試輸入實驗,一定要注意電平標準(MIO 1.8V!!!),不要一不小心,把2K多的板子給燒了…。
如果嘗試輸入實驗,一定要注意電平標準(MIO 1.8V!!!),不要一不小心,把2K多的板子給燒了…。
如果嘗試輸入實驗,一定要注意電平標準(MIO 1.8V!!!),不要一不小心,把2K多的板子給燒了…。
一般的口袋儀器的數字部分電平是LVCMOS 3.3V的,這時候可以考慮使用口袋儀器的信號發生器來構造1.8V的脈衝信號,來進行測試。輸入部分沒事,1.8V勉強可以觸發3.3V,至少燒不壞。
完整測試代碼
from pynq import GPIO
import time
gpio_base = GPIO.get_gpio_base()
print("Ultra96-V2 gpio_base is {}".format(gpio_base))
gpio0 = GPIO(gpio_base + 36, 'out')
for i in range(100):
gpio0.write(1)
time.sleep(0.1)
gpio0.write(0)
time.sleep(0.1)
邏輯分析儀的測量結果如下,符合軟件設置的間隔。
輸入實驗,與輸出實驗類似,唯一要注意的是不要使用不兼容的電壓標準。
2.3 一個小彩蛋
上面使用gpio0 = GPIO(gpio_base + 36, 'out')
對一個MIO部分的GPIO資源進行實例化,這時候可以在Linux Sysfs部分驚奇的發現
root@pynq:/sys/class/leds/ds3# cd /sys/class/gpio/
root@pynq:/sys/class/gpio# tree
.
├── export
├── gpio374 -> ../../devices/platform/amba/ff0a0000.gpio/gpiochip0/gpio/gpio374
├── gpiochip338 -> ../../devices/platform/amba/ff0a0000.gpio/gpio/gpiochip338
└── unexport
2 directories, 2 files
進入相應的目錄,可以與LED類似,直接寫入相應的值進行控制。 PYNQ的GPIO模塊原理就是使用Linux’s GPIO Sysfs API來進行控制GPIO的,使用Python進行進一步封裝,減少開發難度。
3 PS EMIO的使用
3.1 硬件設計
這部分需要加載相應的bit流文件,進行使用。
這裏我拿這6個小傢伙作爲EMIO示例,約束爲可以輸入可以輸出,具體如何使用,需要軟件進一步配置
很簡單的一個設計,可以在Vivado中的TCL控制檯通過如下命令,進行快速重建
source 1.ps_emio.tcl
如果打開實現後的器件視圖,可以發現PS的EMIO正確的連接到相應的引腳上了
3.2 控制GPIO
使用類似的代碼,即可進行驗證
from pynq import GPIO
from pynq import Overlay
import time
emio_gpio_design = Overlay("./data/1.PS_EMIO.bit")
hd_emio_gpio0_n = GPIO.get_gpio_pin(gpio_user_index= 0)
print("Ultra96-V2 hd_emio_gpio0 numbers is {}".format(hd_emio_gpio0))
hd_emio_gpio0 = GPIO(hd_emio_gpio0_n, 'out')
for i in range(100):
hd_emio_gpio0.write(1)
time.sleep(0.1)
hd_emio_gpio0.write(0)
time.sleep(0.1)
邏輯分析儀的測量結果如下,符合軟件設置的間隔。
EMIO與MIO類似,可以在sysfs中查詢得到,同樣可以進行控制
root@pynq:/sys/class/gpio# tree
.
├── export
├── gpio416 -> ../../devices/platform/amba/ff0a0000.gpio/gpiochip0/gpio/gpio416
├── gpiochip338 -> ../../devices/platform/amba/ff0a0000.gpio/gpio/gpiochip338
└── unexport
4 控制設備樹中的LED
A pure Python 2/3 library for peripheral I/O (GPIO, LED, PWM, SPI, I2C, MMIO, Serial) in Linux.
這裏僅放相應的Github鏈接,並不進行演示,具體可在鏈接中查詢。
注:控制設備樹中的常用外設,與FPGA部分無關,這時候Ultra96-V2與樹莓派之類的板卡類似。
原創不易,嚴禁剽竊!
歡迎大家關注我創建的微信公衆號——小白倉庫
原創經驗資料分享:包含但不僅限於FPGA、ARM、RISC-V、Linux、LabVIEW等軟硬件開發,另外分享生活中的趣事以及感悟。目的是建立一個平臺記錄學習過的知識,並分享出來自認爲有用的與感興趣的道友相互交流進步。