ld链接脚本中ROM_NOCOPY标记的含义及作用是什么
ld链接脚本中
ROM_NOCOPY标记的技术解析 ROM_NOCOPY的本质
ROM_NOCOPY不是GNU ld官方内置的原生关键字,是NXP等车规级MCU厂商在配套芯片SDK的链接脚本模板中自定义的段属性标记,核心作用是告知链接器、启动代码、镜像烧录工具:当前标记的段仅在链接地址空间做占位,不需要在最终烧录镜像中存储段的实际内容,也不需要芯片启动时从ROM拷贝初始化数据到对应的RAM地址。
你提供的脚本片段的实际行为
你之前的推测存在偏差,这段写法并没有把.data_core2_ea_QM输入段重复分配到两个输出段,实际逻辑如下:
.data_core2_ea_QM_ROM ROM_NOCOPY(.data_core2_ea_QM) :> INTERNAL_RAM_CORE2_EA_QM _data_core2_ea_QM_ROM_START = ADDR(.data_core2_ea_QM_ROM); _data_core2_ea_QM_ROM_LIMIT = ADDR(.data_core2_ea_QM_ROM) + SIZEOF(.data_core2_ea_QM_ROM); .data_core2_ea_QM ALIGN(4) : { _data_core2_ea_QM_START = .; *(.data_core2_ea_QM) . = ALIGN(4); _data_core2_ea_QM_END = . - 1; _data_core2_ea_QM_LIMIT = .; } > INTERNAL_RAM_CORE2_EA_QM
- 第一行定义的
.data_core2_ea_QM_ROM是虚拟占位段,和后面真实的.data_core2_ea_QM段大小完全一致、映射的RAM地址完全重叠,不会额外占用内存空间 - 后面的
.data_core2_ea_QM才是实际装载输入段、分配到INTERNAL_RAM_CORE2_EA_QMRAM区域的运行时实体段 - 占位段的唯一作用是导出首尾地址符号,供启动代码、功能安全校验逻辑识别该段的内存范围。
该写法的设计目的
这是车规嵌入式开发中针对*非初始化RAM段(NoInit段)*的标准处理方案,对应脚本中INTERNAL_RAM_CORE2_EA_QM这类RAM区域的特殊用途——这类区域一般用来存储跨复位保持数据、功能安全冗余校验数据、快速启动暂存数据,要求复位后不被启动代码擦写、保留原有内容:
- 普通可读写
.data段的标准流程是:段的初始值固化在ROM/Flash中,芯片启动时由启动代码把初始值拷贝到RAM的运行地址,未初始化的.bss段则由启动代码全部写0 - 加
ROM_NOCOPY标记后可以实现三个核心效果:- 缩小最终烧录镜像体积:不需要在ROM/Flash中预留空间存储该段的初始值
- 跳过启动初始化流程:启动代码遍历待拷贝、待清零的段列表时,会跳过标记了
ROM_NOCOPY的段,不修改对应RAM区域的原有数据 - 明确内存边界:导出的地址符号可以给内存保护单元(MPU)配置、ECC校验、内存越界检测逻辑使用,避免其他代码段意外占用这块特殊RAM区域。
补充说明
你在官方ld手册中查不到ROM_NOCOPY的定义属于正常情况:该标记属于芯片厂商自定义扩展,解析逻辑一般实现在芯片配套的启动汇编文件、镜像格式转换工具、Flash烧录工具中,不属于binutils工具链的原生语法范畴。从脚本中两个段都仅映射到RAM区域、无ROM/Flash区域映射的写法,也可以印证该段不需要ROM存储初始值的属性。
内容的提问来源于stack exchange,提问作者yan
相关产品推荐
相关产品推荐

