2. 理解Zephyr Bootloader架构

任务目标

本案例通过分析Zephyr RTOS官方bootloader(MCUboot)的启动流程与Flash分区表结构,绘制一张架构图,帮助理解Zephyr bootloader的整体工作方式。完成本案例后,应能回答:MCUboot在Zephyr中处于什么位置、启动时执行哪些关键步骤、分区表如何组织。

Zephyr Bootloader架构概述

Zephyr默认使用MCUboot作为bootloader。它位于片内Flash起始地址(通常0x0),负责验证应用镜像的签名与完整性,然后跳转到应用分区执行。Flash布局由pm_static或dts中的partitions节点定义,典型分区包括:mcuboot(bootloader自身)、mcuboot_primary(应用运行区,含image-0)、mcuboot_secondary(应用升级区,含image-1)、scratch(交换临时区)。

启动流程关键步骤

  1. 硬件初始化:由Zephyr的bootloader镜像配置执行,包括时钟、串口(可选调试)、Flash控制器。
  2. 读取分区表:从DTS生成的flash_area结构中获取各分区偏移与大小。
  3. 镜像检查:读取primary分区中image-0的header,验证其magic、版本、签名(若启用)。
  4. 升级决策:若secondary分区存在待升级镜像且签名有效,则执行swap或overwrite升级;否则直接启动primary。
  5. 跳转执行:设置MSP(主栈指针)为镜像header中的entry地址,跳转至应用复位向量。

分区表结构(以nRF52840 DK为例)

在boards/arm/nrf52840dk_nrf52840.overlay中定义:

&flash0 {
    partitions {
        compatible = "fixed-partitions";
        #address-cells = <1>;
        #size-cells = <1>;
        boot_partition: partition@0 {
            label = "mcuboot";
            reg = <0x0 0xc000>;
        };
        slot0_partition: partition@c000 {
            label = "image-0";
            reg = <0xc000 0x76000>;
        };
        slot1_partition: partition@82000 {
            label = "image-1";
            reg = <0x82000 0x76000>;
        };
        scratch_partition: partition@f8000 {
            label = "scratch";
            reg = <0xf8000 0x8000>;
        };
    };
};

实际地址与大小由具体芯片Flash容量决定,上述仅为示例。编译时Zephyr会将这些节点转换为flash_area数组,MCUboot通过flash_area_open()访问。

架构图

nRF52840 Flash 布局 (0x0 - 0x100000) MCUboot Bootloader (0x0 - 0xC000) Primary 分区 (0xC000 - 0x82000) image-0: 当前运行的应用镜像 包含: 镜像头(tlv) + 代码 + 签名 Secondary 分区 (0x82000 - 0xF8000) image-1: 待升级镜像(由OTA写入) MCUboot 验证后交换或覆盖到 primary Scratch 分区 (0xF8000 - 0x100000) — swap升级临时区 ① 上电复位 → ② 验证签名/版本 → ③ 若需升级 → ④ swap/overwrite → ⑤ 跳转 image-0 入口

验证方法

  1. 编译bootloader:在Zephyr源码目录下执行 west build -b nrf52840dk_nrf52840 bootloader/mcuboot/boot/zephyr,生成zephyr.hex。
  2. 查看分区表:编译后执行 west build -t menuconfig,在Storage菜单中确认Flash分区地址与大小与DTS定义一致。
  3. 烧录与日志:使用nrfjprog --program build/zephyr/zephyr.hex --chiperase烧录,串口115200波特率观察启动日志。预期看到类似mcuboot: Starting bootloader输出,随后跳转至应用。
  4. 通过标准:若串口依次输出bootloader初始化信息、镜像验证通过(无签名错误)、并最终执行应用代码(如LED闪烁或打印应用日志),则证明启动流程与分区表配置正确。

注意:若未启用签名,MCUboot默认允许不验证直接启动,此时日志中不会出现签名检查步骤,但仍会执行分区查找与跳转。