在 GNU 链接器脚本中创建额外的可重定位节

标签 c linker arm gnu linker-scripts

我正在尝试在 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/

相关文章:

c++ - 向现有共享对象库添加依赖项

C++顺序读取多个输入文件

c - android中的fwrite有时很慢

linux - 为 cortex-a8 设备交叉编译时出现链接器问题

CMSIS FIR 带通滤波器

linux - 从 linux 交叉编译到 ARM-ELF (ARM926EJ-S/MT7108)

c++ - ARM 架构中的指针处理和 Valgrind 方法

c - 程序不断返回段错误

C 获取代码内的编译选项

c++ - 在运行时链接外部库