baremetal-startup

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

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.
指导Agent完成从复位到
main()
的裸机启动流程:复位与异常向量、
.data
/
.bss
初始化、栈与堆设置、C运行时与链接脚本的集成,以及Cortex-M和RISC-V启动过程中的常见问题。

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
  • 固件在进入
    main()
    前挂起
  • 移植到无厂商HAL的新MCU
  • 编写自定义
    startup.s
    Reset_Handler
  • skills/embedded/linker-scripts
    集成
  • 调试启动时未初始化的全局变量或栈溢出

Workflow

工作流程

1. Boot sequence mental model

1. 启动序列思维模型

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)
上电 / 复位
├── CPU 从vector[0]加载SP
├── CPU 从vector[1]跳转到Reset_Handler
├── Reset_Handler:初始化时钟(可选)、复制.data、清零.bss
├── 配置栈指针(若未从vector设置)
├── 调用SystemInit() / platform_init()
└── 调用main() —— 禁止返回(循环或WFI)

2. Cortex-M vector table

2. Cortex-M向量表

On Cortex-M, the vector table starts at address 0 or a relocatable base (VTOR):
IndexEntry
0Initial stack pointer (
_estack
)
1
Reset_Handler
2
NMI_Handler
3
HardFault_Handler
4+IRQ handlers per NVIC
asm
/* 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 .
c
/* Linker symbols — declared extern in startup */
extern uint32_t _estack, _sidata, _sdata, _edata, _sbss, _ebss;
在Cortex-M中,向量表起始于地址0或可重定位基址(VTOR):
索引条目
0初始栈指针(
_estack
1
Reset_Handler
2
NMI_Handler
3
HardFault_Handler
4+对应NVIC的IRQ处理函数
asm
/* startup.s —— 极简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
    /* ... 厂商CMSIS提供的设备IRQ向量 ... */

.section .text.Reset_Handler
.thumb_func
.global Reset_Handler
Reset_Handler:
    ldr r0, =_sidata    /* .data加载地址(LMA) */
    ldr r1, =_sdata     /* .data虚拟内存地址起始 */
    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 .
c
/* 链接器符号 —— 在启动代码中声明为extern */
extern uint32_t _estack, _sidata, _sdata, _edata, _sbss, _ebss;

3. VTOR relocation (Cortex-M)

3. VTOR重定位(Cortex-M)

c
#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).
c
#include "core_cm4.h"  /* CMSIS */

void relocate_vector_table(uint32_t base) {
    SCB->VTOR = base & 0xFFFFFF80U;  /* 必须符合ARM参考手册的对齐要求 */
    __DSB();
    __ISB();
}
Bootloader跳转到应用程序时,通常需要将VTOR设置为应用程序的向量表地址(例如STM32闪存上的
0x08020000
)。

4. RISC-V startup (overview)

4. RISC-V启动(概述)

asm
/* 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
.
asm
/* entry.S —— 简化版 */
.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 .
陷阱向量:M模式下使用
mtvec
;详见
skills/platform/riscv-privileged

5. crt0 responsibilities

5. crt0的职责

TaskWho does it
Copy
.data
LMA→VMA
Reset_Handler
/ crt0
Zero
.bss
Reset_Handler
Init stackVector[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
任务执行者
复制
.data
从LMA到VMA
Reset_Handler
/ crt0
清零
.bss
Reset_Handler
初始化栈Vector[0]或显式设置
sp
堆(
_sbrk
可选;由libc或自定义实现
C++构造函数若使用完整libc则调用
__libc_init_array()
FPU使能Cortex-M4F/M7上由
SystemInit
完成

6. Linker script integration

6. 链接脚本集成

ld
_estack = ORIGIN(RAM) + LENGTH(RAM);
_sidata = LOADADDR(.data);
Cross-link
skills/embedded/linker-scripts
for MEMORY/SECTIONS layout.
ld
_estack = ORIGIN(RAM) + LENGTH(RAM);
_sidata = LOADADDR(.data);
交叉参考
skills/embedded/linker-scripts
获取MEMORY/SECTIONS布局。

7. Agent usage examples

7. Agent使用示例

/baremetal-startup My STM32 never reaches main — what should Reset_Handler do?
/baremetal-startup How do I relocate the vector table after bootloader jump?
/baremetal-startup 我的STM32永远无法进入main——Reset_Handler应该做什么?
/baremetal-startup 引导加载程序跳转后,如何重定位向量表?

Common Problems

常见问题

SymptomCauseFix
HardFault immediatelyStack pointer invalidSet
_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 fireVTOR 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 crashConstructors before clocksCall
SystemInit
first
症状原因修复方案
立即触发HardFault栈指针无效
_estack
设置为有效的RAM顶部地址
启动时全局变量值错误
.data
未复制
在Reset_Handler中实现从LMA到VMA的复制
BSS非零
.bss
未清零
添加BSS清零循环
中断无法触发VTOR指向错误的表
SCB->VTOR = app_vector_addr
main
返回后进入垃圾代码
main后无循环添加
while(1)
或WFI循环
C++静态初始化崩溃构造函数调用早于时钟初始化先调用
SystemInit

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
  • skills/embedded/linker-scripts
    ——
    _estack
    、LMA/VMA、段布局
  • skills/baremetal/interrupts-and-exceptions-baremetal
    —— 向量表中断条目
  • skills/baremetal/bootloaders-embedded
    —— 应用跳转时的VTOR重定位
  • skills/embedded/openocd-jtag
    —— 使用GDB在
    Reset_Handler
    处暂停
  • skills/low-level-programming/assembly-arm
    —— Thumb-2语法
  • skills/platform/riscv-privileged
    —— RISC-V陷阱设置