STM32MP1 系列(MP15x/MP13x)自举程序通过 USB DFU(Device Firmware Upgrade)和 USART 协议,实现非易失性存储器(NVM)的嵌入式编程,支持外部 Flash(NAND/NOR/eMMC/SD)、OTP、PMIC NVM 等器件的固件下载与烧录。本文基于 AN5275 应用笔记,拆解两种协议的核心配置、编程序列、指令集与实操要点,覆盖 “从复位编程” 和 “从 U-Boot 编程” 两大场景,助力快速落地编程服务。
资料获取:STM32MP1 系列自举程序中使用的 USB DFU/USART 协议
1. 协议核心概述
1.1 核心用途与支持范围
- 嵌入式编程服务:通过 STM32CubeProgrammer 工具,经 USB/USART 接口将二进制文件写入 NVM,涉及 ROM 代码、TF-A(FSBL)、U-Boot(SSBL)三级协同;
- 支持 NVM 类型:外部 Flash(NAND/NOR/eMMC/SD 卡)、片上 OTP、PMIC(如 STPMIC1)的 NVM;
- 适配系列:STM32MP15x(ROM 代码与 TF-A 共享 USB 描述符)、STM32MP13x(FSBL 阶段需重新枚举 USB)。
1.2 编程序列两大核心场景
- 场景 1:从复位编程(首次烧录):通过启动引脚选择外设,ROM 代码加载 TF-A→TF-A 初始化 DDR 并加载 U-Boot→U-Boot 解析布局文件并编程 NVM;
- 场景 2:从 U-Boot 编程(固件更新):已烧录器件通过按键、控制台指令或 Linux 重启模式进入编程模式,直接由 U-Boot 提供编程服务。
1.3 关键概念:阶段 ID(Phase ID)
阶段 ID 用于标识待下载的分区,是协议通信的核心标识,关键 ID 含义如下:
- 0x00:布局文件(TSV 格式,定义分区列表);
- 0x01:FSBL(TF-A),由 ROM 代码加载;
- 0x03:SSBL(U-Boot,含 FIP 映像),由 TF-A 加载;
- 0x10~0xF0:用户分区(uImage、dtb、rootfs 等);
- 0xF1:虚拟分区(用于 GetPhase/SetOffset 指令);
- 0xF2:OTP 分区;
- 0xF4:PMIC NVM 分区;
- 0xFE:操作结束;
- 0xFF:复位(错误时返回)。
2. USART 协议详解:串口编程实现
2.1 核心配置(ROM 代码默认设置)
- 波特率:115200;
- 数据格式:8 位数据位 + 1 位起始位 + 1 位停止位 + 偶校验(EVEN);
- 连接触发:ROM 代码扫描所有 USART_RX 引脚,接收 0x7F 数据帧后建立连接。
2.2 主循环与通信流程
- 主机发送 0x7F 触发 USART 连接;
- 主机通过 Get 指令获取支持的指令列表,再通过 GetPhase 获取当前阶段 ID;
- 按阶段 ID 下载对应映像(TF-A→U-Boot→布局文件→用户分区);
- 每包数据含校验和(字节异或),器件返回 ACK(0x79)、NACK(0x1F)或 ABORT(0x5F)响应;
- 所有分区下载完成后,发送 0xFE 标识操作结束,器件复位。
2.3 核心指令集(关键指令详解)
| 指令代码 | 指令名称 | 核心功能 | 响应格式要点 |
|---|---|---|---|
| 0x00 | Get | 获取自举程序版本与支持指令 | 含 ACK + 版本号 + 指令代码列表 + 尾 ACK |
| 0x02 | Get ID | 获取芯片 ID | 0x0500(MP15x)/0x0501(MP13x) |
| 0x03 | Get Phase | 获取下一个分区 ID | 含阶段 ID + 下载地址(0xFFFFFFFF 表示写入 NVM) + 附加信息 |
| 0x31 | Download | 下载映像到 RAM/NVM | 含数据包编号 + 数据块(最大 256 字节) + 校验和 |
| 0x12 | Read Partition | 读取分区数据 | 需指定分区 ID 与偏移量,返回最多 256 字节 |
| 0x21 | Start | 跳转到 RAM 执行代码或刷新 NVM | 地址为 0xFFFFFFFF 时完成 NVM 写入 |
3. USB DFU 协议详解:高速编程实现
3.1 协议基础(基于 DFU v1.1)
- 核心差异:DFU_DETACH 在 dfuIDLE 状态可接受,返回 appIDLE 模式;不支持 STM32 MCU 的 DFUSE 扩展;
- 核心优势:传输速率高于 USART,适合大容量映像(如 rootfs)烧录;
- 枚举特点:通过 “替代设置” 映射分区,每个替代设置对应一个阶段 ID。
3.2 关键概念:替代设置与虚拟分区
- 替代设置:USB 枚举时,每个分区对应一个替代设置,字符串描述符含分区 ID、大小、类型(E = 可写,A = 可读);
- 虚拟分区 0xF1:用于核心指令交互,支持:
- DFU_UPLOAD:获取 GetPhase 结果(阶段 ID、下载地址、偏移);
- DFU_DOWNLOAD:SetOffset(设置分区偏移)、Start(跳转到指定地址执行)。
3.3 编程序列(以 MP15x 为例)
- 器件上电,ROM 代码初始化 USB 并枚举为 DFU v1.1 设备;
- 主机通过替代设置 1 下载 TF-A(阶段 ID=0x01),器件进入 dfuMANIFESTSYNC 状态;
- TF-A 启动后恢复 USB 连接(无需重新枚举),主机下载 U-Boot(阶段 ID=0x03);
- U-Boot 初始化后,主机下载布局文件(阶段 ID=0x00),器件重新枚举并列出所有分区替代设置;
- 按替代设置依次下载用户分区,每完成一个分区执行 DFU 表现(刷新 NVM);
- 发送 0xFE 结束操作,器件复位。
3.4 核心指令交互(基于虚拟分区 0xF1)
| 指令类型 | 核心功能 | 数据格式 |
|---|---|---|
| DFU_UPLOAD | GetPhase:获取当前阶段 ID | 响应含阶段 ID + 下载地址 + 偏移 + 附加信息 |
| DFU_DOWNLOAD | SetOffset:设置分区偏移 | 数据含阶段 ID(0x00~0xF0) + 分区偏移(4 字节) |
| DFU_DOWNLOAD | Start:执行代码 | 数据含 0xFF + 目标地址(4 字节) |
4. 实操关键要点与避坑指南
4.1 布局文件(TSV 格式)
- 核心作用:定义分区列表,含阶段 ID、映像路径、目标 NVM、起始地址、大小;
- 示例字段:
PhaseID ImagePath NVMTarget Address Size; - 必须与阶段 ID 一一对应,否则会导致烧录失败。
4.2 映像预处理要求
- 加 STM32 头文件:MP15x 用版本 1(256 字节),MP13x 用版本 2(512 字节);
- 签名要求:封闭器件需用 SigningTool 签名,否则 ROM 代码拒绝执行;
- 校验要求:所有传输数据含异或校验和,主机需确保数据包完整性。
4.3 错误处理与兼容性
- 响应含义:ACK(0x79)= 成功,NACK(0x1F)= 数据错误(可重试),ABORT(0x5F)= 不可恢复错误(需复位);
- 系列差异:MP13x 在 ROM 代码与 TF-A 之间需重新枚举 USB,MP15x 无需;
- 调试技巧:通过 STM32CubeProgrammer 的 “-d” 选项指定映像,“-c” 指定通信接口(usart/usb)。
4.4 特殊分区操作
- OTP(阶段 ID=0xF2):仅支持特定字节写入,需通过 USART 的 Download 指令(数据包编号 = 0xF2)或 USB 替代设置 0xF2 操作;
- PMIC NVM(阶段 ID=0xF4):需确保 PMIC 与 MCU 通信正常,仅支持特定型号(如 STPMIC1)。
STM32MP1 的 USB DFU/USART 协议是自举程序编程的核心,核心逻辑可概括为 “阶段 ID 标识分区 + 三级自举协同 + 校验保障完整性”:
- USART 协议适合小容量映像、无 USB 接口场景,配置简单但速率较低;
- USB DFU 协议适合大容量烧录,速率快但需关注枚举与替代设置;
- 实操中需重点关注布局文件正确性、映像签名与校验,以及 MP15x/MP13x 的系列差异。
两种协议均兼容 STM32CubeProgrammer 工具,无需手动编写复杂通信代码,按阶段 ID 顺序下载即可完成 NVM 编程。
阅读全文
115