简介:在Zynq SoC平台的Linux开发中,由于芯片同时集成ARM Cortex-A9与FPGA,驱动与硬件交互复杂,调试宏头文件便成为定位问题的利器;一份极简压缩包聚焦调试宏头文件设计,面向嵌入式驱动开发、系统优化及底层维护人员,可在Linux v2.13.6环境下辅助跟踪变量状态与函数调用、检查寄存器及中断处理逻辑、定位性能瓶颈。包内共2个文件,包含1个C源程序与1个C++源程序,整体大小仅2KB,却集中呈现了调试宏的编译开关控制、断言处理和自定义日志输出等可复用写法,调试宏通常定义在头文件以便多文件共享,借助编译选项可灵活开启或关闭调试信息,便于在发布版本中优化性能与存储占用,非常适合快速阅读并迁移到实际驱动项目中。压缩包内容涉及音频设备驱动与Zynq硬件访问封装,开发者可借此理解驱动与硬件交互过程中如何输出关键信息、在条件不满足时终止程序,以及自定义宏记录函数执行时间用于性能分析。目前已有191人学习下载,无论是刚入门Zynq Linux开发的工程师,还是需要精简代码结构、加快驱动排错的老手,都能从中得到启发。
1. 拿到 zynq.rar_V2 先看这 3 个文件,再决定要不要解压
做 Zynq 的人收到一个zynq.rar_V2,第一反应不是解压,而是猜交付物里有什么。V2 通常意味着硬件改过版或者工程迭代过一轮,压缩包里大概率是一整套 Zynq Linux 启动文件:FSBL、bitstream、U-Boot、内核、设备树,甚至还有 .xsa 硬件导出文件。判断这套材料能不能直接上板,只需要找三个文件:BOOT.BIN、boot.scr、image.ub。三个都在,说明构建链路完整,解压后做一张 SD 卡就能启动;缺任何一个,都得从 PetaLinux 重新构建。这篇就把从 rar 解压到 Zynq Linux 上电启动的完整路径写一遍,覆盖解包、构建、制卡、烧写和验证。
2. 解压与识别:Linux 下解开 rar 并确认 Zynq 启动链路文件
2.1 用 unar 解压 rar,处理中文文件名乱码
常见的unrar在处理交付物时有两个痛点:一是部分 Windows 侧打包的 rar 用了 GBK 编码文件名,解压到 Linux 后中文目录名乱码,检索里面文件根本对不上号;二是unrar对 rar5 压缩包的支持不稳定。我一般直接用unar,它会自动识别文件名编码,对 CJK 场景省事很多。安装和解压命令如下:
# Ubuntu / Debian 系 sudo apt update sudo apt install -y unar unrar p7zip-full # 先列出压缩包内容,确认是否有 BOOT.BIN 等关键文件 lsar ./zynq.rar_V2 # 解压到指定目录,避免把当前目录搞乱 unar -o ./zynq_v2 ./zynq.rar_V2逻辑说明:lsar只列出归档内容不解压,适合先确认包内文件是否存在;unar -o指定输出目录,解压后文件编码会被自动修正。如果老板或者同事传过来的压缩包是分卷zynq.rar_V2.part1这种形式,直接解压第一个分卷即可,unar 会自动读取后续分卷。参数补充:-e可以强制指定编码,比如-e GBK,但一般不需要,自动模式识别失败时再用。
2.2 用 file 命令识别 Zynq 启动链路文件
解压完之后,不要直接拿 Vivado 去烧,先用file命令把所有二进制过一遍。Zynq 启动链表里的文件格式各不相同,file的输出能直接暴露文件的真实身份,防止把 bitstream 当 U-Boot 用。
cd ./zynq_v2 file BOOT.BIN boot.scr image.ub u-boot.elf system.bit zynq_fsbl.elf以 Zynq-7020 全流程工程为例,输出通常长这样:
| 文件 | file 输出特征 | 在启动链路中的作用 |
|---|---|---|
| zynq_fsbl.elf | ELF 32-bit LSB executable, ARM, version 1 | 第一级引导,初始化 DDR、时钟和 MIO |
| system.bit | Xilinx BIT data | 可编程逻辑配置,PL 侧 bitstream |
| u-boot.elf | ELF 32-bit LSB executable, ARM | 第二级引导,负责加载内核 |
| BOOT.BIN | Xilinx Bootgen Boot Image | 三者封装,Zynq BootROM 直接加载它 |
| boot.scr | U-Boot script | U-Boot 的启动脚本,替代交互式命令 |
| image.ub | FIT Image / uImage | 打包 kernel + dtb(有时含 rootfs) |
逻辑说明:BOOT.BIN实际是 FSBL、bitstream 和 U-Boot 的封装体,由 Bootgen 生成;image.ub是 Flattened Image Tree,内核、设备树和可选 ramdisk 都在里面。如果file BOOT.BIN输出是 "Xilinx Bootgen Boot Image" 而不是 data,说明这个文件可以被 BootROM 识别;如果显示data,则多半是部分烧写脚本直接把 BIT 或者 ELF 改名成.bin了,这种交付物没法用。
2.3 核对目录:缺什么文件会导致什么现象
对着目录结构检查完整性,比逐个打开文件快得多。Zynq Linux 交付物从构建产物到可启动 SD 卡,文件关系可以归纳成下面这张对照:
tree -L 2 ./zynq_v2一个健康的 V2 交付目录应该长这样:
zynq_v2/ ├── BOOT.BIN ├── boot.scr ├── image.ub ├── zynq_fsbl.elf ├── u-boot.elf ├── system.bit ├── system.dtb └── hw/zynq_v2.xsa检查要点:缺BOOT.BIN,BootROM 无文件可引导,串口没有任何输出;缺boot.scr,U-Boot 起来后停在Hit any key to stop autoboot,需要手动输入命令;缺image.ub,U-Boot 有脚本但 load 不到内核,日志停在Wrong Image Format;缺.xsa,后续想改配置重新构建会非常被动,PetaLinux 创建工程没法挂硬件描述。这四个文件里.xsa和BOOT.BIN是硬关联,拿到BOOT.BIN没有.xsa也能启动,但改不了 FSBL 配置;反过来只有.xsa没有BOOT.BIN,就得走一遍完整构建流程,下一章做这件事。
3. PetaLinux 2025.1 生成 boot.bin、boot.scr、image.ub 的命令链
3.1 PetaLinux 2025.1 下生成 BOOT.BIN 的完整命令
交付物里缺BOOT.BIN或BOOT.BIN版本和 V2 硬件不匹配时,直接用 PetaLinux 2025.1 重建是效率最高的路径。PetaLinux 对 Zynq-7020 生成 FSBL 是开箱即用的,不需要手动写任何 C 代码,前提是拿到.xsa。整个构建链路两端都是 Xilinx 系工具链,Vivado 导出.xsa,PetaLinux 消费它,版本对齐了基本不会出幺蛾子。
source /opt/Xilinx/PetaLinux/2025.1/settings.sh petalinux-create --type project --template zynq --name zynq_v2_app cd zynq_v2_app petalinux-config --get-hw-description ../hw/zynq_v2.xsa petalinux-build petalinux-package --boot \ --fsbl ./images/linux/zynq_fsbl.elf \ --fpga ./images/linux/system.bit \ --u-boot ./images/linux/u-boot.elf \ --output ./images/linux/BOOT.BIN逻辑说明:petalinux-create --template zynq指定的是 Zynq-7000 家族模板,对应 Zynq-7020 没有问题;petalinux-config --get-hw-description把硬件描述导入工程,FSBL 会按.xsa里的 DDR、MIO、时钟配置生成。参数说明里最需要注意的是--fpga:当system.bit需要和 FSBL 一起打包时,--boot后面必须显式指定;如果 PL 侧没有逻辑,省略--fpga可以缩小 BOOT.BIN 体积,启动时间也能缩短几十毫秒。同理,DDR 初始化参数和 FSBL 里的 PS 配置不匹配时,恰好是 BOOT.BIN 不可用的高发原因之一,重新打包前务必确认.xsa版本和实际硬件版本一致。
表:petalinux-package --boot的常用参数
| 参数 | 作用 | 不传会怎样 |
|---|---|---|
--fsbl | 指定 FSBL 的 elf | Bootrom 没有可执行的引导代码,卡死在启动 |
--fpga | 把 PL bitstream 并入 BOOT.BIN | 逻辑不加载,PS 侧 Linux 不受影响 |
--u-boot | 指定 U-Boot elf | 无法进入第二级引导 |
--output | 指定输出文件名 | 默认生成images/linux/BOOT.BIN |
--offset | 指定 partition 偏移 | QSPI 启动时配合 flash 布局使用 |
3.2 手写 boot.cmd 并用 mkimage 生成 boot.scr
petalinux-package --boot只打包 FSBL、bit 和 U-Boot,不生成boot.scr。PetaLinux 工程里虽然能看到boot.scr相关工具,但最常见、最可控的做法是手写一份boot.cmd,再用mkimage转成 U-Boot 脚本。U-Boot 支持脚本文件,这个机制是启动链里最灵活的一环,想改启动参数、换分区、模拟在线升级场景都要动它。
cat > boot.cmd <<'EOF' setenv bootargs 'console=ttyPS0,115200 root=/dev/mmcblk0p2 rw rootfstype=ext4 rootwait' load mmc 0:1 0x2080000 image.ub bootm 0x2080000 EOF mkimage -A arm -O linux -T script -C none -d boot.cmd boot.scr逻辑说明:boot.cmd里第一行是内核命令行,console=ttyPS0对应 Zynq 的 UART0,波特率 115200;root=/dev/mmcblk0p2指向 SD 卡第二个分区,也就是 rootfs 所在的 ext4 分区。load mmc 0:1表示从 SD 卡控制器 0 的 1 号分区加载文件,地址0x2080000是 Zynq DDR 里避开 BootROM 和 U-Boot 占用的常规加载地址。bootm 0x2080000从该地址引导 FIT 镜像,bootm会自动解析image.ub里的内核、设备树和 ramdisk。mkimage 的参数里,-A arm指定 ARM 架构,-O linux是操作系统类型,-T script表示生成的是脚本而非内核镜像,-C none表示不压缩。
3.3 image.ub 的自检与 FIT 结构观察
image.ub是 PetaLinux 在petalinux-build阶段自动生成的 FIT 镜像,它和 BOOT.BIN 的最大区别是:BOOT.BIN 是 BootROM 的引导格式,FIT 是 U-Boot 的引导格式。拿到交付物之后验证image.ub是否完整,最直接的办法是解包看里面有什么。U-Boot 源码的tools/目录下有dumpimage命令,安装了u-boot-tools就会自带。
dumpimage -l ./image.ub输出里能看到类似下面的结构:
FIT description: U-Boot fitImage kernel plus DTB Created: Thu Oct 24 10:24:08 2025 Configuration: conf@zynq-7020 Kernel Image: kernel@1 FDT: fdt@1逻辑说明:Configuration字段给出的是配置名,Zynq 工程下一般是conf@zynq-7020;Kernel Image是内核本体,FDT是设备树。如果dumpimage -l报错Invalid FIT image,说明image.ub损坏或被误改名,U-Boot 阶段必然加载失败。这种情况下不要重新打包 BOOT.BIN,直接回到petalinux-build重新生成 image.ub 再接petalinux-package。
4. Zynq Linux SD 卡制卡、烧写与 FSBL 报错处理
4.1 用 sfdisk 脚本给 SD 卡分两个区
Zynq Linux 的 SD 启动布局非常固定:第一个分区 FAT32,放 BOOT.BIN、boot.scr、image.ub;第二个分区 ext4,放 rootfs。手工用fdisk交互式分区容易误操作,交付物验证场景下用脚本一次性搞定更稳,执行环境是 Ubuntu 宿主机。
# 假设 SD 卡设备节点是 /dev/sdb,先确认再执行! lsblk # 清空分区表 sudo wipefs -a /dev/sdb # 用 sfdisk 创建两个分区:1G FAT32 + 剩余空间 ext4 sudo sfdisk /dev/sdb <<EOF ,1G,c ,,L EOF sudo mkfs.vfat -F 32 -n BOOT /dev/sdb1 sudo mkfs.ext4 -L rootfs /dev/sdb2逻辑说明:sfdisk的输入格式里,c表示 W95 FAT32 (LBA) 类型,L是 Linux 分区。wipefs -a先清掉 SD 卡上遗留的分区签名,避免 mkfs 阶段报 superblock 错误。参数说明:FAT32 分区大小给 1G 足够,image.ub一般不到 30MB,BOOT.BIN也就十几 MB,留 1G 是为了以后在线升级放多版本文件不成瓶颈;ext4 分区用剩余全部空间放 rootfs。分区完成后格式化,FAT32 卷标建议用BOOT,PetaLinux 的默认 fstab 里有时会引用卷标,顺手取个不折腾。
挂载后拷贝文件,顺序要固定:
sudo mkdir -p /mnt/boot /mnt/rootfs sudo mount /dev/sdb1 /mnt/boot sudo mount /dev/sdb2 /mnt/rootfs sudo cp BOOT.BIN boot.scr image.ub /mnt/boot/ # 如果交付物带 rootfs 目录,解压进去 sudo cp -a rootfs/* /mnt/rootfs/ sync4.2 烧写 BOOT.bin 时报 valid FSBL file 的三种处理
交付场景里最容易卡的报错是 Vitis 烧写工具弹出的a valid fsbl file is required for flash operation,第一次碰到容易误判为 BOOT.BIN 损坏。这个报错的本质是烧写工具需要用一个 FSBL 来初始化 DDR 和时钟,再去擦写 flash,而不是直接认你的 BOOT.BIN。
# 方法:QSPI Flash 模式下显式指定 FSBL 和 BOOT.BIN program_flash -f ./BOOT.BIN \ -fsbl ./zynq_fsbl.elf \ -flash_type qspi-x4-single \ -offset 0参数说明:-fsbl指定用于 flash 编程器的 FSBL,必须和 BOOT.BIN 中打包的是同一个 elf,否则 DDR 参数不一致会在编程过程中随机失败;-flash_type按硬件连接选择,Zynq-7020 开发板常见的是qspi-x4-single,个别板子用qspi-x1-single,型号写错报错信息一样。另外两种替代处理:一是只检查不烧写,用dumpimage -l BOOT.BIN或bootgen -arch zynq -image boot.bif -w -o BOOT.BIN重新生成后再烧;二是从 SD 启动直接跳过 flash,很多验证工作不必碰 QSPI,SD 卡启动省掉烧写环节,等 system.bit 在 PL 侧验证通过再回烧 QSPI。把 FSBL、bit、U-Boot 的 elf 存好,遇到 flash 编程时随手能用。
4.3 启动模式拨码与日志断点
SD 卡和 QSPI 的启动文件都备好之后,拨码设置错误是最隐蔽的上板失败原因。Zynq BootROM 根据 MIO 启动模式引脚选择引导方式,开发板上通常是 5 位拨码开关,具体对应关系受限于板级设计,不存在的拨码组合会导致 BootROM 直接挂死,串口不打印任何信息。
| 启动媒体 | MIO[4:0] | 开发板常见设置 | 说明 |
|---|---|---|---|
| SD 卡 | 0b00110 | 2、3 拨上,其余拨下 | 最常用 |
| QSPI | 0b01010 | 1、3 拨上,其余拨下 | 回烧后使用 |
| JTAG | 0b00000 | 全部拨下 | 调试时用,不会自动启动 |
| NAND | 0b01100 | 视板卡而定 | 部分 7020 板型有 |
拨码错误的表现是:上电后串口 115200 无任何输出,minicom -D /dev/ttyUSB0一点日志都没有。此时不要怀疑 BOOT.BIN 坏了,先核对拨码,再查电源指示灯,最后看串口接线交叉(RX/TX 反接)的问题。串口有输出但卡在某一行的断点定位法:卡在 FSBL Banner 之前是 BootROM 没找到 BOOT.BIN;卡在Hit any key to stop autoboot是 boot.scr 没加载;卡在Wrong Image Format是 image.ub 坏了或加载地址不对。
5. 上电验证:用日志特征和文件校验确认 Zynq Linux 正常启动
5.1 串口日志里三个必须看到的特征行
验证 Zynq Linux 是否真正起来,不用看完整 log,三个特征行足够。把 SD 卡插上,设置为 SD 启动模式,上电,串口 115200 capture:
minicom -D /dev/ttyUSB0 -b 115200第一个必须看到的特征行是Xilinx Zynq FSBL开头的 banner,它出现在上电后几百毫秒内,表明 BootROM 成功解析了 BOOT.BIN,FSBL 开始初始化 DDR;第二个特征行是 U-Boot 的版本号,说明二级引导已接管;第三个特征是Starting kernel ...之后出现内核版本字符串,说明 kernel 和设备树被正确加载。三个特征行逐级出现,整条启动链就是通的。卡在 U-Boot 之前,问题在 BOOT.BIN 的 FSBL 或 DDR 时序;卡在Starting kernel之后,问题在 rootfs 或内核命令行参数。
5.2 面向在线升级的 SD 卡文件核对脚本
交付物验证和后续升级场景里,最容易犯的错误是构建目录里的 image.ub 和 SD 卡上的 image.ub 不是同一版本。手动比对 md5 太费时,写一个两行核心的脚本,用于升级前确认目标文件一致:
#!/bin/bash REF_DIR=/opt/zynq_v2/images/linux SD_DIR=/media/user/BOOT for f in BOOT.BIN boot.scr image.ub; do if cmp -s "$REF_DIR/$f" "$SD_DIR/$f"; then echo "OK $f" else echo "DIFF $f" fi done逻辑说明:cmp -s静默模式只返回状态码,不需要md5sum二次处理;循环对象固定三个文件,升级时只改image.ub的版本即可。脚本输出三行,全部OK才允许断电重启;只要出现DIFF,说明 SD 卡上文件与构建产物不一致。在线升级场景下,只有内核和设备树变更时,单独拷 image.ub 覆盖 FAT 分区即可,BOOT.BIN和boot.scr无需重烧,FSBL 和 U-Boot 是 boot 这套耦合的二进制镜像,动一个就要重烧整个分区。升级后从串口日志观察U-Boot 2025.01到Starting kernel的间隔,再确认两个特征行,Zynq Linux 的迭代就闭环了。
本文还有配套的精品资源,点击获取