Creating Symbols for Stack and Heap Boundaries
In this lesson, you will learn how to use the linker script to create symbolic markers that allow your startup code to programmatically locate and initialize the stack and heap memory regions.
Why Linker Symbols Matter
When your system boots, the C runtime environment needs to know exactly where the stack should reside to store local variables and return addresses, and where the heap begins for dynamic memory allocation. Because these memory regions are defined in your linker script’s MEMORY commands, the C code itself doesn't inherently know their addresses.
We bridge this gap by defining symbols in the linker script. These symbols act as labels that the linker replaces with absolute memory addresses during the final link stage.
Implementing Boundaries
Inside your linker script, you can define symbols by assigning them to the current location counter (.). Here is how you typically define the boundaries for a RAM region:
/* Inside the MEMORY section */
MEMORY {
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128K
}
SECTIONS {
/* Define symbols at the end of the data/bss sections */
.heap : {
_heap_start = .;
. += 0x8000; /* Allocate 32KB for heap */
_heap_end = .;
} > RAM
/* Place stack at the very end of RAM */
_stack_top = ORIGIN(RAM) + LENGTH(RAM);
}
Accessing Symbols in C
To use these symbols in your C code, you must declare them as extern variables. Crucially, because these symbols represent addresses rather than data, you must declare them as extern uint32_t and always take their address using the & operator.
extern uint32_t _heap_start;
extern uint32_t _heap_end;
extern uint32_t _stack_top;
void init_memory_system() {
uint32_t heap_size = (uint32_t)&_heap_end - (uint32_t)&_heap_start;
// Initialize heap allocator using these bounds...
}
By defining these boundaries, you maintain a clean separation between your hardware-specific memory layout and your portable C application code.
Key Takeaway: Use linker symbols to create address labels in your script and reference them as extern pointers in C to dynamically initialize stack and heap boundaries during system startup.