ARTICLE DETAIL

资讯详情

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

ZYNQ+Linux实战:Petalinux 2023.1定制系统全流程与排坑指南

ZYNQ+Linux实战:Petalinux 2023.1定制系统全流程与排坑指南 如果你手头有一块ZYNQ开发板想让PS端的ARM核跑起来Linux那Petalinux大概率是你绕不开的工具。今年我把项目环境从Petalinux 2020.2整体切到了2023.1重新走了一遍定制Linux系统的完整流程从环境安装、硬件导出、内核配置到打包烧写中间又踩了不少新坑。这篇文章就围绕ZYNQ开发板实战把Petalinux 2023.1定制Linux系统的全流程整理出来重点记录报错和解决思路。内容偏实操适合刚接触ZYNQLinux的新手也适合用过旧版本、想切到2023.1的开发者参考。1. 为什么用Petalinux而不是自己手搓Linux很多从裸机转过来的朋友第一次接触ZYNQ Linux时会问我不就是编译一个内核、一个U-Boot、做一个根文件系统吗为什么非要单独学一套工具链这个问题的答案等你真正把ZYNQ跑起来之后就明白了。ZYNQ的难点不在于Linux本身而在于PS和PL协同工作时那一大堆硬件描述、设备树、启动镜像之间的关系。1.1 ZYNQ的软硬件协同架构ZYNQ-7000系列芯片内部有PSProcessing System和PLProgrammable Logic两部分PS是双核ARM Cortex-A9PL是FPGA可编程逻辑。PS端可以独立跑Linux但它要访问PL里的IP核、要控制DDR时序、要管理中断这些信息必须通过设备树告诉内核。而设备树的生成又依赖Vivado里画的硬件工程硬件工程的配置又决定了FSBLFirst Stage Boot Loader怎么初始化DDR和时钟。这套链路里只要有一个环节对不上板上就起不来系统。用手工方式去写内核、U-Boot、设备树不是不能做但每次硬件工程一改就要同步改一整套文件非常容易漏。Petalinux的核心价值就是把这套链路的工具化它接收Vivado导出的XSA硬件描述文件自动生成和硬件匹配的设备树源码、内核配置和U-Boot配置把“硬件变更”到“Linux可启动”的距离缩到最短。1.2 Petalinux到底帮你做了什么Petalinux本质上是一个基于Yocto的构建系统它帮你管理了以下几件事第一核对了BSP和工具链版本。Petalinux 2023.1对应Vivado 2023.1使用配套的工具链版本可以避免很多底层ABI不匹配的问题。第二根据XSA自动生成FSBL、PMU固件、设备树源文件你不需要手写启动代码。第三提供了一层meta-user的定制接口你可以在不破坏官方BSP的情况下把自定义的设备树片段、内核补丁、应用程序全部加进去后续做版本升级时改动非常集中。我在实际项目中特别依赖meta-user这个机制。比如要给ZYNQ增加一个PL侧的DMA节点我只需要在system-user.dtsi里补充设备树节点然后在应用层写驱动根本不碰官方BSP的文件这样同事之间协作也不会互相覆盖。2. 环境准备安装Petalinux 2023.1的完整记录Petalinux的安装本身不算难但宿主机的环境要求非常苛刻版本不对、依赖缺失后面所有操作都会连环报错。这一节把我的安装过程完整贴出来包括几个容易卡住的地方。2.1 宿主机选型和依赖包安装Petalinux 2023.1官方支持Ubuntu 18.04、20.04和22.04我使用的是Ubuntu 22.04 LTS 64位。首先明确一点24.04也可以尝试但官方不在支持列表里依赖包版本容易出现偏差不建议在生产环境用。在安装依赖之前先更新一下软件源避免apt索引太久导致安装失败sudo apt update sudo apt upgrade -y然后安装Petalinux所需的主要依赖包sudo apt install -y \ autoconf automake bison build-essential chrpath cpio \ diffstat flex gawk gcc gcc-multilib git gnupg \ g g-multilib libncurses5-dev libssl-dev libtool \ libtool-bin m4 make net-tools python3 python3-git \ python3-jinja2 python3-pexpect python3-pip \ python3-setuptools screen socat tar texinfo unzip \ wget xterm xvfb zlib1g-dev这里有一个非常需要注意的坑Ubuntu 22.04的apt源里可能没有libncurses5-dev和libtinfo5而Petalinux 2023.1的很多脚本又依赖libtinfo.so.5这个库。如果你在安装依赖时提示找不到这两个包需要手动从Ubuntu 20.04的软件源下载libtinfo5的deb包来安装wget http://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2ubuntu1_amd64.deb sudo dpkg -i libtinfo5_6.3-2ubuntu1_amd64.deb装完之后可以用dpkg -l | grep tinfo确认。这个包不装好后面运行petalinux-config时很可能会直接报libtinfo.so.5: cannot open shared object file千万别在这一步偷懒。2.2 安装Petalinux和解锁环境变量从Xilinx官网下载petalinux-v2023.1-installer.run安装包建议放在一个不含中文和空格的路径下。安装目录我习惯放在/opt/pkg/petalinux这样可以在多用户之间共享工具链。mkdir -p /opt/pkg chmod x petalinux-v2023.1-installer.run ./petalinux-v2023.1-installer.run /opt/pkg/petalinux安装过程中会先检查hostname是否包含特殊字符还要用/bin/sh执行如果默认shell不对可以用sudo sh ./petalinux-v2023.1-installer.run /opt/pkg/petalinux规避。另外强烈建议安装时提示选择sstate-cache时把sstate包一并解压到/opt/pkg/petalinux/sstate目录。sstate是预编译缓存能极大缩短后续首次构建时间否则从零编译一个完整镜像可能要等好几个小时。安装完成后需要source环境变量配置文件这一步不要写错路径source /opt/pkg/petalinux/settings.sh我建议直接把这句加到~/.bashrc里免得每次开终端都要手动执行。但要注意如果同时安装了Vitis和Vivado环境变量之间的顺序冲突也是常见的报错来源后source的Petalinux环境应该最后生效。2.3 验证安装是否成功环境配置好之后第一时间验证安装是否正常which petalinux-create pdversion如果petalinux-create能找到pdversion能输出2023.1相关信息说明工具链安装成功。提示如果执行pdversion时提示找不到命令多半是settings.sh没source成功检查一下PETALINUX环境变量是否设置了正确路径echo $PETALINUX。3. 从Vivado到Petalinux硬件配置的传递Petalinux不是凭空构建的它的起点是Vivado导出的XSA文件。这个环节如果理解不到位很容易出现“内核起来了但外设全失效”这种奇怪问题。3.1 Vivado工程与XSA导出我是在Vivado 2023.1中搭建的ZYNQ-7000最小硬件系统包含ZYNQ7 Processing System IP、一个AXI GPIO、一个UART和一个SD控制器。这些外设的地址、中断号、时钟频率全部由Vivado分配Linux内核完全依赖设备树来获取这些信息。关键步骤是硬件导出。在Vivado中完成综合、实现、生成比特流之后执行File Export Hardware弹窗中务必勾选Include bitstream输出的XSA文件同时包含硬件描述和PL配置Petalinux后续打BOOT.BIN时会用到里面的比特流。注意不要把老版本的HDF文件当作XSA使用。Petalinux 2023.1只认XSA格式老工程迁移时需要在Vivado里重新导出。我见过一个同事直接把旧项目的.hdf改名为.xsa丢给Petalinux结果编译的时候各种莫名其妙的问题。3.2 创建Petalinux工程并导入硬件描述有了XSA之后在工程目录下创建Petalinux工程。ZYNQ-7000系列使用的模板是zynq如果是Zynq UltraScale MPSoC则用zynqMPpetalinux-create -t project -n edge_zynq --template zynq cd edge_zynq petalinux-config --get-hw-description/path/to/vivado/edge_zynq.xsa执行petalinux-config之后会进入一个menuconfig图形界面这里有几个配置项需要重点关注第一Subsystem AUTO Hardware Settings Memory确认DDR配置和Vivado工程一致一般会自动带入不需要手动改。第二Subsystem AUTO Hardware Settings Serial Settings确认串口设备选择正确ZYNQ通常对应uart1默认波特率115200。第三Image Packaging Configuration Root filesystem type我习惯选ext4方便后续挂载到SD卡的第二分区。配置完成后按Exit保存Petalinux会根据XSA自动生成设备树和FSBL相关源码。这一步结束后project-spec目录下就出现了整套可定制的工程文件。3.3 看懂设备树Petalinux如何认识硬件设备树是ZYNQ Linux跑起来之后内核了解板级硬件配置的唯一途径。Petalinux生成的主设备树文件在project-spec/meta-user/recipes-bsp/device-tree/files/目录下其中system-top.dts是顶层文件system-user.dtsi是用户自定义设备树片段pl.dtsi是PL侧IP对应的设备树节点。新手最容易犯的错误是直接修改官方生成的system.dts。官方文件在每次重新导入XSA时会被覆盖所以官方提供的定制入口是system-user.dtsi。例如我要给PL侧挂的一个AXI DMA添加兼容性描述就在system-user.dtsi里写amba { axi_dma_0: axi-dma40400000 { compatible xlnx,axi-dma-7.1; reg 0x40400000 0x10000; interrupts 0 29 4; #dma-cells 1; }; };然后重新编译设备树部分即可petalinux-build -c device-tree。这也是网上常见问题“怎么通过petalinux编译外部的设备树和内核”的答案不要改官方文件把自定义内容放进meta-user层再单独编译对应组件。4. 定制系统内核、文件系统和U-Boot硬件描述导入成功之后就到了整个定制过程中最灵活的环节。你要裁剪内核、选择文件系统软件包、调整U-Boot启动参数让这个Linux真正符合你的业务需要。4.1 内核裁剪的要点执行petalinux-config -c kernel会调出内核的menuconfig界面。第一次进入时界面刷得很快不用慌它是在解压内核源码等完全出来之后再做配置。ZYNQ-7000内核裁剪的首要原则是先保证功能再压缩体积。我一般优先确认以下几项Device Drivers Serial 勾选对应串口驱动内核启动日志必须靠它输出Device Drivers Block devices 确认RAM block device支持用于initramfs启动场景File systems 勾选ext4、proc、sysfs、devtmpfs等基础文件系统如果要跑Qt应用还需要Framebuffer、DRM相关的驱动以及CONFIG_FB_TFT这类小屏驱动裁剪时要注意不要轻易关闭内核符号表CONFIG_KALLSYMS和模块加载支持CONFIG_MODULES否则后面排查问题、加载驱动模块时会非常痛苦。我一般会勾选CONFIG_DEVTMPFS_MOUNT让内核启动时自动挂载/dev省掉手动mdev的步骤。提示内核配置保存在工程目录下的project-spec/configs/linux-xlnx/config里每次修改后建议用petalinux-build -c kernel单独验证而不是直接全量编译。4.2 根文件系统的选择与配置根文件系统是整个定制过程里最影响使用体验的部分。执行petalinux-config -c rootfs之后同样进入menuconfig界面里面有大量的软件包选项。如果你的板子内存不大或者对启动速度要求极高可以使用initramfs。initramfs是把整个文件系统打包进一个镜像启动时由U-Boot加载到内存中好处是不需要挂载SD卡/Flash缺点是文件系统里的任何修改在重启后都会丢失。如果是做产品原型验证我强烈建议用ext4根文件系统然后把应用和配置放在SD卡上这样调试效率高很多。在Image Packaging Configuration里把Root filesystem type设为ext4后可以在Filesystem Packages里配置要预装的软件包。我常用的是console-tools提供常用终端命令openssh-sshd远程登录调试必备ethtool、iperf3网络调试can-utils如果用到CAN总线python3-core跑脚本需要软件包尽量在Petalinux层面选好不要在启动后再手动装。原因是Petalinux的软件包和内核版本是严格匹配的你在目标板上用opkg装包有时候会遇到依赖冲突。4.3 U-Boot启动参数配置U-Boot是ZYNQ的二级引导程序负责加载内核和设备树。U-Boot配置通过petalinot-config主菜单里的U-Boot Configuration进入而启动参数则通常在project-spec/meta-user/recipes-bsp/u-boot/u-boot-appended-dtb.bbappend或者环境变量文件中调整。对SD卡启动场景我使用的bootargs是consolettyPS0,115200 root/dev/mmcblk0p2 rw rootwait其中ttyPS0对应ZYNQ的UART/dev/mmcblk0p2指向SD卡的第二分区。如果换成initramfs启动则要把root参数去掉改为指定initrd加载路径。一个比较隐蔽的坑是U-Boot环境变量里的bootcmd。Petalinux默认可能从FAT分区读取image.ub如果你的SD卡根目录放了多个镜像文件U-Boot会按顺序尝试加载到第一个损坏文件时会卡在Starting kernel之前。排查这类问题进U-Boot命令行按任意键打断自动启动后手动执行printenv bootcmd printenv bootargs fatls mmc 0:1可以快速确认启动流程到底走到哪一步。5. 编译、打包与烧写让ZYNQ真正跑起来前面所有配置做完最终要把它们变成可以烧写到板子上的镜像。这一节讲的是编译打包的完整流程以及SD卡启动和QSPI固化两种烧写方式的实际操作。5.1 petalinux-build编译与阶段控制执行全量编译很简单一条命令petalinux-build但全量编译会很耗时所以在调试阶段我一般只编译改动过的部分。常用的阶段控制命令有petalinux-build -c device-tree # 只编译设备树 petalinux-build -c kernel # 只编译内核 petalinux-build -c rootfs # 只编译文件系统 petalinux-build -c u-boot # 只编译U-Boot如果是第一次编译建议在命令行加个-j 8之类的并行参数吗Petalinux默认已经根据CPU核心数做了并行构建不需要额外指定。如果构建过程中途失败优先去看构建日志而不是反复重跑全量编译。日志一般在build/tmp/work/对应的组件目录下的temp/log.do_compile文件里定位到具体报错的代码位置再针对性处理。5.2 生成启动镜像BOOT.BIN与image.ub编译完成后在images/linux/目录下会生成多个文件。最终需要打包成两个关键启动文件第一个是BOOT.BIN它是由FSBL、PL比特流和U-Boot拼接而成的启动镜像负责芯片初始化、加载PL配置、然后跳转到U-Boot。生成命令petalinux-package --boot --fsbl --fpga --u-boot --forcePetalinux会自动在images/linux/下寻找zynq_fsbl.elf、system.bit和u-boot.elf。如果指定了多个比特流需要手动指定--fpga参数例如petalinux-package --boot --fsbl zynq_fsbl.elf --fpga system.bit --u-boot u-boot.elf --force第二个是image.ub它整合了内核、设备树和initramfs如果有U-Boot启动时直接加载这个文件即可。这个文件在petalinux-build之后默认生成不需要额外打包。提示BIOS中如果使用QSPI Flash启动BOOT.BIN需要和Flash大小匹配ZYNQ-7000常用的QSPI Flash容量是16MB或32MB如果BOOT.BIN超过10MB要考虑裁剪根文件系统或改用SD卡启动。5.3 SD卡启动与QSPI固化SD卡启动是调试阶段最方便的方案。用fdisk将SD卡分成两个分区第一分区为FAT32大小建议1GB左右放BOOT.BIN和image.ub第二分区为ext4占剩余空间放根文件系统。格式化并拷贝文件的操作如下sudo fdisk /dev/sdb # 创建分区1类型cFAT32创建分区2类型83Linux sudo mkfs.vfat -F 32 /dev/sdb1 sudo mkfs.ext4 /dev/sdb2 sudo mount /dev/sdb1 /mnt/fat sudo cp images/linux/BOOT.BIN /mnt/fat/ sudo cp images/linux/image.ub /mnt/fat/ sudo umount /mnt/fat sudo mount /dev/sdb2 /mnt/rootfs sudo tar xf images/linux/rootfs.tar.gz -C /mnt/rootfs sudo umount /mnt/rootfs注意rootfs解压这一条命令非常容易踩坑。如果你之前设置的根文件系统类型是initramfs则没有rootfs.tar.gz不要按部就班地执行。另外rootfs.tar.gz解压可能需要一两分钟别在中间按CtrlC打断否则文件系统不完整启动时会卡在挂载根分区。QSPI固化适用于产品发布阶段。用Vivado Hardware Manager连接JTAG加载BOOT.BIN到QSPI过程不依赖DDR因为固化动作本身是把镜像写入Flash。但如果你的BOOT.BIN里包含PL比特流JTAG加载时需要先初始化DDR来存储部分临时数据所以一些流程会要求先连接DDR。实际操作中我通常先用Vivado烧写QSPI再设置为QSPI启动模式上电就能跑系统不需要每次接JTAG。6. 高频报错与排查这一节是标题里的另一个重点我把Petalinux 2023.1使用过程中遇到的高频报错按环境、编译、启动三个分类整理成速查表。遇到问题时可以直接对照着看节省定位时间。6.1 环境类报错装不好后面全白搭环境类报错集中在安装阶段和首次运行阶段表现通常是命令找不到、动态库缺失、Python版本不兼容。报错信息原因解决办法petalinux-create: command not found没有source settings.sh执行source /opt/pkg/petalinux/settings.sh并加入~/.bashrclibtinfo.so.5: cannot open shared object file缺少libtinfo5库手动下载Ubuntu 20.04的libtinfo5 deb包安装ImportError: No module named yamlPython环境缺少pyyaml模块pip3 install pyyaml或者sudo apt install python3-yamlAttributeError: module asyncio has no attribute coroutinePython 3.10 移除了asyncio.coroutine使用Python 3.8/3.9环境或为相关依赖应用适配补丁Fatal error: opensslv.h: No such file or directory缺少libssl-devsudo apt install libssl-dev第一次遇到asyncio报错时我印象特别深当时刚从Python 3.8换成3.10Petalinux 2023.1的某些脚本就立刻罢工了。如果你的系统默认Python版本过高最简单的办法是创建一个Python 3.8的虚拟环境然后在启动Petalinux之前激活它实测可以规避大部分Python层面的兼容性问题。6.2 编译类报错看日志三步定位编译报错是Petalinux里最常见的报错类型但大多数报错的根因并不难找。我的排查套路分三步第一步看构建日志的尾部找到最终的error行。第二步沿着error往上翻找到具体的文件名和行号确认是代码问题还是资源问题。第三步如果是依赖或版本问题搜索该组件在Yocto recipe里的依赖关系。报错信息原因解决办法No space left on device磁盘空间不足清理Petalinux缓存或换到大分区磁盘ERROR: recipe ... failed to do_compile组件编译失败查看temp/log.do_compile定位具体编译错误ERROR: Failed to build image根文件系统构建失败优先检查rootfs包依赖必要时清空build/tmp重新构建Unable to copy file ... Operation not permitted权限问题或文件被占用检查工程目录权限避免在root用户和普通用户之间反复切换磁盘空间这个坑特别值得提醒。Petalinux 2023.1默认会使用build/tmp存放所有中间产物我见过一个最小工程构建完都占用了20GB以上空间。如果你的磁盘分区只有30GB剩余构建到一半报No space left on device是大概率事件。建议工程目录所在分区至少留出100GB空间或者定期清理petalinux-build -x mrproper这个命令会清理大部分构建产物但别在工程刚建好的时候执行因为首次构建原本就要几小时一旦清掉就得重来。6.3 启动与烧写类报错启动阶段的报错比较隐蔽因为它们不会像编译错误那样直接打印到终端而是表现为串口无输出、卡在某个位置、内核panic等各种形态。现象原因解决办法上电后串口完全没有输出启动模式拨码错误或BOOT.BIN未正确烧写检查启动模式引脚确认QSPI/SD启动开关状态U-Boot卡在Starting kernel ...设备树DDR地址不匹配或内核镜像损坏检查XSA与内核DTS重新编译Missing separate debuginfo无关紧要但系统起不来KERNEL配置里CONFIG_CMDLINE与U-Boot传参冲突在U-Boot里检查bootargs是否生效根文件系统挂载失败VFS: Unable to mount root fsSD卡分区、根文件系统格式与bootargs不匹配确认root/dev/mmcblk0p2与实际分区一致Kernel panic - not syncing: No working init foundrootfs没有正确解压或者init程序不存在重新解压rootfs.tar.gz确认文件系统完整关于“ZYNQ 7020使用JTAG固化Flash时是否必须使用DDR”这个问题我也在这里一并回答固化这个动作本身不需要DDR参与你把BOOT.BIN烧进QSPI主要依赖FSBL和编程逻辑。但有两种情况会让人觉得“必须要DDR”第一种你的PL比特流比较大FPGA在加载配置时需要先用DDR做临时缓存第二种你是从SD卡启动系统再把系统镜像写入QSPI这种情况下DDR当然参与了数据搬运。如果只是想用JTAG把BOOT.BIN烧进QSPI不跑系统、不搬运大数据不连DDR也能完成。几个我在实际调试中养成的习惯最后聊几个我自己的实操习惯。第一个每次修改设备树或内核配置之后不要急着全量编译先跑petalinux-build -c device-tree或者petalinux-build -c kernel确认单独组件没问题再全量构建这样定位问题快很多也不容易被旧的编译产物干扰。第二个工程目录的备份非常关键。Petalinux工程动辄几十GB我习惯在配置完硬件导入、还没做复杂定制的时候先做一个干净的备份后续改坏了直接恢复比重新建工程快得多。第三个日志文件是排查问题的第一现场。不要只盯着终端输出报错优先去build/tmp/work/下的对应组件目录找temp/log.do_compile和log.do_configure这两个文件会记录完整的编译细节和配置行为。平时养着看日志的习惯能在遇到稀奇古怪的问题时省下一大把时间。ZYNQ Petalinux这套组合入门的时候觉得命令多、概念多但当你真正把一个定制系统从零构建、烧写、跑起来之后回头看整个流程就会清晰很多。希望这篇文章能帮你少走一些弯路。
返回列表