Walk through building STM32 blinky with no HAL, no CMSIS: vector table, linker script, .data copy, and reset handler all written by hand.
Key Takeaways
At power-on, Cortex-M4 reads 4 bytes at 0x08000000 as the initial stack pointer, then jumps to the reset vector at 0x08000004; bit 0 must be set or you get an immediate HardFault.
The linker script is the only thing connecting compiler output sections (.text, .data, .bss) to physical flash/RAM addresses; the compiler itself has no knowledge of memory layout.
.data variables require two addresses: LMA in flash for storage, VMA in RAM for runtime; the startup code must copy them before main() runs.
volatile on memory-mapped register macros is mandatory, not stylistic; without it the compiler eliminates accesses as dead stores and the peripheral never activates.
GPIO read-modify-write (LDR/ORR/STR) is non-atomic on Cortex-M; use BSRR for atomic set/clear on output pins without needing bit-band or LDREX/STREX.
Hacker News Comment Review
One commenter confirms the ESP32 bare-metal point: despite initial skepticism, ESP-IDF lock-in is real because Espressif’s chips are architecturally diverse enough that even their own low-level API is the only practical common interface.