2016-04-08 06:11 AM
Hello,
while writing a bootloader, I had the need for a few bytes (4) that retain the content during a software reset. I�ve read that is true for the first bytes of the SRAM. So I�ve added a new section at the beginning of the RAM to my linker scripted. Everything looked great until I�ve stumbled over a wrong initialized static variable.
The reason for this is, that the section followed my new section, is the .data section. And that second definition starts with:
.data :
{
. = ALIGN(8);
_sdata = .; /* create a global symbol at data start */
�
. = ALIGN(4); _edata = .; /* define a global symbol at data end */which leads to _sdata (0x20000008) and _edata (0x20000010) being 8 byte aligned. Because my 4 byte long new section is in front of the .data section, the .data section starts on a 4 byte aligned address (0x20000004), the linker adds 4 byte padding at the front of the .data .
Now the startup code, initializes the .data segment with values from _sidata, which is the load address of the .data segment:
_sidata = LOADADDR(.data);
And as the .data segment is padded with 4 bytes at the beginning, the first static initialized variable is filled with that padding, the second variable is initialized with the value from the first and so on.
My question: why are the first values of the .data segment aligned to 8 bytes? I�ve changed the alignment to 4 and now everything works fine.
TIA
Torsten
#alignment #.data #linkerscript2016-04-08 09:12 AM
Presumably to allow the linker to control the granularity and placement of a section or load region.
While perhaps not critical on the M3/M4, ARM has 64-bit alignment rules in their ABI for stacks and 64-bit values (doubles, or whatever) that can be loaded via LDRD, etcData caching, when available, also tends to favour courser granularity so data does not span line widths.A lot of GNU/GCC linker scripts I see also have unaligned/odd stack pointer settings. These will cause slower memory access, and in the case of ARM7/9 and M0, alignment faults.If you want the linker to keep out of specific regions you can do so by advancing the starting address, and/or shrinking the size of the load region. I would do so at a minimum granularity of 16 bytes, or the cache line, whichever is larger.2016-04-08 09:46 AM
Hello Clive,
well, better speed for certain aligned data would require that every element in that section section would be aligned to 8 bytes, not just the first element of the section. And in this case, the .bss section should be aligned to 8 bytes too (but it's aligned to 4 bytes).The only two reasons, I can think of are, that the official gcc STM32L476 linker script was copied from somewhere, where the 8 byte aligment made sense, or that the loop that copies the flash content to RAM works faster if the source and target addresses are 8 byte aligned.But in both cases, if the linker would have to force the alignment of the first element in the .data segment by adding padding, the startup code is broken, because the flash source address would have to be adjusted by the number of padding bytes that where added to the .data section. In an unmodified linker script, the start address of the .data section is always 8 byte aligned, because it's the first section ;-).> If you want the linker to keep out of specific regions you can do so by advancing the> starting address, and/or shrinking the size of the load region.
Well, I'm just happy, that the linker is doing its job and places the specific regions as I need them. Otherwise I would have to manage addresses on my own.Cheers,Torsten2016-04-08 10:24 AM
Each data are aligned correctly to size.
Aligment in linker are for startup to copy/ fill '0'.