STM32下ARM GCC链接脚本:实现RAM内.data区重复初始化
解决方案:ARM GCC链接脚本修改实现RAM内.data初始值复制
1. 调整MEMORY区域定义
确保RAM区域有足够空间容纳程序(.text)、.data初始值区(.data_init)、实际.data区以及.bss区。以STM32F4系列芯片为例,RAM配置示例如下:
MEMORY { RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K // 根据实际芯片RAM大小调整 }
2. 定义独立的.data初始值段
在SECTIONS块中,先创建.data_init段专门存放.data变量的初始值(驻留RAM独立区域),再定义实际运行的.data段,通过加载地址(LMA)关联到.data_init,同时导出启动代码需要的关键符号:
SECTIONS { /* 程序代码段,放在RAM起始位置 */ .text : { . = ALIGN(4); KEEP(*(.isr_vector)) /* 中断向量表 */ *(.text) /* 程序代码 */ *(.text*) /* 其他代码段 */ *(.glue_7) /* 链接器生成的代码 */ *(.glue_7t) . = ALIGN(4); _etext = .; /* 程序代码结束地址 */ } >RAM /* .data变量的初始值存储段,放在.text之后的RAM区域 */ .data_init : { . = ALIGN(4); _sidata = .; /* 初始值区起始地址 */ *(.data) /* 将.data的初始值存入此段 */ *(.data*) . = ALIGN(4); _eidata = .; /* 初始值区结束地址 */ } >RAM /* 实际运行的.data段,放在.data_init之后的RAM区域 */ .data : AT(_sidata) /* 指定加载地址为.data_init的起始 */ { . = ALIGN(4); _sdata = .; /* .data段运行时起始地址 */ *(.data) /* 运行时变量的实际存储位置 */ *(.data*) . = ALIGN(4); _edata = .; /* .data段结束地址 */ } >RAM /* BSS段,未初始化变量,放在.data之后 */ .bss : { . = ALIGN(4); _sbss = .; *(.bss) *(.bss*) *(COMMON) . = ALIGN(4); _ebss = .; } >RAM /* 栈和堆的定义,按需调整预留空间 */ _estack = ORIGIN(RAM) + LENGTH(RAM); _heap_start = _ebss; _heap_end = _estack - 0x400; /* 预留栈空间,可根据需求修改 */ }
3. 验证启动代码的复制逻辑
启动文件中的.data复制逻辑无需修改,因为核心逻辑仍是从_sidata复制数据到_sdata直到_edata,只是现在两个地址都位于RAM的不同区域:
/* 启动代码中的.data复制片段示例 */ uint32_t *pSrc = &_sidata; uint32_t *pDest = &_sdata; while(pDest < &_edata) { *pDest++ = *pSrc++; }
关键说明
.data_init与.data段同属RAM但地址不重叠:前者存初始值,后者是运行时变量的实际存储区;- 通过
AT(_sidata)指定.data段的加载地址,链接器会自动将.data变量的初始值打包到.data_init段; - 需确保RAM总容量能容纳所有段:.text + .data_init + .data + .bss + 栈 + 堆的总和不能超过芯片RAM的实际大小。
内容的提问来源于stack exchange,提问作者cyclone125
相关产品推荐
相关产品推荐

