概述
OTA(空中下载技术)升级机制允许设备在固件正常运行时,通过 WiFi、SPI、UART 以及文件系统等方式, 根据接收到的数据进行自我更新,可及时升级设备功能与性能。
使用 OTA 之前请先参考 Flash布局与配置 章节了解更多关于Flash布局的细节。
固件分区
在Flash布局中配置了两个固件分区(OTA1和OTA2)用于冗余存储和版本控制,如下图所示。BOOT 程序基于验证标准在这些分区之间进行选择。
固件标签和版本号
在 OTA1/OTA2 之间的启动选择主要依赖于证书和 Manifest 中的固件标签和版本号。如下图所示,证书和 Manifest 中均包含 8 字节的固件标签, 2 字节的主版本号和 2 字节的次版本号。
固件标签是一个固定的8字节长度的数据。OTA 选择流程检查固件标签的有效性, BOOT 程序和 APP 程序有不同的固件标签, 其中 BOOT 程序在 Manifest 中检查固件标签, APP 程序在证书中检查固件标签。
版本号是主版本号和次版本号的组合。版本号计算方式如下:
OTA 选择流程比较版本号的大小, BOOT 程序和 APP 程序可以有不同的版本号,其中 BOOT 程序在 Manifest 中检查版本号, APP 程序在证书中检查版本号。
设备在 OTA 升级后的下一次启动, BOOT 程序中会检查固件标签的有效性和比较版本号大小,以决定从 OTA1 或 OTA2 启动。固件标签和版本一致性确保了可靠的启动。每个固件必须检查以下项目:
检查 OTA1 和 OTA2 的固件标签是否有效。
如果只有一个固件标签有效,则从有效的固件启动。
如果两个固件标签都无效,则启动失败。
比较 OTA1 和 OTA2 的版本号。
如果 OTA1 和 OTA2 都有效且版本号不同,设备将从版本号更大的固件启动。
如果 OTA1 和 OTA2 都有效但版本号相同,设备将从 OTA1 启动。
对于升级后的下一次启动需要切换到新的固件运行, OTA 支持以下两种方式在下次启动时切换到新的固件:
在新固件的 Manifest 中设置一个更高的版本号,下次启动将会从新固件启动。该方式需要在每次升级时都修改新固件的版本号,才能保证下次从新固件启动。
在项目文件夹中配置文件 manifest.json
中修改新固件的版本号。
为 BOOT 程序配置版本号,版本号范围为 0 到 32767 。
"boot": { "IMG_ID": "0", "IMG_VER_MAJOR": 1, "IMG_VER_MINOR": 1, ... },
为 APP 程序配置版本号,版本号范围为 0 到 65535。
"app": { "IMG_ID": "1", "IMG_VER_MAJOR": 1, "IMG_VER_MINOR": 1, ... },
不修改新固件的 Manifest 中的版本号,而是在升级完成后破坏旧固件的固件标签,比如将旧固件的固件标签全部写为 0 ,这样旧固件转为无效固件,下次启动将会从新固件启动。 该方式不需要修改版本号,更为简单。
将 ameba_ota.h
中定义的 OTA_CLEAR_PATTERN 修改为 1 ,则采用该方式。
用户可以根据需求选择 取决于版本号的方式
或 取决于固件标签的方式
。
防回滚
防回滚功能用于防止版本回滚攻击。当防回滚启用时,证书或清单中的版本号不能小于设置在 OTP 中的防回滚版本。 否则,该固件将被视为无效,而芯片将不会从无效固件启动。 通常,如果 OTA 更新与安全性相关,用户可以在 OTP 中编程一个更大的防回滚版本号,并同时更新带有更大主版本的固件以防止回滚攻击。
防回滚流程如下所示。一旦防回滚启用,设备将分别比较从 OTA1 和 OTA2 固件获取的主版本号与 OTP 中的防回滚版本号。 如果固件的主版本号小于防回滚版本号,则该固件将被视为无效。
用户可以通过以下步骤启用防回滚功能:
更改 BOOT 程序的防回滚版本号。默认情况下,所有固件使用 OTP 中相同的防回滚版本作为阈值以防止防回滚攻击。
名称
OTP 地址
长度
描述
BOOT 程序版本号
物理地址 0x36E~0x36F
16 位
BOOT 程序的防回滚版本号
防回滚的 BOOT 程序版本默认值为0。用户可以更改’0’位的数量以增加BOOT 程序版本。
例如,通过以下命令将防回滚的 BOOT 程序版本设置为 1 :
EFUSE wraw 36E 2 FFFE
通过以下命令写入 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 程序的布局如下图所示。
用户可通过以下步骤使能升级 BOOT 程序:
参考 配置 SDK (menuconfig) 进入
CONFIG OTA OPTION
配置,勾选Enable Bootloader OTA
,此步骤将BOOT 程序固件集成到 ota_all.bin 中。将 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 选择流程如下图所示。
APP 程序
OTA 固件
应用程序固件 ( km0_km4_app.bin
) 包含 KM0、KM4 非安全和 KM4 安全应用程序。此固件可以通过 OTA 更新,并且能够从 OTA1 或 OTA2 启动。
应用程序固件的布局如下图所示。
应用程序固件 ( kr4_km4_app.bin
) 包含 KR4、KM4 非安全和安全应用程序。此固件可以通过 OTA 更新,并且能够从 OTA1 或 OTA2 启动。
应用程序固件的布局如下图所示。
用户可以通过两种方案加载 DSP 固件,更多细节请参考 DSP 固件 。
DSP 固件
用户可以通过以下两种方案加载 DSP 固件。在接下来的操作中,我们选择 DSP 固件合并到应用固件中 的方案,并使用文件 kr4_km4_dsp_app.bin
。
在此方案中, Flash 布局中分别有两个名为 IMG_APP_OTA1
和 IMG_APP_OTA2
的分区。由于 DSP 固件被合并到应用程序固件中,
这样可以避免当只有一个 DSP 分区时,由于通过 OTA 应用更新 DSP 固件可能导致的 DSP 启动失败的问题。对于 MP (量产)设备,
推荐使用DSP 固件合并到应用固件中的方案,这样 DSP 可以选择从 OTA1 或 OTA2 启动。
选择此方案后,只需下载一个名为 kr4_km4_dsp_app.bin
的应用程序固件,如下图所示。

生成 kr4_km4_dsp_app.bin
的步骤如下:
参考 配置 SDK (menuconfig) 进入
CONFIG DSP Enable
配置,勾选Enable DSP
和DSP within APP image
,以启用应用程序固件中的 DSP
配置。配置
DSP_IMAGE_TARGET_DIR
为dsp.bin
的路径。*** --------MENUCONFIG FOR General--------- *** CONFIG DSP Enable ---> [*] Enable DSP [*] DSP within APP image (../component/dsp) DSP_IMAGE_TARGET_DIR CONFIG TrustZone ---> ...
注意
DSP_IMAGE_TARGET_DIR 是相对于 amebalite_gcc_project 来设置的。
例如,一旦 DSP SDK 编译完成,将生成两个文件:dsp.bin
和 dsp_all.bin
,它们位于 {DSP_SDK}\project\image
目录。
将
dsp.bin
复制到{SDK}\component\dsp
中,因此dsp.bin
的路径为../component/dsp
。按照上面的第 3 步设置路径。在
SDK\amebalite_gcc_project\menuconfig\.config
文件中检查路径设置是否正确。# CONFIG DSP Enable # CONFIG_DSP_EN=y CONFIG_DSP_WITHIN_APP_IMG=y CONFIG_DSP_IMAGE_TARGET_DIR="../component/dsp" # end of CONFIG DSP Enable
重新编译项目。
kr4_km4_dsp_app.bin
文件生成在{SDK}\amebalite_gcc_project
中。
在此方案中, Flash 布局中只有一个名为 IMG_DSP
的区域用于下载 DSP 固件。当 DSP 应用程序被修改时,
用户只需将名为 dsp_all.bin
的 DSP 固件重新下载到 IMG_DSP
中,如下图所示。因此,在设备处于 DSP 开发阶段时,建议使用此方案以便便捷高效地开发 DSP 应用程序。

要选择此方案,用户可以通过以下步骤禁用 DSP within APP image
的配置:
参考 配置 SDK (menuconfig) 进入
CONFIG DSP Enable
配置,取消勾选DSP within APP image
。重新编译项目。
kr4_km4_app.bin
文件生成在{SDK}\amebalite_gcc_project
中。
注意
此方案建议仅在设备 DSP 开发阶段使用。
OTA 选择流程
BOOT 程序根据 APP 程序证书中的版本号选择 OTA 固件, APP 程序 OTA 选择流程如下图所示。
OTA 压缩固件
当启用 OTA 固件压缩功能时, OTA 固件将被压缩,从而减小固件的大小,这可以有效节省 Flash 空间。
OTA 固件压缩仅适用于后缀为 app.bin 的 APP 程序固件。压缩完成后,生成的压缩固件文件将放在目录 image 中,文件后缀为 app_compress.bin 。 同时,压缩后的 APP 程序固件将被整合到 ota_all.bin 文件中。
压缩算法采用 LZMA(Lempel-Ziv-Markov 链算法),这是一种由 Igor Pavlov 开发的无损数据压缩算法,以其高压缩比和相对较低的解压内存要求而著称。 LZMA 算法通常用于 7z 格式的文件压缩,并广泛应用于 7-Zip 软件。
在这里,我们使用压缩率来衡量压缩效率。压缩率的计算公式如下:
压缩率会受到固件内容的影响。通常,压缩率在 60 %到 70 %之间。原始固件内容越复杂,压缩率往往越高。
一旦压缩的 APP 程序固件被下载到一个 OTA 分区,系统将始终优先选择压缩固件。压缩固件将解压到另一个 OTA 分区,然后系统从该分区启动。 这意味着两个分区之间只有一个有效的 APP 程序固件。例如,如果设备目前从 OTA1 启动并运行 OTA 应用,压缩固件将被下载到 OTA2。 下一次启动时,系统将选择压缩固件,将其解压到 OTA1 ,然后继续从 OTA1 启动。
用户可通过以下步骤生成 OTA 压缩固件:
参考 配置 SDK (menuconfig) 进入
CONFIG OTA OPTION
配置,勾选Enable Compress APP Image
来启用压缩固件。编译项目,包含压缩 APP 程序固件的
ota_all.bin
将生成在{SDK}\amebadxxx_gcc_project
中。
编译 OTA 固件
修改配置
生成 OTA 固件
在编译项目时, OTA 固件将自动生成。
km0_km4_app.bin
文件默认包含在ota_all.bin
文件中。重新编译项目。OTA 固件 (
ota_all.bin
) 将生成在{SDK}\amebadplus_gcc_project
目录下。
在编译项目时, OTA 固件将自动生成。
kr4_km4_dsp_app.bin
文件默认包含在ota_all.bin
文件中。重新编译项目。OTA 固件 (
ota_all.bin
) 将生成在{SDK}\amebalite_gcc_project
目录下。
注意
生成文件 kr4_km4_dsp_app.bin
的步骤可以参考 DSP 合并到应用固件中 。
在编译项目时, OTA 固件将自动生成。
kr4_km4_app.bin
文件默认包含在ota_all.bin
文件中。重新编译项目。OTA 固件 (
ota_all.bin
) 将生成在{SDK}\amebalite_gcc_project
目录下。
在编译项目时, OTA 固件将自动生成。
km0_km4_ca32_app.bin
文件默认包含在ota_all.bin
文件中。重新编译项目。OTA 固件 (
ota_all.bin
) 将生成在{SDK}\amebesmart_gcc_project
目录下。
OTA 固件格式
ota_all.bin
的文件格式如下所示。
项目 |
地址偏移 |
大小 |
描述 |
---|---|---|---|
Version |
0x00 |
4 字节 |
OTA 头中的版本号, 默认值是 0xFFFFFFFF。 |
Header Number |
0x04 |
4 字节 |
OTA 头的数量。 值为 1 或 2。 |
Signature |
0x08 |
4 字节 |
OTA 头的标签。 值为 |
Header Length |
0x0C |
4 字节 |
OTA 头的长度。 值为 0x18 * OTA 头的数量。 |
Checksum |
0x10 |
4 字节 |
升级固件的校验和。 |
Image Length |
0x14 |
4 字节 |
升级固件的长度。 |
Offset |
0x18 |
4 字节 |
在当前固件中升级固件的起始位置。 |
Image ID |
0x1C |
4 字节 |
升级固件的固件ID:
|
从无线网络更新
本节介绍通过无线网络服务器进行 OTA 的设计原则和用法。它具有良好的可移植性,便于用户移植到自己的 OTA 应用程序中。
网络服务器 OTA 显示设备如何从网络下载服务器升级固件。网络下载服务器基于网络套接字将固件发送给设备,如下图所示。
注意
确保设备和 PC 连接到同一局域网。
OTA 例程
按照以下步骤运行 OTA 例程以从 HTTP 服务器升级:
如果在 修改配置 中选择
取决于固件标签的方式
,则按照该方式中描述修改,否则跳过此步骤。编辑 example_ota.c。
根据服务器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"
将 OTA 类型编辑为
OTA_HTTP
。ret = ota_update_init(ctx, (char *)host, PORT, (char *)resource, OTA_HTTP);
使用命令
./build.py -a ota
重新编译项目并将固件下载到设备。如果在 修改配置 中选择
取决于版本号的方式
,则按照该方式中描述修改,否则跳过此步骤。使用命令
./build.py
重新编译项目,并将ota_all.bin
复制到 DownloadServer(HTTP)。编辑 http_server.py。
server_ip = '192.168.31.193' server_port = 8082
使用命令
python http_server.py
执行脚本,以启动下载服务器程序。重置设备并连接到 HTTP 服务器。
固件下载完成后,设备将自动重置并从新固件启动。
用户配置
Flash 布局请参考 Flash布局与配置 章节。如果有需要,请修改 Flash 布局。用户应该提前规划好Flash 布局,并且预留足够的空间。