我正在尝试在 ARM MCU 中为初始化数据创建一个额外的 ram 部分(在我的 GNU 链接器脚本中)。该部分必须放置在已知地址,以便我可以在 MPU 中为其设置特定属性。 我在使用所有链接器魔法时遇到了一些麻烦。
内存划分如下:
/* Memory Spaces Definitions */
MEMORY
{
rom (rx) : ORIGIN = 0x00420200, LENGTH = 0x001DFE00
ram (rwx) : ORIGIN = 0x20400000, LENGTH = 0x0005e000
ram_nocache_section (rwx) : ORIGIN = 0x2045e000, LENGTH = 0x00002000
sdram(rwx): ORIGIN = 0x70000000, LENGTH = 0x00200000
}
这是我正在尝试处理的“ram_nocache_section”。
我可以定义适当的部分,如下所示:
/* no cache section */
.ram_nocache :
{
. = ALIGN(8);
*(.ram_nocache)
} > ram_nocache_section
这可行,但生成的二进制文件非常巨大。 0.5 GB。这是因为 RAM 地址空间与 Flash 地址空间相距 0.5 GB。处理这个问题的方法是“重新定位”初始化的内存数据。该脚本的执行方式如下:
.text :
{
...
} > rom
. = ALIGN(4);
_etext = .;
.relocate : AT (_etext)
{
. = ALIGN(4);
_srelocate = .;
*(.ramfunc .ramfunc.*);
*(.data .data.*);
. = ALIGN(4);
_erelocate = .;
} > ram
这将神奇地在闪存和 RAM 中分配初始化数据(和 RAM 函数)。所以这很容易复制,对吗?就像这样:
. = ALIGN(4);
_etext = .;
.relocate : AT (_etext)
{
. = ALIGN(4);
_srelocate = .;
*(.ramfunc .ramfunc.*);
*(.data .data.*);
. = ALIGN(4);
_erelocate = .;
} > ram
. = ALIGN(4);
_eramdata = .;
.relocate2 : AT ( _eramdata )
{
. = ALIGN(4);
_srelocate2 = .;
. = ALIGN(8);
*(.ram_nocache)
. = ALIGN(4);
_erelocate2 = .;
} > ram_nocache_section
这可以编译,但生成的二进制文件仍然很大。这是因为 _eramdata 符号以某种方式放置在 ram 中,而不是像 _etext 一样放置在闪存中。
那么...根据这个document ,我应该能够做这样的事情:
.relocate2 : AT ( _etext + SIZEOF(.data) + SIZEOF(.ramfunc) )
{
. = ALIGN(4);
_srelocate2 = .;
. = ALIGN(8);
*(.ram_nocache)
. = ALIGN(4);
_erelocate2 = .;
} > ram_nocache_section
但这不会编译。相反,我可以像这样创建所需的结果:
.relocate2 : AT ( _etext + 10k )
{
. = ALIGN(4);
_srelocate2 = .;
. = ALIGN(8);
*(.ram_nocache)
. = ALIGN(4);
_erelocate2 = .;
} > ram_nocache_section
然而,这是一个相当脆弱且浪费的解决方案。
我该如何正确地执行此操作?我想将“relocate2”部分放置在常规“relocate”部分旁边。没有任何多余的浪费或预定义的代码限制。
最佳答案
我更喜欢这个结构:
. = ALIGN(4);
_etext = .;
.relocate :
{
. = ALIGN(4);
_srelocate = .;
*(.ramfunc .ramfunc.*);
*(.data .data.*);
. = ALIGN(4);
_erelocate = .;
} > ram AT>rom
.relocate2 :
{
. = ALIGN(4);
_srelocate2 = .;
. = ALIGN(8);
*(.ram_nocache)
. = ALIGN(4);
_erelocate2 = .;
} > ram_nocache_section AT>rom
这两个部分都必须更改为 AT>rom。 (禁止混合。)
关于在 GNU 链接器脚本中创建额外的可重定位节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36132975/