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绘画提示词生成器的技术实现与优化策略 的探讨之前,我想先分享一个最近让我觉得很有意思的全栈技术挑战。 我们常说 AI 是未来,但作为开发者,如何将大模型(LLM)真正落地为一个低延迟、可交互的实时系统,而不仅仅是调个 API? 这里有一个非常硬核的动手实验:基于火山引擎豆包大模型,从零搭建一个实时语音通话应用。它不是简单的问答,而是需要你亲手打通 ASR(语音识别)→ LLM(大脑思考)→ TTS(语音合成)的完整 WebSocket 链路。对于想要掌握 AI 原生应用架构的同学来说,这是个绝佳的练手项目。 从0到1构建生产级别应用,脱离Demo,点击打开 从0打造个人豆包实时通话AI动手实验 AI绘画提示词生成器的技术实现与优化策略 背景痛点:为什么我们需要提示词生成器? AI绘画工具虽然强大,但用户常常面临一个共同难题:如何写出高质量的提示词(prompt)。以下是当前存在的主要挑战: * 语义偏差问题:用户输入的简单描述与AI理解存在差距,导致生成图像与预期不符 * 多样性不足:基础提示词往往产生相似风格的输出,

llama.cpp + llama-server 的安装部署验证

飞桨AI Studio星河社区-人工智能学习与实训社区 用的是 魔塔的免费资源 不太稳定 我的Notebook · 魔搭社区 cat /etc/os-release  Ubuntu 22.04.5 LTS (Jammy Jellyfish) —— 这是一个长期支持(LTS)且完全受支持的现代 Linux 发行版,非常适合部署 llama.cpp + llama-server。Ubuntu 22.04 自带较新的 GCC(11+)、CMake(3.22+)和 Python 3.10+,无需手动升级工具链,部署过程非常顺畅。 一、安装系统依赖 sudo apt update sudo apt install -y

用 C# 扩展 Dynamics 365 Copilot:自定义插件与场景

Dynamics 365 Copilot 作为基于 AI 的智能助手,为企业用户提供了自动化流程、智能分析和自然语言交互的能力,但通用功能往往无法满足特定行业或企业的定制化需求。本文将详细介绍如何通过 C# 编写自定义插件,扩展 Dynamics 365 Copilot 的能力,并结合实际业务场景实现定制化 AI 交互。 一、核心基础:Dynamics 365 Copilot 扩展架构 Dynamics 365 Copilot 的扩展主要依赖于 Power Platform 插件框架 和 Copilot Studio 的自定义连接器,核心技术栈包括: * C# (.NET Framework 4.8 或 .NET 6+):编写业务逻辑插件 * Dynamics 365 SDK:

【GitHub】github学生认证,在vscode中使用copilot的教程

【GitHub】github学生认证,在vscode中使用copilot的教程

github学生认证并使用copilot教程 * 写在最前面 * 一.注册github账号 * 1.1、注册 * 1.2、完善你的profile * 二、Github 学生认证 * 注意事项:不完善的说明 * 三、Copilot * 四、在 Visual Studio Code 中安装 GitHub Copilot 扩展 * 4.1 安装 Copilot 插件 * 4.2 配置 Copilot 插件(新安装) * 4.3 换 Copilot 插件账号 🌈你好呀!我是 是Yu欸🌌 2024每日百字篆刻时光,感谢你的陪伴与支持 ~🚀 欢迎一起踏上探险之旅,挖掘无限可能,共同成长!