So, I have this linker script:
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 */
}
And lets focus on the flash. The flash starts at 0x0 and first the entire kernel.text is written to it, then kernel.data is written to it. And I want a MPU to protect this memory region. This MPU can only work on memory sections with a size of a power of two. I want the entire kernel section in the flash (data + text) to be protected under a single region by the MPU, so I need its total size to be a power of two. The align command on .core.text will do this for me, for now. I know for a fact that .kernel.text + .kernel.data = 3960 bytes long, so I want to align to 2^12 = 4096 = 0x1000. Now I can protect from 0x0 to 0x1000 under a single region and protect the kernel under a single MPU region. Party on!
But the project is far from done and code will be added, so we might cross this boundry. The first time this is not a problem: the memory will align to the next 4096 barrier, which is 8192 and 2^13. But after that, the memory will align to 12288, which is not a power of two, so my MPU will spit at me and scoff me.
Is there a way to make this linker script always align to the next power of two?
Thankfully, GNU ld provides a handy-dandy log2ceil()
function for instances just like this. Simply write your linker script as follows:
/* ... */
_flash_text_data_end_aligned = (2 << LOG2CEIL( _etext + SIZEOF(.data)));
/* ... */
.core.text: ALIGN(_flash_text_data_end_aligned)
/* ... */
User contributions licensed under CC BY-SA 3.0