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不用多說,很簡單明瞭。

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

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