Flash双冗余程序切换功能实现文档

1. 项目概述

本项目基于Xilinx Zynq-7000 SoC平台,在Vivado 2018.3+Xilinx SDK 2018.3环境下开发,实现了Flash双冗余程序功能。该功能使系统能够在单一Flash芯片上存储两套不同的程序,并根据定时器自动在两个程序之间进行切换。

2. 硬件参数

  • 处理器平台:Xilinx Zynq-7000系列SoC (双核ARM Cortex-A9)
  • 处理器频率:333MHz
  • 存储设备:QSPI Flash (用于程序存储),eMMC (用于配置数据存储)
  • 定时器:SCU定时器 (Timer0用于系统定时,Timer1用于程序切换)
  • 内存:OCM (On-Chip Memory) 用于程序加载和执行
  • 网络接口:以太网接口 (PS7_ETHERNET_0)
  • 串口:PS7_UART_1 (用于程序切换信息输出)

3. 修改文件说明

本次修改涉及以下文件:

3.1 新建文件

  1. CTRL_SYS/src/include/program_switch.h

    • 目的:定义程序切换功能的接口
    • 内容:声明InitProgramSwitch函数,提供程序切换功能的初始化入口
  2. CTRL_SYS/src/source/program_switch.c

    • 目的:实现Flash双冗余程序切换功能
    • 内容
      • QSPI Flash初始化和容量检测
      • 程序加载和执行功能
      • 定时器中断处理程序切换
      • 用户界面信息输出

3.2 修改文件

  1. CTRL_SYS/src/source/main.c

    • 目的:集成程序切换功能到现有系统
    • 修改
      • 添加program_switch.h头文件
      • 在main函数中初始化程序切换功能
  2. CTRL_SYS/src/include/timer_intr.h

    • 目的:支持多个定时器操作
    • 修改
      • 添加定时器相关常量定义
      • 增加函数文档注释
      • 定义第二个定时器的中断ID (TIMER_SWITCH_INTR)

4. 项目流程与模块功能

4.1 整体流程

  1. 系统启动

    • FSBL启动后加载主程序
    • 主程序初始化系统组件(控制系统、中断系统等)
  2. 程序切换初始化

    • 初始化QSPI Flash并检测容量
    • 计算程序A和程序B的偏移地址
    • 设置定时器中断(5秒触发一次)
    • 初次加载并执行程序A
  3. 运行时切换

    • 定时器每5秒触发一次中断
    • 中断处理程序切换当前运行的程序
    • 从Flash读取新程序到OCM
    • 执行新加载的程序
    • 通过串口输出切换信息

4.2 模块功能

  1. QSPI Flash控制模块

    • 初始化QSPI设备
    • 自动检测Flash容量
    • 从Flash读取程序到内存
  2. 程序加载与执行模块

    • 将程序从Flash加载到OCM
    • 执行加载的程序
    • 管理程序切换标志
  3. 定时器中断模块

    • 配置5秒定时器
    • 处理定时器中断
    • 触发程序切换
  4. 状态输出模块

    • 通过串口输出切换信息
    • 提供系统状态和错误信息

5. 需要调整的参数

根据实际项目需求,可能需要调整以下参数:

  1. 程序A偏移地址

    • 文件:CTRL_SYS/src/source/program_switch.c
    • 参数:program_a_offset
    • 当前值:0x00040000 (FSBL后的位置)
    • 说明:根据实际FSBL大小可能需要调整
  2. 程序大小

    • 文件:CTRL_SYS/src/source/program_switch.c
    • 功能:SwitchProgram()函数中的program_size
    • 当前值:1024 * 1024 (1MB)
    • 说明:根据实际程序大小调整
  3. 切换时间间隔

    • 文件:CTRL_SYS/src/source/program_switch.c
    • 功能:SetupProgramSwitchTimer()函数
    • 当前值:333000000 * 5 (5秒)
    • 说明:根据需要调整切换频率
  4. 加载地址

    • 文件:CTRL_SYS/src/source/program_switch.c
    • 参数:PROGRAM_LOAD_ADDR
    • 当前值:0xFFFF0000 (OCM区域)
    • 说明:根据实际内存布局可能需要调整

6. 前期准备工作

  1. 环境准备

    • 安装Xilinx Vivado 2018.3和SDK 2018.3
    • 配置Zynq开发板和JTAG调试器
  2. 程序准备

    • 准备两个独立的程序二进制文件 (位于bin文件夹)
    • 确保程序符合自立运行要求
  3. Flash准备

    • 确保QSPI Flash正常工作并有足够容量
    • 清除可能的现有程序干扰

7. 实际应用步骤

7.1 环境准备与项目打开

  1. 启动Xilinx Vivado 2018.3

    • 在Windows开始菜单中找到"Xilinx Design Tools" > "Vivado 2018.3" > "Vivado 2018.3"
    • 等待Vivado完全启动(显示开始页面)
  2. 导入硬件描述文件

    • 点击"Open Project"按钮
    • 导航到项目所在文件夹,选择.xpr项目文件,点击"OK"
    • 等待项目完全加载
  3. 导出硬件设计

    • 在Vivado主界面左侧"Flow Navigator"中,点击"Program and Debug" > "Generate Bitstream"
    • 如果出现提示,点击"Yes"运行所需的任何先前步骤
    • 等待比特流生成完成(可能需要几分钟)
    • 点击菜单"File" > "Export" > "Export Hardware..."
    • 选中"Include bitstream"复选框
    • 点击"OK"完成硬件平台导出
  4. 启动Xilinx SDK 2018.3

    • 在Vivado中,点击"File" > "Launch SDK"
    • 或者单独启动SDK:在Windows开始菜单中找到"Xilinx Design Tools" > "SDx 2018.3" > "Xilinx SDK 2018.3"
    • 如果单独启动,需要选择工作空间位置指向项目文件夹,点击"Launch"

7.2 添加程序切换功能实现

  1. 打开项目

    • 在SDK中,如果没有自动加载项目,点击"File" > "Open Projects from File System..."
    • 选择项目路径,点击"Finish"
  2. 创建新文件

    • 右击项目中的"src/include"文件夹,选择"New" > "File"

    • 命名为program_switch.h,点击"Finish"

    • 复制上面提供的program_switch.h内容到该文件

    • 保存文件(Ctrl+S)

    • 同样方式,右击"src/source"文件夹,创建program_switch.c文件

    • 复制上面提供的program_switch.c内容到该文件

    • 保存文件(Ctrl+S)

  3. 修改现有文件

    • 在项目浏览器中双击打开src/include/timer_intr.h

    • 按照前面描述的修改更新文件内容

    • 保存文件(Ctrl+S)

    • 双击打开src/source/main.c

    • 添加program_switch.h头文件包含语句

    • 在main函数中添加程序切换初始化代码

    • 保存文件(Ctrl+S)

  4. 编译项目

    • 点击顶部工具栏上的锤子图标(Build All)或按Ctrl+B
    • 等待编译完成,检查"Console"窗口中是否有错误信息
    • 如有错误,根据提示修复后重新编译

7.3 生成二进制文件

  1. 创建FSBL(第一阶段引导加载程序)

    • 点击"File" > "New" > "Application Project"
    • 输入项目名称(例如"fsbl")
    • 确保选择了正确的处理器和硬件平台
    • 点击"Next"
    • 选择"Zynq FSBL"模板
    • 点击"Finish"
    • 等待FSBL项目生成和编译完成
  2. 创建BOOT.bin文件

    • 点击"Xilinx" > "Create Boot Image"
    • 在"Output BIF file path"中选择保存路径
    • 确保"Output format"设置为"BIN"
    • 在"Boot image partitions"部分:
      • 添加FSBL.elf作为第一个文件(类型为bootloader)
      • 添加您的应用程序.elf文件作为第二个文件(类型为datafile)
    • 点击"Create Image"
  3. 导出二进制文件

    • 右击应用程序项目
    • 选择"Build Project"确保最新构建
    • 打开项目的Debug或Release文件夹
    • 找到生成的.elf文件
    • 右击项目,选择"Create Boot Image"
    • 配置启动镜像包括FSBL和您的应用程序
    • 点击"Create Image"生成BOOT.bin文件
  4. 准备独立二进制文件

    • 在SDK中,点击"Xilinx Tools" > "Create Zynq Boot Image"
    • 点击"Add"按钮,添加ELF文件
    • 对于"Partition type"选择"data"
    • 点击"OK",然后点击"Create Image"
    • 这将在指定位置生成.bin文件
    • 为两个程序分别执行此步骤,生成两个独立的bin文件
    • 将生成的bin文件复制到开发板上的bin文件夹

7.4 将程序烧录到QSPI Flash

  1. 连接硬件

    • 将Zynq开发板通过JTAG/USB线缆连接到计算机
    • 确保开发板电源已接通
    • 确保跳线配置为JTAG引导模式
  2. 启动Xilinx硬件服务器

    • 在SDK中,点击"Xilinx" > "Xilinx Hardware Server Settings"
    • 确认连接设置正确,点击"OK"
    • 如果未自动连接,点击"Refresh"按钮查找设备
  3. 打开SDK终端

    • 在SDK中,点击"Window" > "Show View" > "Terminal"
    • 在Terminal视图中,点击"+"按钮打开新终端
    • 选择"Serial Terminal"
    • 选择正确的COM端口(可在设备管理器中查看)
    • 设置波特率为115200,数据位8,停止位1,无校验
    • 点击"OK"
  4. 启动XSDB终端

    • 在SDK中,点击"Xilinx" > "XSDB Console"
    • 在XSDB控制台中输入以下命令连接到处理器:
      connect
      
    • 查看可用目标设备:
      targets
      
    • 选择Cortex-A9处理器(通常为目标2):
      targets 2
      
  5. 擦除QSPI Flash

    • 在XSDB中输入以下命令停止处理器:
      stop
      
    • 擦除整个QSPI Flash(这可能需要几分钟):
      fpga -f [path_to_bit_file]/design_1_wrapper.bit
      exec load_image {[path_to_fsbl]/fsbl.elf};
      after 5000
      rst
      exec {ps7_init}
      after 1000
      dow [path_to_fsbl]/fsbl.elf
      con
      after 5000
      stop
      
    • 现在Flash已准备好编程
  6. 烧录程序A

    • 在XSDB控制台中输入以下命令:
      dow -data [完整路径]/bin/programA.bin 0x00040000
      
    • 等待操作完成,确认没有错误信息
  7. 确定Flash容量并烧录程序B

    • 查看QSPI Flash信息确定总容量(通常是16MB或32MB)
    • 计算中点地址(例如16MB Flash的中点是0x00800000)
    • 烧录程序B到中点位置:
      dow -data [完整路径]/bin/programB.bin 0x00800000
      
    • 等待操作完成
  8. 验证烧录结果

    • 在XSDB中使用以下命令读取Flash内容并验证:
      rrd -bin [偏移地址] [长度] [输出文件路径]
      
    • 例如,验证程序A:
      rrd -bin 0x00040000 0x100000 verify_a.bin
      
    • 使用文件比较工具比较原始文件和读取文件
  9. 配置启动模式并重启系统

    • 配置开发板跳线为QSPI引导模式
    • 在XSDB中重启处理器:
      rst
      con
      
    • 或者,断开电源并重新连接

7.5 监控与测试

  1. 连接串口终端

    • 确保SDK Terminal已配置好(或使用Tera Term、PuTTY等终端软件)
    • 设置波特率:115200
    • 数据位:8
    • 停止位:1
    • 奇偶校验:无
    • 流控制:无
  2. 上电启动系统

    • 确保开发板设置为QSPI引导模式
    • 接通电源或按下复位按钮
  3. 观察串口输出

    • 系统启动后应看到以下信息:
      Initializing program switching functionality...
      Flash size: xx MB
      Program A offset: 0x00040000
      Program B offset: 0x00800000
      Program switch initialized successfully
      Initial program: Program A
      Initial program loaded successfully, executing...
      
  4. 验证程序切换

    • 等待约5秒钟,观察串口输出
    • 应看到以下消息表示切换到程序B:
      Timer triggered. Switching program...
      Switching to Program B
      Program loaded successfully, executing...
      
    • 再等待5秒,应看到切换回程序A
  5. 长时间测试

    • 让系统持续运行至少30分钟
    • 确认程序每5秒稳定切换
    • 观察是否有任何错误消息或异常行为
  6. 故障排查

    • 如果没有看到预期输出,检查串口连接和设置
    • 如果输出中断,检查电源稳定性
    • 如果程序未切换,确认QSPI Flash烧录成功
    • 如果出现错误消息,记录下来并检查相应代码逻辑

8. 注意事项

  1. 程序A和程序B需要设计为可重入,保证切换后系统状态一致
  2. 使用英文进行串口输出,确保信息正确显示
  3. 程序切换过程中可能暂时中断其他功能,需在设计中考虑
  4. 处理器缓存控制关键,确保程序加载后正确执行
  5. 实际Flash容量可能与检测结果不同,可能需要手动调整
  6. 项目路径不应包含中文字符,避免编译和烧录问题
  7. 确保使用的Vivado和SDK版本完全匹配(都是2018.3)
  8. 为避免意外断电导致数据丢失,建议使用稳定电源

文档版本:1.1
最后更新:2023年

闲来无事,记录琐事