MCU Startup Explained: From Reset Vector to main()
Understanding how a Microcontroller Unit (MCU) starts execution is fundamental to embedded systems development. From the moment power is applied, a tightly defined sequence of hardware and software interactions determines how your program begins.
Whether working with a Cortex-M microcontroller or a higher-end Cortex-A processor, the startup process follows a structured and predictable flow.
🧭 Where the CPU Fetches Its First Instruction #
At power-on or reset, the CPU does not “search” for code—it is hardwired to access a predefined memory location, traditionally address 0x00000000.
Cortex-M Startup Behavior #
Modern ARM Cortex-M processors perform an automatic vector fetch:
- Address 0x00000000 → Initial Stack Pointer (MSP)
- Address 0x00000004 → Reset Handler address
These values are loaded into:
- MSP (Main Stack Pointer)
- PC (Program Counter)
Execution then jumps directly to the Reset_Handler, marking the true start of firmware execution.
Legacy Behavior (ARM7TDMI) #
Older architectures like ARM7TDMI behave differently:
- Execution begins directly at
0x00000000 - Developers must place a branch instruction at that address
This makes Cortex-M startup more structured and less error-prone.
🧠 What Lives at Address 0x00000000? #
The contents of address 0x00000000 are not fixed—they depend on the MCU’s boot configuration.
Common Memory Mapping Options #
-
User Flash Memory
- Standard production mode
- Contains application firmware and vector table
-
System Memory (BootROM)
- Manufacturer-provided bootloader
- Used for firmware updates via UART, USB, etc.
-
Embedded SRAM
- Used during debugging or fast execution scenarios
Boot Selection Mechanism #
- Controlled via BOOT pins, fuses, or configuration bits
- Determines which memory region is mapped (aliased) to
0x00000000
Cortex-A Contrast #
High-performance Cortex-A systems typically:
- Start execution from internal BootROM
- Initialize external memory controllers (DDR, QSPI, etc.)
- Load application code into RAM before execution
This adds an additional boot stage compared to Cortex-M systems.
🧰 Linker Script: Defining the Vector Table #
The placement of the vector table is controlled by the linker script, not by the compiler alone.
Key Concept #
- A dedicated section (e.g.,
.isr_vector) is defined - The linker ensures it is placed at the start of Flash memory
Example (GCC Linker Snippet) #
KEEP(*(.isr_vector)) /* Ensure vector table is retained and placed correctly */
Startup File Role #
In the startup assembly file (e.g., startup_xxx.s):
- The vector table is explicitly defined
- The first entry sets the initial stack pointer
- The second entry points to Reset_Handler
This guarantees correct initialization during the hardware vector fetch.
🔄 Flexible Startup: Beyond Address 0x00000000 #
Modern MCUs provide more flexibility than earlier designs.
Vector Table Offset Register (VTOR) #
High-end Cortex-M devices (e.g., Cortex-M7) include:
- VTOR (Vector Table Offset Register)
- Allows relocating the vector table to different memory regions
Benefits #
- Support for bootloaders
- Dual-bank firmware updates
- Running applications from external memory
Configuration Methods #
- Option bytes / configuration fuses
- Software-controlled relocation via VTOR
This removes the strict dependency on address 0x00000000.
🔁 Complete Startup Flow #
The MCU startup process can be summarized as follows:
-
Hardware Reset
- Power stabilizes
- BOOT configuration is sampled
-
Memory Mapping
- Selected memory region is mapped to
0x00000000
- Selected memory region is mapped to
-
Vector Fetch
- Initial SP and PC are loaded from the vector table
-
Reset Handler Execution
- Initializes system clocks (
SystemInit) - Sets up memory (data/BSS sections)
- Initializes system clocks (
-
Application Entry
- Control is transferred to
main()
- Control is transferred to
🧠 Final Take: Deterministic and Configurable #
MCU startup may seem automatic, but it is the result of precise coordination between hardware design, linker configuration, and startup code.
- Cortex-M systems emphasize deterministic startup via vector tables
- Modern MCUs introduce flexibility through VTOR and boot configuration
- Understanding this flow is essential for debugging, bootloader design, and system bring-up
Mastering MCU startup gives you full control over how your system powers on, initializes, and begins execution—a foundational skill in embedded development.