☰
自制Zynq UltraScale+ MPSoC开发板:从硬件决策到Petalinux系统构建全记录
2026/10/2 15:56:37 网站建设 项目流程

很多工程师在官方开发板上把Petalinux跑起来之后,都会觉得ZynqMP不过如此。等真正为一块custom pcb dev-board从零搭Vivado工程,再给这块没有出厂镜像的板子构建完整系统时,之前那些"理所当然"就全都变成了坎。这篇文章是我从零做一个基于Zynq UltraScale+ MPSoC的自制PCB开发板的完整记录,包括前期的硬件决策、Vivado硬件工程搭建、Petalinux软件栈构建,以及首板调试的踩坑复盘。适合正准备画自己的ZynqMP板卡、或者已经在画但是对后续软件流程没底的工程师,也适合想从官方开发板跳到真实产品的嵌入式老兵。

1. 自制ZynqMP板卡的早期决策:软件要为硬件选型提前站台

很多人画板子的时候只盯着原理图和PCB,等板子回来了才拿着Petalinux的BSP去对照,结果发现官方BSP里一堆东西和自己的硬件对不上。这里最大的问题不是技术难度,而是硬件已经焊死了,软件只能去适配。所以我在原理图阶段就把后面软件要用到的决策全部定了,这一步省下来的调试时间远比想象中多。

1.1 芯片选型:ZU系列怎么选

Zynq UltraScale+ MPSoS不是一个芯片,而是一个家族。ZU2CG、ZU2EG、ZU3EG、ZU4EV、ZU7EV这些型号,PS侧(四核A53 + 双核R5 + GPU)基本一致,差异主要在PL侧的资源规模和GT高速收发器数量上。如果只是做控制类或者带简单接口的产品,ZU2CG就够用了,逻辑单元大概四十几万,DSP也不缺。但如果你想在PL里塞一个完整的图像处理管线,或者挂PCIe、10G以太网这种高速接口,就得往ZU4EV以上看。

选型最容易忽略的是封装和引脚。ZynqMP基本都是BGA封装,引脚密度大,PCB布线难度直线上升。如果你的团队没画过BGA,建议选引脚间距大一点的封装,哪怕芯片价格高一点,PCB加工和焊接的良率成本算下来反而是省的。另一个容易被忽略的是速度等级,速度等级高的芯片PL时序更好收敛,但价格和功耗也高。作为一个开发板项目,1级速度基本够用,没必要追最高的。

1.2 存储与启动模式:两个最容易返工的点

DDR的选择直接决定了后面FSBL和Petalinux的配置。现在主流是先DDR4,你自己画板也可以用LPDDR4——LPDDR4布线相对简单,适合低功耗产品,但Petalinux和FSBL里面针对LPDDR4的配置项和DDR4不一样,你得在Vivado的PS配置里选对颗粒类型、数据宽度、Rank数和地址映射。我的建议是第一次做自制ZynqMP板,容量做到1GB起,DDR4颗粒用市面上常见的型号,比如Micron或者海力士的DDR4 x16单Die或者双Die,这样Vivado预设库里大概率能找到对应的颗粒型号,就算找不到,手动填时序参数也比用冷门颗粒稳得多。

启动模式是另一个大坑。ZynqMP的BootROM会根据BOOT_MODE引脚的电平决定从QSPI、SD/eMMC还是JTAG启动。我强烈建议在板上留一组拨码开关或者跳线,至少能在SD启动和JTAG启动之间切换。调试阶段JTAG启动是最爽的,你可以在线加载FSBL和U-Boot,完全不用反复烧写Flash;等系统稳定了再切到SD或者QSPI启动。很多自制板为了省几个电阻电容,把启动模式直接焊死成一种,结果要么只能反复烧Flash,要么就只能JTAG,调试效率低一大截。

1.3 MIO分配与电源时序:原理图阶段就要对着参考手册

ZynqMP的PS外设通过MIO引脚引出,但MIO不是随便接的。MIO0到MIO25属于Bank 500,MIO26到MIO51属于Bank 501,这两个Bank的电平标准是独立的,你得根据外设电平去配置IO电压。比如UART一般接3.3V电平,SD卡接口建议接3.3V,个别外设可能需要1.8V。我在原理图阶段就把UART0分配到MIO18和MIO19,SD卡分配到比较顺手的MIO位置,并且确保这两个Bank的VCCO电压一致或者单独配置正确。如果等Vivado里配置PS时才发现某组外设和Bank电压对不上,板子可能就得飞线了。

电源时序也要在原理图阶段设计好。ZynqMP的电源轨多,PS侧有VCCPINT、VCCPAUX、VCCPSIO,DDR有VCCO_DDR,PL侧还有VCCINT、VCCBRAM、VCCO。上电顺序有严格要求,一般要PS核心电压先起来,然后是辅助电压和IO电压,DDR电压也不能乱。很多自制板用简单的电阻电容延时去做上电时序,这在电流不大的情况下还行,如果PL侧逻辑规模大、上电瞬间电流大,最好还是用专门的电源时序控制芯片,或者至少把PS_POR_B和PS_SRST_B的复位时序留足。PMU(电源管理单元)在ZynqMP里不是摆设,Petalinux的PMUFW固件是会参与电源管理的,所以电源侧的稳定性直接影响后面系统能不能跑稳。

1.4 调试接口:JTAG和UART是生命线

做自制ZynqMP板,别的接口都可以省,JTAG和UART绝对不能省。JTAG建议引到一个标准的10pin或者14pin插针上,用Xilinx USB Cable或者第三方的JTAG调试器都能连。注意给JTAG供电的是VCCO_PSIO对应Bank的电压,如果电压不对,调试器识别不到设备。UART就简单了,从PS_UART的MIO引到一颗USB转串口芯片,CP2102、CH340、FT232都行,我习惯选CP2102,驱动成熟,Linux下直接识别。这两个接口一旦在原理图阶段遗漏或者接错,板子回来之后你连个hello world都看不到,排查起来非常痛苦。

还有一个小建议:在板上预留几个测试点,把各电源轨、核心电压、DDR电压都引出来,方便上电时用万用表/示波器量。首板调试时你会发现这些测试点比JTAG还救急,因为很多时候不是逻辑问题而是电源没起来。

2. Vivado工程搭建:Block Design、约束和比特流的实战细节

硬件设计冻结之后,Vivado工程就是连接硬件和软件的桥梁。这一步做得干净,后面Petalinux就顺;这一步埋了雷,后面全是雷。

2.1 工程组织与"工程清理"那点事

Vivado工程有个很烦人的特点:跑完综合实现之后,目录体积能膨胀到几十GB。这里分享一个我常用的做法:工程源码(RTL、XDC、BD文件)用Git管理,Vivado生成的临时文件(.runs、.cache、.hw、.sim这些目录)全部不纳入版本控制,并且可以随时删除。具体操作是,写一个脚本把整个工程导出成一个Tcl脚本:

write_project_tcl -force ${project_dir}/scripts/rebuild_project.tcl

这个Tcl脚本记录了完整工程信息,包括所有源文件、IP配置、约束文件。等临时文件被清掉之后,你只需要在Vivado Tcl Console里source这个脚本,工程就会自动重建。这个习惯特别适合做开发板项目,因为你会频繁切换Vivado版本或者换机器,源码和脚本才是真正的资产,那些几百GB的生成目录随时可以重新生成。

如果你只是想快速瘦身,也可以直接关掉Vivado,手动删除工程目录下的.runs、.cache、.sim、.hw等文件夹,只保留.xpr和src目录。下次打开Vivado会提示重新生成,速度会慢一点,但能跑。还要提醒一句:工程路径不要有中文,也不要有空格,最好路径也别太深,否则综合时序报告和仿真阶段会冒出各种奇怪问题。

2.2 Block Design与PS配置:最不能抄作业的部分

创建Block Design之后最关键的一步,是添加Zynq UltraScale+ MPSoC这个IP。Vivado的IP配置界面有一堆页面,Presets里面可以直接选官方开发板预设,比如ZCU102。但做自制板绝对不能直接套预设,因为你的DDR颗粒、MIO分配、启动模式和官方板都不一样。

我总结了一个配置PS的顺序,照着走基本不会漏:

  1. 先配置PS-PL接口。选低功耗或者全功耗的AXI接口,我习惯打开AXI HPM0 FPD和AXI LPD两个主接口,这样PL侧自定义IP有足够的总线带宽。M_AXI_HPM0用于高速数据搬运,M_AXI_LPD用于低功耗外设访问,具体选哪个取决于你的PL侧外设需求。
  2. 配置DDR。这是最关键的。选好DDR类型(DDR4/LPDDR4)、位宽(16/32/64)、Rank数和寻址方式。如果你的颗粒在Vivado列表里搜不到,就手动输入设备型号和时序参数。这里多花一点时间,后面FSBL就少踩一个坑。
  3. 配置MIO。把UART、SD、QSPI这些PS固定外设的MIO引脚选好。系统会自动检测MIO冲突,但Bank电压匹配必须自己确认。
  4. 配置启动模式。如果你的板子用拨码开关切换启动方式,这里要把几种启动模式都勾上,比如QSPI和SD都选。
  5. 配置PL时钟。从PS输出pl_clk0和pl_clk1,频率根据PL侧外设需求设定,一般pl_clk0给100MHz或者150MHz。

Block Design里添加PL外设也有一点讲究。比如添加AXI GPIO,你需要在下游地址空间里给它分配地址。Vivado有自动分配地址的功能,但我还是习惯手动指定。比如把GPIO分配在0xA0000000这种地址,方便后面在设备树里对照。地址分配的原则是:避开PS保留地址和设备控制器的地址空间,冲突的话Vivado会报错,但手动分配心里更有数。

2.3 管脚约束和时序约束:自制板没有现成约束可用

官方开发板都有现成的XDC文件,自制板就得自己写。管脚约束这部分我建议在原理图设计阶段就同步做一张引脚分配表,把所有PL侧用到的信号、所属Bank、电平标准、引脚号列出来,画完原理图之后直接对照写XDC。典型案例是LED和按键:

set_property PACKAGE_PIN H5 [get_ports {led[0]}] set_property IOSTANDARD LVCMOS33 [get_ports {led[0]}] set_property PACKAGE_PIN J5 [get_ports {led[1]}] set_property IOSTANDARD LVCMOS33 [get_ports {led[1]}] set_property PACKAGE_PIN K6 [get_ports {btn[0]}] set_property IOSTANDARD LVCMOS33 [get_ports {btn[0]}]

时序约束比管脚约束更容易翻车。自制板上PL侧时钟如果来自PS的pl_clk0,那在Block Design里就自动知道了时钟频率,Vivado会推断出来。但如果有外部时钟芯片给PL供时钟,就得手动在XDC里创建时钟约束:

create_clock -period 10.000 -name ext_clk [get_ports ext_clk]

还有一个高频踩法:PL侧外设通过AXI总线接入PS,AXI总线的时钟和PL外设自己的时钟往往不是同一个域,此时要对跨时钟域路径做约束。最省事的做法是在XDC里对跨时钟域的同步器链路加set_false_path,但这要分清楚哪些路径是真的异步、哪些只是名字不同但物理同源。我的习惯是先把设计综合出来看时序报告,再决定哪些路径需要特殊处理。

2.4 生成比特流失败:先看报告再猜原因

生成比特流失败是个很让人抓狂的问题,因为Vivado报错的信息有时候很隐晦。常见的几类情况和我的排查思路:

  • 时序违例(Timing Failure)。看Implementation的时序报告,重点看WNS和TNS。如果WNS是负的,说明有路径不满足时序要求。先检查约束是否完整,再考虑用Implementation策略。Vivado提供一堆实现策略,比如PerformanceExplore、CongestionSpreadLogic这些,有时候换一个策略就过了。
  • 布局布线失败(Routing Failure)。一般是资源过度拥塞,比如BRAM和DSP排布不合理,或者某些跨bank的信号把布线资源耗尽。这时候回头看原理图引脚分配,检查是否有信号跨了过远的bank。
  • 非HDL错误。比如引脚约束冲突、IP输出接口不匹配。这种报错会定位到具体对象,按照Vivado报告的提示检查即可。

比特流生成成功之后,习惯上导出硬件时要把比特流包含进去:File → Export Hardware,勾选Include bitstream。这样导出的XSA文件里就有FPGA配置数据,后面Petalinux打包BOOT.BIN时会用到。

3. Petalinux系统构建:版本匹配与设备树是成败关键

Vivado这边把硬件描述文件XSA导出来之后,就到了Petalinux的战场。Petalinux本质上是一套Yocto的封装,它吃进XSA,吐出一整套启动镜像和根文件系统。用好了很省心,用不好各种诡异问题。我的经验是,第一要务是版本匹配,第二要务是学会改设备树。

3.1 Petalinux版本与Vivado版本必须严格对齐

Petalinux的版本号和Vivado的版本号是绑定的,Vivado 2023.1就用Petalinux 2023.1。我见过有人拿Petalinux 2020.2去配Vivado 2023.1的XSA,结果工程导入直接报错,或者编译出来的镜像起不来。版本不匹配的问题不会在导入时报出来,而是在你烧到板子上才发现系统起不来,这种低级错误排查起来很崩溃。

安装Petalinux本身也有讲究。官方安装器是个.run文件,安装之前要把依赖装好:

sudo apt install -y gawk xvfb libncurses5-dev libssl-dev zlib1g-dev \ libyaml-dev libpython3-dev python3-venv chrpath diffutils \ autoconf automake libtool gcc g++ gperf texinfo

安装器运行之后会把Petalinux部署到指定目录,比如/opt/petalinux。每次打开新终端都要source一下环境:

source /opt/petalinux/settings.sh

Petalinux对Ubuntu版本也有要求,装之前先查一下当前Petalinux版本对应的官方支持OS列表。系统版本太新或者太旧都会导致编译阶段一堆奇怪的错误。这个真的别硬抗,直接换一个受支持的Ubuntu版本最省时间。

3.2 创建工程:用XSA生成硬件描述

环境准备好之后,创建工程的流程是固定的:

petalinux-create --type project --template zynqMP --name myboard cd myboard petalinux-config --get-hw-description=../vivado/export/

--get-hw-description后面跟的是包含XSA文件的目录,它会自动解析硬件配置,生成对应的设备树、FSBL、PMUFW等组件的配置。导入之后不要急着编译,先进petalinux-config的主界面看一下关键配置项。我每次都会检查这几个地方:

  • Linux Components Selection(U-Boot和内核的源码获取方式,建议默认即可)
  • DTG Settings(设备树生成相关,保持默认)
  • Root filesystem type。这里很关键,想快速验证就用INITRAMFS,它把根文件系统打进内存里,启动快,但任何修改都会在掉电后丢失。如果要跑真实应用,选EXT4或者SD卡根文件系统,后面把rootfs放到SD卡分区里。
  • Image Packaging Configuration。决定最后如何打包启动镜像,默认会生成BOOT.BIN和image.ub。

还有一个值得注意的选项是U-Boot的配置。ZynqMP的U-Boot默认从启动设备加载镜像,如果你从SD启动,U-Boot会自动去找SD卡上的BOOT.BIN和image.ub。如果从QSPI启动,得确保QSPI里烧的东西和U-Boot的加载路径一致。

3.3 设备树:集中火力改system-user.dtsi

设备树是ZynqMP开发里绕不开的坎,自制板尤其如此。Petalinux生成设备树的源头是XSA,但XSA只是一部分信息,真正的设备树内容是Petalinux根据XSA里的硬件配置自动生成的。如果你要添加自己的外设配置信息,不要直接去改生成的文件,因为下次重新导入XSA或者重新配置时会被覆盖。正确做法是改这个文件:

project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi

这个dtsi会被自动包含进最终生成的设备树里。我习惯在system-user.dtsi里自定义设备树的model名、chosen节点的bootargs、以及PL侧自定义外设的节点。

以PL侧一个AXI GPIO到LED为例,典型的system-user.dtsi片段:

/include/ "system-conf.dtsi" / { model = "MyBoard ZynqMP"; chosen { bootargs = "console=ttyPS0,115200 earlycon root=/dev/mmcblk0p2 rw rootfstype=ext4"; }; }; &axi_gpio_0 { #address-cells = <1>; #size-cells = <0>; compatible = "xlnx,axi-gpio-2.0"; reg = <0x0 0xa0000000 0x0 0x10000>; interrupts = <0 29 4>; /* SPI中断,29号,高电平触发 */ };

这里有个非常容易搞错的地方:ZynqMP是64位地址系统,所以设备的reg属性要写两对<地址 大小>,分别表示地址的高32位和低32位。如果只写reg = <0xa0000000 0x10000>,设备树解析的时候会当成64位地址的最高32位,直接导致驱动访问到了错误的地址空间。这个坑我踩过,当时一个自定义IP死活读不到数据,最后发现就是reg写法不对。

还有UART的别名问题。Linux启动时console如果指定为ttyPS0,系统会在设备树里找serial0这个别名。Petalinux生成的设备树通常是对的,但如果你的板卡只有UART1而别名指向了UART0,控制台就没有输出。保险的做法是启动的时候看U-Boot的环境变量和内核的命令行,确认console=ttyPS0对应的是真正接出来的那路UART。

3.4 编译打包与SD卡启动结构

配置好了就编译:

petalinux-build

编译时间取决于你的机器配置和包的数量,第一次全量编译可能需要一二十分钟,后面增量编译就快多了。编译完在images/linux目录下会生成Image、system.dtb、rootfs.ext4等文件。然后打包启动镜像:

petalinux-package --boot --fsbl --fpga --u-boot --force

这个命令会生成BOOT.BIN,它由FSBL、PMUFW、FPGA比特流(来自XSA里的bit文件)、ARM Trusted Firmware(ATF)和U-Boot组成。BOOT.BIN就是ZynqMP上电后BootROM加载的第一个文件。

SD卡启动的布局很简单:第一个FAT32分区放BOOT.BIN和image.ub(image.ub是内核+设备树+ramdisk的打包),第二个分区是ext4格式放根文件系统。如果你用ext4根文件系统,把rootfs.ext4或者解包的内容拷贝到SD第二个分区即可。

有一点要特别提醒:自制板如果没有跑过官方BSP,第一次启动建议先用INITRAMFS形式的image.ub验证整个链路,等串口控制台、DDR、SD卡都确认没问题,再切换到ext4根文件系统,这样排查问题范围小很多。

4. 首板调试全记录:从短路检查到Linux控制台输出

板子到手的那一刻开始,才是这个项目真正的高潮。首板调试讲究一个词:胆小如鼠。每一步都做最小验证,不要指望一次就把系统跑起来。

4.1 上电前检查:万用表比示波器先上场

PCB贴片回来之后,我先不急着焊所有器件,而是先做两个检查:

第一,用万用表蜂鸣档测电源网络对地阻抗。重点测3.3V、1.8V、VCCINT、VCCO_DDR这些电源轨对地是否有短路。如果某个电源网络阻抗几乎为零,先别上电,排查虚焊和连锡。这一步能救回至少一半的首板问题。

第二,上电前把电源的过流保护设到比较低的值,比如500mA或者1A。ZynqMP核心电压上电瞬间电流不会太大,如果电流突然飙上去,说明有短路或者某个电源轨起不来。我用可调电源给板子供电,电流限制先设小,看到静态电流正常之后再逐步放开。

4.2 JTAG与XSCT:还没有Petalinux时怎么验证硬件

板子上电之后,如果PS的电源和时钟正常,JTAG应该能识别到设备。打开Vivado Hardware Manager,点击Open Target,第一次连接可能需要扫描JTAG链。识别不到设备的话,先查JTAG Bank的供电电压,再看TCK频率——自制板布线没那么讲究,JTAG信号质量一般,把TCK频率从默认的15MHz降到5MHz往往就能连上。

如果能识别到设备,我做的第一件事是连XSCT命令行,确认A53核心是活的。启动一个XSCT:

connect targets

如果targets列表里有ARM A53核,说明PS侧基本工作正常。接下来初始化DDR,这是验证整块板DDR硬件通路最直接的方法:

targets -set -filter {name =~ "*A53*#0"} dow -data /path/to/ddr_test.bin 0x00000000 con

如果你还没编译出任何Petalinux镜像,先用Vivado导出的XSA配套的FSBL或者直接用xsct的mwr指令去读写DDR地址,如果写读一致,DDR大概率的硬件和初始化没问题。这个阶段把问题解决掉,比自己盲目烧镜像再猜要好得多。

4.3 启动阶段故障地图:现象定位思路

有了JTAG基础,接下来把BOOT.BIN放到SD卡上,切换到SD启动模式,接上串口,上电看输出。我把启动过程中经常会遇到的故障现象整理成一张表,方便对照:

启动阶段典型现象可能原因排查方向
BootROM串口完全无输出BOOT_MODE引脚设置错误、BootROM没读到BOOT.BIN量BOOT_MODE电平、检查SD卡FAT32分区和文件名
FSBL卡在FSBL阶段,没有U-Boot输出DDR配置错误、PS时钟异常检查Vivado里DDR型号/位宽/Rank配置,检查PS_PLL
PMUFW串口输出PMU相关错误电源时序异常、PMUFW配置与硬件不符检查电源电压,重新配置PMU并打包
U-Boot输出停在U-Boot启动,找不到image.ubSD卡分区/文件名错误、U-Boot环境变量异常确认image.ub在FAT32分区,进入U-Boot命令行检查env
内核QEMU/内核启动到一半崩溃设备树错误、bootargs参数不对重点查console设备、root设备号、reg属性
rootfs报错Unable to mount rootfs内核找不到根文件系统确认bootargs里root=/dev/mmcblk0p2与实际分区一致

第一次启动最常见的现象是:串口完全没输出。我遇到过两种情况,一种是BOOT_MODE拨码开关没拨对,另一种是SD卡的FAT32分区第一个分区不是活跃分区。还有一次是FSBL起来之后没有任何输出,排查了半天,最后发现是UART的MIO引脚在Vivado里根本没勾选启用,这个错误原理图阶段就该发现,但实际就是很容易漏。

4.4 设备树不对导致外设不工作

系统启动到Linux之后,外设不工作是大概率事件。有一次我加了一个PL侧的AXI UART IP,地址分配在0xA0000000,设备树里也写了reg属性,但Linux启动后/dev/ttyUL0这个设备就是不存在。排查了一下午,发现是地址写错了:

/* 错误写法 */ reg = <0xa0000000 0x10000>; /* 正确写法:ZynqMP是64位地址 */ reg = <0x0 0xa0000000 0x0 0x10000>;

这个错误非常隐蔽,因为设备树的错误提示不明显,只是说设备初始化失败。从那以后,我每次在ZynqMP上写自定义外设的设备树节点,都会再三确认reg的写法。还有一次是中断号不对。ZynqMP上PL侧中断是SPI类型,中断号在设备树里不是随便写的,你得对照PS的gic中断控制器映射。比如PL外设通过AXI接口接到PS,中断号范围通常从121到136,具体取决于Vivado里分配的连接关系。设备树里写错中断号,驱动request_irq的时候会返回错误,外设就注册失败。查这个问题最快的方法是在内核启动日志里搜对应设备的probe失败信息,通常能看到中断申请失败的报错。

5. 一个小而全的实战示例:让LED全链路亮起来

前面讲了不少理论,最后我用一个"PL侧LED点亮"的完整示例,把整套流程串一遍。很多人觉得LED太简单,其实它是在验证硬件、工具链、设备树、驱动和应用层整条链路,非常适合作为自制板卡调试的"hello world"。

5.1 Vivado侧:AXI GPIO与地址分配

在Block Design里添加AXI GPIO IP,双击配置成4位输出,连接到PS的AXI接口(比如M_AXI_HPM0_LPD或者M_AXI_LPD,取决于你选哪条总线)。在Address Editor里给这个AXI GPIO手动分配一个地址,比如0xA0000000。然后重新综合实现、生成比特流、导出XSA。

这里有个经验:PL侧外设地址尽量安排在低地址区间,比如0xA0000000附近,这样在设备树和应用程序里写地址不容易出错。高地址区间的访问虽然也能用,但容易和PS保留空间混淆。

5.2 Petalinux侧:确认设备树节点

导入新的XSA并重新编译之后,查看生成的设备树:

petalinux-build cat project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi

如果设备树生成正确,里面应该能看到axi_gpio_0节点。如果没有,就要检查Vivado里的AXI接口是否接对了。我通常会在system-user.dtsi里单独追加一个chosen节点,把bootargs设为方便调试的参数。等设备树确认无误,重新打包BOOT.BIN。

5.3 写个小程序控制LED

Linux启动后,AXI GPIO的通用驱动gpio-xilinx一般会自动加载。你可以直接看/sys/class/gpio下的gpiochip信息确认:

cat /sys/kernel/debug/gpio

如果gpiochip出现,根据base号和offset找到对应的GPIO引脚,通过sysfs或者libgpiod控制:

# 使用libgpiod,假设gpiochip0 base是0,对应的LED是line 0 gpioset gpiochip0 0=1 gpioset gpiochip0 0=0

如果你用的是自定义IP,没有现成的驱动,那就得写一个简单的字符设备驱动,通过ioremap映射地址去操作寄存器。这种驱动几十行就能搞定,配合用户空间的小程序,能验证从AXI总线到设备寄存器的全链路。

5.4 这个示例的价值

LED这个例子最大的价值是:它能确凿地证明硬件、FPGA比特流、设备树、内核驱动、用户空间程序这五个层级都通了。如果LED不亮,逐级排查——先看Vivado的仿真输出对不对,再看设备树节点在/sys下有没有生成,再看驱动probe有没有成功,最后看寄存器读写值是否正确。这套排查思路是通用的,后面换成任何复杂外设,流程一模一样。我每次做一块新板卡,第一件事必然是把所有PL侧的LED和按键都点亮一遍,确认基础外设没有问题,才敢跑复杂功能。

其实我最终做这块板子,从原理图到Linux控制台输出,前后花了不到两周,大部分时间都耗在DDR配置和第一次SD卡启动上。回头看,所有大坑都能追溯到硬件设计阶段的一个小决定:MIO分配、启动模式、DDR颗粒选型、调试接口预留。所以想自己做ZynqMP开发板的工程师,先把前面这些决策做扎实,后面的Petalinux和Vivado反而都是体力活。最后再分享一个经验:每次上电前把那套启动故障地图贴在工位上,遇到问题先对号入座,不要盲目改配置,首板调试最贵的就是时间。希望这篇记录能帮你少走几步弯路。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询