为何启动文件需将.data与.bss段从Flash复制到SRAM?
为什么MCU启动时要把.data/.bss段从Flash复制到SRAM?
首先得明确MCU的两种核心存储介质的差异:
- Flash:非易失性存储,上电后内容保留,但读写速度慢,且不适合频繁随机写入(擦写寿命有限)。
- SRAM:易失性存储,掉电数据丢失,但读写速度极快,支持高效随机存取,是MCU运行时处理变量、临时数据的理想载体。
先看.data段:带初始值的全局/静态变量
.data段存储的是有明确初始值的全局变量、静态变量(比如int g_count = 5;)。
这些初始值会在编译烧录阶段被写入Flash(因为Flash能保存数据),但MCU运行时需要快速读写这些变量——总不能每次修改g_count都去Flash里操作,不仅速度慢,还会损耗Flash寿命。所以必须在启动阶段把Flash里的.data初始值复制到SRAM对应的区域,让程序后续直接操作SRAM里的变量。
再看.bss段:未初始化/初始值为0的全局/静态变量
.bss段存储的是未初始化或显式设为0的全局、静态变量(比如int g_temp;或者int g_flag = 0;)。
SRAM上电后内部是随机的脏数据,但C语言标准要求这类变量默认初始化为0。因为所有值都是0,没必要在Flash里占用存储空间存一堆0,所以启动阶段不需要复制数据,只需要把SRAM中.bss对应的区域全部清0即可——这一步和.data的复制同属启动初始化流程。
具体的复制/清0机制
编译链接时,链接器会自动生成几个关键地址符号(这些符号会被启动文件引用):
__data_start:SRAM中.data段的起始地址__data_end:SRAM中.data段的结束地址__data_load_start:Flash中.data初始值的存储起始地址__bss_start:SRAM中.bss段的起始地址__bss_end:SRAM中.bss段的结束地址
启动文件里的汇编代码会执行两个核心操作:
- 复制.data段:
通过循环将Flash中__data_load_start开始的数据,逐字节(或按字)复制到SRAM的__data_start区域,直到覆盖整个.data段。对应C逻辑大概是:char *src = (char*)__data_load_start; char *dest = (char*)__data_start; while (dest < __data_end) { *dest++ = *src++; } - 清0.bss段:
通过循环把SRAM中__bss_start到__bss_end的区域全部设为0。对应C逻辑大概是:char *bss_ptr = (char*)__bss_start; while (bss_ptr < __bss_end) { *bss_ptr++ = 0; }
这两步操作必须在main()函数执行前完成,否则程序用到的全局/静态变量会是错误值,直接导致逻辑异常。
内容的提问来源于stack exchange,提问作者Sudhir Patel
相关产品推荐
相关产品推荐

