ZYNQ SDK实战指南:从Vivado工程创建到SDK开发全流程

📅 发布时间:2026/7/6 21:17:04 👁️ 浏览次数:
ZYNQ SDK实战指南:从Vivado工程创建到SDK开发全流程
1. 从零开始搭建你的第一个ZYNQ Vivado工程很多刚接触ZYNQ的朋友一上来就被Vivado和SDK这两个工具搞懵了感觉流程特别长不知道从哪里下手。我自己刚开始学的时候也这样总觉得PS处理器系统是硬核应该很简单结果发现不建工程、不配置ARM核根本动不起来。今天我就用一个最直白的方式带你走一遍从Vivado画“图纸”到SDK写“软件”的全过程保证你跟着做一遍就能点亮板子上的灯。首先你得把Vivado打开。别怕第一步永远是“Create Project”。点击之后会有一个向导你一路点“Next”就行但有几个地方要留心。项目类型Project Type这里一定要选RTL Project然后勾上“Do not specify sources at this time”。这么做的意思是我们先搭好项目的架子具体的硬件设计代码也就是RTL我们后面再添加。项目名字和存放路径我建议你起个有意义的比如“zyng_led_test”路径里千万不要有中文和空格这是很多软件的通病遇到奇怪错误先检查这个。到了选择默认芯片型号的步骤这里就关键了。你得根据自己手里的开发板型号来选。比如我用的是Zynq-7000系列的XC7Z020芯片那我就在筛选器里选好“Family”为“Zynq-7000”“Package”为“clg400”“Speed grade”为“-1”然后找到对应的型号。这一步选错了后面生成的硬件信息对不上你的板子SDK里就没法正确运行。这些都搞定之后Vivado会为你创建一个空的项目界面中间一大片空白区域就是我们接下来要“画图”的地方了。2. 核心配置玩转ZYNQ的PS系统项目建好了现在要请出我们今天的主角——ZYNQ的处理器系统PS。在Vivado左侧的“Flow Navigator”面板里找到“IP INTEGRATOR”这一项点击“Create Block Design”。给你的这个设计图起个名比如“system”然后确定。这时候中间空白画布就出来了我们需要在这里搭建硬件系统。2.1 添加并配置ZYNQ7 Processing System IP在画布空白处右键选择“Add IP…”然后在搜索框里输入“ZYNQ7”你会看到“ZYNQ7 Processing System”这个IP核双击它。一个代表PS的模块就出现在画布上了。这个绿色的模块就是ZYNQ芯片里那个双核ARM Cortex-A9硬核加上一堆外设控制器比如DDR、UART、USB等的图形化表示。双击这个模块会弹出一个非常复杂的配置界面别慌我们一步步来。首先看“Page Navigator”里的“Zynq Block Design”。这里有个“Presets”选项简直是新手福音。如果你的开发板厂商比如Digilent、Avnet等提供了预设文件你可以直接在这里导入它能帮你把DDR型号、时钟、常用外设引脚都配好省去大量时间。如果没有我们就得手动配置几个最关键的地方。第一是DDR配置在“PS-PL Configuration” - “PS-PL Interfaces” - “General”里确保“AXI Non Secure Enable”是勾上的这关系到PS和PL可编程逻辑之间的数据通道。然后进入“MIO Configuration”这里配置的是PS直接管理的那54个多功能IO引脚。我们需要根据原理图把用到的外设比如UART、GPIO、SD卡等分配到正确的MIO引脚上。比如我要用UART1做调试串口我就在“I/O Peripherals” - “UART 1”里勾选启用并选择正确的MIO引脚通常是MIO48和MIO49。2.2 理解MIO与EMIO引脚复用的艺术这里插一句很多朋友对MIO和EMIO的概念比较模糊。你可以把MIO想象成ARM核“亲生的”管家一共就54个直接连着芯片外面的引脚能干的活很多GPIO、UART、SPI等但每个引脚具体干啥活功能复用是固定的不能随便指派。比如MIO48这个引脚它可能既能做UART的TX也能做GPIO的输出但你不能把它指定为SPI的时钟。那如果54个MIO不够用怎么办这时候EMIO就出场了。EMIO是“扩展的MIO”它依然是PS的“手下”但它不直接连到芯片引脚而是先连接到PL可编程逻辑部分再由PL的引脚连出去。这就相当于ARM核通过PL这个“中介”又扩展出了一批IO。配置EMIO就是在“PS-PL Configuration” - “General” - “EMIO GPIO”里设置你需要的EMIO GPIO宽度比如64位这样你就多了64个可以通过PL控制的GPIO。配置完PS后点击“OK”关闭窗口。回到Block Design画布你会发现ZYNQ IP核上多了很多接口其中最重要的一组叫“M_AXI_GP0_ACLK”和“M_AXI_GP0”。这是一个AXI总线接口是PS主动发起与PL通信的主设备通道。我们需要让它“生效”。在画布上方的绿色提示栏里点击“Run Block Automation”Vivado会自动帮我们把这个AXI主接口的时钟和复位信号连接好。这时候你的PS模块才算真正配置完成可以接收或发送数据到PL了。3. 连接PL逻辑让硬件系统“活”起来只有PS的ZYNQ系统是不完整的我们得给它加点“私活”也就是可编程逻辑PL部分。假设我们要实现一个最简单的功能通过PS控制PL部分的一个LED灯。这需要在PL里设计一个接受PS命令、驱动LED的模块。3.1 添加自定义IP或使用现有IP在Block Design画布空白处再次右键“Add IP”这次我们搜索“AXI GPIO”并添加它。AXI GPIO是一个Xilinx提供的标准IP它一端是AXI总线接口可以挂到PS的AXI总线上另一端就是普通的GPIO信号非常适合PS控制PL侧的LED、按键等。添加后双击这个AXI GPIO IP进行配置。在“Board”标签页如果你用的开发板有预设可以直接把“GPIO”接口关联到板子的LED上。如果没有我们就在“IP Configuration”里把“GPIO Width”改成1因为我们先控制1个LED并且把“GPIO”接口类型选为“All Outputs”。接下来就是“连线”了。用鼠标点击ZYNQ IP核上的“M_AXI_GP0”接口拖出一根线连接到AXI GPIO的“S_AXI”接口上。Vivado会自动识别并连接整个AXI总线组包括数据、地址、控制信号。然后我们需要给这个AXI GPIO提供一个时钟。点击“Run Connection Automation”Vivado会智能地提示你发现AXI GPIO的时钟信号“s_axi_aclk”没有连接它会建议你将其连接到ZYNQ IP的“FCLK_CLK0”上这是PS提供给PL的一个固定频率时钟比如50MHz或100MHz。我们接受这个建议同时把复位信号也一并连上。连线完成后的框图应该非常清晰PS通过AXI总线控制着AXI GPIO模块。3.2 生成顶层文件与硬件描述硬件框图设计好了相当于画完了电路原理图接下来要把它变成Vivado能综合、实现的“语言”。在Block Design界面的“Sources”面板右键你的“system.bd”文件选择“Generate Output Products”。这个过程Vivado会为我们生成这个IP核的所有输出文件包括RTL源码、仿真模型、约束文件等等。特别要注意的是对于ZYNQ的PS部分其引脚约束比如UART用哪两个MIO已经在IP配置时定好了Vivado在生成过程中会自动产生对应的XDC约束文件。这意味着我们通常不需要像纯FPGA开发那样手动写一堆set_property语句来绑定引脚省了不少事。生成成功后再次右键“system.bd”选择“Create HDL Wrapper”。这里通常选择“Let Vivado manage wrapper and auto-update”让Vivado自动创建并管理顶层的Verilog或VHDL封装文件。这个顶层文件比如system_wrapper.v就是我们整个设计的“总入口”它实例化了我们刚才画的整个“system”模块。至此硬件设计部分就告一段落了。如果你只是用PS那么可以直接进入下一步。但因为我们添加了PL部分的AXI GPIO来控制LED所以还需要让Vivado把这个设计真正“制造”出来也就是生成比特流文件。在左侧“Flow Navigator”里点击“Generate Bitstream”。Vivado会依次执行综合、布局、布线、生成比特流这一整套流程。这个过程比较耗时取决于设计复杂度和电脑性能第一次跑可能要好几分钟甚至更久。期间如果遇到时序违例等警告只要不是严重错误Critical Warning对于这种简单设计通常可以先忽略。4. 导出硬件平台为SDK铺路比特流生成成功后我们就要为软件开发准备“土壤”了。这一步的目标是生成一个硬件平台描述文件它包含了PS的所有配置信息时钟、外设、内存映射等以及可选的PL比特流。SDK现在叫Vitis需要这个文件来创建对应的板级支持包BSP这样你的C代码才知道寄存器地址在哪、该怎么初始化外设。在Vivado菜单栏选择“File” - “Export” - “Export Hardware…”。会弹出一个对话框这里有两个关键选项。如果你设计的硬件不包含PL部分或者PL部分暂时不需要加载比如你只跑一个纯PS的裸机程序那么你可以选择“Exclude bitstream”。这样导出的只是一个描述硬件信息的.xsa文件老版本是.hdf文件。但像我们这个例子PS需要通过AXI总线控制PL里的LED那么PL的硬件电路即比特流就必须和PS程序一起配置到芯片里。因此我们要选择“Include bitstream”。点击“Next”后选择导出文件的路径。我习惯在Vivado工程目录下新建一个export文件夹专门存放。点击“OK”后Vivado就会把硬件信息打包成.xsa文件。这个文件就是连接Vivado硬件世界和SDK软件世界的桥梁至关重要。你可以把它理解为一套完整的“硬件驱动说明书”和“硬件配置文件”的集合。5. SDK开发实战编写你的第一个ZYNQ程序硬件平台准备好我们转到软件开发环境。关闭或最小化Vivado启动Xilinx SDK或Vitis。第一次启动会让你选择工作空间Workspace这个路径同样不要有中文和空格你可以指定到Vivado工程目录下的一个sd文件夹方便管理。5.1 创建硬件平台与板级支持包BSP进入SDK后首先需要把我们刚才导出的硬件“安装”进来。选择“File” - “New” - “Platform Project”。给平台项目起个名比如led_hw_platform然后点击“Next”。在下一个界面点击“Browse…”选择我们刚才导出的那个.xsa文件。SDK会解析这个文件识别出硬件配置。点击“Finish”完成创建。SDK会自动根据这个硬件平台生成一个对应的板级支持包。BSP是什么它是一套针对你这个特定硬件平台的底层驱动库、启动代码和编译配置。你的应用程序将基于这个BSP来编写这样你就不用去操心DDR怎么初始化、UART的波特率寄存器地址是多少这些底层细节了。5.2 创建应用工程并编写代码有了硬件平台和BSP现在可以写真正的应用程序了。选择“File” - “New” - “Application Project”。在弹出窗口中输入工程名例如led_test_app。下面“Target Hardware”部分应该会自动选中我们刚创建的led_hw_platform。在“Board Support Package”旁边选择“Create New”SDK会自动关联一个同名的BSP如led_test_app_bsp这样这个应用工程就独享一份BSP配置避免多个应用互相干扰。点击“Next”这里会出现一个“Templates”选择窗口。SDK很贴心地为各种外设提供了示例代码模板。对于新手我强烈建议先从“Hello World”开始。别小看它这个模板会自动生成通过串口打印“Hello World”的代码能帮你验证PS的DDR内存、UART外设是否工作正常。我们先选“Hello World”点击“Finish”。SDK会自动生成一个完整的工程里面包含main.c还有编译脚本、链接脚本等。打开src文件夹下的helloworld.c你会看到里面就一个main函数调用了print(“Hello World\n”)。这个print函数最终是通过UART1输出到串口终端的。我们现在要给它加点功能控制我们PL部分的那个LED。在main函数里我们需要先初始化GPIO然后控制它。代码大致如下#include stdio.h #include “platform.h” #include “xgpio.h” // AXI GPIO驱动头文件 int main() { init_platform(); // 初始化平台时钟、串口等 XGpio gpio_led; // 声明GPIO实例 int status; // 初始化AXI GPIO参数0表示第0个AXI GPIO设备我们只加了一个 status XGpio_Initialize(gpio_led, XPAR_AXI_GPIO_0_DEVICE_ID); if (status ! XST_SUCCESS) { xil_printf(“GPIO Initialization Failed\r\n”); return XST_FAILURE; } // 设置GPIO第1通道我们只有1个LED的方向为输出 XGpio_SetDataDirection(gpio_led, 1, 0x0); xil_printf(“Start LED Blinking…\r\n”); while (1) { // 第1通道写入1点亮LED XGpio_DiscreteWrite(gpio_led, 1, 0x1); usleep(500000); // 延时500ms // 第1通道写入0熄灭LED XGpio_DiscreteWrite(gpio_led, 1, 0x0); usleep(500000); } cleanup_platform(); // 实际上while循环不会退出到这里 return 0; }这段代码做了几件事包含必要的头文件初始化AXI GPIO硬件将对应的通道设置为输出模式然后在一个死循环里不断翻转LED的状态实现闪烁效果。XPAR_AXI_GPIO_0_DEVICE_ID这个常量是在BSP生成时自动定义的它对应了我们硬件系统中那个AXI GPIO的基地址。所有硬件设备的ID、基地址等常量都在工程名_bsp目录下的include文件夹里的xparameters.h文件中定义SDK就是通过这个文件把硬件和软件联系起来的。5.3 编译、下载与调试代码写好后在工程上右键选择“Build Project”进行编译。如果代码没有语法错误编译会成功在工程目录下的Debug文件夹里生成.elf可执行文件。接下来就是最激动人心的时刻把程序下载到板子上运行。首先确保你的开发板已经上电并且JTAG下载器通常是USB转JTAG已经连接好电脑和板子。在SDK下方“SDK Terminal”标签页里点击“”号新建一个串口终端端口号选择你板载USB转串口对应的COM口Windows设备管理器里查看波特率通常设置为115200。这个终端用来接收程序通过UART打印的信息。然后在左侧“Project Explorer”里右键你的应用工程led_test_app选择“Run As” - “Launch on Hardware (System Debugger)”。SDK会通过JTAG首先将PL的比特流文件如果导出时包含了配置到FPGA中建立起我们设计的硬件电路包含AXI GPIO然后将编译好的应用程序.elf文件加载到PS的DDR内存中最后让ARM核开始执行。如果一切顺利你应该能看到板子上有一颗LED开始有规律地闪烁同时在SDK Terminal里看到“Start LED Blinking…”的打印信息。如果你想单步调试可以右键工程选择“Debug As” - “Launch on Hardware (System Debugger)”。SDK会进入调试视图你可以设置断点查看变量一步步跟踪代码执行这对于排查复杂问题非常有用。第一次调试时可能会提示配置调试器通常保持默认设置即可。6. 进阶技巧与常见问题排查走通了整个流程你已经掌握了ZYNQ开发的基础闭环。但在实际项目中肯定会遇到各种问题。这里分享几个我踩过的坑和对应的解决办法。6.1 硬件配置与软件地址映射不匹配这是最常见的问题之一。症状是在SDK里编译没问题但一下载运行就卡死或者操作外设如GPIO写数据没反应。根本原因往往是Vivado里硬件系统的地址分配和SDK的BSP里xparameters.h文件定义的地址对不上。怎么排查首先在Vivado里生成比特流后打开“Address Editor”标签页。这里列出了PS上所有AXI主设备如M_AXI_GP0访问从设备如我们的axi_gpio_0的基地址和范围。记下axi_gpio_0的Offset Address例如0x4120_0000。然后去SDK打开你的BSP工程下的include/xparameters.h文件搜索XPAR_AXI_GPIO_0_BASEADDR。看看它的值是不是0x41200000。如果不一致那软件访问的地址根本就不是你硬件里那个GPIO当然没反应。解决办法是在Vivado中确认硬件设计无误并重新导出.xsa文件然后在SDK中删除旧的硬件平台和BSP工程重新导入创建。6.2 利用现有IP示例代码加速开发SDK提供了一个非常实用的功能导入IP核的示例代码。比如你不太清楚怎么用AXI GPIO的中断功能或者想用AXI DMA但不知从何写起。你可以在“Project Explorer”里找到你的BSP工程例如led_test_app_bsp展开它找到system.mss文件并双击。右侧会打开一个视图列出了当前硬件平台支持的所有驱动和外设。找到你感兴趣的IP比如“axi_gpio”点击下面的“Import Examples”。SDK会弹出一个对话框里面有几个示例工程可选比如“Polling Example”查询方式、“Interrupt Example”中断方式。选择一个导入SDK会自动创建一个新的、完整的示例应用工程里面包含了该IP核的标准用法代码。你可以直接在这个工程上修改或者参考它的代码结构移植到自己的工程里能节省大量查阅手册的时间。6.3 PL逻辑修改后的更新流程开发过程中经常需要修改PL部分的逻辑。比如觉得LED闪烁太快想改一下PL里的分频器。很多新手会直接去改Vivado里的设计然后重新生成比特流但忘了更新SDK的硬件平台。正确的流程是在Vivado中修改Block Design - 重新“Generate Output Products” - 重新“Generate Bitstream” - 重新“Export Hardware”包含比特流。然后回到SDK不需要删除整个工程。只需要右键你的硬件平台工程如led_hw_platform选择“Update Hardware Specification…”然后选择新导出的.xsa文件。SDK会更新硬件信息并提示你BSP需要重新生成。确认后你的应用工程就能基于新的硬件配置运行了。如果只是PL逻辑变动PS的软件代码通常不需要修改除非地址映射发生了改变。整个流程走下来你会发现ZYNQ的开发虽然步骤多但逻辑是清晰的Vivado负责搭建硬件舞台配置PS、设计PLSDK负责编写在这个舞台上表演的软件程序。两者通过一个硬件描述文件.xsa紧密耦合。多练习几遍把每一步的作用都想明白你就能从“跟着做”变成“知道为什么这么做”进而设计出更复杂的系统。记住遇到问题先检查硬件配置和地址映射再看软件驱动初始化大部分问题都能在这两个环节找到答案。