GCC链接脚本如何实现.bss段自动拆分到两块不连续SRAM区域
GCC链接器自动拆分BSS段到多SRAM区域实现方案
核心实现原理
GNU Binutils 2.36及以上版本新增了非连续内存区域段分配支持,允许链接器自动将单个逻辑段的内容优先分配到指定内存区域,容量不足时自动溢出到其他指定内存区域,无需人工拆分变量或目标文件。
步骤1:配置链接脚本MEMORY区域
首先在链接脚本中按优先级顺序定义两块SRAM内存区域,优先分配的小容量SRAM放在前面:
MEMORY { /* 16KB SRAM 放前面,优先分配BSS内容 */ SRAM1 (rw!x) : ORIGIN = 0x20000000, LENGTH = 16K /* 96KB SRAM 作为溢出存储区域 */ SRAM2 (rw!x) : ORIGIN = 0x20040000, LENGTH = 96K }
步骤2:编写自动溢出的BSS段定义
在链接脚本的段定义部分,按如下方式配置BSS段:
SECTIONS { /* 其他段(.text、.data等)定义保持不变 */ .bss (NOLOAD) ALIGN(4) : { __bss_sram1_start = .; /* 匹配所有BSS类型变量 */ *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON) . = ALIGN(4); __bss_sram1_end = .; } > SRAM1 .bss (NOLOAD) ALIGN(4) : { __bss_sram2_start = .; /* 自动匹配SRAM1放不下的剩余BSS变量 */ *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON) . = ALIGN(4); __bss_sram2_end = .; } > SRAM2 /* 其他段定义保持不变 */ }
步骤3:添加必要链接参数
在编译链接选项中添加以下参数,开启非连续段分配支持:-Wl,--enable-non-contiguous-regions -Wl,--sort-section=alignment
--enable-non-contiguous-regions:允许单个逻辑段分布在多个不连续的内存区域--sort-section=alignment:按变量对齐值从小到大排序分配,最大化内存利用率,减少碎片
步骤4:修改启动代码BSS清零逻辑
由于BSS段现在分布在两个不连续的内存区域,需要修改启动代码中的BSS清零逻辑,分别清零两个区域的BSS内容:
#include <stdint.h> /* 链接脚本导出的符号 */ extern uint8_t __bss_sram1_start[]; extern uint8_t __bss_sram1_end[]; extern uint8_t __bss_sram2_start[]; extern uint8_t __bss_sram2_end[]; void bss_init(void) { /* 清零SRAM1区域的BSS */ for (uint8_t *p = __bss_sram1_start; p < __bss_sram1_end; p++) { *p = 0; } /* 清零SRAM2区域的BSS */ for (uint8_t *p = __bss_sram2_start; p < __bss_sram2_end; p++) { *p = 0; } }
兼容性说明
如果使用的Binutils版本低于2.36,原生不支持自动溢出分配,建议升级Binutils到2.36或以上版本即可直接使用上述方案。
内容的提问来源于stack exchange,提问作者ckain
相关产品推荐
相关产品推荐

