3. STM32固件烧录基础:固件文件格式、烧录原理与Flash编程
在进入STM32CubeProgrammer的实操之前,必须先建立对固件烧录底层逻辑的清晰认知。很多初学者在烧录失败时往往归咎于工具问题,而实际上,超过60%的烧录异常源于固件文件格式选择错误、存储器地址配置不当或对Flash编程约束理解不足。本章将围绕固件文件格式(HEX、BIN、ELF)、烧录原理、存储器映射与Flash编程基础四个核心维度展开,帮助您建立从“文件”到“硅片”的完整知识链路。
3.1 固件文件格式:HEX、BIN与ELF的深度对比
3.1.1 核心原理:三种格式的本质差异
固件文件本质上是“程序数据+元信息”的编码载体。STM32开发中最常接触的三种格式各有其设计目标:HEX(Intel HEX)是文本格式,每行以冒号开头,包含长度、地址、类型、数据和校验和,它自带地址映射信息,适合分段烧录;BIN(Binary)是原始内存映像,没有任何地址信息,烧录时必须由工具或用户指定起始地址;ELF(Executable and Linkable Format)是编译器直接输出的格式,包含段表、符号表、调试信息,但STM32CubeProgrammer通常需要将其转换为HEX或BIN后再烧录。
| 特性 | HEX | BIN | ELF |
|---|---|---|---|
| 编码方式 | ASCII文本 | 纯二进制 | 二进制+结构头 |
| 地址信息 | 每行记录地址 | 无,需外部指定 | 段表包含虚拟地址 |
| 校验机制 | 每行1字节校验和 | 无内置校验 | 无内置校验 |
| 调试符号 | 不支持 | 不支持 | 完整支持 |
| 烧录方式 | 按地址逐段写入 | 连续写入 | 需转换后烧录 |
| 典型大小 | 比BIN大约2倍 | 最小 | 最大(含调试信息) |
3.1.2 判断方法:如何选择正确的文件格式
选择文件格式应遵循以下原则:量产烧录优先使用HEX,因为其自带地址和校验,可避免地址错位;OTA升级或固件合并场景使用BIN,因为其体积小且便于拼接;调试阶段使用ELF,配合IDE进行源码级调试。在STM32CubeProgrammer中,如果加载BIN文件,必须手动填写起始地址(如0x08000000),否则工具会默认从0x00000000开始写入,导致程序无法启动。
Read功能备份原始固件。
3.1.3 案例拆解:HEX文件解析实战
以下是一段典型的HEX文件内容(STM32F103的启动代码片段):
:020000040800F2
:1000000000040020E5010008ED010008F1010008
:10001000F5010008F9010008FD01000801020008
:0400000508000001FE
:00000001FF
逐行解析:第一行:020000040800F2表示扩展线性地址记录,将基地址设为0x0800;第二行:10000000...是数据记录,从0x08000000开始写入16字节数据(即初始堆栈指针和复位向量);最后一行:00000001FF是文件结束标志。通过这种结构,烧录工具可以精确地将数据写入指定Flash地址。
3.1.4 常见误区与复盘
- 误区一:认为BIN文件比HEX“更高级”。实际上BIN只是HEX的数据部分,缺少地址和校验。
- 误区二:直接烧录ELF文件。STM32CubeProgrammer虽然支持ELF,但会丢弃调试信息,且部分版本对ELF的段处理有兼容性问题。
- 复盘建议:在工程配置中,同时生成HEX和BIN文件(Keil中勾选"Create HEX File",IAR中设置输出格式),根据场景灵活选用。
3.2 烧录原理:从文件到Flash的完整链路
3.2.1 核心原理:烧录的四个阶段
无论使用何种工具,固件烧录都遵循“连接→解析→擦除→编程→校验”的流程。以STM32CubeProgrammer通过SWD接口烧录为例:首先,工具通过SWD协议读取目标芯片的IDCODE,确认芯片型号;然后解析固件文件,提取地址和数据;接着按扇区擦除Flash(STM32的Flash必须按扇区擦除,不能按字节擦除);之后执行编程操作,将数据写入Flash;最后回读数据与源文件比对,完成校验。
3.2.2 判断方法:烧录接口的选择依据
| 接口 | 速度 | 适用场景 | 注意事项 |
|---|---|---|---|
| SWD | 4-10 MHz | 开发调试、量产 | 仅需2线(SWDIO/SWCLK) |
| JTAG | 10-50 MHz | 复杂调试 | 占用引脚多,速度更快 |
| UART Bootloader | 115200-921600 | 无调试器场景 | 需BOOT0拉高,使用USART1/2 |
| USB DFU | USB Full Speed | 产品升级 | 需芯片支持USB DFU类 |
| CAN Bootloader | 1 Mbps | 汽车电子 | 需自定义协议 |
3.2.3 案例拆解:SWD烧录失败排查
场景:某工程师使用STM32CubeProgrammer通过ST-Link烧录STM32G474,点击“Connect”后提示Error: Connection error (target not found)。
排查过程:①检查ST-Link驱动是否正常(设备管理器识别);②测量目标板供电(3.3V正常);③检查SWDIO/SWCLK接线(发现SWCLK虚焊);④重新焊接后连接成功。此案例说明,烧录链路中任何一环(工具、线缆、目标板供电、复位电路)异常都会导致连接失败。
Connect under reset模式。
3.2.4 常见误区与总结
- 误区:认为烧录速度越快越好。过高的SWD时钟(如超过10MHz)在长线缆或高阻抗环境下容易出错。
- 误区:忽略“校验”步骤。量产时务必开启校验,防止因Flash写入异常导致的不良品流出。
- 总结:烧录原理的核心是“地址映射+擦写时序”,理解这一点后,无论使用何种工具都能快速定位问题。
3.3 存储器映射与Flash编程基础
3.3.1 核心原理:STM32的存储器布局
STM32采用ARM Cortex-M内核的统一编址方式,Flash起始地址固定为0x08000000,SRAM起始地址为0x20000000。以STM32F103C8T6为例,其Flash容量为64KB(0x08000000-0x0800FFFF),SRAM为20KB(0x20000000-0x20004FFF)。系统存储器(0x1FFF0000)中固化了出厂Bootloader,用于UART/USB/DFU烧录。选项字节(Option Bytes)区域则用于配置读保护、写保护、硬件看门狗等。
3.3.2 判断方法:Flash编程的关键参数
- 扇区大小:不同系列差异很大。F1系列为1KB/扇区,F4系列为16KB/扇区(前4个)和128KB/扇区(后续),G4系列为2KB/扇区。
- 编程粒度:STM32 Flash支持半字(16位)编程,部分系列支持双字(64位)或突发编程。
- 擦除时间:典型扇区擦除时间约20-40ms,全片擦除约1-2秒。
- 编程电压:内置电荷泵,无需外部VPP,但VDD必须稳定在2.0-3.6V。
3.3.3 案例拆解:Flash写入导致程序跑飞
背景:某产品需要在运行时保存校准参数到Flash最后2KB(0x0800F800-0x0800FFFF)。工程师直接调用HAL_FLASH_Program写入数据,但写入后程序立即跑飞。
分析:查看链接脚本发现,中断向量表位于0x08000000,而代码段占用了0x08000000-0x0800F7FF。问题在于:①写入地址虽然正确,但未先擦除扇区(Flash只能从1写0,不能从0写1);②写入过程中发生了中断,而Flash编程期间CPU暂停取指,导致中断处理异常。
解决方案:①在写入前先调用HAL_FLASH_Unlock并擦除目标扇区;②在编程期间关闭所有可屏蔽中断(使用__disable_irq());③写入完成后重新使能中断并锁定Flash。
HAL_FLASH_Unlock();
__disable_irq();
FLASH_Erase_Sector(FLASH_SECTOR_7, VOLTAGE_RANGE_3); // 擦除最后一个扇区
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, 0x0800F800, data);
__enable_irq();
HAL_FLASH_Lock();
3.3.4 常见误区与复盘
- 误区一:忽略Flash写保护。如果选项字节中启用了写保护(RDP级别1),任何调试工具都无法读取或写入Flash,必须先解除保护(会触发全片擦除)。
- 误区二:在Flash编程期间喂狗或处理中断。这会导致编程失败或数据损坏。
- 复盘:设计Flash存储方案时,应预留至少一个扇区作为“双备份”区域,防止写入中途断电导致数据丢失。同时,建议在应用层增加CRC校验,确保写入数据的完整性。