本文將探討如何以 Zynq UltraScale 器件上的 IP 核為目標(biāo),使用 Python 來(lái)創(chuàng)建一些強(qiáng)大的應(yīng)用和實(shí)用工具。
此處提供了一個(gè)程序包,供您用于讀取設(shè)備樹(shù)和訪(fǎng)問(wèn) IP 核。此外還提供一個(gè)實(shí)用工具,用于讀取物理寄存器和開(kāi)關(guān) LED。
Python 是現(xiàn)如今最常用的編程語(yǔ)言之一。原因在于這種語(yǔ)言高產(chǎn)、易于部署且直觀。并且正因其熱門(mén),產(chǎn)生了大量共享程序包可供其他用戶(hù)使用。
本教程將為您展示如何在 ZCU104 開(kāi)發(fā)板上輕松使用 Python 來(lái)啟動(dòng)并運(yùn)行程序。
用戶(hù)在構(gòu)建文件系統(tǒng)時(shí),所有必需的程序包都應(yīng)已準(zhǔn)備就緒。此處并未詳細(xì)列出所有程序包,因?yàn)橛脩?hù)更了解自己的應(yīng)用需要哪些程序包。
由于最終設(shè)計(jì)目標(biāo)是嵌入式軟件系統(tǒng),因此更為實(shí)用的用例之一是接入嵌入式軟件系統(tǒng)的存儲(chǔ)器/外設(shè)。這里我們使用 mmap 程序包來(lái)打開(kāi) /dev/mem 并獲取訪(fǎng)問(wèn)權(quán)。隨后,我們可以在其中創(chuàng)建自己的程序包,以供在各種應(yīng)用或?qū)嵱霉ぞ咧惺褂谩?
我們還可以使用 subprocess 等程序包來(lái)訪(fǎng)問(wèn)文件系統(tǒng)。我曾經(jīng)使用此方法來(lái)讀取設(shè)備樹(shù),查看有哪些 IP 已啟用以及這些 IP 的配置方式。
我提供了一個(gè)用于通過(guò) Python 控制嵌入式系統(tǒng)的定制程序包,供用戶(hù)作為參考。
硬件設(shè)計(jì):
本演示中使用的塊設(shè)計(jì) (BD) 如下所示。我使用的是 ZCU104 開(kāi)發(fā)板,但此處流程應(yīng)該是普遍適用的。
請(qǐng)參閱此處,獲取有關(guān) Vivado 2020.1 中的嵌入式流程的更多信息。
為 PetaLinux 工程添加 Python 支持
petalinux-create -t project --template zynqMP -n linux_image cd <plnx proj> petalinux-config --get-hw-description=<path to XSA> DTG Settings -> (zcu104-revc) MACHINE_NAME (請(qǐng)?jiān)L問(wèn)此處鏈接,獲取受支持的開(kāi)發(fā)板 .dtsi 文件的完整列表) petalinux-config -c kernel kernel hacking → [] Filter access to /dev/mem petalinux-config -c rootfs Filesystem Packages → devel →python python-mmap python-shell python-io python-distutils python-pydoc Filesystem Packages → devel →python-numpy → [*] python-numpy petalinux-build cd images/linux petalinux-package --boot --fpga system.bit --u-boot
在 Python 中使用 /dev/mem:
創(chuàng)建 Linux 鏡像后,可以嘗試對(duì)硬件設(shè)計(jì)中的外設(shè)進(jìn)行讀寫(xiě)。我們可以使用 /dev/mem,以物理方式接入存儲(chǔ)器/寄存器。我們將使用 Python 中包含的 mmap 程序包:
f = os.open("/dev/mem", os.O_RDWR | os.O_SYNC)
mem = mmap.mmap(f, mmap.PAGESIZE, mmap.MAP_SHARED, mmap.PROT_READ | mmap.PROT_WRITE,offset=addr & ~MAP_MASK)
其中,addr 即為我們要接入的存儲(chǔ)器或寄存器。
創(chuàng)建程序包:
用戶(hù)可以自行創(chuàng)建程序包,以便將自己的函數(shù)添加到其它應(yīng)用中(請(qǐng)參閱附件)。
我已經(jīng)創(chuàng)建了 1 個(gè)此類(lèi)程序包,它支持用戶(hù)執(zhí)行以下操作:
使用該程序包來(lái)執(zhí)行讀寫(xiě):
import mypackages.myutils as util
xx = util.read(0xff0e0000)
print(hex(xx))
使用該程序包來(lái)運(yùn)行簡(jiǎn)單的 LED 開(kāi)關(guān)應(yīng)用:
以下示例可用于開(kāi)關(guān) AXI GPIO LED:
import mypackages.myutils as util
import time
import sys
def toggle_leds():
util.write(0x80000000, 0x0)
while True:
for x in range(0, 8):
util.write(0x80000000, x)
time.sleep(1)
if __name__ == '__main__':
sys.exit(toggle_leds())
此程序包將永久循環(huán)。用戶(hù)可使用 Ctrl+ Z 將其停止。
使用該程序包來(lái)讀取 MDIO:
此處我們將使用實(shí)用工具通過(guò) MDIO 來(lái)讀取 PHY:
import mypackages.myutils as util
#GEM 地址、物理地址、偏移
xx = util.read_mdio(0xff0e0034, 0x0c, 0x00000000)
print(xx)
使用該程序包來(lái)檢測(cè)有效的物理 (PHY) 地址:
我們可以在此處搜索有效的 PHY 地址:
import mypackages.myutils as util
xx = util.get_phy_addr(0xff0e0034)
print(xx)
使用該程序包來(lái)執(zhí)行 MII 轉(zhuǎn)儲(chǔ):
在該程序包中包含 mii_dump 實(shí)用工具,它將搜索設(shè)備樹(shù)中的任何已啟用的 GEM IP、自動(dòng)檢測(cè)有效的 PHY 地址并轉(zhuǎn)儲(chǔ) PHY 寄存器:
import mypackages.myutils as util
xx = util.mii_dump()
讀取設(shè)備樹(shù)節(jié)點(diǎn):
我已經(jīng)創(chuàng)建了一個(gè)實(shí)用工具,用于讀取內(nèi)核中的設(shè)備樹(shù)節(jié)點(diǎn)。創(chuàng)建普遍適用任何設(shè)計(jì)的腳本時(shí),此工具很有用,因?yàn)橛脩?hù)可以根據(jù)硬件來(lái)創(chuàng)建/使用應(yīng)用。
例如,我們可以返回設(shè)備樹(shù)中的所有 IP:
import mypackages.myutils as util
xx = util.get_ip('all_ip')
print(xx)
我們還可以篩選此搜索,查找設(shè)備樹(shù)中已啟用的所有 GEM:
import mypackages.myutils as util
xx = util.get_ip('ethernet', status='okay')
print(xx)
用戶(hù)還可以?xún)H搜索狀態(tài)設(shè)置為“okay”的所有器件節(jié)點(diǎn):
import mypackages.myutils as util
xx = util.get_ip(status='okay')
print(xx)
XC6SLX25-2CSG324I
XC6SLX25-2FTG256C
XC6SLX4-2TQG144C
XC6SLX45-2FGG676C
XC6SLX45-2FGG484C
XC6SLX45-L1CSG324I
XC6SLX45T-2FGG484I
XC6SLX75T-3FGG484I
XC6SLX9-2CSG324C
XC6SLX9-2CSG324I
XC6SLX9-2FTG256C
XC6SLX9-2FTG256I
XC6SLX9-2TQG144C
XC7A75T-2FGG676I
XC7K160T-2FFG676C
XC7K160T-2FFG676I
XC7Z010-2CLG400I
XC7Z020-1CLG400I
XC7Z030-1FBG484C
XC7Z045-2FFG900I