Nordic nRF Connect SDK链接脚本疑问:__ramfunc_size未定义却生效?
链接脚本中提前引用__ramfunc_size却正常工作的解惑
问题背景与疑问
MPU所用内存段需满足两个要求:
- 段起始地址必须与段大小对齐
- 段大小必须是2的幂(如32、64、1024等)
以下代码取自Nordic_nRF_Connect_SDK\v2.4.2\zephyr\arch\common\ramfunc.ld,经测试可成功实现符合MPU要求的对齐,但存在疑问:在.ramfunc段定义中,前后两次调用MPU_ALIGN(__ramfunc_size)时,__ramfunc_size是在段定义外后续才通过__ramfunc_end - __ramfunc_start计算得到的。若按链接脚本逐行顺序解析的认知,此时__ramfunc_size应为0,但实际项目中代码却能正常工作,恳请解惑。
相关代码
#define MPU_ALIGN(region_size) \ . = ALIGN(_region_min_align); \ . = ALIGN( 1 << LOG2CEIL(region_size))
SECTION_DATA_PROLOGUE(.ramfunc,,) { MPU_ALIGN(__ramfunc_size); __ramfunc_start = .; *(.ramfunc) *(".ramfunc.*") MPU_ALIGN(__ramfunc_size); __ramfunc_end = .; } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) __ramfunc_size = __ramfunc_end - __ramfunc_start;
解惑
链接器处理链接脚本并非单次逐行顺序执行,而是分多阶段完成整个链接过程,这是核心原因:
- 第一阶段:收集段内容与初步计算
链接器首先扫描所有输入目标文件,收集.ramfunc及其子段的所有内容,先确定__ramfunc_start和__ramfunc_end的初始位置(此时还未执行MPU对齐调整),并计算出__ramfunc_size的初步非零值。 - 第二阶段:基于实际大小完成对齐调整
拿到第一阶段得到的真实__ramfunc_size后,链接器会重新处理.ramfunc段中的MPU_ALIGN指令:- 先调整段起始地址,使其与
__ramfunc_size对齐,同时满足最小对齐要求_region_min_align - 放置完
.ramfunc段内容后,再调整段结束地址,确保最终的段大小是2的幂,且结束地址也符合对齐要求
- 先调整段起始地址,使其与
- 最终更新
完成对齐调整后,链接器会更新__ramfunc_end的最终值,并重新计算出符合MPU要求的__ramfunc_size。
简单来说,链接器会先“预估”出.ramfunc段的实际大小,再用这个大小去做对齐调整,最后确定最终的段地址和大小,而非严格按脚本的书写顺序单次执行。
内容的提问来源于stack exchange,提问作者pasu
相关产品推荐
相关产品推荐

