我们先试试基本开发,现在先测试一下模块sd卡记录。先把模块基本加电测试,然后完成简单的ps端vivado项目,需要配置ddr,uart,sd卡,qspi flash。编译项目,导出硬件。
首先,需要测试helloword串口能够输入输出。
然后,开始测试sd卡,按照以下程序替代helloword.c
'''#include "xil_printf.h"
#include "xdevcfg.h"
#include "xparameters.h"
#include "platform.h"
#include "ff.h"
int SD_Init(void);
int Sd_Test_Write(void);
int Sd_Test_Read(void);
int main()
{
init_platform();
print("Hello World\n\r");
print("zynq_sd_card_fatfs-test \r\n");
SD_Init();
Sd_Test_Write();
Sd_Test_Read();
while(1)
{
;
}
cleanup_platform();
return 0;
}
static FATFS fatfs;
#define _MAX_SS 100
int SD_Init(void)
{
FRESULT rc;
BYTE work_MAX_SS; // 格式化所需的工作区,大小至少为一个扇区
// 1. 尝试挂载现有文件系统
rc = f_mount(&fatfs, "1:", 0);
// 2. 如果挂载失败(例如卡未格式化),则尝试格式化
if (rc == FR_NO_FILESYSTEM) {
xil_printf("No filesystem found. Formatting...\r\n");
// 参数说明:
// "": 路径,表示默认驱动器(0)
// FM_FAT: 格式化为FAT文件系统
// 0: 使用默认的分配单元(簇)大小
// work, sizeof(work): 提供的工作缓冲区及其大小
rc = f_mkfs("1:", FM_FAT, 0, work, sizeof(work));
if (rc) {
xil_printf("ERROR: Formatting failed with error %d\r\n", rc);
return XST_FAILURE;
}
xil_printf("Formatting successful. Remounting...\r\n");
// 3. 格式化后,重新尝试挂载
rc = f_mount(&fatfs, "1:", 0);
}
// 4. 检查最终挂载结果
if (rc) {
xil_printf("ERROR: f_mount returned %d\r\n", rc);
return XST_FAILURE;
}
xil_printf("SD Card filesystem mounted successfully.\r\n");
return XST_SUCCESS;
}
int Sd_Test_Write()
{
FIL fil;
FRESULT rc;
UINT br;
const char src_str1\[\] = "bsp test sd card write and read line1 string. if you see this message,sd_card fatfs test ok!\r\n";
rc = f_open(&fil,"1:/test.txt",FA_WRITE|FA_CREATE_NEW);
if(rc)
{
xil_printf("ERROR : f_open returned %d\r\n",rc);
return XST_FAILURE;
}
rc = f_write(&fil,src_str1,sizeof(src_str1),&br);rc = f_sync(&fil);
rc = f_close(&fil);
}
int Sd_Test_Read()
{
FIL fil;
FRESULT rc;
UINT br;
const char src_str4096={0};
rc = f_open(&fil,"1:/test.txt",FA_READ);
if(rc)
{
xil_printf("ERROR : f_open returned %d\r\n",rc);
return XST_FAILURE;
}
rc = f_lseek(&fil, 0);
rc = f_read(&fil,src_str,4096,&br);
xil_printf(src_str);
rc = f_close(&fil);
}'''
编译软件,加载运行。编译的时候会出现头文件问题,库问题。需要在设置里面增加链接相应库,增加库查找目录,才能编译通过。
运行程序,按照预期执行,就是测试通过,否则回到vivado查找问题,或者看硬件。
2,形成加载的boot.bin
使用vitis软件,把flsb.elf,bit硬件流,
刚刚编译的elf文件放在一起。
生成以下bif文件:
'''
the_ROM_image:
{
// 第一部分: FSBL - 必须位于 0x0
bootloader fsbl.elf
// 第二部分: 硬件比特流文件
// 大小: 4,045,676 字节, FSBL 之后,对齐到 0x70000
offset = 0x70000 design_1_wrapper.bit
// 第三部分: 应用程序
// 大小: 432,408 字节, 比特流之后,对齐到 0xAF0000
offset = 0xAF0000 testfile.elf
}'''
要注意按照文件字节大小,修改offset。
我将为您详细讲解从生成BOOT.BIN到烧写QSPI Flash的全过程,包括必要的配置和注意事项。
3. 生成BOOT.BIN文件
1.1 准备BIF文件
见上面
1.2 使用bootgen生成BOOT.BIN
# 基本命令
bootgen -image boot.bif -arch zynq -o BOOT.BIN -w
# 详细参数说明:
# -image: 指定BIF文件
# -arch: 指定架构(zynq, zynqmp, microblaze等)
# -o: 输出文件名
# -w: 覆盖已存在的输出文件
# -log: 生成日志文件(可选)
# 示例:生成带日志的BOOT.BIN
bootgen -image boot.bif -arch zynq -o BOOT.BIN -w -log bootgen.log
4. 烧写前准备工作
4.1 硬件连接检查
-
JTAG连接:确保JTAG下载器正确连接
-
电源检查:确保开发板供电正常
-
启动模式配置:将开发板设置为JTAG启动模式
-
Zynq-7000: MIO5:0 = 6'b001010
-
Zynq UltraScale+: MODE3:0 = 4'b0101
-
4.2 Vivado硬件管理器设置
# 在Vivado TCL控制台中操作
# 1. 打开硬件管理器
open_hw_manager
# 2. 连接到目标
connect_hw_server
open_hw_target
# 3. 检查设备是否识别
current_hw_device [get_hw_devices xc7z*]
# 4. 刷新设备
refresh_hw_device [lindex [get_hw_devices] 0]
5. 烧写QSPI Flash的完整流程
5.1 使用XSCT命令烧写(推荐)
# 创建烧写脚本 flash_program.tcl
# 1. 连接目标
connect
# 2. 选择目标处理器
targets -set -filter {name =~ "ARM*#0"}
# 3. 停止当前运行的程序
stop
# 4. 初始化DDR(如果需要)
# 5. 烧写BOOT.BIN到QSPI Flash
# 方法A:使用通用Flash编程
dow BOOT.BIN
# 或者使用方法B:指定Flash类型和地址
flash write_bank 0 BOOT.BIN 0
5.2 完整的烧写脚本示例
# flash_program.tcl
#!/bin/tclsh
# 设置变量
set BOOT_BIN "BOOT.BIN"
set FLASH_OFFSET 0x0
set FLASH_TYPE "qspi-x4-single"
# 连接硬件
connect
after 1000
# 选择目标
targets -set -filter {name =~ "Cortex-A9*#0"}
after 500
# 复位并停止
rst
after 1000
stop
# 初始化PS(如果需要在烧写前运行FSBL)
# source ps_init.tcl
# 配置Flash参数
flash config -freq 100000000
# 执行烧写
puts "正在擦除Flash..."
flash erase_sector 0 0 127
puts "擦除完成"
puts "正在烧写BOOT.BIN..."
flash write $BOOT_BIN $FLASH_OFFSET $FLASH_TYPE
puts "烧写完成"
# 验证烧写
puts "正在验证..."
flash verify $BOOT_BIN $FLASH_OFFSET $FLASH_TYPE
puts "验证成功!"
# 断开连接
disconnect
puts "Flash烧写完成,请将启动模式切换为QSPI启动"
5.3 执行烧写
# 运行XSCT执行TCL脚本
xsct flash_program.tcl
# 或者交互式执行
xsct
# 然后逐行输入TCL命令
6. 使用Vivado GUI烧写(备选)
6.1 GUI操作步骤
-
打开Vivado → Open Hardware Manager
-
连接目标设备
-
右键点击FPGA设备 → Add Configuration Memory Device
-
选择正确的Flash型号(如n25q128-3.3v-spi-x1_x2_x4)
-
指定BOOT.BIN文件路径
-
点击Program
7. 验证和启动测试
7.1 验证烧写结果
# 在XSCT中读取Flash内容验证
# 读取前256字节
mrd 0xFC000000 64
# 或者
flash read_bank 0 0x100000 256
7.2 切换启动模式
-
硬件配置:
-
Zynq-7000: 将MIO5:0设为6'b001001(主QSPI)
-
Zynq UltraScale+: 将MODE3:0设为4'b0010(QSPI 32位)
-
-
重新上电 或系统复位
8. 注意事项和故障排除
8.1 重要注意事项
-
启动顺序必须正确:FSBL → Bitstream → Application
-
Bit文件大小:确保bit文件是完整配置文件,不是局部bit文件
-
Flash型号匹配:确认实际Flash型号与烧写时选择的型号一致
-
电压匹配:Flash电压(3.3V/1.8V)需与硬件设计一致
-
时钟频率:初次烧写建议使用较低频率(如50MHz)
8.2 常见问题解决
# 1. 如果连接失败
# 检查JTAG连接,尝试:
connect_hw_server -url TCP:localhost:3121
# 或重启hw_server
# Linux: hw_server &
# Windows: 从Vivado启动Program and Debug
# 2. 如果Flash识别失败
# 检查电源和接线
# 尝试更低频率
flash config -freq 25000000
# 3. 如果烧写验证失败
# 检查电源稳定性
# 尝试分段烧写
flash write_bank 0 fsbl.elf 0
flash write_bank 0 system.bit 0x80000
flash write_bank 0 application.elf 0x100000
6.3 调试命令
# 查看目标状态
targets
# 查看处理器状态
reg
# 查看内存
mrd 0xF8000258 1 # 读取启动模式寄存器
# 检查Flash ID
flash probe 0
9. 自动化脚本示例
#!/bin/bash
# generate_and_program.sh
# 生成BOOT.BIN
echo "生成BOOT.BIN..."
bootgen -image boot.bif -arch zynq -o BOOT.BIN -w
# 检查文件是否存在
if [ ! -f "BOOT.BIN" ]; then
echo "错误:BOOT.BIN生成失败!"
exit 1
fi
# 烧写到Flash
echo "开始烧写QSPI Flash..."
xsct << EOF
connect
targets -set -filter {name =~ "ARM*#0"}
stop
flash write_bank 0 BOOT.BIN 0
verify_bank 0 BOOT.BIN 0
disconnect
EOF
if [ $? -eq 0 ]; then
echo "烧写成功!"
echo "请将启动模式切换为QSPI模式并重新上电"
else
echo "烧写失败!"
fi
总结
-
确保启动镜像顺序正确
-
烧写前确认硬件连接和启动模式
-
首次烧写建议使用较低频率
-
烧写后必须验证
-
切换启动模式后重新上电
按照这个流程,您应该能成功将BOOT.BIN烧写到QSPI Flash并启动系统。完成了,sd卡测试。