<font color="#FF8000">作者:MacMahon Stephen</font>
本文将探讨如何以 Zynq UltraScale 器件上的 IP 核为目标,使用 Python 来创建一些强大的应用和实用工具。
此处提供了一个程序包,供您用于读取设备树和访问 IP 核。此外还提供一个实用工具,用于读取物理寄存器和开关 LED。
Python 是现如今最常用的编程语言之一。原因在于这种语言高产、易于部署且直观。并且正因其热门,产生了大量共享程序包可供其他用户使用。
本教程将为您展示如何在 ZCU104 开发板上轻松使用 Python 来启动并运行程序。
用户在构建文件系统时,所有必需的程序包都应已准备就绪。此处并未详细列出所有程序包,因为用户更了解自己的应用需要哪些程序包。
由于最终设计目标是嵌入式软件系统,因此更为实用的用例之一是接入嵌入式软件系统的存储器/外设。这里我们使用 mmap 程序包来打开 /dev/mem 并获取访问权。随后,我们可以在其中创建自己的程序包,以供在各种应用或实用工具中使用。
我们还可以使用 subprocess 等程序包来访问文件系统。我曾经使用此方法来读取设备树,查看有哪些 IP 已启用以及这些 IP 的配置方式。
我提供了一个用于通过 Python 控制嵌入式系统的定制程序包,供用户作为参考。
硬件设计:
本演示中使用的块设计 (BD) 如下所示。我使用的是 ZCU104 开发板,但此处流程应该是普遍适用的。
<center><img src="http://xilinx.eetrend.com/files/2022-10/wen_zhang_/100563730-269207-zyn…; alt=""></center>
请参阅<a target="_self" href="https://docs.xilinx.com/v/u/2020.1-English/ug898-vivado-embedded-design…;,获取有关 Vivado 2020.1 中的嵌入式流程的更多信息。
<p data-aura-rendered-by="75:785;a">为 PetaLinux 工程添加 Python 支持</p>
<ul data-aura-rendered-by="75:785;a">
<li>petalinux-create -t project --template zynqMP -n linux_image</li>
<li>cd <plnx proj></li>
<li>petalinux-config --get-hw-description=<path to XSA>
<ul>
<li>DTG Settings -> (zcu104-revc) MACHINE_NAME</li>
<li>(请访问<a target="_self" href="https://github.com/Xilinx/device-tree-xlnx/tree/master/device_tree/data…,获取受支持的开发板 .dtsi 文件的完整列表)</li>
</ul>
</li>
<li>petalinux-config -c kernel
<ul>
<li>kernel hacking → [] Filter access to /dev/mem</li>
</ul>
</li>
<li>petalinux-config -c rootfs
<ul>
<li>Filesystem Packages → devel →python
<ul>
<li>python-mmap</li>
<li>python-shell</li>
<li>python-io</li>
<li>python-distutils</li>
<li>python-pydoc</li>
</ul>
</li>
<li>Filesystem Packages → devel →python-numpy → [*] python-numpy</li>
</ul>
</li>
</ul>
<ul data-aura-rendered-by="75:785;a">
<li>petalinux-build</li>
<li>cd images/linux</li>
<li>petalinux-package --boot --fpga system.bit --u-boot</li>
</ul>
在 Python 中使用 /dev/mem:
创建 Linux 镜像后,可以尝试对硬件设计中的外设进行读写。我们可以使用 /dev/mem,以物理方式接入存储器/寄存器。我们将使用 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 即为我们要接入的存储器或寄存器。
创建程序包:
用户可以自行创建程序包,以便将自己的函数添加到其它应用中(请参阅附件)。
我已经创建了 1 个此类程序包,它支持用户执行以下操作:
<li>读取寄存器/存储器</li>
<li>写入寄存器/存储器</li>
<li>执行系统命令,如 cat、ls 等</li>
<li>读取 mdio</li>
<li>获取物理地址</li>
<li>mii 转储</li>
<li>读取设备树节点</li>
<li>获取设备树属性</li>
使用该程序包来执行读写:
import mypackages.myutils as util
xx = util.read(0xff0e0000)
print(hex(xx))
使用该程序包来运行简单的 LED 开关应用:
以下示例可用于开关 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())
此程序包将永久循环。用户可使用 Ctrl+ Z 将其停止。
使用该程序包来读取 MDIO:
此处我们将使用实用工具通过 MDIO 来读取 PHY:
import mypackages.myutils as util
#GEM 地址、物理地址、偏移
xx = util.read_mdio(0xff0e0034, 0x0c, 0x00000000)
print(xx)
使用该程序包来检测有效的物理 (PHY) 地址:
我们可以在此处搜索有效的 PHY 地址:
import mypackages.myutils as util
xx = util.get_phy_addr(0xff0e0034)
print(xx)
使用该程序包来执行 MII 转储:
在该程序包中包含 mii_dump 实用工具,它将搜索设备树中的任何已启用的 GEM IP、自动检测有效的 PHY 地址并转储 PHY 寄存器:
import mypackages.myutils as util
xx = util.mii_dump()
读取设备树节点:
我已经创建了一个实用工具,用于读取内核中的设备树节点。创建普遍适用任何设计的脚本时,此工具很有用,因为用户可以根据硬件来创建/使用应用。
例如,我们可以返回设备树中的所有 IP:
import mypackages.myutils as util
xx = util.get_ip('all_ip')
print(xx)
我们还可以筛选此搜索,查找设备树中已启用的所有 GEM:
import mypackages.myutils as util
xx = util.get_ip('ethernet', status='okay')
print(xx)
用户还可以仅搜索状态设置为“okay”的所有器件节点:
import mypackages.myutils as util
xx = util.get_ip(status='okay')
print(xx)