3. Gecko Bootloader架构解析

Gecko Bootloader 是 Silicon Labs 为 EFM32、EFR32 系列 MCU 提供的二级引导程序框架。它并不是一个单一固件,而是一套由 Core 内核、驱动层、插件(Plugin) 和 应用接口 组成的可裁剪架构。理解它的类型划分、Flash 布局、启动链路以及与应用程序的接口约定,是后续做 OTA 升级、双区切换和回滚设计的基础。

一、Bootloader 的三种类型

在 Simplicity Studio 的 Bootloader 组件中,按功能范围可分为三类:

  • None(无 Bootloader):不烧录引导程序,应用程序直接从 Flash 起始地址运行。仅用于开发调试,不具备 OTA 能力。
  • Standalone Bootloader(独立型):Bootloader 自身包含通信协议栈(如 UART、SPI、I2C 或 Radio),上电后先运行 Bootloader,等待主机下发固件;超时未收到则跳转到应用程序。它不依赖应用侧配合,适合出厂烧录或现场串口升级。
  • Application Bootloader(应用型):Bootloader 只负责搬运和校验,通信由应用程序实现。应用收到新固件后写入 Slot 区,再通过 bootloader_rebootAndInstall() 请求重启,由 Bootloader 完成拷贝。这是 OTA 场景最常用的类型。

选择依据很直接:如果设备没有可用的应用侧通信通道,选 Standalone;如果已有 OTA 通信能力(如 Zigbee/Bluetooth 的 OTA Cluster),选 Application 型,因为它体积小、升级过程可控、支持双区回滚。

二、存储布局:Bootloader、Slot 与 NVM

Gecko Bootloader 的 Flash 布局由 bootloader-storage 组件决定,典型布局如下(以 EFR32MG21、1 MB Flash 为例):

区域起始地址大小用途
Bootloader0x00000000约 32 KB引导程序本体
Bootloader NVM0x000080008 KB存储升级标志、Slot 元数据
Application0x0000A000约 480 KB当前运行的应用固件
Slot 0(Storage)0x00082000约 480 KBOTA 下载的新固件暂存区
NVM3 / 用户数据0x000FA00024 KB非易失参数、配对信息

关键点在于:Slot 区必须与 Application 区大小一致或更大,否则新固件无法完整写入。Bootloader NVM 区保存了 Bootloader_Storage 结构,其中包含 Slot 起始地址、Slot 大小、当前有效 Slot 编号以及升级状态标志。应用程序通过 bootloader_getStorageInfo() 读取这些信息,而不是硬编码地址。

在 Simplicity Studio 中修改 Slot 大小时,必须同步更新 bootloader-storage 组件的 Storage Slot Size 参数,并重新生成 btl_storage_config.h,否则应用侧计算出的写入地址会与 Bootloader 实际布局不一致,导致升级后校验失败。

三、启动流程:从复位向量到应用跳转

上电或复位后,CPU 从 0x00000000 的复位向量进入 Bootloader。Bootloader 首先初始化时钟和存储驱动,然后读取 NVM 中的升级标志:

  1. 若 Bootloader_Nvm 中 upgradePending 为真,说明应用已请求安装新固件。Bootloader 会校验 Slot 区固件的 CRC 和签名,通过后将 Slot 内容拷贝到 Application 区,清除标志,再跳转到应用。
  2. 若标志为假,Bootloader 直接跳转到 Application 区入口。跳转前会关闭已使用的外设、设置栈指针、重定向向量表。
  3. 若 Application 区固件校验失败(如 CRC 不匹配),Bootloader 会停留在引导模式,等待主机通过 Standalone 协议重新下发固件,或根据配置进入安全模式。

整个跳转过程由 Bootloader_JumpToApplication() 完成,核心动作是读取应用向量表的初始 MSP 和 Reset Handler,然后执行 __set_MSP() 并跳转。应用程序的链接脚本必须把起始地址设置为 Application 区起始地址(如 0x0000A000),否则跳转后取指会落到错误位置。

Gecko Bootloader 启动流程与存储布局 Flash 布局(1 MB 示例) Bootloader 0x00000000 · 32 KB Bootloader NVM 0x00008000 · 8 KB Application 0x0000A000 · 480 KB Slot 0(Storage) 0x00082000 · 480 KB NVM3 / 用户数据 0x000FA000 · 24 KB Slot 大小 ≥ Application 大小 启动与升级判断流程 复位 / 上电 读取 NVM 升级标志 upgradePending = true ? 是 校验 Slot 固件 CRC 拷贝到 Application 区 清除标志 · 跳转应用 否 直接跳转 Application 跳转动作:读取应用向量表 MSP / Reset Handler → __set_MSP() → 跳转

四、与应用程序的接口约定

Application Bootloader 与应用程序之间通过一组 API 和共享内存结构通信,核心约定包括:

  • 存储信息查询:应用调用 bootloader_getStorageInfo(&info) 获取 Slot 起始地址、大小和当前 Slot 编号,避免硬编码。
  • 写入新固件:应用通过 bootloader_writeStorage() 将 OTA 数据写入 Slot 区,写入前需调用 bootloader_eraseStorageSlot() 擦除目标 Slot。
  • 请求安装:写入完成后调用 bootloader_rebootAndInstall(),该函数会设置 NVM 中的升级标志并触发复位,由 Bootloader 完成后续拷贝。
  • 校验与回滚:Bootloader 在拷贝前校验 Slot 固件的 CRC32 和可选签名。若校验失败,标志被清除,应用继续运行旧固件,实现天然回滚。

接口约定中有一个容易忽略的细节:应用链接脚本的起始地址必须与 Bootloader 配置中的 Application 起始地址一致。在 Simplicity Studio 中,这个值由 bootloader-storage 组件的 Application Start Address 参数决定,并自动写入 btl_storage_config.h。如果应用链接脚本仍使用默认的 0x00000000,跳转后会出现 HardFault。

修改 Bootloader 布局后,必须同时重新编译 Bootloader 和应用程序,并确保两者使用同一份 btl_storage_config.h。只更新其中一方会导致地址错位,升级后设备无法启动。

五、实操检查清单

在完成 Bootloader 配置后,建议按以下顺序核对:

检查项预期值 / 操作判断依据
Bootloader 类型Application 型组件中 Bootloader Type 选择正确
Application 起始地址0x0000A000(示例)与应用链接脚本一致
Slot 大小≥ Application 区大小btl_storage_config.h 中 Slot Size 字段
NVM 区域独立于 Slot 和 Application地址不重叠
跳转测试烧录后复位,应用正常启动串口输出应用版本号
升级测试写入 Slot 后调用 rebootAndInstall重启后运行新固件版本