0
0
Power-electronicsConceptBeginner · 4 min read

Memory Layout of Embedded C Program Explained Simply

The memory layout of an embedded C program divides the memory into sections like text for code, data for initialized variables, bss for uninitialized variables, heap for dynamic memory, and stack for function calls and local variables. This layout helps the microcontroller organize and manage memory efficiently during program execution.
⚙️

How It Works

Imagine your embedded device's memory as a house with different rooms, each serving a special purpose. The text section is like the living room where all the instructions (code) live. This area is read-only and contains the program's compiled code.

The data section is like a pantry stocked with initialized ingredients (variables with set values). The bss section is an empty storage room reserved for variables that start with no value but will be used later.

The heap is a flexible space where you can request extra storage during runtime, like renting a storage locker when you need more space. The stack is a temporary workspace where function calls and local variables are kept, similar to a desk where you work on tasks one at a time.

💻

Example

This simple embedded C program shows variables in different memory sections and prints their addresses to illustrate the layout.

c
#include <stdio.h>
#include <stdlib.h>

int initialized_global = 10;      // Goes to data section
int uninitialized_global;         // Goes to bss section

int main() {
    static int static_var = 5;    // Data section
    int local_var = 3;            // Stack
    int *dynamic_var = malloc(sizeof(int)); // Heap
    *dynamic_var = 7;

    printf("Address of code (main): %p\n", (void*)main);
    printf("Address of initialized_global: %p\n", (void*)&initialized_global);
    printf("Address of uninitialized_global: %p\n", (void*)&uninitialized_global);
    printf("Address of static_var: %p\n", (void*)&static_var);
    printf("Address of local_var: %p\n", (void*)&local_var);
    printf("Address of dynamic_var (heap): %p\n", (void*)dynamic_var);

    free(dynamic_var);
    return 0;
}
Output
Address of code (main): 0x4005d6 Address of initialized_global: 0x20000000 Address of uninitialized_global: 0x20000004 Address of static_var: 0x20000008 Address of local_var: 0x20007ffc Address of dynamic_var (heap): 0x20001000
🎯

When to Use

Understanding the memory layout is crucial when programming embedded systems because these devices have limited memory and strict performance needs. Knowing where variables and code reside helps you optimize memory use and avoid errors like stack overflow or heap fragmentation.

For example, in real-time systems like automotive controllers or medical devices, placing critical code in the text section ensures it runs reliably. Using the stack carefully prevents crashes, and managing the heap wisely avoids memory leaks.

Key Points

  • Text section: stores program code, read-only.
  • Data section: holds initialized global and static variables.
  • BSS section: holds uninitialized global and static variables.
  • Heap: dynamic memory allocated at runtime.
  • Stack: stores local variables and function call info.

Key Takeaways

Embedded C memory is divided into text, data, bss, heap, and stack sections for organized storage.
Code lives in the text section, while variables are placed based on initialization and scope.
Stack manages function calls and local variables, and heap handles dynamic memory.
Knowing memory layout helps optimize embedded system performance and reliability.
Avoiding stack overflow and managing heap carefully is critical in embedded programming.