【问题标题】:Force the linker to put the same code in 2 sections强制链接器将相同的代码放在 2 个部分中
【发布时间】:2016-02-29 12:07:12
【问题描述】:

我试图强制链接器(来自 XC32 的 ld)将相同的可执行代码放置在闪存的两个不同部分中。

该应用程序使代码可以作为独立应用程序运行,并且还可以使引导加载程序覆盖重置向量,然后可以分支到伪重置向量。

我的链接器脚本的相关部分是

MEMORY
{
  kseg1_boot_mem     : ORIGIN = 0xBFC00000, LENGTH = 0x480
  bootload_boot_mem  : ORIGIN = 0x9D1F0000, LENGTH = 0x480
}

SECTIONS
{
  .reset 0xBFC00000 :
  {
    KEEP(*(.reset))
  } > kseg1_boot_mem

  .bootloadreset 0x9D1F0000 :
  {
    KEEP(*(.reset))
  } > bootload_boot_mem
}

使用它,0xBFC00000 处的区域按预期填充,但在 0x9D1F0000 处没有放置任何内容。我尝试将选项 --no-gc-sections 传递给链接器,但似乎没有任何区别。

我的问题是:是否可以强制链接器将相同的代码放入 2 个不同的部分,以及如何做到这一点?

【问题讨论】:

  • 我会在构建系统中解决这个问题,方法是将相同的代码编译两次并进行适当的变体。它的效率有点低,但它只依赖于链接器中易于理解的行为。

标签: linker ld pic


【解决方案1】:

无论是否是解决这个问题的正确方法,我想出的解决方案是:

通过从 .reset 部分删除 KEEP(*(.reset)) 块,将启动代码移动到 0x9D1F0000 区域。 在跳转到重新定位的启动代码的复位地址处放置一个 asm 函数。 允许引导加载程序覆盖 asm 函数,因为它会在完成工作后跳转到启动代码。

【讨论】:

    【解决方案2】:

    我通过添加新的内存区域解决了这个问题

    MEMORY
    {
      virtual_boot               : ORIGIN = 0xBFC00000, LENGTH = 0x200
      .
      .
      .
    } 
    

    然后在我添加的部分中

    SECTIONS
    {
      .virtualboot :
      {
        /*KEEP(*(.virtualboot))*/
        LONG(0x08000000 | ((_RESET_ADDR & 0x1FFFFFFF) >> 2));
        LONG(0x00);
      } > virtual_boot
      .
      .
      .
    }
    

    _RESET_ADDR 应该在前面定义,在我的代码中是

    _RESET_ADDR = (0x9D006000 + 0x1000);
    

    通过这个,我的代码可以在有/没有引导加载程序的 MCU 上运行

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-10
      • 1970-01-01
      • 2022-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-02
      相关资源
      最近更新 更多