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(交换临时区)。
启动流程关键步骤
- 硬件初始化:由Zephyr的
bootloader镜像配置执行,包括时钟、串口(可选调试)、Flash控制器。 - 读取分区表:从DTS生成的
flash_area结构中获取各分区偏移与大小。 - 镜像检查:读取primary分区中image-0的header,验证其magic、版本、签名(若启用)。
- 升级决策:若secondary分区存在待升级镜像且签名有效,则执行swap或overwrite升级;否则直接启动primary。
- 跳转执行:设置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()访问。
架构图
验证方法
- 编译bootloader:在Zephyr源码目录下执行
west build -b nrf52840dk_nrf52840 bootloader/mcuboot/boot/zephyr,生成zephyr.hex。 - 查看分区表:编译后执行
west build -t menuconfig,在Storage菜单中确认Flash分区地址与大小与DTS定义一致。 - 烧录与日志:使用
nrfjprog --program build/zephyr/zephyr.hex --chiperase烧录,串口115200波特率观察启动日志。预期看到类似mcuboot: Starting bootloader输出,随后跳转至应用。 - 通过标准:若串口依次输出bootloader初始化信息、镜像验证通过(无签名错误)、并最终执行应用代码(如LED闪烁或打印应用日志),则证明启动流程与分区表配置正确。
注意:若未启用签名,MCUboot默认允许不验证直接启动,此时日志中不会出现签名检查步骤,但仍会执行分区查找与跳转。