18.2.3 Initialize Stack Pointer and Heap

The Stack Pointer (sp) register must be initialized in the start-up code. To enable the start-up code to initialize the sp register, the linker must initialize a variable which points to the end of KSEG0/KSEG1 data memory.

Note: The end of data memory is different based on whether RAM functions exist. If RAM functions exist, then part of the DRM must be configured for the kernel program to contain the RAM functions, and the Stack Pointer is located one word prior to the beginning of the DRM kernel program boundary address. If RAM functions do not exist, then the Stack Pointer is located at the true end of DRM.

The linker allocates the stack to KSEG0 on devices featuring an L1 data cache. It allocates the stack to KSEG1 on devices that do not have an L1 cache.

This variable is named _stack. The user can change the minimum amount of stack space allocated by providing the command line option --defsym _min_stack_size=N to the linker. _min_stack_size is provided by the linker script with a default value of 1024. On a similar note, the user may wish to utilize a heap with their application. While the start-up code does not need to initialize the heap, the standard C libraries (sbrk) must be made aware of the heap location and its size. The linker creates a variable to identify the beginning of the heap. The location of the heap is the end of the utilized KSEG0/KSEG1 data memory.

The linker allocates the heap to KSEG0 on devices that have an L1 cache. It allocates the heap to KSEG1 on devices that do not have an L1 cache.

This variable is named _heap. A user can change the minimum amount of heap space allocated by providing the command line option --defsym=_min_heap_size=M to the linker. If the heap is used when the heap size is set to zero, the behavior is the same as when the heap usage exceeds the minimum heap size. Namely, it overflows into the space allocated for the stack.

The heap and the stack use the unallocated KSEG0/KSEG1 data memory, with the heap starting from a low address in KSEG0/KSEG1 data memory, and growing upwards towards the stack while the stack starts at a higher address in KSEG1 data memory and grows downwards towards the heap. The linker attempts to allocate the heap and stack together in the largest gap of memory available in the KSEG0/KSEG1 data memory region. If enough space is not available based on the minimum amount of heap size and stack size requested, the linker issues an error.

Figure 18-1. Stack and Heap Layout
Figure 18-2. Stack and Heap Layout with RAM Functions

The linker must then group all of the above input sections together. This grouping is handled by the default linker script. The run-time start-up code must initialize the gp register to point to the “middle” of this output section. To enable the start-up code to initialize the gp register, the linker script must initialize a variable which is 32 KB from the start of the output section containing the “small” variables and constants. This variable is named _gp (to match core linker scripts). Besides being initialized in the standard GPR set, the Global Pointer must also be initialized in the register shadow set.