Skip to main content
Mike Rosing
Associate III
May 6, 2026
Solved

Linker script puts bss into flash - why?

  • May 6, 2026
  • 1 reply
  • 137 views

When I'm done compiling, the memory details show

"FLASH";"0x08000000";"";"64 KB"
".ITCMSection";"0x00000000";"0x080002a0";"1.36 KB"
".isr_vector";"0x08000000";"0x08000000";"672 B"
".text";"0x08000810";"0x08000810";"29.19 KB"
".rodata";"0x08007cd0";"0x08007cd0";"84 B"
".ARM";"0x08007d24";"0x08007d24";"8 B"
".init_array";"0x08007d2c";"0x08007d2c";"4 B"
".fini_array";"0x08007d30";"0x08007d30";"4 B"
".data";"0x20000000";"0x08007d34";"144 B"
".bss";"0x20000090";"0x08007dc4";"868 B"
"RW_NONCACHEABLE";"0x200003f4";"0x08007dc4";"36 B"
"._user_heap_stack";"0x20000418";"0x08007dc4";"190.98 KB"

All sections from .bss on should NOT be in FLASH. The linker script has

 /* Used by the startup to initialize data */
 _sidata = LOADADDR(.data);

 /* Initialized data sections into "RAM" Ram type memory */
 .data :
 {
 . = ALIGN(4);
 _sdata = .; /* create a global symbol at data start */
 *(.data) /* .data sections */
 *(.data*) /* .data* sections */
 *(.RamFunc) /* .RamFunc sections */
 *(.RamFunc*) /* .RamFunc* sections */

 . = ALIGN(4);
 _edata = .; /* define a global symbol at data end */

 } >DTCM AT> FLASH

 /* Uninitialized data section into "RAM" Ram type memory */
 . = ALIGN(4);
 .bss (NOLOAD):
 {
 /* This is used by the startup in order to initialize the .bss section */
 _sbss = .; /* define a global symbol at bss start */
 __bss_start__ = _sbss;
 *(.bss)
 *(.bss*)
 *(COMMON)

 . = ALIGN(4);
 _ebss = . + 0x100; /* define a global symbol at bss end */
/* __bss_end__ = _ebss; */
 } > DTCM

 RW_NONCACHEABLE (NOLOAD):
 {
 __NONCACHEABLEBUFFER_BEGIN = .;/* create symbol for start of section */
 KEEP(*(noncacheable_buffer))
 __NONCACHEABLEBUFFER_END = .; /* create symbol for start of section */
/* } > RAM_NONCACHEABLEBUFFER*/
 } > DTCM

 */
 /* User_heap_stack section, used to check that there is enough Ram type memory left */
 ._user_heap_stack (NOLOAD):
 {
 . = ALIGN(8);
 PROVIDE ( end = . );
 PROVIDE ( _end = . );
/* . = . + _Min_Heap_Size;
 . = . + _Min_Stack_Size; */
 . = ABSOLUTE(_estack);
 . = ALIGN(8);
 } > DTCM

The fixed data should go into flash, but the rest of it should not. Why is the linker adding those sections to flash?

Best answer by Pavel A.

Hmm, maybe the orphaned  . = ALIGN(4) in line 20 causes the problem, because it is outside of any section block?

 

1 reply

Mike Rosing
Associate III
May 6, 2026

The problem was assuming "." is reset with section assignment. I had to add

 . = ORIGIN(DTCM) + SIZEOF(.data);

before the .bss section. Now the linker is not trying to load the flash with empty space (and attempt to consume 3* as much memory as actually exists!)

Pavel A.
Pavel A.Answer
Super User
May 6, 2026

Hmm, maybe the orphaned  . = ALIGN(4) in line 20 causes the problem, because it is outside of any section block?

 

Mike Rosing
Associate III
May 7, 2026

That's worth an experiment:

Removing both lines does solve the problem - .bss is not in FLASH when the orphaned . = is removed, so that's a much simpler way to go!