Skip to main content
crwper
Senior
March 5, 2023
Solved

SBSFU: Issue with 16-byte alignment in linker script?

  • March 5, 2023
  • 1 reply
  • 2814 views

I've run into an issue with the section of the UserApp linker script which ensures that the binary size is a multiple of 16 bytes:

.align16 :
{
 . = . + 1; /* _edata=. is aligned on 8 bytes so could be aligned on 16 bytes: add 1 byte gap */
 . = ALIGN(16) - 1; /* increment the location counter until next 16 bytes aligned address (-1 byte) */
 BYTE(0); /* allocate 1 byte (value is 0) to be a multiple of 16 bytes */
} > APPLI_region_ROM

This seems to fail for some binary sizes, where the following error is given:

ld.exe:STM32WB5MMGHX_FLASH.ld:139 cannot move location counter backwards (from 0000000008032340 to 000000000803233f)

If I change the size of the binary by adding some other command, the error goes away. I believe what's happening here is this:

  • For a binary size of 0x3233f bytes, the first line advances the location counter to 0x32340.
  • The second line rounds this to 0x32340, since it's already a multiple of 16 bytes, but then subtracts 1 byte, so it's attempting to set the location counter to 0x3233f, i.e., moving it backwards.
  • The third line would advance the counter to 0x32340 again, except that it never gets called because an error is thrown in the second line.

I'm struggling to come up with an alternative to this which will ensure that the binary is a multiple of 16 bytes, but won't have the same issue.

This topic has been closed for replies.
Best answer by crwper

Thanks for all your help. I think I've found the answer to my question.

It appears that LD normally does not create output sections with no contents, and presumably moving the location counter doesn't count as "contents". So the following replacement (provided by ST support) fixes the issue:

.align16 :
{
 BYTE(0xAA);
 . = ALIGN(16);
}

This does have the side effect of writing at least one byte (so binaries which are already a multiple of 16 bytes will have an additional 16 bytes added). However, it keeps everything in the linker script, and the extra padding shouldn't make a difference.

1 reply

crwper
crwperAuthor
Senior
March 16, 2023

Would the following code fulfil the intended function of the original code, without the possibility of moving the location counter backward?

.align16 :
{
 _padding = (16 - ((. + 1) % 16)) % 16;
 . = . + _padding;
 BYTE(0);
} > APPLI_region_ROM

Pavel A.
Super User
March 16, 2023
.padding16 :
{
 . = (( . + 0xF) & ~0xF);
} > APPLI_region_R
 

crwper
crwperAuthor
Senior
March 22, 2023

This doesn't seem to work. I think the problem is that the location counter gets moved forward, but no bytes are written, so there is no effect on the size of the file. This is why the solution I proposed rounds (. + 1) instead of (.), then adds a byte at the end.

Edit: It looks like my solution doesn't work, either, and I'm not quite sure why. For a particular binary, no padding gives a size of 63,526 bytes, ST's solution gives a size of 63,536 bytes (but fails for binaries whose size is a multiple of 16 bytes minus one), mine gives 63,542 bytes, and yours gives 63,526 bytes.