Apollo V2 QSPI Flash XIP 设计说明

工程参考

ReturnDY/ApolloH743QSPI_FLASH_XIP

目标

在阿波罗 V2 STM32H743 开发板上,将应用程序存放在板载 W25Q256 QSPI Flash 中,并直接从外部 Flash 执行(XIP,Execute In Place)。

MCU 上电后,内部 Flash 中的 Bootloader 初始化 QSPI,开启 memory-mapped 模式,然后跳转至外部 Flash 中的应用。

存储布局

区域 地址范围 用途
STM32 内部 Flash 0x08000000 Bootloader、上电复位入口
QSPI 映射窗口 0x90000000 - 0x91FFFFFF W25Q256,32 MiB
QSPI 镜像元数据 0x90000000 - 0x9000FFFF magic、版本、长度、CRC、升级状态
QSPI XIP 应用 0x90010000 应用向量表、代码、只读常量、.data 初值
AXI SRAM 0x24000000 应用 .data.bss、堆、栈

应用起始地址必须在以下四处完全一致:

  1. XIP 应用 Scatter 文件中的 LR_XIP 0x90010000

  2. Keil Flash Download 中应用镜像的下载地址。

  3. Bootloader 中的 APP_XIP_BASE

  4. 跳转前写入 SCB->VTOR 的向量表地址。

三类构建产物

产物 链接地址 下载位置 作用
Bootloader 0x08000000 STM32 内部 Flash 初始化硬件并启动应用
XIP 应用 0x90010000 W25Q256 QSPI Flash 直接从 QSPI 执行
W25Q256.FLM Keil 临时装入 SRAM 不保留在产品中 擦除、写入 QSPI Flash

Bootloader 与 XIP 应用应使用两个 Keil Target,或使用两个独立工程;两者各自使用独立 Scatter 文件。

Scatter 文件只在链接期由编译器使用,MCU 运行时不会读取 Scatter 文件。

Keil 下载算法

Keil 下载程序时,会将 Flash Algorithm 临时装入 MCU SRAM 并调用其接口擦写 Flash。下载结束后,.FLM 不会留在 MCU 或 QSPI Flash 中。

Bootloader 一般使用 Keil 自带的 STM32H743 内部 Flash 下载算法。XIP 应用需要自定义 W25Q256.FLM,并在 Keil 的 Flash Download 设置中选中。

外部 Flash 下载算法至少实现:

 int Init(unsigned long adr, unsigned long clk, unsigned long fnc);
 int UnInit(unsigned long fnc);
 int EraseSector(unsigned long adr);
 int ProgramPage(unsigned long adr, unsigned long sz, unsigned char *buf);
 int EraseChip(void);

针对 W25Q256,算法需要自行完成 QSPI/GPIO 初始化、写使能、忙等待、4 KiB 扇区擦除、256 字节分页写入和读回校验。Flash 基地址定义为 0x90000000,容量为 0x02000000,擦除扇区粒度为 4 KiB。

生成 W25Q256 下载算法 FLM

本项目的下载算法工程位于:

 *\keli5\ARM\flash\<QSPI_FLASH>\NewDevice.uvprojx

它不是 XIP 应用工程。Keil 下载时会把它临时复制到 MCU SRAM 中执行,所以 FLM 的 Scatter 文件不能使用 LR_XIP。工程必须包含以下源文件:

 FlashPrg.c        FlashOS 调用入口:Init、EraseSector、ProgramPage 等
 FlashDev.c        FlashDevice 描述:名称、地址、容量、扇区大小
 qspi_w25q256.c    与 HAL/CubeMX 无关的 QSPI 硬件与 W25Q256 驱动
 FlashStk.s        下载算法 SRAM 栈大小(当前 0x400)

FlashDev.c 中的设备范围必须与目标芯片一致:

 EXTSPI,
 0x90000000,       /* Flash 映射起始地址 */
 0x02000000,       /* W25Q256:32 MiB */
 0x001000, 0x000000, /* 4 KiB 扇区 */

Options for Target -> Linker 中选择 Target.lin

其内容如下。PRG 0 PI 表示下载算法以位置无关形式组织,Keil 会把它装入 SRAM;DSCR 区域保存 FlashDevice 描述,供 Keil 识别算法支持的地址范围。

 PRG 0 PI
 {
     PrgCode +0 { * (+RO) }
     PrgData +0 { * (+RW,+ZI) }
 }
 ​
 DSCR +0
 {
     DevDscr +0 { FlashDev.o }
 }

Options for Target -> Linker -> Misc Controls 中加入:

 --keep FlashDevice

否则链接器可能删除未被普通 C 调用引用的 FlashDevice 描述,生成的文件无法作为 Flash Algorithm 使用。

Options for Target -> Output 中:

  • 勾选 Create Executable

  • Output Name 设置为 STM32H743_W25Q256

  • 不需要生成 HEX 或 BIN。

Options for Target -> User -> After Build/Rebuild 中勾选 Run User Program 1,命令为:

 cmd.exe /C copy "Objects\%L" ".\@L.FLM"

Keil 首先生成 Objects\STM32H743_W25Q256.axf。上述命令把这个符合 FlashOS Scatter 布局的 AXF 复制为:

 D:\keli5\ARM\QSPI_FLASH\STM32H743_W25Q256.FLM

构建成功后,将 FLM 放入 Keil 算法目录:

*\keli5\ARM\Flash\STM32H743_W25Q256.FLM

在 XIP 应用工程中选用 FLM

打开 XIP 应用工程的 Options for Target -> Utilities -> Settings -> Flash Download。点击 Add,在弹窗中选中 W25Q256 QSPI Flash (32MB) 后,必须再点击弹窗右下角的 Add。返回上一窗口后,Programming Algorithm 列表应实际出现以下范围:

W25Q256 QSPI Flash (32MB)    0x90000000 - 0x91FFFFFF

只在弹窗中选中算法但未点击 Add 不会把算法加入工程,会导致下载日志出现:

No Algorithm found for: 90000000H

XIP 应用项目不应保留 STM32H7x_2048 片内 Flash 算法。Bootloader 工程仍使用该片内 Flash 算法;XIP 应用工程只使用 W25Q256 QSPI Flash (32MB)

当前已实现的最小 XIP 配置将应用向量表放在 0x90000000。本文前述 0x90010000 是为未来 64 KiB 镜像元数据预留的布局。若采用该预留布局,必须同步修改 XIP Scatter、Boot 的应用基址与 VTOR;不能只修改其中一处。

两份 Scatter 文件

Bootloader

Bootloader 是普通内部 Flash 程序,向量表和代码位于 0x08000000,可写数据、堆和栈位于 SRAM。

LR_BOOT 0x08000000 0x00020000
{
    ER_BOOT 0x08000000 0x00020000
    {
        *.o (RESET, +First)
        *(InRoot$$Sections)
        .ANY (+RO)
    }

    RW_RAM 0x24000000 0x00080000
    {
        .ANY (+RW +ZI)
    }
}

XIP 应用

应用的代码和只读常量位于 QSPI,所有可写数据位于 SRAM:

LR_XIP 0x90010000 0x01000000
{
    ER_XIP 0x90010000 0x01000000
    {
        *.o (RESET, +First)
        *(InRoot$$Sections)
        .ANY (+RO)
    }

    RW_AXI 0x24000000 0x00080000
    {
        .ANY (+RW +ZI)
    }
}

应用启动代码会将 .data 初值从 QSPI 复制至 SRAM,并清零 .bss;流程与普通 Flash 应用相同,只是代码存储区由内部 Flash 变成 QSPI Flash。

运行流程

上电复位
  -> STM32 Boot ROM 根据 BOOT 配置从内部 Flash 启动
  -> Bootloader 的 Reset_Handler(0x08000000)
  -> 配置时钟、MPU/Cache、QSPI GPIO 和 W25Q256
  -> QSPI 进入 memory-mapped 模式
  -> 校验 QSPI 应用的镜像头、向量表和 CRC
  -> 设置 VTOR 为 0x90010000,跳转到应用 Reset_Handler
  -> 应用直接从 QSPI 执行

Bootloader 必须在读取 0x90010000 前完成 W25Q256 QE 位、四字节地址模式与 QSPI memory-mapped 读模式配置。

Bootloader 跳转应用

这里是普通跳转,不是硬件复位。因此 QSPI 的 GPIO、时钟和 memory-mapped 配置都会保留。

#define APP_XIP_BASE 0x90010000UL

typedef void (*app_entry_t)(void);

static void boot_jump_to_xip_app(void)
{
    uint32_t msp = *(volatile uint32_t *)APP_XIP_BASE;
    uint32_t reset = *(volatile uint32_t *)(APP_XIP_BASE + 4U);

    __disable_irq();
    SysTick->CTRL = 0;
    SysTick->LOAD = 0;
    SysTick->VAL = 0;

    for (uint32_t i = 0; i < 8U; i++)
    {
        NVIC->ICER[i] = 0xFFFFFFFFU;
        NVIC->ICPR[i] = 0xFFFFFFFFU;
    }

    SCB->VTOR = APP_XIP_BASE;
    __DSB();
    __ISB();
    __set_MSP(msp);
    ((app_entry_t)reset)();
}

跳转前至少校验:MSP 位于有效 SRAM、Reset Handler 的 Thumb 位有效(reset & 1U)、Reset Handler 位于 QSPI 应用范围内、镜像 CRC 正确。

XIP 应用不得重新初始化、反初始化、复位 QSPI,也不得退出 QSPI memory-mapped 模式。应用启动代码应继续保持:

SCB->VTOR = 0x90010000UL;

NVIC_SystemReset()、看门狗复位、NRST 或掉电复位会丢失 QSPI 配置。此时 MCU 会重新进入内部 Flash Bootloader,Bootloader 再次初始化 QSPI 后跳转应用。

MPU 与 Cache

0x90000000 映射区必须配置为可执行的 Normal Memory。XIP 常规读操作建议启用 Cache 以获得性能。

擦写 QSPI 后、重新读取或执行新内容前,需要进行 Cache 维护:

SCB_InvalidateICache();
SCB_InvalidateDCache();
__DSB();
__ISB();

XIP 运行时更新限制

应用从 QSPI 执行期间,不能安全擦写同一颗 QSPI Flash。擦写前必须退出 memory-mapped 模式,而这会使 CPU 无法从 QSPI 取指。

第一版建议由内部 Flash Bootloader 执行所有 QSPI 镜像更新;XIP 应用只运行,不写自身所在的 QSPI Flash。

若以后确实需要应用在线更新,以下内容必须全部放入 SRAM:

  • 擦除、写入函数及其所有调用函数;

  • 这些函数使用的字符串、常量、查找表;

  • 向量表和可能触发的 ISR,或在更新期间全局关闭中断;

  • 栈和运行期间使用的 DMA 描述符。

完成擦写后重新进入 memory-mapped 模式,失效 Cache,之后才能恢复 XIP 执行。

当前阶段边界

  • 不要把 Bootloader 与 QSPI 应用链接成一个普通镜像。

  • 不要在 XIP 应用中调用 CubeMX 生成的 MX_QUADSPI_Init()

  • 不要把 Keil .FLM 当作产品 Bootloader。

  • 不要让镜像元数据区与可执行代码区重叠。

  • A/B 分区、回滚、签名与在线升级应在基础 XIP 启动验证成功后再加入。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐