baremetal-startup

v2026.09.24

Bare-metal startup skill for reset-to-main bring-up. Use when writing startup code, vector tables, .data/.bss init, stack setup, or crt0 for Cortex-M/RISC-V. Activates on queries about reset vector, VTOR, startup.s, bss init, or bare-metal entry point.

GitHub
Install command
npx skhub add mohitmishra786/baremetal-startup
Markdown
SKILL.md

Bare-Metal Startup

Purpose

Guide agents through bare-metal startup from reset to main(): reset and exception vectors, .data/.bss initialization, stack and heap setup, C runtime integration with linker scripts, and common Cortex-M and RISC-V bring-up bugs.

When to Use

  • Firmware hangs before reaching main()
  • Porting to a new MCU without vendor HAL
  • Writing custom startup.s or Reset_Handler
  • Integrating with skills/embedded/linker-scripts
  • Debugging uninitialized globals or stack overflows at boot

Workflow

1. Boot sequence mental model

Power-on / reset
├── CPU loads SP from vector[0]
├── CPU branches to Reset_Handler from vector[1]
├── Reset_Handler: init clocks (optional), copy .data, zero .bss
├── Configure stack pointer (if not already from vector)
├── Call SystemInit() / platform_init()
└── Call main() — must not return (loop or WFI)

2. Cortex-M vector table

On Cortex-M, the vector table starts at address 0 or a relocatable base (VTOR):

IndexEntry
0Initial stack pointer (_estack)
1Reset_Handler
2NMI_Handler
3HardFault_Handler
4+IRQ handlers per NVIC
/* startup.s — minimal Cortex-M */
.syntax unified
.thumb

.section .isr_vector,"a",%progbits
.global g_pfnVectors
g_pfnVectors:
    .word _estack
    .word Reset_Handler
    .word NMI_Handler
    .word HardFault_Handler
    /* ... device IRQ vectors from vendor CMSIS ... */

.section .text.Reset_Handler
.thumb_func
.global Reset_Handler
Reset_Handler:
    ldr r0, =_sidata    /* .data load address (LMA) */
    ldr r1, =_sdata     /* .data VMA start */
    ldr r2, =_edata
    b LoopCopyDataInit
CopyDataInit:
    ldr r3, [r0], #4
    str r3, [r1], #4
LoopCopyDataInit:
    cmp r1, r2
    blt CopyDataInit
    ldr r2, =_sbss
    ldr r4, =_ebss
    movs r3, #0
    b LoopFillZerobss
FillZerobss:
    str r3, [r2], #4
LoopFillZerobss:
    cmp r2, r4
    blt FillZerobss
    bl SystemInit
    bl main
    b .
/* Linker symbols — declared extern in startup */
extern uint32_t _estack, _sidata, _sdata, _edata, _sbss, _ebss;

3. VTOR relocation (Cortex-M)

#include "core_cm4.h"  /* CMSIS */

void relocate_vector_table(uint32_t base) {
    SCB->VTOR = base & 0xFFFFFF80U;  /* must be aligned per ARM ref manual */
    __DSB();
    __ISB();
}

Bootloader jumping to app often requires setting VTOR to the application's vector table address (e.g., 0x08020000 on STM32 flash).

4. RISC-V startup (overview)

/* entry.S — simplified */
.section .text.entry
.global _start
_start:
    la sp, _stack_top
    la t0, _bss_start
    la t1, _bss_end
clear_bss:
    beq t0, t1, bss_done
    sw zero, 0(t0)
    addi t0, t0, 4
    j clear_bss
bss_done:
    call main
    j .

Trap vector: mtvec for M-mode; see skills/platform/riscv-privileged.

5. crt0 responsibilities

TaskWho does it
Copy .data LMA→VMAReset_Handler / crt0
Zero .bssReset_Handler
Init stackVector[0] or explicit sp
Heap (_sbrk)Optional; libc or custom
C++ constructors__libc_init_array() if using full libc
FPU enableSystemInit on Cortex-M4F/M7

6. Linker script integration

_estack = ORIGIN(RAM) + LENGTH(RAM);
_sidata = LOADADDR(.data);

Cross-link skills/embedded/linker-scripts for MEMORY/SECTIONS layout.

7. Agent usage examples

/baremetal-startup My STM32 never reaches main — what should Reset_Handler do?
/baremetal-startup How do I relocate the vector table after bootloader jump?

Common Problems

SymptomCauseFix
HardFault immediatelyStack pointer invalidSet _estack to valid RAM top
Globals wrong at boot.data not copiedCopy LMA→VMA in Reset_Handler
BSS non-zero.bss not zeroedAdd bss clear loop
IRQs don't fireVTOR points to wrong tableSCB->VTOR = app_vector_addr
main returns into garbageNo loop after mainwhile(1) or WFI loop
C++ static init crashConstructors before clocksCall SystemInit first

Related Skills

  • skills/embedded/linker-scripts — _estack, LMA/VMA, section placement
  • skills/baremetal/interrupts-and-exceptions-baremetal — vector table IRQ entries
  • skills/baremetal/bootloaders-embedded — VTOR relocation on app jump
  • skills/embedded/openocd-jtag — halt at Reset_Handler with GDB
  • skills/low-level-programming/assembly-arm — Thumb-2 syntax
  • skills/platform/riscv-privileged — RISC-V trap setup
Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.24

Published

Sep 24, 2026

Category

Uncategorized

License

MIT

Source path

skills/baremetal/baremetal-startup

Default branch

main

Latest commit

bdc5847

Tree SHA

1178323