{"id":7152,"date":"2021-02-09T13:11:56","date_gmt":"2021-02-09T21:11:56","guid":{"rendered":"https:\/\/visualgdb.com\/w\/?p=7152"},"modified":"2021-02-09T13:11:56","modified_gmt":"2021-02-09T21:11:56","slug":"stack-and-heap-layout-of-embedded-projects","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/documentation\/embedded\/stackheap\/","title":{"rendered":"Stack and Heap Layout of Embedded Projects"},"content":{"rendered":"<p>Embedded projects developed with the C\/C++ languages use 3 different memory regions to store the variables:<\/p>\n<ul>\n<li><strong>Global Variables<\/strong> declared outside functions\/methods are placed directly after each other starting at the beginning of RAM.<\/li>\n<li><strong>Local (automatic) variables <\/strong>declared in functions and methods are stored in the <strong>stack<\/strong>.<\/li>\n<li>Variables allocated dynamically (vie the <strong>malloc() <\/strong>function or the <strong>new()<\/strong> operator) are stored in the <strong>heap<\/strong>.<\/li>\n<\/ul>\n<p>The default linker script layout places the heap directly after the last global variable, and the stack directly before the end of RAM:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/02\/stack-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7154\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/02\/stack-1.png\" alt=\"\" width=\"558\" height=\"320\" \/><\/a><\/p>\n<p>Both heap and stack grow dynamically. When the program&#8217;s entry point is called, the heap does not yet exist and the stack points to the address of the <strong>_estack<\/strong> symbol (normally at the end of RAM). Once the entry point calls other functions and they use stack to store variables and return addresses, the stack pointer grows towards the beginning of the RAM. The <strong>$sp<\/strong> register of the CPU normally points to the current end of the stack.<\/p>\n<p>If the application calls <strong>malloc()<\/strong> or <strong>new()<\/strong> to allocate memory dynamically, the standard C\/C++ library calls the <strong>_srbk()<\/strong> function to create a heap right after the last global variable (the <strong>_end<\/strong> symbol) and increase its size as needed. The default <strong>_sbrk()<\/strong> implementation stores the end of the heap address in the static <strong>heap_end<\/strong> variable.<\/p>\n<p>Note that both heap and stack grow towards each other and may collide, leading to memory corruption.<\/p>\n<h2>Fixed-size Stack and Heap<\/h2>\n<p>If you are using VisualGDB-generated linker scripts, you can reserve fixed amounts of memory for the stack and heap:\u00a0<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/02\/fixed.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7155\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/02\/fixed.png\" alt=\"\" width=\"999\" height=\"761\" \/><\/a>This will create 2 additional sections in the ELF file:<\/p>\n<ul>\n<li><strong>.heap<\/strong> will be used to store the heap. The fixed-size heap will never exceed the size reserved for it. Instead, <strong>malloc()<\/strong> will return <strong>NULL<\/strong>.<\/li>\n<li><strong>.reserved_for_stack<\/strong> will reserve the specified amount of memory for the stack, triggering a linker error if there was not enough free RAM left. Note that the actual stack will be still placed at the end of RAM.<\/li>\n<\/ul>\n<h2><a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/02\/stack2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7156\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/02\/stack2.png\" alt=\"\" width=\"638\" height=\"320\" \/><\/a>FreeRTOS<\/h2>\n<p>If you are using a real-time operating system (e.g. FreeRTOS), each thread will have its own stack. The size of the stack for each thread is specified when calling the <strong>xTaskCreate()<\/strong> function. Many examples use the <strong>configMINIMAL_STACK_SIZE<\/strong> as the default stack size (note that the stack size passed to <strong>xTaskCreate()<\/strong> is specified in machine words, not bytes).<\/p>\n<p>FreeRTOS allocates stacks for each thread from the FreeRTOS heap that is different from the stdlib heap. Use the <strong>configTOTAL_HEAP_SIZE<\/strong> variable to control the FreeRTOS heap size.<\/p>\n<p>The stack\/heap layout for FreeRTOS applications is shown here:<\/p>\n<h2><a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/02\/stack3.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7157\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/02\/stack3.png\" alt=\"\" width=\"568\" height=\"320\" \/><\/a>Editing Stack\/Heap Layout<\/h2>\n<p>You can arbitrarily change the stack and heap layout of your application by editing the linker script and providing a custom implementation of <strong>_sbrk():<\/strong><\/p>\n<ul>\n<li>Set the <strong>_estack<\/strong> symbol in linker script (see <a href=\"https:\/\/visualgdb.com\/tutorials\/arm\/linkerscripts\/\">this tutorial<\/a>) to the desired initial location of the stack. The startup code will automatically initialize the stack pointer accordingly.<\/li>\n<li>Provide your own implementation of the <strong>_sbrk()<\/strong> function. The standard C library will call it each time it needs to increase the size of the heap. On the first call, it should return the starting address of the heap. On subsequent calls, it should return the previous end of the heap, or <strong>-1<\/strong> in case it cannot be extended by the requested number of bytes.<\/li>\n<\/ul>\n<p>You can use the following <strong>_sbrk()<\/strong> implementation from newlib as a starting point:<\/p>\n<pre class=\"\">register char *stack_ptr asm(\"sp\");\r\n\r\nvoid *_sbrk(ptrdiff_t incr)\r\n{\r\n    extern char end asm(\"end\"); \/* Defined by the linker.  *\/\r\n    static char *heap_end;\r\n\r\n    char *prev_heap_end;\r\n\r\n    if (heap_end == NULL)\r\n        heap_end = &amp;end;\r\n\r\n    prev_heap_end = heap_end;\r\n\r\n    if (heap_end + incr &gt; stack_ptr)\r\n    {\r\n        errno = ENOMEM;\r\n        return (void *)-1;\r\n    }\r\n\r\n    heap_end += incr;\r\n    return (void *)prev_heap_end;\r\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Embedded projects developed with the C\/C++ languages use 3 different memory regions to store the variables: Global Variables declared outside<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[197],"tags":[230,173],"_links":{"self":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/7152"}],"collection":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/comments?post=7152"}],"version-history":[{"count":1,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/7152\/revisions"}],"predecessor-version":[{"id":7158,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/7152\/revisions\/7158"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=7152"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=7152"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=7152"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}