Stack & Heap

If you like it, share it

Stack and Heap are software concepts, not hardware concepts.
The hardware (MCU) provides is memory (RAM).
Defining zones of memory, one of which is called “stack” and one of which is called “heap”, is a choice of your program.
The way to define Stack and Heap depend of the MCU that you use and often depends on the compiler you are using.
To choose the heap and stack size, the only relevant information from the hardware is how much total memory you have (RAM).
You then make your choice depending on what you want to store in memory (allowing for code, static data, and other programs).


STACK
Stack is used to store the local variables and book keeping data of subroutinesWhen you declare a variable it is stored in Stack area.
When you use a function that use a local variables they stored in the stack.
Stack area is a region of MCU RAM managed directly to the MCU.
The advantage of using the stack to store variables, is that memory is managed for you. You don’t have to allocate memory by hand, or free it once you don’t need it any more.
Again the MCU organizes stack memory so efficiently, reading from and writing to stack variables is very fast.
Another feature of the stack to keep in mind, is that there is a limit (varies with OS) on the size of variables that can be store on the stack.
This is not the case for variables allocated on the heap.


HEAP
The heap is a region of your MCU memory (RAM) that is not managed automatically for you.
It is a more free-floating region of memory (and is larger).
To allocate memory on the heap, you must use malloc() or calloc(), which are built-in C functions.
For release memory use free().
Once you have allocated memory on the heap, you are responsible for using free() to deallocate that memory once you don’t need it any more.
If you fail to do this, your program will have what is known as a memory leak.
Unlike the stack, the heap does not have size restrictions on variable size (apart from the obvious physical limitations of your computer).
Heap memory is slightly slower to be read from and written to, because one has to use pointers to access memory on the heap.
Unlike the stack, variables created on the heap are accessible by any function, anywhere in your program. Heap variables are essentially global in scope.

See below, malloc and free:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
 
void my_func(void){
     char * buffer;
 
 buffer = malloc(512); //allocate 512 bytes for buffer on the heap
 if ( buffer == NULL ){
    perror("Failed to allocate memory");
    return;
    }
 
 //now buffer can be treated as if it were declared char buffer[512]
 memset(buffer, 0, 512); //zero out the buffer
        
  //show buffers address
 sprintf(buffer, "Buffer is at location 0x%lX\n", buffer); 
 
 //This frees 512 bytes to be used by another call to malloc()
 free(buffer);  }

When should you use the heap, and when should you use the stack?
If you need to allocate a large block of memory (e.g. a large array, or a big struct), and you need to keep that variable around a long time (like a global), then you should allocate it on the heap.
If you are dealing with realtively small variables that only need to persist as long as the function using them is alive, then you should use the stack, it’s easier and faster.
If you need variables like arrays and structs that can change size dynamically (e.g. arrays that can grow or shrink as needed) then you will likely need to allocate them on the heap, and use dynamic memory allocation functions like malloc(), calloc(), realloc() and free() to manage that memory “by hand”.

ARM Cortex Mx
In the ARM compiler normally there is a file named startup.s where you have the possibility to define Stack and Heap space.
See the example below.

; Amount of memory (in bytes) allocated for Stack
; Tailor this value to your application needs
; <h> Stack Configuration
;   <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>

Stack_Size      EQU     0x00000400

                AREA    STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem       SPACE   Stack_Size
__initial_sp


; <h> Heap Configuration
;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>

Heap_Size       EQU     0x00000200

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem        SPACE   Heap_Size
__heap_limit

…
__Vectors       DCD     __initial_sp               ; Top of Stack
                DCD     Reset_Handler              ; Reset Handler
                DCD     NMI_Handler                ; NMI Handler

…

                 EXPORT  __initial_sp
                 EXPORT  __heap_base
                 EXPORT  __heap_limit
...
...
...

For STM32, ST use some .s file that start with the name of the STM32 that you use, see the example below for STM32F401 (startup_stm32f401xc.s).

;******************** (C) COPYRIGHT 2016 STMicroelectronics ******************
;* File Name          : startup_stm32f401xc.s
;* Author             : MCD Application Team
;* Version            : V2.5.1
;* Date               : 28-June-2016
;* Description        : STM32F401xc devices vector table for MDK-ARM toolchain. 
;*                      This module performs:
;*                      - Set the initial SP
;*                      - Set the initial PC == Reset_Handler
;*                      - Set the vector table entries with the exceptions 
;*                             ISR address
;*                      - Branches to __main in the C library (which eventually
;*                        calls main()).
;*                      After Reset the CortexM4 processor is in Thread mode,
;*                      priority is Privileged, and the Stack is set to Main.
;* <<< Use Configuration Wizard in Context Menu >>>   
;*****************************************************************************
; 
...
...
...
;*****************************************************************************

; Amount of memory (in bytes) allocated for Stack
; Tailor this value to your application needs
; <h> Stack Configuration
;   <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>

Stack_Size      EQU     0x00000400

                AREA    STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem       SPACE   Stack_Size
__initial_sp


; <h> Heap Configuration
;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>

Heap_Size       EQU     0x00000200

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem        SPACE   Heap_Size
__heap_limit

                PRESERVE8
                THUMB


; Vector Table Mapped to Address 0 at Reset
...
...
...