ARTICLE DETAIL

资讯详情

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

Zynq-7000工程包解压与中断例程实战:从ZIP修复到Vivado导入

Zynq-7000工程包解压与中断例程实战:从ZIP修复到Vivado导入 简介本资源是面向嵌入式实时系统开发者的VxWorks驱动工程完整实现基于正点原子领航者ZYNQ-7020开发板专为需要在Xilinx Zynq平台上构建高可靠性VxWorks BSP的工程师与高校研究者设计。项目严格采用VxBus架构开发全部外设驱动显著提升模块复用性与移植便捷性覆盖UART、eMMC及TFFS文件系统、QSPI Flash及外设文件系统、PL侧千兆网口逻辑与驱动、PS侧Gem千兆以太网驱动、I²C接口RTC与EEPROM等核心功能并以U-Boot作为VxWorks启动引导方式。压缩包含68个文件主体为27个C源码驱动与BSP逻辑、14个头文件接口定义与配置、14个目标文件编译中间产物及Makefile、CDF、README等关键构建与说明文件总大小3.77MB结构规范便于理解VxWorks 7下Zynq平台驱动分层设计与集成流程。已有881人学习下载提供全部可编译源码、启动镜像bootrom.bin、符号表与参考配置是深入掌握VxBus驱动模型与Zynq软硬协同开发的实用工程范例。 前几天同事发给我一个文件名字叫xlnx_zynq7k_zd.zip一看就是 Xilinx Zynq-7000 系列的工程包。这种包在嵌入式开发圈子里太常见了Vivado 工程、Vitis/SDK 工程、BOOT.bin、设备树源码有时候还夹着几份 PDF 和 README统一打包从 QQ、网盘或者 Gitee 发给别人。但越常见越容易翻车解压时弹file is not a zip file或者解压出来了却不知道怎么导入 Vivado最后卡在一个中断例程上折腾两三天。这篇文章我就以xlnx_zynq7k_zd.zip为例从文件头识别开始一直讲到中断例程跑在板子上顺带把 ZIP 解压里那些 EOCD 缺失、分卷解压、伪加密、中文乱码的坑全部填一遍。适合刚接触 Zynq 开发、以及经常在网上下载各种工程包却屡屡被 zip 搞心态的人。1. 拿到压缩包第一件事先确认它到底是不是 Zip1.1 第一行字节就能看出很多问题我见过太多人拿到一个.zip二话不说双击Windows 自带解压工具弹窗“文件已损坏”然后整个人就慌了。其实第一步永远是用file命令确认文件真实类型尤其是从网盘、QQ、邮件下载的包后缀名和真实内容经常对不上。file xlnx_zynq7k_zd.zip正常情况会输出类似Zip archive data, at least v2.0 to extract。如果输出的是HTML document或者data那基本可以断定这个包有问题可能是下载链接跳转到了一个网页也可能是服务器返回了错误页。用xxd看文件头更直观前两个字节应该是PK也就是十六进制的50 4B。PK是 ZIP 格式创始公司 Phil Katz 的名字缩写看到PK\x03\x04是本地文件头PK\x05\x06是文件末尾的 EOCD 记录。这里补一点 ZIP 格式基础一个正常的 zip 由三部分组成最前面是每个文件的本地文件头中间是压缩数据最后是中央目录和 EOCD。解压工具读取的时候会先跳到文件末尾找 EOCD再根据中央目录找到各个文件的位置。所以 EOCD 一旦丢了整个包就不知道从哪开始读这就是各种“not a zip file”“could not find eocd”错误的根源。1.2 EOCD 缺失是怎么回事该怎么修invalid zip archive: could not find eocd这个报错我在 Vitis、MATLAB、Python 的 zipfile 里都撞见过。EOCD 缺失最直接的原因是文件没下载完整文件末尾 22 个字节被截掉了。还有几个容易被忽略的场景用 FTP 传文件时走了 ASCII 模式导致二进制内容被改坏某些网盘客户端断点续传出问题杀毒软件在下载过程中拦截了部分数据。判断方法很简单先看文件大小和源文件对不对得上。如果原文件有 MD5 或 SHA256算一下马上就知道有没有坏。如果找不到原始哈希就把unzip -l的输出和压缩包内文件数量做个粗略核对。确定文件不完整最好的修复方式其实是重新下载因为你不知道数据在哪里断掉。但在实在没有别的渠道的情况下可以试一下 Info-ZIP 的修复命令zip -FF xlnx_zynq7k_zd.zip --out repaired.zip-F模式会用中央目录和文件头之间的信息进行修复-FF模式更激进会扫描整个文件尝试恢复数据。修复完一定要跑unzip -t repaired.zip验证完整性。这里说句大实话修复出来的包文本和代码文件通常能救回来但二进制文件比如.bit比特流、.xsa这种很可能是能解压但数据已经不对了。用sha256sum和原始值比对一下对不上就直接放弃别在一个烂包上死磕。如果在 Vivado 或 Vitis 里导入工程时看到failed to copy spatial iop zip、could not find eocd这类提示别急着怀疑软件问题。先用 7-Zip 打开工程包让它自己检查一遍十有八九是打包或者传输环节把 zip 弄坏了。你需要的不是技术支持而是一个干净的包。1.3 解压时注意路径穿越和中文编码确认 zip 文件本身没问题解压前还有一个容易被忽略的步骤先看一眼包里的文件清单确认没有恶意路径和没有价值的多余文件。unzip -l xlnx_zynq7k_zd.zip # 或者 zipinfo -1 xlnx_zynq7k_zd.zip重点看有没有../这样的路径。正常的工程包不会出现../../etc/xxx这种条目如果有这叫 zip slip 路径穿越攻击解压时会往系统目录写文件安全风险极高。我建议养成习惯任何来源不明的包都先zipinfo -1扫一眼。中文乱码问题在嵌入式工程包里也特别常见。Windows 自带压缩功能生成 zip 时文件名用的往往是本地代码页在中国大陆就是 GBK/CP936而 Linux 下的unzip默认按 UTF-8 解码结果就是解压出来一堆“锟斤拷”或者问号。解决乱码有几个办法安装unar它自动检测文件名编码解压时能正确还原中文unar xlnx_zynq7k_zd.zip。如果你的unzip版本支持-O参数可以显式指定编码unzip -O CP936 xlnx_zynq7k_zd.zip。已经解压乱了用convmv -f GBK -t UTF-8 --notest -r 解压目录批量转码重命名。为什么这么在意文件名因为 Vivado 和 Vitis 对路径编码很敏感工程路径里只要有中文、空格或者特殊符号经常会在某些环节炸掉比如error opening zip file or jar manifest missing这种 Java 工具链报错很多就是路径乱码导致的。我个人的习惯是解压出来之后马上把整个工程目录放到一个纯英文、无空格的路径下比如C:\work\zd_demo或者~/work/zd_demo之后再导入工具能避开一大堆无意义的坑。2. 打开 xlnx_zynq7k_zd 之前先搞清楚 Zynq-7000 工程里有什么2.1 Zynq-7000 软硬件结构速览如果你是从别的嵌入式平台转过来的第一次接触 Zynq 可能会被 PS 和 PL 的概念绕晕。简单说Zynq-7000 是一颗单芯片里面同时集成了双核 ARM Cortex-A9 处理器PS 端和可编程逻辑 FPGAPL 端二者通过 AXI 总线互联。PS 端跑软件可以裸机也可以跑 Linux自带 UART、SPI、I2C、SDIO、USB、CAN、以太网、DMA 等常用外设。PL 端跑逻辑你可以写 Verilog/VHDL搭自定义 IP也可以直接在 Vivado 里拖现成的 IP 核。PS 和 PL 之间通过 AXI_GP、AXI_HP、AXI_ACP 这些接口通信数据带宽和延迟都有差异具体选哪个取决于应用场景。中断路径是理解 Zynq 例程的关键。PL 里产生的中断信号一般接到 PS 端的IRQ_F2P[7:0]中断端口这几个端口每个可以配置为上升沿或高电平敏感然后统一进入 GICGeneric Interrupt Controller中断控制器由 GIC 分发给两个 Cortex-A9 核。PS 内部的外设中断则走 SPIS共享外设中断或 PPIS私有外设中断。GIC 在整个中断体系里相当于总调度谁的优先级高、发给哪个 CPU 核都是它说了算。xlnx_zynq7k_zd.zip里的 “xlnx” 是 Xilinx 的缩写“zynq7k” 就是 Zynq-7000 系列“zd” 大概率是“中断”的拼音缩写这是国内 Zynq 教学例程里很常见的命名方式。所以拿到这个包脑子里的第一印象应该是这是一个 Zynq-7000 裸机或者 Linux 下的中断实验工程目标大概率是演示 PL 中断或者 PS 外设中断怎么配、怎么写服务函数。2.2 典型工程包的目录构成Zynq 工程包拆开之后里面可能出现的东西五花八门但核心无非这么几类Vivado 硬件工程文件.xpr工程文件、.srcs源码目录、.runs综合实现结果、.cache缓存、.gen生成文件还有.xdc约束文件。硬件平台文件Vivado 2020.1 之后普遍用.xsaXilinx Support Archive老版本 SDK 时代是.hdf。这个文件打包了硬件描述、外设配置、地址映射等关键信息Vitis 软件工程全靠它。软件工程目录Vitis 工程下的src、platform、bsp、project_spec.ymlSDK 时代则是BSP和src。启动镜像BOOT.BIN、image.ub、uImage、devicetree.dtb、uEnv.txt这些是往 SD 卡里放的东西。文档README、原理图 PDF、应用笔记别嫌烦先看。我自己拿到工程包后的标准动作是先找顶层有没有 README有就看 README没有就找.xsa或者.hdf用 Vivado 的版本信息确认工程是用哪个版本创建的。工具版本不匹配强行导入大概率报错与其浪费时间不如先确认。2.3 “zd”这个中断例程到底在干什么以“中断”为主题的 Zynq 例程典型玩法有这么几种。第一种是按键中断外部的按键按下PL 检测到上升沿或下降沿产生一个脉冲送到IRQ_F2PGIC 收到后触发 CPU 中断中断服务程序里翻转一颗 LED 或者在串口打印一行信息。第二种是定时器中断PS 端的私有定时器周期性产生中断用来做精确延时或者操作系统的心跳。第三种是 PL 里的自定义 IP 完成某个运算后通过 AXI 或者中断信号通知 PS。这些例程看起来简单但背后涉及的知识链路一点都不短PL 逻辑怎么写、引脚约束怎么加、中断引脚怎么连到 PS、GIC 中断号怎么查、中断服务程序怎么注册、清中断标志的顺序是什么。任何一个环节掉了链子现象都是“按了按键没反应”。如果你下载到的包里面已经带了完整的 Vivado 工程和 Vitis 工程那要做的其实就是把整个流程跑通然后对照代码理解每一步在干什么。别一上来就改代码先把原始工程原封不动跑一遍确认硬件环境和开发环境都正常再开始动手改。3. 实操把工程导入 Vivado/Vitis 并真正跑起来3.1 用 Vivado 重建/导入硬件工程先说最简单的情况包里有.xpr文件。双击或者在 Vivado 里 File → Project → Open 打开即可。如果工程是用更高版本 Vivado 创建的软件会提示升级工程一般点确认就行。但升级之后一定要重新跑一遍综合和实现确保没问题再往下走。很多网上下载的工程包不带.xpr只提供了一个 Tcl 脚本比如create_project.tcl。这种情况最省事的方式就是打开 Vivado 的 Tcl Console切到工程目录然后source ./create_project.tcl脚本会在当前目录重建整个工程所有源码、约束、IP 配置都会自动加好。前提是你用的 Vivado 版本和作者一致至少大版本要接近不然脚本里的 IP 版本号可能不兼容。最麻烦的情况是包里面只有散落的源码和约束文件比如 Verilog 文件、XDC 约束、IP 核的.xci文件没有工程也没有 Tcl 脚本。这时候就要手动创建工程Tcl 命令是set part xc7z020clg400-1 create_project zd_demo ./zd_demo -part $part read_verilog [glob ./src/*.v] read_xdc ./constraints/zd_demo.xdc update_compile_order -fileset sources_1注意part参数一定要跟你的板卡芯片型号匹配。Zynq-7000 常见的有xc7z010clg400-1、xc7z020clg400-1Zynq-7020 的xc7z020clg400-1用得最多。型号不对Synthesis 阶段就会报错后面全部白干。3.2 综合、实现并导出 XSA工程创建好之后传统做法是点 Flow Navigator 里的 Run Synthesis、Run Implementation、Generate BitstreamGUI 操作我就不展开了命令行更实用launch_runs synth_1 -jobs 4 wait_on_run synth_1 launch_runs impl_1 -to_step write_bitstream -jobs 4 wait_on_run impl_1 open_run impl_1 write_bitstream ./zd_demo.bit-jobs 4是让综合器用 4 个线程并行跑机器性能好可以调成 8。综合和实现的时间取决于工程复杂度xlnx_zynq7k_zd这种教学级工程一般几分钟就完事。综合完成之后File → Export Hardware勾选 Include bitstream生成.xsa文件。这里必须强调Vitis 不像老版本 SDK 那样直接吃.bit加.hwh它需要 XSA 文件因为 XSA 打包了硬件平台描述、地址映射、外设配置等一整套信息。如果你在 Vitis 里新建 Platform 时提示找不到文件多半是 XSA 没生成全或者路径里有中文。3.3 Vitis 工程里写中断逻辑附代码拿到 XSA 之后打开 Vitis先新建 Platform Project把它导入。然后新建 Application Project选择 Hello World 模板或者空应用。如果压缩包里已经带了 Vitis 工程源码直接在 Vitis 里 Import Projects 导入然后右键 Update Platform 关联到当前 XSA。中断例程的代码骨架长这样#include xscugic.h #include xil_exception.h #include xparameters.h static XScuGic gic; void my_isr(void *arg) { // 清除中断标志 // 翻转 LED 或打印信息 } int main(void) { XScuGic_Config *cfg; cfg XScuGic_LookupConfig(XPAR_SCUGIC_0_DEVICE_ID); XScuGic_CfgInitialize(gic, cfg, cfg-CpuBaseAddress); Xil_ExceptionInit(); Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, gic); Xil_ExceptionEnable(); XScuGic_Connect(gic, XPAR_MY_IP_INTR_ID, (Xil_ExceptionHandler)my_isr, NULL); XScuGic_Enable(gic, XPAR_MY_IP_INTR_ID); while (1) ; }这段代码的逻辑一句话能说清初始化 GIC注册异常向量表把 GIC 的中断处理函数挂到 CPU 异常入口然后连接具体的中断源并使能。XPAR_MY_IP_INTR_ID来自xparameters.h这个头文件是根据 XSA 自动生成的里面定义了所有 IP 的中断 ID。不同工程这个宏可能完全不同别想当然。写中断服务程序时最容易被坑的是清中断标志。GIC 的中断 pending 要清源头 IP 内部的中断状态寄存器也要清两者缺一不可。我在实际调试中遇到过一次第一次触发中断正常第二次按按键死活没反应查了半天发现是 PL 侧的 IP 中断状态寄存器没清导致中断线一直拉低CPU 以为中断还没处理完。加了一行清寄存器代码问题立刻消失。ISR 里也要尽量别做耗时操作串口打印这种能省则省否则在中断里打一整屏日志不光慢还可能把系统拖死。3.4 生成 BOOT.BIN 并完成启动裸机程序要脱离 JTAG 独立启动需要生成启动镜像。最简单的方式是在 Vitis 里 Xilinx → Create Boot Image然后添加三样东西FSBL、Bitstream、Application ELF。FSBL 是 First Stage Boot LoaderVitis 会根据你的平台自动生成Bitstream 就是刚刚导出的.bitELF 就是编译出来的裸机程序。生成出来的BOOT.BIN拷到 FAT32 格式的 SD 卡根目录板卡拨码开关切到 SD 启动上电串口工具连上板卡的 UART波特率一般 115200就能看到 FSBL 的打印信息然后跳转到裸机程序执行。如果跑 Linux那启动镜像就更复杂还需要 U-Boot、内核、设备树、根文件系统。常见做法是把BOOT.BIN和image.ub放到 FAT 分区image.ub是 U-Boot 打包的内核 设备树 rootfs 的统一镜像。启动日志里看到U-Boot 2018.xx之后卡住多半是设备树不对或者内核没挂上根文件系统这个后面再展开。4. 跑起来之后中断不触发的排查实录4.1 中断异常的排查顺序中断例程跑不起来现象通常是“LED 不亮、串口没打印、程序好像死在某处”。遇到这种问题我建议按下面的顺序查效率最高。先确认代码有没有跑到main。别笑我见过不少例子是链接脚本出问题程序根本没进main。在 GIC 初始化之前加一行print(before init)在while循环里加一行print(alive)串口能看到输出起码说明程序在跑。再查 PL 中断源有没有真正产生中断信号。如果中断是 PL 产生的在 Vivado 里插入 ILA 抓一下中断信号或者先用一个简单的手段把中断信号接到一个 GPIO LED 上看有没有波形。软件查不到硬件层面先确认是可靠的。然后是 GIC 中断号。打开xparameters.h找到你那个 IP 对应的中断 ID确认和XScuGic_Connect里填的一致。中断 ID 写错中断永远不会进来这个错误很隐蔽。最后检查中断服务程序标志清除。前面提到的清中断标志问题这里是最常见的重灾区。正确的顺序是先清外设源的中断状态寄存器再清 GIC 的 pending防止在 ISR 执行期间新的中断被丢弃或者旧的中断被重复触发。4.2 启动链路问题的典型表现裸机之外很多人会把 Zynq 跑 Linux然后发现中断问题变得更为复杂。这里列几个我在实际调试中遇到的典型现象和对应的解决思路。上电后串口完全没有输出。检查顺序串口线是不是真的接在 PS 的 UART 引脚上很多板子同时有 USB 转串口芯片和 PS 原生 UART两个不一样波特率对不对BOOT.BIN 是否生成成功有没有把 FSBL 带上SD 卡格式是不是 FAT32文件放的位置对不对。我曾经在一张 128GB 的卡上栽过跟头分区表有问题U-Boot 怎么都找不到 BOOT.BIN换张 16GB 老卡就好了。有 U-Boot 打印但卡住不动。先看最后一行打印在哪如果停在内核解压之前说明设备树可能不对内存大小、外设地址对不上硬件如果内核已经开始解压但后面没动静可能是内核参数问题比如root指定的设备和实际分区不一致。Linux 下/proc/interrupts里看不到你的设备中断说明驱动或者设备树配置的问题。检查设备树里 interrupt-parent 是否指向 GICinterrupts 属性的描述是否和 Vivado 里 PS-PL 中断配置一致还要确认设备节点 status 是okay而不是disabled。这几个问题在xlnx_zynq7k_zd这样的例程里不一定出现但真遇到了思路比答案重要。先定位是在哪一层断掉的再针对那一层查别从应用层开始猜硬件问题。5. 顺手把 Zip 的使用问题一次性说透5.1 用 zip -FF 修复损坏包前面第 1 节讲了zip -FF的用法这里再说细一点。ZIP 修复的核心原理就是尽量从残留的数据中重建中央目录和 EOCD。zip -F和zip -FF的区别在于扫描深度前者只尝试用文件头和现有目录信息修复后者会全盘扫描把游离的数据块也捞回来。修复命令zip -FF xlnx_zynq7k_zd.zip --out repaired.zip修复完跑unzip -t验证。如果验证通过不代表数据内容百分之百正确尤其是二进制文件。我遇到过修完的包能解压但里面的.xsa导入 Vitis 时依然报 invalid本文还有配套的精品资源点击获取
返回列表