ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

自制Zynq UltraScale+ MPSoC开发板:从硬件决策到Petalinux系统构建全记录

自制Zynq UltraScale+ MPSoC开发板:从硬件决策到Petalinux系统构建全记录 很多工程师在官方开发板上把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 500MIO26到MIO51属于Bank 501这两个Bank的电平标准是独立的你得根据外设电平去配置IO电压。比如UART一般接3.3V电平SD卡接口建议接3.3V个别外设可能需要1.8V。我在原理图阶段就把UART0分配到MIO18和MIO19SD卡分配到比较顺手的MIO位置并且确保这两个Bank的VCCO电压一致或者单独配置正确。如果等Vivado里配置PS时才发现某组外设和Bank电压对不上板子可能就得飞线了。电源时序也要在原理图阶段设计好。ZynqMP的电源轨多PS侧有VCCPINT、VCCPAUX、VCCPSIODDR有VCCO_DDRPL侧还有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的顺序照着走基本不会漏先配置PS-PL接口。选低功耗或者全功耗的AXI接口我习惯打开AXI HPM0 FPD和AXI LPD两个主接口这样PL侧自定义IP有足够的总线带宽。M_AXI_HPM0用于高速数据搬运M_AXI_LPD用于低功耗外设访问具体选哪个取决于你的PL侧外设需求。配置DDR。这是最关键的。选好DDR类型DDR4/LPDDR4、位宽16/32/64、Rank数和寻址方式。如果你的颗粒在Vivado列表里搜不到就手动输入设备型号和时序参数。这里多花一点时间后面FSBL就少踩一个坑。配置MIO。把UART、SD、QSPI这些PS固定外设的MIO引脚选好。系统会自动检测MIO冲突但Bank电压匹配必须自己确认。配置启动模式。如果你的板子用拨码开关切换启动方式这里要把几种启动模式都勾上比如QSPI和SD都选。配置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总线接入PSAXI总线的时钟和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.shPetalinux对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 SelectionU-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 consolettyPS0,115200 earlycon root/dev/mmcblk0p2 rw rootfstypeext4; }; }; 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的环境变量和内核的命令行确认consolettyPS0对应的是真正接出来的那路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 FirmwareATF和U-Boot组成。BOOT.BIN就是ZynqMP上电后BootROM加载的第一个文件。SD卡启动的布局很简单第一个FAT32分区放BOOT.BIN和image.ubimage.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核心是活的。启动一个XSCTconnect 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_PLLPMUFW串口输出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 写个小程序控制LEDLinux启动后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 01 gpioset gpiochip0 00如果你用的是自定义IP没有现成的驱动那就得写一个简单的字符设备驱动通过ioremap映射地址去操作寄存器。这种驱动几十行就能搞定配合用户空间的小程序能验证从AXI总线到设备寄存器的全链路。5.4 这个示例的价值LED这个例子最大的价值是它能确凿地证明硬件、FPGA比特流、设备树、内核驱动、用户空间程序这五个层级都通了。如果LED不亮逐级排查——先看Vivado的仿真输出对不对再看设备树节点在/sys下有没有生成再看驱动probe有没有成功最后看寄存器读写值是否正确。这套排查思路是通用的后面换成任何复杂外设流程一模一样。我每次做一块新板卡第一件事必然是把所有PL侧的LED和按键都点亮一遍确认基础外设没有问题才敢跑复杂功能。其实我最终做这块板子从原理图到Linux控制台输出前后花了不到两周大部分时间都耗在DDR配置和第一次SD卡启动上。回头看所有大坑都能追溯到硬件设计阶段的一个小决定MIO分配、启动模式、DDR颗粒选型、调试接口预留。所以想自己做ZynqMP开发板的工程师先把前面这些决策做扎实后面的Petalinux和Vivado反而都是体力活。最后再分享一个经验每次上电前把那套启动故障地图贴在工位上遇到问题先对号入座不要盲目改配置首板调试最贵的就是时间。希望这篇记录能帮你少走几步弯路。
返回列表