我刚刚开始使用嵌入式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将始终为true.这意味着我们将内存复制到.text部分之外,根据链接器脚本没有定义任何内容.
对我来说,这导致三种情况中的一种,或者A)在.text部分之外的rom中存在垃圾,并且它被复制到.relocate(以及随后的.data),或者B).text之外的内存是空的在器件编程之前进行芯片擦除操作之后,在这种情况下.relocate被置零,或者C)这里发生了一些轻微的手魔术,其中.data值放在rom中的.text之后,并且必须加载到ram中;在这种情况下,评论应该是s / relocate / data.
第三种情况似乎最有可能,但根据链接器脚本,这不可能是真的.有人可以对此有所了解吗?
最佳答案 你是对的,这是第三种选择. AT()告诉链接器将.ramfunc和.data部分(两者都是读/写)放在从_etext开始的目标文件中. “> ram”告诉链接器解析重定位,好像这些节放在RAM中一样,这是使用MEMORY命令完成的,如下所述:
https://sourceware.org/binutils/docs/ld/MEMORY.html#MEMORY结果是复制循环将数据从只读区域移动到读取/程序启动时写入区域.
这是一个指向gnu ld文档的链接,其中描述了控制LMA(加载地址):https://sourceware.org/binutils/docs/ld/Output-Section-LMA.html