bootloaders-embedded

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Embedded Bootloaders

嵌入式Bootloaders

Purpose

用途

Guide agents through embedded bootloader fundamentals: vector table relocation, safe handoff from bootloader to application, flash partitioning, and basic firmware-update patterns (UART, USB DFU, or custom protocol) on Cortex-M and similar MCUs.
引导开发者掌握嵌入式Bootloader的核心知识:向量表重定位、Bootloader到应用的安全切换、闪存分区,以及Cortex-M和类似MCU上的基础固件更新模式(UART、USB DFU或自定义协议)。

When to Use

适用场景

  • Application must run at non-zero flash offset (e.g.
    0x08010000
    )
  • Implementing OTA or USB DFU without vendor HAL
  • Debugging "app works when flashed alone but not via bootloader"
  • Integrating with
    skills/baremetal/baremetal-startup
    and
    skills/baremetal/stm32-baremetal
  • 应用需在非零闪存偏移地址运行(例如
    0x08010000
  • 不使用厂商HAL实现OTA或USB DFU
  • 调试“单独烧录应用正常,但通过Bootloader启动异常”问题
  • skills/baremetal/baremetal-startup
    skills/baremetal/stm32-baremetal
    集成

Workflow

工作流程

1. Memory layout (typical STM32)

1. 内存布局(典型STM32)

RegionAddressSizeContent
Bootloader
0x08000000
16–64 KBBL code, update logic
Application
0x08010000
remainderApp vector + code
Linker script for app must set
FLASH ORIGIN
to app base; vector table must live at app base.
区域地址大小内容
Bootloader
0x08000000
16–64 KBBootloader代码、更新逻辑
应用
0x08010000
剩余空间应用向量表 + 代码
应用的链接脚本必须将
FLASH ORIGIN
设置为应用基地址;向量表必须位于应用基地址处。

2. Valid application image check

2. 验证应用镜像有效性

Before jump, verify:
App vector[0] (initial SP) points into RAM region
App vector[1] (Reset) points into flash region and has Thumb bit set (LSB=1)
Optional: CRC or magic word in app metadata section
c
#define APP_BASE  0x08010000U

static int app_valid(uint32_t base)
{
    uint32_t sp = *(uint32_t *)base;
    uint32_t reset = *(uint32_t *)(base + 4);
    if (sp < SRAM_BASE || sp > SRAM_END)
        return 0;
    if ((reset & 1U) == 0U)
        return 0;
    if (reset < base || reset > FLASH_END)
        return 0;
    return 1;
}
跳转前需验证:
App vector[0](初始栈指针SP)指向RAM区域
App vector[1](Reset向量)指向闪存区域且Thumb位已设置(最低位LSB=1)
可选:验证应用元数据段中的CRC或魔术字
c
#define APP_BASE  0x08010000U

static int app_valid(uint32_t base)
{
    uint32_t sp = *(uint32_t *)base;
    uint32_t reset = *(uint32_t *)(base + 4);
    if (sp < SRAM_BASE || sp > SRAM_END)
        return 0;
    if ((reset & 1U) == 0U)
        return 0;
    if (reset < base || reset > FLASH_END)
        return 0;
    return 1;
}

3. Cortex-M handoff sequence

3. Cortex-M切换流程

c
typedef void (*app_entry_t)(void);

void jump_to_app(uint32_t app_base)
{
    uint32_t sp    = *(uint32_t *)app_base;
    uint32_t reset = *(uint32_t *)(app_base + 4);

    /* Disable interrupts and de-init peripherals/boot-owned hardware */
    __disable_irq();
    SysTick->CTRL = 0;
    for (int i = 0; i < 8; i++) {
        NVIC->ICER[i] = 0xFFFFFFFFU;
        NVIC->ICPR[i] = 0xFFFFFFFFU;
    }

    SCB->VTOR = app_base;
    __set_MSP(sp);
    __DSB();
    __ISB();

    app_entry_t entry = (app_entry_t)reset;
    entry(); /* does not return */
}
Application must set
SCB->VTOR = APP_BASE
early in
Reset_Handler
if startup assumes relocatable vector table.
c
typedef void (*app_entry_t)(void);

void jump_to_app(uint32_t app_base)
{
    uint32_t sp    = *(uint32_t *)app_base;
    uint32_t reset = *(uint32_t *)(app_base + 4);

    /* 禁用中断并初始化外设/Bootloader占用的硬件 */
    __disable_irq();
    SysTick->CTRL = 0;
    for (int i = 0; i < 8; i++) {
        NVIC->ICER[i] = 0xFFFFFFFFU;
        NVIC->ICPR[i] = 0xFFFFFFFFU;
    }

    SCB->VTOR = app_base;
    __set_MSP(sp);
    __DSB();
    __ISB();

    app_entry_t entry = (app_entry_t)reset;
    entry(); /* 不会返回 */
}
如果启动代码假设向量表可重定位,应用必须在
Reset_Handler
早期设置
SCB->VTOR = APP_BASE

4. Bootloader responsibilities

4. Bootloader职责

Power-on
├── Init minimal clock + UART/USB for update
├── Check update flag in RTC backup / GPIO strap
├── If update requested → receive image, verify, program flash
└── Else if valid app → jump_to_app()
    └── Else stay in bootloader shell
上电
├── 初始化最小时钟 + UART/USB用于更新
├── 检查RTC备份区 / GPIO引脚的更新标志
├── 如果请求更新 → 接收镜像、验证、烧录闪存
└── 否则如果应用有效 → 调用jump_to_app()
    └── 否则停留在Bootloader交互界面

5. STM32 system memory DFU (factory ROM)

5. STM32系统内存DFU(工厂ROM)

STM32 chips expose USB DFU in system memory when BOOT0=1. Custom bootloaders are separate — do not confuse ROM DFU with user flash BL.
当BOOT0=1时,STM32芯片会在系统内存中启用USB DFU。自定义Bootloader是独立的——请勿将ROM DFU与用户闪存中的Bootloader混淆。

6. Update safety

6. 更新安全性

  • Write to scratch sector, verify CRC, then swap metadata pointer (A/B)
  • Never erase the only valid image without recovery path
  • Reset watchdog only after verified commit
  • 先写入临时扇区,验证CRC,再交换元数据指针(A/B分区)
  • 没有恢复路径时,切勿擦除唯一有效的镜像
  • 仅在验证提交完成后重置看门狗

7. Agent usage

7. 技能调用方式

/bootloaders-embedded Write STM32F4 jump-to-app at 0x08010000 with VTOR setup
/bootloaders-embedded Write STM32F4 jump-to-app at 0x08010000 with VTOR setup

Common Problems

常见问题

SymptomCauseFix
HardFault after jumpSP invalid or Thumb bit missingValidate vectors; ensure
reset | 1
IRQs hit bootloader handlersVTOR not relocatedSet
SCB->VTOR
before enabling IRQs
App OK standalone, fails via BLLinker still at
0x08000000
Relink app with correct ORIGIN
UART garbage after jumpBL left UART runningDe-init or reset peripherals
Brick after OTAPower loss mid-eraseDual-bank or metadata rollback
症状原因解决方法
跳转后出现HardFault栈指针SP无效或缺失Thumb位验证向量表;确保 `reset
中断触发Bootloader处理函数VTOR未重定位启用中断前设置
SCB->VTOR
单独运行应用正常,通过Bootloader启动异常链接脚本仍指向
0x08000000
使用正确的ORIGIN重新链接应用
跳转后UART输出乱码Bootloader未关闭UART初始化或重置外设
OTA后设备变砖擦除过程中断电使用双区分区或元数据回滚机制

Related Skills

相关技能

  • skills/baremetal/baremetal-startup
    — vector table and Reset_Handler
  • skills/baremetal/stm32-baremetal
    — flash map and CMSIS
  • skills/baremetal/interrupts-and-exceptions-baremetal
    — NVIC disable pattern
  • skills/embedded/linker-scripts
    — VMA/LMA for split images
  • skills/embedded/openocd-jtag
    — recover bricked flash
  • skills/baremetal/baremetal-startup
    — 向量表与Reset_Handler
  • skills/baremetal/stm32-baremetal
    — 闪存映射与CMSIS
  • skills/baremetal/interrupts-and-exceptions-baremetal
    — NVIC禁用模式
  • skills/embedded/linker-scripts
    — 拆分镜像的VMA/LMA设置
  • skills/embedded/openocd-jtag
    — 恢复变砖的闪存