5.5.16 · D1Embedded Systems & Real-Time Software

Foundations — Startup code — vector table, reset handler, stack initialization

3,139 words14 min readBack to topic

Before you can read the parent note, you need the vocabulary it speaks. This page builds every term and piece of notation from absolute zero — no prior knowledge of CPUs, memory, compilers or linkers assumed. Read top to bottom; each block leans on the one above it. Two words you'll meet early — reset handler and linker — get a one-line preview here and a full definition later:


1. Memory: a giant numbered wall of boxes

The 0x prefix means the number is written in hexadecimal (base-16) — a compact way to write big addresses. 0x10 is sixteen, 0xFF is 255. Engineers use hex because memory addresses look tidy in it.

Figure s01 below draws this wall: five boxes in a row, each labelled with its address 0x00, 0x04, 0x08, …. The red note reminds you that addresses jump by 4 because one word spans 4 boxes. Keep this picture in mind: every later step is "go to that box, read or write a word."

Figure — Startup code — vector table, reset handler, stack initialization

Related layout ideas live in Stack vs Heap memory layout.


2. Flash vs RAM — two very different shelves

Figure s02 contrasts them as two boxes: Flash (black) holds your code and the init value 42; RAM (black) is where variable g actually lives at runtime but starts as garbage. The red arrow between them is the single most important action on this whole page — the copy of 42 from Flash into RAM. Everything the reset handler does is captured by that one red arrow plus a wipe.

Figure — Startup code — vector table, reset handler, stack initialization

3. The CPU, the Program Counter, and "executing"

More on the Cortex-M machine model: ARM Cortex-M exception and interrupt model.


4. The stack and the Stack Pointer (SP / MSP)

Figure s03 stands memory up vertically. The top marker is _estack; below it sit two pushed items (a return address and a local variable). The red arrow on the left is the SP, always pointing at the last item written; the red arrow on the right shows the growth direction — downward, because each push subtracts 4 first, then writes. Read the figure top-to-bottom as "high addresses at the top, stack eating downward toward low addresses."

Figure — Startup code — vector table, reset handler, stack initialization

Compare with the heap in Stack vs Heap memory layout.


5. Pointers and function pointers


6. Sections: .text, .rodata, .data, .bss

Figure s04 lines up the sections and labels each with the action the boot code takes: .text and .rodata (do nothing — already in Flash, read directly), .data in red (COPY Flash→RAM), and .bss (WIPE to 0). The red highlight on .data marks the one section that needs the copy from Figure s02. Reading the figure teaches the mental sorting rule: "what must happen to me at startup?"

Figure — Startup code — vector table, reset handler, stack initialization

Full detail: Linker scripts and memory sections (.text .data .bss).


7. Linker symbols: _sdata, _edata, _sbss, _ebss, _sidata, _estack

Details in Linker scripts and memory sections (.text .data .bss) and The C runtime and crt0.


8. The vector table (putting it together)

You now have every piece to read it:

  • It's an array (Section 1: numbered boxes in a row, 4-byte aligned).
  • Its entries are addresses of code = function pointers (Section 5).
  • Except entry 0, which is the stack-top address _estack (Section 4 & 7).

Relocating this table lives in Bootloaders and VTOR relocation. Registers like VTOR are touched via Volatile, memory-mapped registers and hardware init.


9. volatile and memory-mapped registers (one-line primer)


Prerequisite map

How to read this diagram: each box is one foundation from the sections above; an arrow "A → B" means "you need A before B makes sense." Follow any path from the top and you are walking the exact order this page teaches. Every path eventually feeds into the box "Startup code topic" at the bottom — that is the parent note you are preparing for. The two middle merge-points (the reset handler's copy/zero work, and the vector table) are where several foundations come together, so they are the ideas worth over-learning.

Memory as numbered boxes

Flash vs RAM

Pointers and function pointers

CPU and Program Counter

Alignment and byte order

Sections text rodata data bss

Linker boundary symbols

Stack and Stack Pointer

Full-descending stack

Vector table as address array

Reset handler copies and zeros

Startup code topic


Equipment checklist

Test yourself — each should feel obvious before you open the parent note.

An address is
the permanent number stamped on one box (byte) in memory.
0x in front of a number means
the number is written in hexadecimal (base-16).
The underscore inside a number like 0x2000_5000 means
nothing about the value — it is just a digit separator for readability, like a comma.
A word on Cortex-M is
4 bytes (32 bits), so words sit at addresses 4 apart.
"Aligned" means
the address is a multiple of the value's size; a word must start at a multiple of 4, or the access can fault.
Little-endian means
the least-significant byte of a multi-byte value is stored at the lowest address.
Flash keeps its contents when
power is off; RAM's contents are undefined at power-up.
The Program Counter (PC) holds
the address of the next instruction; jumping = writing a new address into it.
The Stack Pointer (SP/MSP) holds
the address of the current top of the stack.
"Full-descending" means
SP points at the last item used, and a push subtracts 4 first, then writes — the stack grows downward.
A function pointer is
a variable holding the address of a function's first instruction; type void (*)(void).
The reset handler is
the first piece of your code that runs after power-on; it copies .data, zeros .bss, then calls main.
The linker is
the tool that assigns an address to every function and variable and glues the program together, dropping boundary symbols.
.rodata holds
read-only constants like string literals; they stay in Flash and are read directly, needing no copy or zero.
.data holds
globals with non-zero initial values, copied from Flash into RAM at startup.
.bss holds
zero-initialized globals, wiped to 0 by startup (not stored in Flash).
_estack is
the top of the stack — the first invalid byte just past the end of RAM (rounded to alignment), loaded into MSP at reset.
_sidata is
the Flash address where .data's initial values are stored, to be copied into RAM.
We use &_sdata (its address) not _sdata because
linker symbols carry meaning only in their address, marking a region boundary.
*dst++ = *src++ does
copy the value src points at into where dst points, then advance both pointers.