所以,我有这个链接器脚本:
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的幂对齐?
答案 0 :(得分:2)
值得庆幸的是,GNU ld为这样的实例提供了一个方便的log2ceil()
函数。只需编写链接器脚本,如下所示:
/* ... */
_flash_text_data_end_aligned = (2 << LOG2CEIL( _etext + SIZEOF(.data)));
/* ... */
.core.text: ALIGN(_flash_text_data_end_aligned)
/* ... */