在GNU链接描述文件中创建额外的可重定位部分

时间:2016-03-21 13:57:24

标签: 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地址空间与闪存地址空间相距0.5 GB。解决这个问题的方法是“重新定位”初始化的ram数据。该脚本执行此操作:

.text :
{
    ...
} > rom

. = ALIGN(4);
_etext = .;

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

这将在flash和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那样放在flash中。

那么......根据这个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'部分旁边。没有任何多余的浪费或预定义的代码限制。

2 个答案:

答案 0 :(得分:2)

我更喜欢这种结构:

. = 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。 (没有混合。)

答案 1 :(得分:0)

我可能自己找到了解决方案:

.relocate2 : AT ( _etext + SIZEOF(.relocate) )
{
    . = ALIGN(4);
    _srelocate2 = .;
    . = ALIGN(8);
    *(.ram_nocache)
    . = ALIGN(4);
    _erelocate2 = .;
} > ram_nocache_section

我确信我已经尝试过类似的东西了。但这似乎是我想要的。尽管如此,仍然不是最优雅的解决方案。