了解 ARM Cortex-M0+ 重定位

Understanding ARM Cortex-M0+ relocation

我刚刚开始进行嵌入式 arm 开发,有一段代码让我很头疼:

/* Initialize the relocate segment */
pSrc = &_etext;
pDest = &_srelocate;

if (pSrc != pDest) 
{
    while (pDest < &_erelocate) 
    {
        *pDest++ = *pSrc++;
    }
}

其中 _etext_srelocate 是链接描述文件中定义的符号:

. = ALIGN(4);
_etext = .;

.relocate : AT (_etext)
{
    . = ALIGN(4);
    _srelocate = .;
    *(.ramfunc .ramfunc.*);
    *(.data .data.*);
    . = ALIGN(4);
    _erelocate = .;
} > ram

其中ram为原点为0x20000000的内存段。我看到的问题是 _etext 是一个标记 .text 段结束边界的符号,它是另一个内存段 rom 的一部分。这意味着除非上述内存段已 100% 满,否则 _etext != _srelocate 将始终为真。这意味着我们正在将内存复制到 .text 部分之外,根据链接器脚本没有任何内容被定义为存在。

对我来说,这会导致以下三种情况之一:A) rom.text 部分之外存在垃圾,它被复制到 .relocate 中(并且随后 .data),或 B) .text 之后的存储器在器件编程之前的芯片擦除操作后为空,在这种情况下 .relocate 被清零,或 C) 有一些轻微的这里发生了魔法,其中 .data 值放在 rom 中的 .text 之后,并且必须加载到 ram 中;在这种情况下,评论应该是 s/relocate/data.

第三种情况似乎最有可能,但根据链接描述文件,这不可能是真的。有人可以阐明这一点吗?

你没看错,就是第三个选项。 A​​T() 告诉 linker 将 .ramfunc.data目标文件中的部分(两者都是 read/write),从 _etext 开始。 “> ram”告诉 linker 解析重定位,就像将这些部分放在 RAM 中一样,这是使用此处描述的 MEMORY 命令完成的:https://sourceware.org/binutils/docs/ld/MEMORY.html#MEMORY 结果是复制循环移动数据从只读区到程序启动时的read/write区

这是 gnu ld 文档的 link,其中描述了控制 LMA(加载地址):https://sourceware.org/binutils/docs/ld/Output-Section-LMA.html