Loading header...

Reset and the Boot Vector — The First Microsecond of a CPU's Life

You've studied Von Neumann vs Harvard memory layouts. You know an ALU does math and a control unit "controls" things. But none of that explains the single strangest moment in a CPU's existence: the instant before it has executed a single instruction, when every register is garbage, every flag is undefined, and the chip has no idea what program it's supposed to run. How does silicon go from "meaningless electrical noise" to "predictably executing line one of your firmware" in under a microsecond? The answer is one of the most elegant tricks in computer engineering — and it's where our story of "what is a CPU actually doing" begins.


Power-On Is Chaos — Reset Is Order

When VCC first ramps up, internal flip-flops settle into random states. SRAM contents are noise. The program counter (PC) could, in principle, point anywhere in the address space. If the CPU just started fetching from wherever the PC happened to land, it would execute garbage opcodes and likely crash or do something unpredictable — every single time you applied power.

Every CPU architecture solves this the same way: a reset signal forces specific hardware registers to specific known values, before any instruction fetch occurs.

flowchart TD classDef cpu fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a classDef mem fill:#dcfce7,stroke:#16a34a,color:#14532d classDef clk fill:#fef9c3,stroke:#ca8a04,color:#713f12 classDef warn fill:#fee2e2,stroke:#dc2626,color:#7f1d1d A["VCC ramps up\n(power applied)"]:::warn B["Internal reset circuit\nholds RESET asserted\nuntil VCC stable"]:::clk C["PC forced to fixed value\n(0x0000 or vector table)"]:::cpu D["SP / status flags\nforced to known defaults"]:::cpu E["RESET released —\nfirst instruction fetch begins"]:::mem A --> B --> C --> D --> E

The reset circuit's only job is to hold the CPU in a deterministic "frozen" state until power is clean and stable, then release it into a known starting condition. This is the answer to "how does a chip wake up the same way every single time" — it doesn't rely on logic that hasn't run yet; it relies on hardware that doesn't need any instructions to do its job.


Learning Objectives

By the end of this lesson, you should be able to:

  • Explain why power-on state is not automatically safe or deterministic.
  • Distinguish the reset signal, reset source, reset vector, and reset handler.
  • Compare fixed-code reset vectors with ARM Cortex-M vector-table indirection.
  • Identify the startup responsibilities that happen before main() runs.
  • Debug common "firmware never starts" symptoms using reset-cause and vector-table checks.

The Boot Vector — A Hardwired Starting Address

The single most important value set during reset is the Program Counter. Different families hardwire this differently, but the principle is identical: the very first address the CPU will ever fetch from is fixed in silicon, not in software.

  • 8085: PC resets to 0x0000, where the first instruction usually lives.
  • AVR (ATmega328P): PC resets to program memory 0x0000, normally a reset-vector jump or vector-table entry.
  • ARM Cortex-M: the CPU reads the reset-handler address stored at 0x00000004; that word is a pointer, not the first opcode.
  • x86 real mode: reset starts near firmware ROM at 0xFFFF0 using CS:IP = F000:FFF0.

Notice ARM Cortex-M is architecturally different from the others — and that difference matters enough to call out explicitly.

AVR / 8085 style: PC = fixed code address

On AVR and 8085, reset literally sets PC to an address containing executable code. The CPU fetches from 0x0000 and that's your first opcode, immediately.

flowchart LR classDef cpu fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a classDef mem fill:#dcfce7,stroke:#16a34a,color:#14532d PC["PC := 0x0000"]:::cpu --> FETCH["Fetch opcode\nfrom 0x0000"]:::mem --> EXE["First instruction executes\n(e.g. JMP main)"]:::cpu

ARM Cortex-M style: vector table indirection

ARM Cortex-M adds a layer of indirection. Address 0x00000000 doesn't hold code — it holds the initial stack pointer value, and 0x00000004 holds the address of the Reset_Handler function. The CPU reads that pointer first, then jumps to wherever it points.

flowchart TD classDef cpu fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a classDef mem fill:#dcfce7,stroke:#16a34a,color:#14532d classDef bus fill:#f3e8ff,stroke:#9333ea,color:#581c87 A["Reset asserted"]:::cpu B["Read word at 0x00000000\n→ initial Main Stack Pointer (MSP)"]:::mem C["Read word at 0x00000004\n→ address of Reset_Handler"]:::mem D["PC := Reset_Handler address"]:::cpu E["Reset_Handler runs:\ncopy .data, zero .bss,\ncall main()"]:::bus A --> B --> C --> D --> E

This is why every ARM Cortex-M startup file (startup_*.s or .c) you've ever glanced at begins with a vector table — an array of function pointers, with the stack pointer in slot 0 and Reset_Handler in slot 1, followed by NMI, HardFault, and all the other exception handlers.

A simplified Cortex-M vector table has this shape:

  • Put the table in the .isr_vector linker section.
  • Entry 0x00: initial stack pointer, usually _estack.
  • Entry 0x04: Reset_Handler, with the Cortex-M Thumb bit set.
  • Entry 0x08: NMI_Handler.
  • Entry 0x0C: HardFault_Handler.
  • Later entries hold the remaining exception and interrupt handlers.

Why Hardwire the Boot Address At All?

This might seem like an obvious design choice, but it's worth asking: could the boot address be configurable in software? The answer is no — and the reason is foundational to everything else in this course.

Software needs a CPU executing instructions to run. The CPU needs to know where instructions are before it can run any. This is a bootstrapping problem, and the only way out of a bootstrapping problem is to anchor something in hardware that requires zero prior execution. The reset vector is that anchor. It's not configurable, not programmable, not negotiable — it's metal traces and transistor logic that exist before your code ever does.

This same idea — some part of the machine must be unconditionally true before logic can build on top of it — is going to reappear in the next lesson when we look at how an opcode becomes control signals. The decoder doesn't "decide" what an opcode means any more than reset "decides" where to start. Both are direct, wired consequences of bit patterns.


Reset Sources Beyond Power-On

Production firmware needs to know why it reset, not just that it did. Most MCUs latch the reset cause into a status register you can read at startup:

flowchart TD classDef warn fill:#fee2e2,stroke:#dc2626,color:#7f1d1d classDef cpu fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a P["Power-On Reset\n(POR)"]:::warn --> R["RESET asserted"]:::cpu B["Brown-out Reset\n(VCC dips too low)"]:::warn --> R W["Watchdog Timeout\n(firmware hung)"]:::warn --> R E["External Reset Pin\n(/RESET pulled low)"]:::warn --> R S["Software Reset\n(write to reset register)"]:::warn --> R

On AVR, this is the MCUSR register (Power-on, External, Brown-out, Watchdog reset flags). On ARM Cortex-M, it's RCC_CSR / RCC_RSTSCLR depending on family. Reading this register first thing in main() is standard defensive practice — if your watchdog keeps firing, you want to know why you rebooted, not just that you did.


Worked Example: Cortex-M Reset Table Check

Suppose a Cortex-M firmware image starts at flash address 0x08000000. The first two 32-bit words in the image are:

Address Value
0x08000000 0x20002000
0x08000004 0x08000181

Interpretation:

  • 0x20002000 is the initial MSP value. It should point inside SRAM, usually near the top of RAM.
  • 0x08000181 is the reset handler address with the Thumb-state bit set in bit 0.
  • The real instruction address is 0x08000180; Cortex-M code executes Thumb instructions, so bit 0 must be 1 in exception vectors.

A quick bring-up check is therefore:

  1. Slot 0 points to valid RAM.
  2. Slot 1 points to valid flash.
  3. Slot 1 is odd on Cortex-M, proving the Thumb bit is set.
  4. The linker script places .isr_vector at the boot address selected by the MCU's boot pins or option bytes.

If any of these are wrong, the CPU may enter HardFault immediately or appear dead before main() is reached.


Timing It Out: The First Few Microseconds

title "Power-on to first fetch"
time start=0 end=10 unit=us divisions=10

VCC: exponential label="VCC ramps" from=0 to=3.3 tau=2 unit=V color=#2563eb
RST: step label="reset released" low=0 high=1 at=6 unit=logic color=#dc2626
CLK: square label="clock valid" low=0 high=1 duty=50 cycles=3 unit=logic color=#ca8a04
PC: step label="PC valid" low=0 high=1 at=7 unit=logic color=#9333ea
F0: pulse label="first fetch" low=0 high=1 at=8 width=1 unit=logic color=#16a34a

marker STABLE at=5 label="power stable"
marker FETCH at=8 label="fetch 0"

Notice the oscillator needs time to stabilize before the clock signal (CLK) is trusted — most MCUs insert an explicit oscillator start-up delay (configurable via fuse bits on AVR, or clock configuration registers on Cortex-M) precisely so the first fetch doesn't happen on a jittery, not-yet-settled clock edge.


Common Mistakes

  • Assuming SRAM or general-purpose registers contain zero after power-on. Only documented reset values are reliable.
  • Confusing the reset vector with a bootloader. A bootloader is code; the vector is the architectural entry mechanism.
  • Placing a Cortex-M vector table correctly in C but incorrectly in the linker script.
  • Forgetting that watchdog, brown-out, external reset, and software reset can all reach the same reset handler.
  • Reading the reset-cause register too late, after startup code or libraries have already cleared it.

Summary

A CPU doesn't "decide" where to start — it is forced there by hardware that exists independently of any program, because bootstrapping a deterministic machine requires at least one undeniable, unconditional truth. Whether that's PC = 0x0000 on an AVR or a vector-table pointer on a Cortex-M, the principle is the same: hardware first, software second. That fixed first address is also the first thing that gets fetched — and what the CPU does with the bits it finds there is exactly where our next lesson picks up.

Next: The Control Unit — Why an Opcode Is Just an Address Into a Decoder

Further Reading

  • Arm, ARMv7-M Architecture Reference Manual, exception model and vector table sections.
  • Microchip, ATmega328P Datasheet, reset sources, interrupt vectors, and fuse configuration.
  • Intel, 8085 Microprocessor User Manual, reset behavior and restart/vector addresses.
  • STMicroelectronics, STM32 reference manuals, reset and clock control reset-cause flags.

Mind Map

mindmap root((Reset and Boot Vector)) Core idea Reset forces known state PC starts at hardware anchor Software begins after first fetch Reset sources Power on reset Brown out Watchdog External reset pin Software reset Vector styles AVR PC equals 0x0000 8085 PC equals 0x0000 Cortex M reads MSP at 0x0 Cortex M reads handler at 0x4 x86 starts near BIOS ROM Practical checks Reset cause register Valid stack pointer in RAM Handler address in flash Thumb bit set on Cortex M Oscillator stable before release Design rules Document boot memory map Keep vector table at linked address Clear bss before main Copy data before main Enable watchdog intentionally Common mistakes Assuming SRAM is zero Wrong linker vector address Cleared reset cause too early Missing startup file Boot pin selects wrong memory