Zynq FPGA UART程序固化完整流程文档

一、概述

本文档详细记录了将UART循环打印程序固化到Zynq FPGA开发板的完整流程。通过FSBL(First Stage Boot Loader)引导程序,实现上电后自动运行UART打印程序。

二、固化前准备

2.1 硬件准备

  • Zynq开发板(如ZedBoard、ZCU102等)
  • USB-JTAG下载器
  • USB转串口线
  • 存储介质(SD卡或QSPI Flash)
  • 电源适配器

2.2 软件准备

  • Vivado Design Suite(包含Vitis)
  • 串口调试助手(如Putty、SecureCRT)
  • 硬件描述文件(.xsa文件)

三、文件系统结构

3.1 所需文件清单

text

固化项目/ ├── fsbl_platform/ # FSBL平台工程 ├── uart_app/ # UART应用程序工程 ├── hardware/ │ └── system.bit # 硬件比特流文件 └── output/ ├── fsbl.elf # FSBL引导程序 ├── uart_app.elf # UART应用程序 ├── system.bit # 硬件比特流 ├── boot.bif # 引导镜像描述文件 └── boot.bin # 最终固化文件

3.2 文件说明

文件名后缀作用来源
fsbl.elf.elf第一阶段引导程序Vitis生成
uart_app.elf.elfUART应用程序Vitis编译
system.bit.bit硬件配置比特流Vivado导出
boot.bif.bif引导镜像描述文件手工创建
boot.bin.bin最终固化文件bootgen生成

四、详细操作步骤

4.1 步骤1:创建FSBL引导程序

4.1.1 在Vitis中创建Platform Project
  1. 打开Vitis软件
  2. File → New → Platform Project
  3. 输入项目名称:fsbl_platform
  4. 选择硬件描述文件(.xsa文件)
  5. 点击Finish
4.1.2 编译FSBL
  1. 在Project Explorer中右键点击fsbl_platform
  2. 选择Build Project
  3. 等待编译完成
4.1.3 获取fsbl.elf文件

编译完成后,文件位于:

text

fsbl_platform/export/fsbl_platform/sw/fsbl_platform/boot/fsbl.elf

4.2 步骤2:创建UART应用程序

4.2.1 创建Application Project
  1. File → New → Application Project
  2. 项目名称:uart_app
  3. 选择平台:fsbl_platform
  4. 选择模板:Hello World(自动生成main.c)
  5. 点击Finish
4.2.2 替换代码
  1. 打开 uart_app/src/main.c
  2. 删除原有代码,粘贴以下UART测试代码:

c

#include <stdio.h> #include "xil_printf.h" #include "xil_types.h" #include "xparameters.h" #include "xuartps.h" // 全局变量 XUartPs UartInst; u8 data_buffer[64]; u32 counter = 0; // 初始化UART int init_uart() { XUartPs_Config *Config; int Status; // 查找UART配置 Config = XUartPs_LookupConfig(XPAR_PS7_UART_0_DEVICE_ID); if (Config == NULL) { return XST_FAILURE; } // 初始化UART Status = XUartPs_CfgInitialize(&UartInst, Config, Config->BaseAddress); if (Status != XST_SUCCESS) { return XST_FAILURE; } // 设置波特率115200 XUartPs_SetBaudRate(&UartInst, 115200); // 自检 Status = XUartPs_SelfTest(&UartInst); if (Status != XST_SUCCESS) { return XST_FAILURE; } return XST_SUCCESS; } // 主函数 int main() { int i; // 初始化UART if (init_uart() != XST_SUCCESS) { return -1; } // 发送启动信息 XUartPs_Send(&UartInst, (u8*)"\r\n=== UART Test Application ===\r\n", 34); XUartPs_Send(&UartInst, (u8*)"Starting continuous transmission...\r\n", 39); // 主循环 while (1) { // 填充数据 for (i = 0; i < 64; i++) { data_buffer[i] = (counter + i) & 0xFF; } counter++; // 发送数据 XUartPs_Send(&UartInst, data_buffer, 64); // 发送换行 XUartPs_Send(&UartInst, (u8*)"\r\n", 2); // 延时约1秒 for (i = 0; i < 10000000; i++); } return 0; }

4.2.3 验证链接地址
  1. 打开 uart_app/lscript.ld 链接脚本
  2. 确认关键配置:ldMEMORY { ps7_ddr_0 : ORIGIN = 0x00100000, LENGTH = 0x1FF00000 /* ... */ } .text : { *(.text) } > ps7_ddr_0 /* 确保.text段在DDR中 */
  3. 关键点:应用程序起始地址必须是 0x00100000
4.2.4 编译应用程序
  1. 右键点击 uart_app 项目
  2. 选择 Build Project
  3. 验证编译成功(无错误)

4.3 步骤3:验证应用程序地址

4.3.1 方法一:使用objdump命令

bash

# 在Vitis Terminal中执行 arm-none-eabi-objdump -h uart_app.elf | grep ".text"

正确输出示例

text

.text 00000500 00100000 00100000 00001000 2**2

关键检查:第三列(VMA)必须是 00100000

4.3.2 方法二:查看.map文件
  1. 打开 uart_app/Debug/uart_app.map
  2. 搜索 .text 查看地址

4.4 步骤4:生成BOOT.BIN文件

4.4.1 准备三个必需文件
  1. fsbl.elf - 从FSBL项目复制
  2. system.bit - 从Vivado硬件工程导出
  3. uart_app.elf - 从UART项目编译得到

将三个文件复制到同一目录(如 output/

4.4.2 创建BIF描述文件

在 output/ 目录下创建 boot.bif 文件,内容:

text

the_ROM_image: { [bootloader] fsbl.elf system.bit uart_app.elf }

4.4.3 生成BOOT.BIN

方法A:使用Vitis GUI

  1. 菜单栏:Xilinx → Create Boot Image
  2. 点击 Add 依次添加:
    • fsbl.elf(类型选择 bootloader
    • system.bit
    • uart_app.elf
  3. 设置输出路径
  4. 点击 Create Image

方法B:使用命令行

bash

cd output bootgen -image boot.bif -arch zynq -o boot.bin -w on

4.4.4 验证生成结果
  • 生成的文件:boot.bin
  • 文件大小:约3-5MB
  • 如果失败,检查文件顺序和类型设置

4.5 步骤5:烧写到存储设备

4.5.1 方法一:SD卡启动(测试用)
  1. 格式化SD卡为FAT32格式
  2. 复制boot.bin到SD卡根目录
  3. 设置开发板为SD卡启动模式(跳线设置)
  4. 插入SD卡,连接串口线
  5. 上电启动
4.5.2 方法二:QSPI Flash固化(永久)
  1. 连接JTAG和串口线
  2. 打开Vivado → Hardware Manager
  3. Open Target → Auto Connect
  4. 右键开发板 → Add Configuration Memory Device
  5. 选择Flash型号(常见:mt25ql256aba
  6. 选择 boot.bin 文件
  7. 点击 Program,等待完成
  8. 重要:烧写完成后
    • 断开JTAG
    • 关闭电源
    • 设置为QSPI启动模式
    • 重新上电

4.6 步骤6:测试验证

4.6.1 串口设置
  • 串口软件:Putty/SecureCRT
  • 波特率:115200
  • 数据位:8
  • 停止位:1
  • 校验位:None
  • 流控制:None
4.6.2 预期输出

上电后串口应输出:

text

=== UART Test Application === Starting continuous transmission... [然后是连续的十六进制数据]

4.6.3 成功标志
  • 上电后自动运行,无需JTAG
  • 串口连续输出数据
  • 断电重启后仍然正常运行

五、故障排除

5.1 常见问题及解决

问题现象可能原因解决方案
无串口输出波特率不匹配检查串口设置为115200
卡在FSBL阶段应用程序地址错误验证.elf文件起始地址为0x00100000
程序不运行BIN文件生成顺序错误确保顺序:fsbl → bit → app
启动失败启动模式设置错误检查开发板跳线设置
部分运行后停止堆栈大小不足修改链接脚本增加堆栈空间

5.2 调试技巧

5.2.1 添加调试信息

在应用程序开头添加:

c

// 在main函数开始处 XUartPs_Send(&UartInst, (u8*)"App Started!\r\n", 14);

5.2.2 验证硬件连接

c

// 强制发送测试字符 volatile u32 *uart = (u32*)0xE0001000; *uart = 'A';

5.3 关键检查点清单

  • FSBL编译成功(fsbl.elf存在)
  • 应用程序编译成功(uart_app.elf存在)
  • 应用程序起始地址为0x00100000
  • boot.bif文件顺序正确
  • boot.bin生成成功
  • SD卡为FAT32格式
  • boot.bin在SD卡根目录
  • 开发板启动模式正确
  • 串口波特率115200
  • 串口线TX/RX连接正确

六、进阶配置

6.1 修改启动延时

在FSBL中可修改启动延时,给用户中断引导的机会:

c

// 在fsbl_main.c中添加 int timeout = 3; // 3秒延时 while (timeout-- > 0 && !CheckUartInput()) { fsbl_printf("Booting in %d seconds...\r\n", timeout); Delay(1000); }

6.2 多应用程序支持

可通过修改FSBL实现多应用程序选择:

c

// 根据按键选择不同应用 if (ReadBootPin() == 0) { // 启动UART测试程序 HandoffAddress = 0x00100000; } else { // 启动其他应用程序 HandoffAddress = 0x00200000; }

6.3 安全性增强

  • 添加应用程序校验和验证
  • 实现安全启动流程
  • 加密固件保护

七、注意事项

7.1 重要提醒

  1. 不要修改FSBL的跳转逻辑,除非你完全理解其工作原理
  2. 应用程序不能使用地址0x00000000-0x000FFFFF区域(FSBL使用)
  3. 固化前务必先用SD卡测试,确认程序能正常运行
  4. QSPI Flash烧写后必须断电重启,不能热复位

7.2 文件管理建议

  1. 保留每个版本的.elf和.bin文件
  2. 记录每次固化的配置参数
  3. 使用版本控制系统管理源码

7.3 性能优化

  1. 减少启动时间:优化应用程序初始化代码
  2. 减小固件大小:移除不必要的库和代码
  3. 提高可靠性:添加看门狗和错误恢复机制

八、附录

8.1 相关命令参考

bash

# 查看ELF文件信息 arm-none-eabi-objdump -h file.elf arm-none-eabi-readelf -a file.elf # 生成反汇编代码 arm-none-eabi-objdump -d file.elf > disassembly.txt # 查看文件大小 arm-none-eabi-size file.elf

8.2 常用内存地址

地址范围用途说明
0x00000000-0x0003FFFFFSBL区域引导程序使用
0x00100000-0x001FFFFF应用程序区主程序放置位置
0xE0000000-0xE00FFFFF外设寄存器UART、GPIO等

8.3 开发板启动模式设置

开发板SD卡模式QSPI模式JTAG模式
ZedBoardMIO5-0: 111010MIO5-0: 000010MIO5-0: 111111
ZCU102SW6: 000010SW6: 001010SW6: 111111
PYNQ-Z2J12: SD模式J12: QSPI模式J12: JTAG模式

文档版本: 1.0
最后更新: 2026年01月
适用平台: Xilinx Zynq-7000系列
注意事项: 本流程基于Vitis 2019.2版本,其他版本可能略有差异

Read more

云端微光,AI启航:低代码开发的智造未来

云端微光,AI启航:低代码开发的智造未来

文章目录 * 前言 * 一、引言:技术浪潮中的个人视角 * 初次体验腾讯云开发 Copilot * 1.1 低代码的时代机遇 * 1.1.1 为什么低代码如此重要? * 1.2 AI 的引入:革新的力量 * 1.1.2 Copilot 的亮点 * 1.3 初学者的视角 * 1.3.1 Copilot 带来的改变 * 二、体验记录:云开发 Copilot 的实际操作与感受 * 2.1 初步接触:云开发 Copilot 的界面和功能布局 * 2.2 操作过程详解:从需求输入到初步成果 * 2.2.1

Flutter for OpenHarmony 实战之基础组件:第十一篇 BottomNavigationBar 与 TabBar 多页切换

Flutter for OpenHarmony 实战之基础组件:第十一篇 BottomNavigationBar 与 TabBar 多页切换

Flutter for OpenHarmony 实战之基础组件:第十一篇 BottomNavigationBar 与 TabBar 多页切换 摘要:一个复杂的 App 通常包含多个功能模块。本文将深入讲解 Flutter 中最核心的两种多页切换模式:底部导航 (BottomNavigationBar) 和顶部选项卡 (TabBar)。我们将探讨 Material 3 风格的新组件 NavigationBar,解决页面切换时的状态丢失问题,并适配鸿蒙系统的底部手势条。 前言 打开你手机里的微信、淘宝或抖音,你会发现它们都有一个共同的架构:底部有 4-5 个图标,点击切换不同的主页面;顶部可能还有“关注/推荐/热榜”这样的分类切换。 这就是移动端最经典的 “底 Tab + 顶 Tab” 双导航架构。 本文你将学到: * BottomNavigationBar (经典) 与

宇树科技机器人核心技术

宇树科技机器人核心技术

前言 宇树科技作为全球足式/人形机器人领域的标杆企业,其技术体系覆盖消费级(Go2)、工业级(B2)、人形(G1/H1)全产品线,以“硬件自研+软件全栈+AI赋能”构建核心壁垒。本文不仅拆解宇树机器人的关键技术(单硬件、单软件、软硬件协同、AI+),还配套就业技能图谱、学习路线与工具推荐,适合机械、电子、计算机、AI领域开发者/求职者参考。 一、宇树科技机器人核心技术全景(附插图建议) 宇树的技术体系可概括为“四层金字塔结构”,从下到上实现“能运动→会运动→智能运动”的进阶: 技术层级核心定位代表技术应用价值底层硬件机器人“躯体骨架”自研伺服电机、分层计算平台、4D激光雷达保障运动性能与环境适配性全栈软件机器人“智慧大脑”MPC/WBC控制算法、SLAM感知融合、ROS2中间件实现精准控制与灵活交互软硬件协同机器人“神经中枢”实时控制闭环、

介绍终身机器人学习的数据集LIBERO

介绍终身机器人学习的数据集LIBERO

1 LIBERO的作用 LIBERO是一个用于研究多任务和终身机器人学习中知识迁移的综合基准测试平台,LIBERO是基于robosuite框架构建的。它专注于机器人操作任务,这些任务需要两类知识: 1. 陈述性知识:关于物体和空间关系的知识 2. 程序性知识:关于运动和行为的知识 2 核心原理 任务生成与基准设计 LIBERO提供了一个程序化生成管道,原则上可以生成无限数量的操作任务。系统包含130个任务,分为四个任务套件,每个套件都有受控的分布偏移: * LIBERO-Spatial/Object/Goal:专注于特定类型知识的迁移 * LIBERO-100:包含需要迁移纠缠知识的100个操作任务 学习框架 系统采用模仿学习作为主要学习方法,因为任务使用稀疏奖励函数(任务完成时获得+1奖励)。LIBERO提供高质量的人类遥操作演示数据集用于训练。 算法与策略架构 LIBERO实现了三种视觉运动策略网络: * bc_rnn_policy:基于RNN的行为克隆策略 * bc_transformer_policy:基于Transformer的行为克隆策略