/baremetal-startup
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.
$ npx -y skills add mohitmishra786/low-level-dev-skills --skill baremetal-startup --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/baremetal-startup
Context preview
The summary Claude sees to decide when to auto-load this skill.
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.
SKILL.md
baremetal-startup.SKILL.mdname: baremetal-startup
description: 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.
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):
| Index | Entry | |-------|-------| | 0 | Initial stack pointer (`_estack`) | | 1 | `Reset_Handler` | | 2 | `NMI_Handler` | | 3 | `HardFault_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
| Task | Who does it | |------|-------------| | Copy `.data` LMA→VMA | `Reset_Handler` / crt0 | | Zero `.bss` | `Reset_Handler` | | Init stack | Vector[0] or explicit `sp` | | Heap (`_sbrk`) | Optional; libc or custom | | C++ constructors | `__libc_init_array()` if using full libc | | FPU enable | `SystemInit` 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
| Symptom | Cause | Fix | |---------|-------|-----| | HardFault immediately | Stack pointer invalid | Set `_estack` to valid RAM top | | Globals wrong at boot | `.data` not copied | Copy LMA→VMA in Reset_Handler | | BSS non-zero | `.bss` not zeroed | Add bss clear loop | | IRQs don't fire | VTOR points to wrong table | `SCB->VTOR = app_vector_addr` | | `main` returns into garbage | No loop after main | `while(1)` or `WFI` loop | | C++ static init crash | Constructors before clocks | Call `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
Read more
name: baremetal-startup description: 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.
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):
| Index | Entry | |-------|-------| | 0 | Initial stack pointer (`_estack`) | | 1 | `Reset_Handler` | | 2 | `NMI_Handler` | | 3 | `HardFault_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
| Task | Who does it | |------|-------------| | Copy `.data` LMA→VMA | `Reset_Handler` / crt0 | | Zero `.bss` | `Reset_Handler` | | Init stack | Vector[0] or explicit `sp` | | Heap (`_sbrk`) | Optional; libc or custom | | C++ constructors | `__libc_init_array()` if using full libc | | FPU enable | `SystemInit` 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
| Symptom | Cause | Fix | |---------|-------|-----| | HardFault immediately | Stack pointer invalid | Set `_estack` to valid RAM top | | Globals wrong at boot | `.data` not copied | Copy LMA→VMA in Reset_Handler | | BSS non-zero | `.bss` not zeroed | Add bss clear loop | | IRQs don't fire | VTOR points to wrong table | `SCB->VTOR = app_vector_addr` | | `main` returns into garbage | No loop after main | `while(1)` or `WFI` loop | | C++ static init crash | Constructors before clocks | Call `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
A curated suite of AI agent skills for systems and low-level programming — C/C++, Rust, Zig, GPU, bare-metal firmware, Linux kernel/driver development, computer architecture, compiler internals, HPC, and more.
Repo: mohitmishra786/low-level-dev-skills
Other skills on low-level-dev-skills.
- /custom-allocators
Custom allocator skill for memory allocation strategies. Use when implementing pool/slab/arena allocators, tuning jemalloc/mimalloc, writing Rust GlobalAlloc, or benchmarking allocator performance. Activates on queries about jemalloc, mimalloc, tcmalloc, arena allocator,
Open skill - /numa-programming
NUMA programming skill for multi-socket memory locality. Use when detecting NUMA topology, binding processes with numactl, using libnuma API, building NUMA-aware data structures, or measuring remote access penalties. Activates on queries about numactl, libnuma, NUMA topology,
Open skill - /af-xdp
AF_XDP skill for high-performance XDP sockets. Use when creating AF_XDP sockets, configuring UMEM and XSK rings, XDP_REDIRECT programs, copy vs zero-copy mode, or comparing with DPDK. Activates on queries about AF_XDP, xsk_umem, XDP_REDIRECT, libbpf xsk, or zero-copy XDP.
Open skill - /dpdk
DPDK skill for userspace packet I/O. Use when initializing EAL, configuring PMD drivers, using mbuf pools and rte_ring, setting up huge pages, RSS, or testpmd validation. Activates on queries about DPDK, EAL, rte_eth_rx_burst, hugepages, PMD, or testpmd.
Open skill - /io-uring
io_uring skill for Linux async I/O. Use when building high-performance servers with liburing, multi-shot operations, provided buffers, fixed files, zero-copy send, or tokio-uring. Activates on queries about io_uring, SQE/CQE, liburing, IORING_OP_PROVIDE_BUFFERS, or io_uring vs
Open skill - /adc-dac-baremetal
Bare-metal ADC and DAC skill. Use when configuring analog sampling, DMA-driven ADC, calibration, or DAC output on MCUs. Activates on queries about ADC bare-metal, sampling time, DMA ADC, or DAC channel setup.
Open skill

