You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GCC绝对地址数据放置及与ROM的潜在冲突问题咨询

关于Flash地址保留与链接器行为的问题

问题背景

我的设备ROM地址0x08016F11处预存了4字节数据,通过以下代码绑定绝对地址访问数据:

/* C应用代码 */
__attribute__((section(".noinit"))) extern const uint32_t __TESTVALUE__; // __TESTVALUE__ 在.ld脚本中定义

// 访问__TESTVALUE__即可获取0x08016F11地址的值
/* GCC链接脚本 */
MEMORY
{
  ROM (rx)  : ORIGIN = 0x08000000,  LENGTH = 1024K
}
PROVIDE(__TESTVALUE__= 0x08016F11); /* 供C代码使用 */

SECTIONS
{
    .isr_vector:
    {
        /* 代码内容 */
    } > ROM
    .text:
    {
        /* 代码内容 */
    } > ROM
    
    /*...*/
}

当前代码可正常访问目标数据,但存在疑问:该地址属于ROM区域,链接器是否可能将.text等其他ROM段内容放置到0x08016F11地址,从而覆盖原有数据?仅通过PROVIDE指定该地址,链接器是否知晓需跳过此处?

若存在覆盖风险,除了在链接脚本中拆分ROM区域外,是否有其他方法可告知链接器保留该Flash地址范围?

问题总结

  1. 链接器是否可能覆盖0x08016F11地址的数据?
  2. 若可能,如何最优地让链接器保留该Flash子集地址?

解答

1. 链接器是否会覆盖目标地址?

完全有可能。PROVIDE仅用于在链接脚本中定义一个全局符号并绑定到指定地址,没有任何“保留该地址不被占用”的语义。链接器在分配.text、.isr_vector等段时,只会按照MEMORY定义的ROM区域范围和段的排列规则填充内容,只要0x08016F11属于ROM的可用空间,且后续段的填充位置刚好落到该地址,就会覆盖原有Flash数据。

2. 如何让链接器保留目标地址范围?

除了拆分ROM区域,还有两种更高效的方案:

方案1:自定义NOLOAD段(适合单个/小范围地址)

在链接脚本中为目标地址定义一个NOLOAD属性的段,明确告诉链接器不要向该段写入内容,同时通过地址占位让链接器认为该区域已被占用:

MEMORY
{
  ROM (rx)  : ORIGIN = 0x08000000,  LENGTH = 1024K
}

SECTIONS
{
    // 先定义保留段,绑定到目标地址
    .reserved_testvalue NOLOAD :
    {
        PROVIDE(__TESTVALUE__ = .);  // 将符号绑定到当前地址(0x08016F11)
        . += 4;  // 占位4字节,告知链接器该区域已被占用
    } > ROM AT>ROM

    // 原有段定义保持不变
    .isr_vector:
    {
        /* 代码内容 */
    } > ROM
    .text:
    {
        /* 代码内容 */
    } > ROM
    
    /*...*/
}
  • NOLOAD:阻止链接器将任何程序内容写入该段,保留Flash原有数据
  • . +=4:让链接器跳过这4字节空间,后续段不会分配到该地址范围
  • C代码无需修改,可直接沿用原有的extern声明

方案2:拆分MEMORY区域(适合大范围地址保留)

如果需要保留连续的Flash地址范围,直接拆分ROM区域为常规使用区和保留区,确保所有程序段只分配到常规区域:

MEMORY
{
  ROM_MAIN (rx)  : ORIGIN = 0x08000000,  LENGTH = 0x16F11  // 覆盖0x08000000 ~ 0x08016F10
  ROM_RESERVED (rx) : ORIGIN = 0x08016F11, LENGTH = 4      // 保留目标4字节
  ROM_REST (rx) : ORIGIN = 0x08016F15, LENGTH = 1024K - 0x16F15  // 剩余ROM空间
}

PROVIDE(__TESTVALUE__= 0x08016F11);

SECTIONS
{
    // 所有常规段分配到ROM_MAIN或ROM_REST
    .isr_vector: { /* 代码内容 */ } > ROM_MAIN
    .text: { /* 代码内容 */ } > ROM_MAIN
    /*...其他段均指向ROM_MAIN/ROM_REST,不要使用ROM_RESERVED */
}

这种方案的隔离性最强,能彻底避免链接器将任何内容分配到保留区域,适合需要长期固定保留的地址范围。

最优方案选择

  • 仅需保留单个或少量连续字节:优先选择方案1,无需拆分ROM区域,配置更简洁
  • 需要保留较大连续地址范围:优先选择方案2,区域划分清晰,管理更直观

内容的提问来源于stack exchange,提问作者bsheikh24

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 17:26:04