链接器脚本:将部分对齐到下一个2的幂

时间:2015-04-07 13:07:48

标签: linker embedded ld linker-scripts

所以,我有这个链接器脚本:

MEMORY
{
    FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
    SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
}
SECTIONS
{
    .kernel.text :
    {
        _kernel_text = .;
        KEEP(kernel.a(.isr_vector))
        KEEP(kernel.a(_sbrk))
        kernel.a(.text*)
        kernel.a(.rodata*)
        _kernel_etext = .;
        _kernel_flash_data = ALIGN(0x4);
    } > FLASH

    .kernel.data : /*AT(ADDR(.text) + SIZEOF(.text))*/ /*contains initialized data*/
    {
        _kernel_data = .;
        kernel.a(vtable)
        kernel.a(.data*)
        _kernel_edata = .;
    } > SRAM AT > FLASH

    .kernel.bss : 
    {
        _kernel_bss = .;
        kernel.a(.bss*)
        kernel.a(COMMON)
        _kernel_ebss = .;
    } > SRAM

    .core.text : ALIGN(0x1000) 
    {
        _core_text = .;
        core.a(.text*)
        core.a(.rodata*)
        _core_etext = .;
        _core_flash_data = ALIGN(0x4);
    } > FLASH
 /* There is lots more, but this is the interesting part */
}

让我们专注于闪光灯。闪存从0x0开始,首先将整个kernel.text写入其中,然后将kernel.data写入其中。我想要一个MPU来保护这个内存区域。该MPU只能用于功率为2的存储器部分。我希望MPU在单个区域内保护flash(数据+文本)中的整个内核部分,因此我需要它的总大小为2的幂。目前,.core.text上的align命令将为我执行此操作。我知道.kernel.text + .kernel.data = 3960字节长的事实,所以我想对齐2 ^ 12 = 4096 = 0x1000。现在我可以在单个区域下保护0x0到0x1000并保护单个MPU区域下的内核。派对!

但是项目还远未完成,代码将被添加,因此我们可能会越过这个边界。第一次这不是问题:内存将与下一个4096屏障对齐,即8192和2 ^ 13。但在那之后,记忆将与12288对齐,这不是两个的力量,所以我的MPU会向我吐口水并嘲笑我。

有没有办法让这个链接器脚本始终与下一个2的幂对齐?

1 个答案:

答案 0 :(得分:2)

值得庆幸的是,GNU ld为这样的实例提供了一个方便的log2ceil()函数。只需编写链接器脚本,如下所示:

/* ... */
_flash_text_data_end_aligned = (2 << LOG2CEIL( _etext + SIZEOF(.data)));
/* ... */
.core.text: ALIGN(_flash_text_data_end_aligned)
/* ... */