Startup Code & the Reset Handler
What happens between power-on and main(): the vector table, copying .data, zeroing .bss and calling SystemInit.
On a PC the operating system loads your program and sets up its memory. On a microcontroller, the first code to run after reset is a small startup routine — usually supplied by the vendor in assembly or C, and worth reading at least once.
Power-on on a Cortex-M
The linker script defines _sidata, _sdata, _edata, _sbss, _ebss and _estack (see the previous module).
Copy loop: initial values of .data are moved from flash to RAM.
Zero loop: .bss is cleared, which is why C guarantees uninitialised globals are 0.
SystemInit configures clocks; then main runs and must never return.
Weak aliases let any ISR you define elsewhere replace the default handler.
Weak symbols and the vector table
void USART2_IRQhandler(void) {... } // lower-case 'h' void USART2_IRQHandler(void) {... }
The name must match the startup file exactly; a typo leaves the weak default (an infinite loop) in the vector table.
Reading a global in a function called before the.data copy Only call code that uses globals after the startup copy/zero loops
Before the copy, initialised globals still contain whatever was in RAM at power-up.
What are the first two entries of a Cortex-M vector table?
The initial value of the main stack pointer, then the address of the reset handler.
Why does an uninitialised global start at 0 on a microcontroller?
Because the startup code explicitly zeroes the .bss section before calling main.