IC:

概述

OTA(空中下载技术)升级机制允许设备在固件正常运行时,通过 WiFi、SPI、UART 以及文件系统等方式, 根据接收到的数据进行自我更新,可及时升级设备功能与性能。

使用 OTA 之前请先参考 Flash布局与配置 章节了解更多关于Flash布局的细节。

固件分区

在 Flash 布局中配置了两个固件分区(OTA1和OTA2)用于冗余存储和版本控制, OTA1 和 OTA2 在 Flash 布局中的位置请参考 Flash布局与配置。 BOOT 程序基于验证标准在这些分区之间进行选择。

固件标签和版本号

在 OTA1/OTA2 之间的启动选择主要依赖于证书和 Manifest 中的固件标签和版本号。如下图所示,证书和 Manifest 中均包含 8 字节的固件标签, 2 字节的主版本号和 2 字节的次版本号。

../../_images/major_and_minor_version_cn.svg

固件标签是一个固定的8字节长度的数据。OTA 选择流程检查固件标签的有效性, BOOT 程序和 APP 程序有不同的固件标签, 其中 BOOT 程序在 Manifest 中检查固件标签, APP 程序在证书中检查固件标签。

版本号是主版本号和次版本号的组合。版本号计算方式如下:

\[\text{版本号} = (\text{主版本号} \ll 16) \, | \, \text{次版本号}\]

OTA 选择流程比较版本号的大小, BOOT 程序和 APP 程序可以有不同的版本号,其中 BOOT 程序在 Manifest 中检查版本号, APP 程序在证书中检查版本号。

设备在 OTA 升级后的下一次启动, BOOT 程序中会检查固件标签的有效性和比较版本号大小,以决定从 OTA1 或 OTA2 启动。固件标签和版本一致性确保了可靠的启动。每个固件必须检查以下项目:

  1. 检查 OTA1 和 OTA2 的固件标签是否有效。

    • 如果只有一个固件标签有效,则从有效的固件启动。

    • 如果两个固件标签都无效,则启动失败。

  2. 比较 OTA1 和 OTA2 的版本号。

    • 如果 OTA1 和 OTA2 都有效且版本号不同,设备将从版本号更大的固件启动。

    • 如果 OTA1 和 OTA2 都有效但版本号相同,设备将从 OTA1 启动。

    ../../_images/ota_select_diagram_cn.svg

对于升级后的下一次启动需要切换到新的固件运行, OTA 支持以下两种方式在下次启动时切换到新的固件:

在新固件的 Manifest 中设置一个更高的版本号,下次启动将会从新固件启动。该方式需要在每次升级时都修改新固件的版本号,才能保证下次从新固件启动。

在项目文件夹中配置文件 manifest.json 中修改新固件的版本号。

  1. 为 BOOT 程序配置版本号,版本号范围为 0 到 32767 。

    "boot":
    {
       "IMG_ID": "0",
       "IMG_VER_MAJOR": 1,
       "IMG_VER_MINOR": 1,
       ...
    },
    
  2. 为 APP 程序配置版本号,版本号范围为 0 到 65535。

    "app":
    {
       "IMG_ID": "1",
       "IMG_VER_MAJOR": 1,
       "IMG_VER_MINOR": 1,
       ...
    },
    

用户可以根据需求选择 取决于版本号的方式 或 取决于固件标签的方式 。

防回滚

防回滚功能用于防止版本回滚攻击。当防回滚启用时,证书或 Manifest 中的主版本号不能小于设置在 OTP 中的防回滚版本。 否则,该固件将被视为无效,而芯片将不会从无效固件启动。

通常,如果 OTA 更新与安全性相关,用户可以在 OTP 中设置一个更大的防回滚版本号,并同时更新带有主版本号比防回滚版本号大的固件以防止回滚攻击。

防回滚流程如下所示:

  1. 设备分别比较从 OTA1 和 OTA2 固件获取的主版本号与 OTP 中的防回滚版本号。

  2. 如果固件的主版本号小于防回滚版本号,则该固件将被视为无效。

../../_images/anti_rollback_flow_cn.svg

用户可以通过以下步骤启用防回滚功能:

  1. 更改 BOOT 程序的防回滚版本号。默认情况下,所有固件使用 OTP 中相同的防回滚版本作为阈值以防止防回滚攻击。

    名称

    OTP 地址

    长度

    描述

    BOOT 程序版本号

    物理地址 0x36E~0x36F

    16 位

    BOOT 程序的防回滚版本号

    防回滚的 BOOT 程序版本默认值为0。用户可以更改’0’位的数量以增加BOOT 程序版本。

    例如,通过以下命令将防回滚的 BOOT 程序版本设置为 1 :

    EFUSE wraw 36E 2 FFFE
    
  2. 通过以下命令写入 OTP 以启用防回滚。

    EFUSE wraw 368 1 BF
    

注意

  • 一旦启用防回滚,就无法禁用。

  • 如果 BOOT 程序和 APP 程序不使用相同的防回滚版本,修改 bootloader\boot_ota_km4.c 或 bootloader\boot_ota_hp.c 中的 BOOT_OTA_GetCertRollbackVer() 并在 OTP 中为 APP 程序定义另一个防回滚版本。

BOOT 程序

OTA 固件

KM4 BOOT 程序(km4_boot_all.bin)可以通过 OTA 更新,并能够从 OTA1 或 OTA2 启动。KM4 BOOT 程序的布局如下图所示。

../../_images/layout_of_km4_bootloader_image_cn.svg

用户可通过以下步骤使能升级 BOOT 程序:

  1. 参考 配置 SDK (menuconfig) 进入 CONFIG OTA OPTION 配置,勾选 Enable Bootloader OTA ,此步骤将BOOT 程序固件集成到 ota_all.bin 中。

  2. 将 BOOT 程序的 OTA2 地址写入 OTP。根据 Flash_Layout 中的 IMG_BOOT_OTA2 设置此地址,参考 用户配置 。

    EFUSE wraw 36C 2 IMG_BOOT_OTA2
    

    例如, IMG_BOOT_OTA2 为 0x08200000 ,则写入 OTP 的命令为:

    EFUSE wraw 36C 2 0082
    

    注意

    • BOOT OTA2 地址为 OTP 地址 0x36C 中的值左移 12 位的值,或 OTP 地址 0x36C 中的值 * 4K。

    • 如果 BOOT OTA2 的默认地址为 0xFFFFFFFF ,则在 OTA 期间不会进行 BOOT 程序升级,设备总是从 BOOT OTA1 启动。

OTA 选择流程

ROM BOOT 程序根据 KM4 BOOT 程序 Manifest 中的版本号选择 OTA 固件, KM4 BOOT 程序 OTA 选择流程如下图所示。

../../_images/km4_bootloader_ota_select_flow_cn.svg

APP 程序

OTA 固件

应用程序固件 ( km0_km4_app.bin ) 包含 KM0、KM4 非安全和 KM4 安全应用程序。此固件可以通过 OTA 更新,并且能够从 OTA1 或 OTA2 启动。 应用程序固件的布局如下图所示。

../../_images/layout_of_application_image_cn.svg

OTA 选择流程

BOOT 程序根据 APP 程序证书中的版本号选择 OTA 固件, APP 程序 OTA 选择流程如下图所示。

../../_images/application_image_ota_select_flow_cn.svg

OTA 压缩固件

当启用 OTA 固件压缩功能时, APP 固件将被压缩,从而减小固件的大小,这可以有效节省 Flash 空间。

OTA 固件压缩仅适用于后缀为 app.bin 的 APP 程序固件。压缩完成后,生成的压缩固件文件将放在目录 image 中,文件后缀为 app_compress.bin 。 同时,压缩后的 APP 程序固件将被整合到 ota_all.bin 文件中,将用于 OTA 应用中。

压缩算法采用 LZMA(Lempel-Ziv-Markov 链算法),这是一种由 Igor Pavlov 开发的无损数据压缩算法,以其高压缩比和相对较低的解压内存要求而著称。 LZMA 算法通常用于 7z 格式的文件压缩,并广泛应用于 7-Zip 软件。

在这里,我们使用压缩率来衡量压缩效率。压缩率的计算公式如下:

\[\text{压缩率(%)} = \left( \frac{\text{压缩后固件大小}}{\text{原始固件大小}} \right) \times 100\]

压缩率会受到固件内容的影响。通常,压缩率在 50 %到 70 %之间。原始固件内容越复杂,压缩率往往越高。

OTA 压缩功能启用后启动流程具有以下特点:

  1. 如果压缩固件的版本号大于或等于非压缩固件的版本号,系统将选择压缩固件。

  2. 压缩固件将被解压到另一个 OTA 分区,同时覆盖该分区的旧固件。

  3. 在成功解压之后,压缩固件的固件标签将被清除。

  4. 压缩固件只需要在下载完成后首次启动时解压一次,之后将不再执行解压程序。

../../_images/compress_image_ota_select_flow_cn.svg

在使能 OTA 固件压缩功能时,建议在 OTA1 区存放非压缩固件, OTA2 区则存放压缩固件。用户可以根据压缩率来提前规划好 Flash 布局。

通过以下图片给出示例:

  1. 设备从 OTA1 启动并运行 OTA 应用。

  2. 压缩固件被下载到 OTA2。

  3. 下一次启动时,系统将选择压缩固件,将其解压到 OTA1 ,然后继续从 OTA1 启动。

../../_images/compress_ota_select_diagram_cn.svg

用户可通过以下步骤生成 OTA 压缩固件:

  1. 参考 配置 SDK (menuconfig) 进入 CONFIG OTA OPTION 配置,勾选 Enable Compress APP Image 来启用 OTA 固件压缩功能。

  2. 编译项目,包含压缩 APP 程序固件的 ota_all.bin 将生成在 {SDK}\amebaxxx_gcc_project 目录下。

编译 OTA 固件

修改配置

  1. 参考 固件标签和版本号 选择启动新固件的方式。

  2. 调整 BOOT 程序的防回滚版本号,并在必要时启用防回滚,启用步骤请参考 防回滚 。

  3. 如果用户需要升级 BOOT 程序,启用步骤请参考 BOOT 程序 。

  4. 如果需要启用 OTA 压缩功能,请按照 OTA 压缩固件 中的步骤进行操作。

生成 OTA 固件

在编译项目时, OTA 固件将自动生成。

  1. 应用程序固件 xxx_app.bin 文件默认包含在 ota_all.bin 文件中。

  2. 编译项目。OTA 固件 ( ota_all.bin ) 将生成在 {SDK}\amebaxxx_gcc_project 目录下。

OTA 固件格式

ota_all.bin 的文件格式如下所示。

../../_images/firmware_format_cn.svg
OTA 文件头

项目

地址偏移

大小

描述

版本号

0x00

4 字节

OTA 文件头中的版本号, 默认值是 0xFFFFFFFF。

数量

0x04

4 字节

OTA 文件头的数量。 值为 1 或 2。

标签

0x08

4 字节

OTA 文件头的标签。 值为 OTA 。

长度

0x0C

4 字节

OTA 文件头的长度。 值为 0x18 * OTA 文件头的数量。

校验和

0x10

4 字节

升级固件的校验和。

固件长度

0x14

4 字节

升级固件的长度。

固件偏移量

0x18

4 字节

在当前固件中升级固件的起始位置。

固件ID

0x1C

4 字节

升级固件的固件ID:

  • OTA_IMGID_BOOT: 0x0

  • OTA_IMGID_APP: 0x1

从无线网络更新

本节介绍通过无线网络服务器进行 OTA 的设计原则和用法。它具有良好的可移植性,便于用户移植到自己的 OTA 应用程序中。

网络服务器 OTA 显示设备如何从网络下载服务器升级固件。网络下载服务器基于网络套接字将固件发送给设备,如下图所示。

../../_images/ota_update_diagram_via_network_cn.svg

注意

确保设备和 PC 连接到同一局域网。

OTA 例程

按照以下步骤运行 OTA 例程以从 HTTP 服务器升级:

  1. 如果在 修改配置 中选择 取决于固件标签的方式 ,则按照该方式中描述修改,否则跳过此步骤。

  2. 编辑 example_ota.c。

    1. 根据服务器IP地址编辑主机。

      #define PORT   8082
      static const char *host = "192.168.31.193";   //"m-apps.oss-cn-shenzhen.aliyuncs.com"
      static const char *resource = "ota_all.bin"; //"051103061600.bin"
      
    2. 将 OTA 类型编辑为 OTA_HTTP。

      ret = ota_update_init(ctx, (char *)host, PORT, (char *)resource, OTA_HTTP);
      
  3. 使用命令 ./build.py -a ota 重新编译项目并将固件下载到设备。

  4. 如果在 修改配置 中选择 取决于版本号的方式 ,则按照该方式中描述修改,否则跳过此步骤。

  5. 使用命令 ./build.py 重新编译项目,并将 ota_all.bin 复制到 DownloadServer(HTTP)。

  6. 编辑 http_server.py。

    server_ip = '192.168.31.193'
    server_port = 8082
    
  7. 使用命令 python http_server.py 执行脚本,以启动下载服务器程序。

  8. 重置设备并连接到 HTTP 服务器。

  9. 固件下载完成后,设备将自动重置并从新固件启动。

用户配置

Flash 布局请参考 Flash布局与配置 章节。如果有需要,请修改 Flash 布局。用户应该提前规划好Flash 布局,并且预留足够的空间。