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 .elf UART应用程序 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. 确认关键配置:

    ld

    复制代码
    MEMORY
    {
        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 TargetAuto 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-0x0003FFFF FSBL区域 引导程序使用
0x00100000-0x001FFFFF 应用程序区 主程序放置位置
0xE0000000-0xE00FFFFF 外设寄存器 UART、GPIO等

8.3 开发板启动模式设置

开发板 SD卡模式 QSPI模式 JTAG模式
ZedBoard MIO5-0: 111010 MIO5-0: 000010 MIO5-0: 111111
ZCU102 SW6: 000010 SW6: 001010 SW6: 111111
PYNQ-Z2 J12: SD模式 J12: QSPI模式 J12: JTAG模式

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

相关推荐
我爱C编程8 小时前
【仿真测试】基于FPGA的2ASK扩频通信链路实现,包含帧同步,定时点,扩频伪码同步,信道,误码统计
fpga开发·帧同步·定时点·ask·扩频通信·扩频伪码同步
minglie112 小时前
Wokwi组件
fpga开发
qq_3375994614 小时前
FPGA知识点
经验分享·fpga开发
s090713614 小时前
连通域标记:从原理到数学公式全解析
图像处理·算法·fpga开发·连通域标记
FPGA_小田老师14 小时前
FPGA例程(4):按键消抖实验
fpga开发·verilog·fpga demo·fpga例程
FPGA小c鸡15 小时前
FPGA摄像头采集处理显示完全指南:从OV5640到HDMI实时显示(附完整工程代码)
fpga开发
jz_ddk15 小时前
[学习] NCO原理与误差分析
fpga开发·gps·gnss·北斗
unicrom_深圳市由你创科技15 小时前
专业fpga定制开发解决方案
fpga开发·fpga
ALINX技术博客15 小时前
【ALINX 教程】FPGA 10G 以太网实现——基于 Zynq US+ Z7-P 开发板+FH1223 子卡
fpga开发
s090713615 小时前
FPGA加速:Harris角点检测全解析
图像处理·算法·fpga开发·角点检测