Lately I've been studying the linker scripts used in auto-generated STM32 projects, and I'm a little bit confused about how the stack and heap memory segments are defined.
As an example, I've been looking at the files provided in ST's "CubeMX" firmware package for their F0 lines of chips, which have ARM Cortex-M0 cores. I'd paste a whole script if the files' licenses allowed it, but you can download the whole package from ST for free if you're curious1. Anyways, here are the parts relevant to my question:
/* Highest address of the user mode stack */
_estack = 0x20001000; /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */
<...>
SECTIONS {
<...>
.bss :
{
<...>
} >RAM
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(8);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(8);
} >RAM
<...>
}
So here's my probably-incorrect understanding of the linker's behavior:
The '_estack' value is set to the end of RAM - this script is for an 'STM32F031K6' chip which has 4KB of RAM starting at 0x20000000. It is used in ST's example vector tables to define the starting stack pointer, so it seems like this is supposed to mark one end of the 'Stack' memory block.
The '_Min_Heap_Size' and '_Min_Stack_Size' values seem like they are supposed to define the minimum amount of space that should be dedicated to the stack and heap for the program to use. Programs that allocate a lot of dynamic memory may need more 'Heap' space, and programs that call deeply-nested functions may need more 'Stack' space.
My question is, how is this supposed to work? Are '_Min_x_Space' special labels, or are those names maybe slightly confusing? Because it looks like the linker script just appends memory segments of those exact sizes to the RAM without consideration for the program's actual usage.
Also, the space defined for the Stack does not appear to necessarily define a contiguous segment between its start and the '_estack' value defined above. If there is no other RAM used, nm
shows that the '_user_heap_stack' section ends at 0x20000600, which leaves a bunch of empty RAM before '_estack'.
The only explanation I can think of is that the 'Heap' and 'Stack' segments might have no actual meaning, and are only defined as a compile-time safeguard so that the linker throws an error when there is significantly less dynamic memory available than expected. If that's the case, should I think of it as more of a minimum 'Combined Heap/Stack' size?
Or honestly, should I just drop the 'Heap' segment if my application won't use malloc or its ilk? It seems like good practice to avoid dynamic memory allocation in embedded systems when you can, anyways.