Reset and boot sequence
When an Arm Cortex-M leaves reset, the hardware reads two words from the vector table: the initial stack pointer and the address of Reset_Handler. Startup code then prepares memory and clocks, and only then calls main().
What causes a reset
Power-on, a supply dip (brown-out), the reset pin, a watchdog timeout, or software calling NVIC_SystemReset(). STM32 parts record the cause in flags in RCC->CSR, which helps you track down an unexpected watchdog reset.
The first two words
No code runs before the CPU has a stack, so the stack pointer is the very first entry in the vector table, followed by the reset vector. In C it looks like this:
__attribute__((section(".isr_vector")))
const uint32_t vector_table[] = {
(uint32_t)&_estack, // 0x00: initial SP (top of SRAM)
(uint32_t)Reset_Handler, // 0x04: where execution starts
(uint32_t)NMI_Handler, // 0x08
(uint32_t)HardFault_Handler, // 0x0C
/* ... one entry per exception and interrupt ... */
};
Startup code builds the C world
C promises that globals start with their initial values and that uninitialised ones start at zero. Before main() can run, Reset_Handler has to make that true:
void Reset_Handler(void) {
uint32_t *src = &_sidata, *dst = &_sdata;
while (dst < &_edata) *dst++ = *src++; // copy .data from Flash
for (dst = &_sbss; dst < &_ebss; ) *dst++ = 0; // zero .bss
SystemInit(); // clocks, e.g. the PLL
main();
while (1) {} // main() should never return
}
The _sdata-style symbols come from the linker script. That copy loop is why int count = 5; already holds 5 when main() starts. Some toolchains call SystemInit() first; the result is the same.