升级机制

MCUboot 支持多种固件升级方式,如下表所示。详细说明可参考 MCUboot 官网介绍

升级方式

特点

Upgrade only

将新固件直接覆盖旧固件,不进行交换,不可回滚

Swap using scratch

通过 scratch 分区做中转,完成新旧固件交换,可回滚

Swap using offset

依靠分区内的偏移布局进行交换,无需 scratch 分区,可回滚

Swap using move

通过移动数据完成交换,无需 scratch 分区,可回滚

Direct XIP

直接原地执行,无需交换

RAM load

将固件完整加载到 RAM 后执行

Firmware loader

通过专用加载器进行升级

当前支持以下两种升级方式:

Swap_using_move

Swap_using_move 是一种无需临时存储区(scratch)的固件交换算法,适用于 主 / 次双槽 OTA 升级场景。 其核心是通过将主槽扇区整体后移一位,再交替复制主槽与次槽内容,完成固件交换。

可通过配置宏 CONFIG_BOOT_SWAP_USING_MOVE 启用此升级方式。采用 --sysbuild 时需在应用程序 sysbuild.conf 中配置 SB_CONFIG_MCUBOOT_MODE_SWAP_USING_MOVE=y

工作原理:

  1. 扇区下移:先将主槽所有扇区向下移动一个扇区位置。

  2. 交替复制:从第 1 个扇区开始,将次槽第 N 个扇区复制到主槽第 N 个扇区,逐扇区重复,直至全部交换完成。

    ../../_images/zephyr_ota_swap_using_move.svg

从图示可知,每个扇区的交换过程包含 3 个状态:

  1. 主槽[N] → 主槽[N+1]已完成

  2. 次槽[N] → 主槽[N] 已完成

  3. 主槽[N+1] → 次槽[N] 已完成

Swap_using_offset

Swap_using_offset 是一种无需临时存储区(scratch)的固件交换算法,是 Swap_using_move 的增强版。 其核心是利用次槽中的一个扇区作为临时缓冲,交替复制主、次槽内容,完成固件交换。

可通过配置宏 CONFIG_BOOT_SWAP_USING_OFFSET 启用此升级方式;采用 --sysbuild 时需在应用程序 sysbuild.conf 中配置 SB_CONFIG_MCUBOOT_MODE_SWAP_USING_OFFSET=y

工作原理:

  1. 固件放置:待升级的新固件必须从次槽的第二个扇区开始存放。

  2. 交替复制:从第 1 个扇区开始,对每个扇区 N 依次执行:

    • 将主槽第 N 个扇区复制到次槽第 N 个扇区;

    • 将次槽第 N+1 个扇区复制到主槽第 N 个扇区。

    逐扇区重复,直至全部交换完成。

    ../../_images/zephyr_ota_swap_using_offset.svg

从图示可知,每个扇区的交换过程包含 2 个状态:

  1. 主槽[N] → 次槽[N] 已完成

  2. 次槽[N+1] → 主槽[N] 已完成

交换类型与状态

交换类型

在正常升级流程中(未异常掉电 / 中断),MCUboot 会根据 固件尾部(Trailer) 中的标志位决定执行的交换类型(swap type)。交换类型有以下几种:

  • BOOT_SWAP_TYPE_NONE:无升级任务,直接启动主槽固件。

  • BOOT_SWAP_TYPE_TEST:测试运行;若未通过设置 image-ok=0x01 确认,下次启动将触发回退。

  • BOOT_SWAP_TYPE_PERM:永久交换,不需要设置 image-ok=0x01 确认。

  • BOOT_SWAP_TYPE_REVERT:上次 TEST 未确认,回退至原有旧固件。

  • BOOT_SWAP_TYPE_FAIL:目标固件无效(如校验失败)。

  • BOOT_SWAP_TYPE_PANIC:交换过程出现不可恢复错误,启动终止。

受 Flash 硬件特性限制,Trailer 的设计并不直观,直接读取原始字节难以解析设备状态。因此,MCUboot 将“各种可能的 Trailer 组合状态”映射为上述交换类型,并按优先级顺序判定:State 编号越小优先级越高,一旦匹配某一状态,立即确定对应的交换类型并停止继续匹配。

State I 场景(仅 Swap_using_offset 模式):在执行 REVERT 前的风险窗口,记录 magic 和 copy-done 到次槽,下次启动会继续执行 REVERT。这是 offset 模式回退过程中的一个中间态,用于保证掉电后仍能续做回退。

State I (swap using offset only)
                 | primary slot | secondary slot |
-----------------+--------------+----------------|
           magic | Any          | Good           |
        image-ok | Any          | Unset          |
       copy-done | Any          | Set            |
-----------------+--------------+----------------'
 result: BOOT_SWAP_TYPE_REVERT                   |
-------------------------------------------------'

State II 场景:次槽固件有效但未确认,执行“测试交换”。系统会将次槽固件交换到主槽并启动。 新固件需在应用中设置 image-ok 完成确认;若未确认,下一次启动将自动 REVERT 。

State II
                 | primary slot | secondary slot |
-----------------+--------------+----------------|
           magic | Any          | Good           |
        image-ok | Any          | Unset          |
       copy-done | Any          | Any            |
-----------------+--------------+----------------'
 result: BOOT_SWAP_TYPE_TEST                     |
-------------------------------------------------'

State III 场景:次槽固件已预先标记 image-ok,执行“永久交换”,升级完成后不会回退。

State III
                 | primary slot | secondary slot |
-----------------+--------------+----------------|
           magic | Any          | Good           |
        image-ok | Any          | 0x01           |
       copy-done | Any          | Any            |
-----------------+--------------+----------------'
 result: BOOT_SWAP_TYPE_PERM                     |
-------------------------------------------------'

State IV 场景:主槽复制已完成(copy-done=Set),但新固件未确认(image-ok=Unset),因此本次启动执行回退,恢复为旧固件。

State IV
                 | primary slot | secondary slot |
-----------------+--------------+----------------|
           magic | Good         | Any            |
        image-ok | 0xff         | Any            |
       copy-done | 0x01         | Any            |
-----------------+--------------+----------------'
 result: BOOT_SWAP_TYPE_REVERT                   |
-------------------------------------------------'

若以上状态 State I~IV 均不匹配,MCUboot 不会执行固件交换,而是进入 State V,选择三种交换类型之一。

State V
                 | primary slot | secondary slot |
-----------------+--------------+----------------|
           magic | Any          | Any            |
        image-ok | Any          | Any            |
       copy-done | Any          | Any            |
-----------------+--------------+----------------'
 result: BOOT_SWAP_TYPE_NONE,                    |
         BOOT_SWAP_TYPE_FAIL, or                 |
         BOOT_SWAP_TYPE_PANIC                    |
-------------------------------------------------'

交换状态

交换状态(Swap status)用于掉电恢复,记录在主槽的 固件尾部(Trailer) 中。 若固件交换过程中发生异常重启,MCUboot 可根据已记录的交换状态恢复现场,继续完成未结束的交换流程。 该区域由一系列单字节状态记录组成,每条记录独立写入,并按照设备的最小写入粒度进行对齐填充。 典型交换流程如下:

  1. 初始化: 同时擦除主、次槽 Trailer;然后在主槽 Trailer 写入 Swap info、Swap size 及 MAGIC 标记。

  2. 逐扇区交换:仅对固件实际占用的扇区(包含 TLV 区域)进行交换,并根据所选算法记录每个扇区的状态。

  3. 收尾:交换完成后,在主槽 Trailer 中写入 Copy done,标记交换流程结束。

0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|sec127,state 0 |sec127,state 1 |sec127,state 2 |sec126,state 0 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|sec126,state 1 |sec126,state 2 |sec125,state 0 |sec125,state 1 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|sec125,state 2 |                                               |
+-+-+-+-+-+-+-+-+                                               +
~                                                               ~
~               [Records for indices 124 through 1              ~
~                                                               ~
~               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
~               |sec000,state 0 |sec000,state 1 |sec000,state 2 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

备注

图示假设 min-write-size = 1,每个“扇区索引”对应 3 个状态记录,适用于 Swap_using_move 模式;而在 Swap_using_offset 模式下,每个扇区仅有 2 个状态记录,所需总空间更小。