• 正文
  • 相关推荐
申请入驻 产业图谱

基于 STM32N6 从 eMMC 启动的 Load & Run 实现

09/29 17:24
304
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

STM32N6 没有内置主 Flash,依靠片上 BootROM 支持 SDCard、eMMC、XSPI‑NOR Flash 等多种外部存储启动。部分产品硬件只外接一片 eMMC 芯片,eMMC 同时存放 FSBL 一级引导程序、用户 APPLI 应用固件以及文件系统,需要采用Load & Run启动模式:FSBL 运行阶段将存放在 eMMC 里的 APPLI 拷贝到 MCU 高速内部 SRAM 中执行。

开发者使用 STM32CubeMX 开启EXTMEM_MANAGER外部存储器中间件生成 Load&Run 工程时会遇到障碍:官方中间件原生只提供 SDCard 驱动,没有现成 eMMC 驱动,直接选用 SDCard 驱动编译工程会报错。 LAT1706 给出一套复用 SDMMC 底层逻辑,基于现有 SDCard 驱动快速移植实现 eMMC 驱动的落地方案。本文完整还原问题背景、驱动实现步骤、关键代码修改点、硬件验证环节以及高频踩坑点。

资料获取:实战经验 | LAT1706 基于STM32N6从EMMC启动的Load & Run实现

1. 方案背景与问题说明

1.1 Load & Run 工作模式简述

Load&Run 是 STM32N6 重要启动模式:

  1. 上电,BootROM 从 eMMC 的 BOOT 分区加载签名合法的 FSBL 镜像拷贝进内部 SRAM,跳转执行 FSBL;
  2. FSBL 初始化 SDMMC 外设访问 eMMC 存储介质;
  3. FSBL 把存放在 eMMC 用户分区的 APPLI 应用固件搬运拷贝到 STM32N6 内部 SRAM;
  4. FSBL 完成跳转,应用在高速片上 SRAM 运行。

优势:应用代码在内部 SRAM 执行,访问延迟低,无需 XIP 外部映射;硬件设计仅用一颗 eMMC,兼顾固件存储与文件系统。

1.2 原生工程的报错根源

EXTMEM_MANAGER中间件用于统一管理外部存储器,支持 Load&Run 启动代码自动生成。该中间件内置驱动包含:XSPI、SDCard,官方没有直接提供 eMMC 驱动文件。 虽然 eMMC 与 SDCard 均由 SDMMC 硬件外设驱动,但二者协议、初始化流程存在差异,不能直接复用 SDCard 驱动实例;如果直接在 CubeMX 中选择 SDCard 驱动用于 eMMC 场景,编译直接报错,无法完成 FSBL 工程构建。

2. eMMC 驱动完整实现步骤

eMMC 与 SDCard 共用 STM32N6 的 SDMMC 硬件外设,因此可以参照 SDCard 的 sal 驱动架构,新增一套 MMC 驱动适配层。整套修改包含新增驱动源文件、修改 sdcard_driver 调度代码、工程实例句柄替换、增加 eMMC 上电复位四部分。

2.1 新增 stm32_sal_mmc 驱动文件

参考已有stm32_sal_sd.c / .h整套文件,新建 eMMC 对应的 3 个驱动文件:

  1. stm32_sal_mmc.c:eMMC SAL 层驱动实现
  2. stm32_sal_mmc_api.h:对外 API 头文件
  3. stm32_sal_mmc_type.h:数据类型定义头文件

文件结构和 sdcard 的 sal 驱动一一对应,宏定义EXTMEM_SAL_MMC用于条件编译控制该套驱动是否参与编译。

2.2 修改 stm32_sdcard_driver.c 调度入口

stm32_sdcard_driver.c是 EXTMEM_MANAGER 的统一调度层,内部使用Link链路类型区分接入的介质,新增EXTMEM_DRIVER_SDCARD_LINKMMC分支,对应 eMMC 设备。 以初始化函数EXTMEM_DRIVER_SDCARD_Init()为示例核心代码片段:

EXTMEM_DRIVER_SDCARD_StatusTypeDef EXTMEM_DRIVER_SDCARD_Init(void *Peripheral, EXTMEM_DRIVER_SDCARD_ObjectTypeDef *SDCARDObject)
{
  EXTMEM_DRIVER_SDCARD_StatusTypeDef retr = EXTMEM_DRIVER_SDCARD_OK;
  SDCARD_DEBUG_STR("initialize the instance");
  switch (SDCARDObject->sdcard_public.Link)
  {
#if EXTMEM_SAL_SD
    case EXTMEM_DRIVER_SDCARD_LINKSD :
      if (HAL_OK != SAL_SD_Init(&SDCARDObject->sdcard_private.SALObject.SDObject, Peripheral, &SDCARDObject->sdcard_private.Info))
        retr = EXTMEM_DRIVER_SDCARD_ERROR;
    break;
#endif

#if EXTMEM_SAL_MMC == 1
    case EXTMEM_DRIVER_SDCARD_LINKMMC:
      if( HAL_OK != SAL_MMC_Init(&SDCARDObject->sdcard_private.SALObject.MMCObject, Peripheral, &SDCARDObject->sdcard_private.Info))
        retr = EXTMEM_DRIVER_SDCARD_ERROR;
    break;
#endif

    default :
      retr = EXTMEM_DRIVER_SDCARD_ERROR_LINKTYPE;
      break;
  }
  return retr;
}

关键点:通过宏EXTMEM_SAL_MMC ==1做条件编译;Link类型设置为EXTMEM_DRIVER_SDCARD_LINKMMC代表当前接入设备是 eMMC。除 Init 初始化函数外,读、写等其余接口同样需要补充对应 case 分支。

2.3 工程实例句柄与链路类型修改

在 FSBL 工程中:

  1. 将 SD 卡实例句柄hsd1替换为 eMMC 句柄hmmc1;
  2. 在调用EXTMEM_MANAGER初始化时,链路参数配置为EXTMEM_DRIVER_SDCARD_LINKMMC,通知中间件当前访问介质为 eMMC。

完成以上修改后,编译报错问题消除。

2.4 必须增加 SDMMC 外设硬件复位(实测关键修复点)

BootROM 已经操作过 SDMMC 外设加载 FSBL,外设寄存器处于非复位状态,直接初始化 eMMC 会失败。 因此 FSBL 执行 eMMC 初始化代码之前,必须对 SDMMC 模块执行软件复位:

__HAL_RCC_SDMMC1_FORCE_RESET();
__HAL_RCC_SDMMC1_RELEASE_RESET();

这是调试中非常容易漏掉的一步,不加复位,FSBL 无法正常读取 eMMC,Load&Run 流程完全失败。增加复位之后,FSBL 才可以正常从 eMMC 读取 APPLI 固件拷贝到内部 SRAM 跳转运行。

3. 硬件验证环境

  • 硬件平台:STM32N6 Nucleo 开发板外接 eMMC 芯片;
  • 方案链路:BootROM 从 eMMC BOOT 分区加载 FSBL → FSBL 复位 SDMMC 外设 → 初始化 eMMC 驱动 → Load&Run 拷贝 APPLI 至内部 SRAM,跳转运行应用;
  • 参考附件:官方提供测试工程压缩包test_stm32n6_emmc_lrun.7z,可以作为移植参考。

4 工程落地排查清单(高频踩坑)

  1. 编译报错,找不到 SAL_MMC 相关符号
    • 核查EXTMEM_SAL_MMC宏是否置 1;确认stm32_sal_mmc.c文件已经添加进工程编译列表。
  2. 编译通过,FSBL 启动后 eMMC 初始化失败
    • 优先检查是否增加 SDMMC 外设 FORCE‑RESET/RELEASE‑RESET 复位代码;BootROM 已经操作 SDMMC,FSBL 必须先复位外设模块。
    • 核对实例句柄是否由hsd1修改为hmmc1;Link参数是否配置EXTMEM_DRIVER_SDCARD_LINKMMC。
  3. 可以初始化 eMMC,但是 Load&Run 读取 APP 数据失败
    • 确认 FSBL 镜像烧录到 eMMC BOOT 分区,用户 APPLI 固件烧录到 eMMC 普通用户分区;分区访问寄存器配置正确。
  4. 混淆 SDCard 与 eMMC 链路类型
    • 不要继续使用EXTMEM_DRIVER_SDCARD_LINKSD链路类型访问 eMMC,会出现协议层异常。

5. 小结

  1. STM32N6 EXTMEM_MANAGER中间件原生不支持 eMMC 驱动,但是 eMMC 和 SDCard 共用 SDMMC 硬件外设,可以复用 SDCard 的 SAL 驱动架构快速实现 eMMC 适配层。
  2. 实现要点:新增stm32_sal_mmc全套驱动文件,修改stm32_sdcard_driver.c增加EXTMEM_DRIVER_SDCARD_LINKMMCcase 分支;工程切换句柄与链路类型。
  3. 关键实操坑点:BootROM 已经操作 SDMMC 外设,FSBL 在初始化 eMMC 之前,必须执行 SDMMC 模块软件复位,否则 eMMC 初始化失败。
  4. 整套方案实现仅使用一颗 eMMC 芯片,既存放 FSBL、用户应用,又提供文件系统存储,适合成本敏感、硬件资源受限的 STM32N6 产品,完成完整 Load&Run 启动流程。

6. FAQ

Q:为什么不能直接使用 SDCard 驱动访问 eMMC?硬件是同一个 SDMMC 外设。 A:SD 卡与 eMMC 上电初始化协议流程、命令序列存在差异,直接复用 SDCard SAL 驱动会执行 SD 卡初始化序列,无法正确识别 eMMC 器件,因此需要独立 MMC‑SAL 适配层。

Q:SDMMC 复位这一步,CubeMX 生成代码为什么没有自动加上? A:CubeMX 生成的 HAL 初始化代码,是芯片冷复位条件下的初始化逻辑。STM32N6 场景,上电之后 BootROM 已经运行并操作过 SDMMC 外设,不是冷复位状态,因此需要用户在 FSBL 中手动增加模块复位。

Q:本方案是否可以直接用于 XIP(原地执行)模式? A:本文档方案针对 Load&Run(拷贝到 SRAM 运行);eMMC 本身不支持 XIP 原地执行,eMMC 只适合 Load&Run,XIP 需要 XSPI NOR‑Flash。

免责声明:本文全部内容基于 ST 官方 LAT1706 文档,实际项目移植以 ST 官方参考手册、附件样例工程为准。

相关推荐