在STM32中,BIN文件内需要加载到RAM的数据由链接脚本(Linker Script) 和启动代码(Startup Code)共同决定,具体机制如下:
一、BIN文件内容结构
STM32的BIN文件包含三类数据:
- Code:程序代码段(存储在Flash中直接执行,无需加载到RAM)
- RO-data:只读常量(如字符串常量,存储在Flash中)
- RW-data:已初始化的全局变量(需从Flash拷贝到RAM)
- ZI-data :未初始化或初始化为0的全局变量(仅需在RAM中预留空间并清零)
- 关键特性:BIN文件中不包含ZI-data,因其内容全为0,仅记录其大小信息。
二、加载逻辑的核心------链接脚本
链接脚本通过定义存储区域划分,明确哪些数据需加载到RAM:
-
存储域(Load Region)与执行域(Execution Region)
- 存储域定义代码/数据在Flash中的存储位置
- 执行域定义运行时数据在RAM中的位置
cppLR_IROM1 0x08000000 { ; Flash存储域 ER_IROM1 0x08000000 { ; 代码段执行域(Flash) *.o (RESET, +RO) ; 代码和只读数据 } RW_IRAM1 0x20000000 { ; RAM执行域 *.o (+RW +ZI) ; 需加载到RAM的读写数据 } }
-
特殊段标记
使用
section
属性显式指定函数/变量到RAM区域:cpp__attribute__((section("RAMCODE"))) void Fast_ISR(void) { // 高频中断服务函数(需在RAM中运行) }
三、启动代码的加载操作
启动代码(如startup_stm32xxx.s
)在main()
执行前完成RAM数据加载:
-
初始化堆栈指针(MSP)
从Flash的起始地址(如
0x08000000
)获取初始栈顶地址(__initial_sp
)。 -
复制RW-data到RAM
cppLDR R0, =_sidata ; Flash中RW-data的源地址 LDR R1, =_sdata ; RAM中RW-data的目标地址 LDR R2, =_edata CopyDataLoop: LDR R3, [R0], #4 STR R3, [R1], #4 CMP R1, R2 BNE CopyDataLoop
-
初始化ZI-data为零
cppLDR R0, =_sbss ; ZI-data起始地址 LDR R1, =_ebss ZeroLoop: MOV R2, #0 STR R2, [R0], #4 CMP R0, R1 BNE ZeroLoop
四、动态加载机制
在Bootloader或自定义加载场景中,可通过以下方式扩展:
-
外部存储加载
从SD卡/SPI Flash读取BIN文件到SDRAM,跳转执行(需配置内存映射)。
-
运行时重定位
使用分散加载文件的
FIXED
属性强制指定代码在RAM中的固定地址:cppER_RAMCODE 0x20000000 FIXED { ; 强制代码在RAM中运行 *.o (RAMCODE) }
五、调试与验证方法
-
查看.map文件
检查符号地址(如
_sdata
、_sbss
)确认数据段分配。 -
逻辑分析仪抓取时序
观测Flash到RAM的数据传输过程。
总结流程

STM32通过链接脚本定义数据归属 ,由启动代码实现物理搬运,最终完成RAM数据加载。