Project 1.01 Section 1 ⚡ Embedded Relevance: Critical Toolchains Preprocessing Compilation Freestanding ELF / Linker Scripts

1.01 The C++ Build Pipeline: Preprocessor, Compiler, Assembler & Freestanding Linker Maps

Executive Summary: Exploring the classic C++ entry point. We deconstruct the 4 stages of the C++ compilation pipeline (Preprocessor, Compiler AST to Assembly, Assembler to Relocatable Object .o, and Linker), contrast Hosted OS environments with Freestanding Bare-Metal microcontrollers, and inspect how linker scripts (.ld) map code sections to Flash and RAM.

💻 1. Annotated Source Code

#include <iostream>


int main() {
	std::cout << "Hello world!" << std::endl;
	return 0;
}

📐 2. Architecture & UML Class Model

📐 C++ Build Pipeline & Linker Section Memory Architecture
+ Public - Private # Protected
<<compilation-unit>> HelloApp Main Translation Unit
+EXIT_SUCCESS : const int32_t = 0
-std : :cout : std::ostream&
+main() : int32_t
-printBanner() : void
<<linker-script>> ELFSectionMapper Memory Map Layout
+FLASH_BASE : uintptr_t = 0x08000000
+SRAM_BASE : uintptr_t = 0x20000000
+.text : Flash ROM[Machine Code]
+.rodata : Flash ROM[Constants & Literals]
+.data : SRAM (VMA) / Flash (LMA)[Initialized]
+.bss : SRAM[Zero-Initialized Globals]
+Reset_Handler() : void
+SystemInit() : void
🔗 Architectural Relationships & Hierarchy
HelloApp ─ ─ > compiled & linked into ─ ─ > ELFSectionMapper

Deconstructs how the high-level C++ entry point maps through preprocessor, compiler, assembler, and linker script into physical Flash and SRAM memory banks.

📚 3. Core C++ Concepts Deep-Dive

1. The 4 Stages of C++ Compilation

  • 1. Preprocessor (cpp): Resolves #include, #define, and conditional compilation flags (#ifdef), emitting pure translation units.
  • 2. Compiler (g++ / clang++): Parses tokens, generates Abstract Syntax Trees (AST), performs type checking and optimizations, and outputs assembly (.s).
  • 3. Assembler (as): Translates assembly mnemonics into machine opcodes, producing relocatable object files (.o / .obj).
  • 4. Linker (ld): Resolves symbols across object files and libraries, calculating absolute memory addresses using a linker script (.ld).

2. Hosted vs Freestanding Environments

A Hosted Environment runs on top of an OS (Windows/Linux) providing standard library features (dynamic heap, file I/O, threads). A Freestanding Environment (bare-metal microcontroller) has no OS; execution begins directly at the hardware Reset Vector.

⚡ 4. Embedded Systems & Hardware Reality

1. Microcontroller Linker Script Anatomy (.ld)

In bare-metal embedded systems, the linker script maps ELF sections to physical silicon memory regions:

  • .text: Executable machine code $\rightarrow$ Flash ROM (Read-Only).
  • .rodata: Constants, string literals, lookup tables $\rightarrow$ Flash ROM.
  • .data: Initialized global/static variables $\rightarrow$ VMA in SRAM, LMA in Flash ROM (copied to RAM at boot).
  • .bss: Zero-initialized global/static variables $\rightarrow$ SRAM (cleared to 0 at boot).
  • .stack / .heap: Runtime stack and heap allocations $\rightarrow$ Top and bottom of SRAM.

💾 ARM Cortex-M Physical Memory Map (Flash ROM vs SRAM)

FLASH ROM (Non-Volatile) .text (Machine Code) .rodata (constexpr constants) .data initial values (LMA) SRAM (Volatile 16-128KB) .data (VMA copied from Flash) .bss (Zero-Cleared Globals) Heap (malloc/new ↑) Stack (Local Vars / ISRs ↓)

💡 5. Production-Ready Embedded Refactoring

Minimal freestanding bare-metal main with zero OS dependencies:

💡 Production-Ready Refactor
#include <cstdint>

// Bare-metal main: never returns in an embedded system
extern "C" int main(void) {
    // Hardware peripheral initialization (RCC clocks, GPIO pins)...
    
    while (true) {
        // Super-loop / RTOS scheduler...
    }
    
    // Unreachable in bare metal
    return 0;
}

📝 Knowledge Verification Quiz

Test your understanding of the C++ concepts and embedded microcontroller trade-offs covered in this guide. Click any option for instant feedback.

Q1. What is the primary difference between a 'Hosted' and a 'Freestanding' C++ implementation?
A A Hosted environment provides full standard libraries and OS services, while Freestanding runs without an OS directly on bare metal with limited standard headers
B Hosted runs only on web browsers
C Freestanding does not support functions
D Hosted code cannot use pointers
Detailed Explanation: C++ standard specifies Freestanding environments for bare-metal targets without an operating system, providing only essential headers like <cstdint>, <cstddef>, and <type_traits>.
Q2. Which stage of the compilation pipeline replaces '#include <header>' with the actual text content of the header file?
A Preprocessor
B Compiler Optimizer
C Assembler
D Linker
Detailed Explanation: The C++ preprocessor performs text substitutions, macro expansions, and file inclusions before compilation begins.
Q3. Where is an initialized global variable (int baud_rate = 115200;) placed in a microcontroller memory map?
A .data section (Load Memory Address in Flash ROM, Virtual Memory Address in SRAM)
B .bss section in SRAM
C .text section in Flash ROM
D On the stack frame
Detailed Explanation: Initialized static variables have their initial values stored in Flash ROM (.rodata/LMA), which startup assembly copies into SRAM (.data/VMA) during boot.
Q4. Why should main() in a bare-metal microcontroller application never return?
A There is no host operating system to return control to; returning jumps to undefined memory or triggers a HardFault/infinite restart
B Returning erases the Flash memory
C Returning lowers the crystal clock
D Returning disables compiler optimizations
Detailed Explanation: On bare-metal CPUs without an OS, returning from main() would branch into whatever uninitialized code exists after main, causing crashes.