固件升级编程指南
概述
OTA (空中下载技术)升级机制允许设备在固件正常运行时,通过 Wi-Fi、SPI、UART 以及文件系统等方式接收新的固件并将其保存到 Flash 对应的固件区,完成后重启即可运行新固件,用以问题修复,新功能发布和性能优化等场景。
使用 OTA 之前请先参考 Flash 布局 章节了解更多 Flash 分区相关细节。
固件分区
在 Flash 布局 中 BOOT 和 APP 固件均有两个固件分区( OTA1 和 OTA2 )用于冗余存储和版本控制。
用户需要根据实际的固件大小以及合理的预留空间来设置这些分区的大小。
备注
BOOT 固件的 OTA 功能默认关闭,如需使用,请参考 BOOT OTA
固件标签和版本号
OTA1/OTA2 固件的启动选择主要依赖于固件头中的固件标签和版本号。如下图所示,固件头包含 8 字节的固件标签、2 字节的主版本号和 2 字节的次版本号。
固件标签和版本号的详细说明如下表所示:
项目 |
描述 |
OTA 选择流程 |
|---|---|---|
固件标签 |
|
检查固件标签的有效性 |
版本号 |
|
比较版本号的大小 |
系统每次启动时, Bootloader 会检查固件标签的有效性并比较版本号,以决定从 OTA1 或 OTA2 分区启动。固件标签和版本号的一致性校验确保了启动过程的可靠性,具体检查流程如下:
检查 OTA1 和 OTA2 分区的固件标签是否有效:
若仅一个固件标签有效,则从该有效固件启动;
若两个固件标签均无效,则启动失败。
比较 OTA1 和 OTA2 分区的版本号:
若两个固件的版本号均有效且不相同,则从版本号较高的固件启动;
若两个固件的版本号均有效但相同,则默认从 OTA1 分区启动。
固件切换策略
基于 固件标签和版本号 中的启动流程, OTA 功能支持以下两种固件切换策略,用于在下次启动时切换到新固件:
备注
有关切换策略的配置,请参考 配置工程(menuconfig) ,进入 进行选择。
在新固件中设置更高的版本号, OTA 升级完成后,设备将在下次启动时自动从新固件启动。 此策略适用于需要版本控制的场景。
配置步骤:
在
menuconfig中选择切换策略:CONFIG OTA OPTION ---> [*] OTA Image Switch Strategy Select Strategy (Version Number Based) ---> (X) Version Number Based ( ) Valid Header Based
在目标 IC 的配置文件
manifest.json5中修改新固件的版本号:RTL8721Dx:github source code
RTL8720E:github source code
RTL8710E:github source code
RTL8726E:github source code
RTL8713E:github source code
RTL8730E:github source code
RTL8721F:github source code
RTL8720F:github source code
RTL8735C:github source code
BOOT 固件版本号配置(有效范围:0 ~ 32767)
"image1": { "img_id": 0, "img_ver_major": 1, "img_ver_minor": 1, ... },
APP 固件版本号配置(有效范围:0 ~ 65535)
"image2": { "img_id": 1, "img_ver_major": 1, "img_ver_minor": 1, ... },
小技巧
每次 OTA 升级时,应递增版本号,确保新固件的版本号高于当前运行的固件。
该策略无需修改新固件的版本号,而是在 OTA 升级完成后破坏旧固件的固件标签,使其变为无效固件,从而强制 Bootloader 使用新升级的固件。 此策略会主动使旧固件失效,适用于长期运行测试或无需版本控制的场景。
配置步骤:
在 menuconfig 中选择切换策略:
CONFIG OTA OPTION --->
[*] OTA Image Switch Strategy
Select Strategy (Version Number Based) --->
( ) Version Number Based
(X) Valid Header Based
警告
此策略会破坏旧固件的头部信息,导致其无法启动。若新固件存在问题,需重新烧录固件。
特性 |
基于版本号切换 |
基于有效标签切换 |
|---|---|---|
版本号要求 |
需递增版本号 |
无需修改版本号 |
配置复杂度 |
中等(需维护版本号) |
简单(无需额外配置) |
旧固件状态 |
保留完整 |
标签损坏 |
BOOT OTA 支持 |
所有芯片均支持 |
部分支持( RTL8726E/RTL8713E/RTL8720E/RTL8710E 不支持) |
APP OTA 支持 |
所有芯片均支持 |
所有芯片均支持 |
防回滚功能
防回滚功能用于防止设备回滚到主版本号低于 OTP 中防回滚版本号的固件。启用该功能后,固件头中的主版本号不能小于 OTP 中设置的防回滚版本号,否则该固件将被视为无效。
通常,若本次 OTA 升级修复了旧版本的安全问题,可在升级完成后,将防回滚版本号设置为本次升级固件的主版本号,以防止设备回滚到存在该问题的旧版本。
防回滚流程如下:
分别读取 OTA1 和 OTA2 固件头中的主版本号,并与 OTP 中的防回滚版本号比较。
若固件的主版本号小于防回滚版本号,则该固件无效。
OTP 配置说明:
防回滚版本号存储在芯片的 OTP 区域中:
OTP 的物理地址范围为 0x36E ~ 0x36F。
OTP 值中比特 0 的个数即为防回滚版本号。OTP 默认值为全 F ,对应的防回滚版本号为 0。
OTP 的比特位只能从 1 写为 0 ,且该地址范围共 16 位,因此最多支持 16 个防回滚版本号(版本号范围:1 ~ 16)。
启用防回滚:
启用防回滚功能需完成以下 2 个步骤:
设置 OTP 中的防回滚版本号:
通过以下命令读取当前的防回滚版本号:
AT+OTP=RRAW,36E,2
通过以下命令写入防回滚版本号:
AT+OTP=WRAW,36E,2,<Value_OTP>
其中
<Value_OTP>为目标版本号对应的 OTP 值,计算示例如下:例 1:写入
FFFC或FFCF均可。两个值中都有 2 个比特为 0 ,OTP 中的防回滚主版本号为 2 ,版本号小于(2 << 16)的固件将被禁止启动。例 2:写入
FFF0或0FFF均可。两个值中都有 4 个比特为 0 ,OTP 中的防回滚主版本号为 4 ,版本号小于(4 << 16)的固件将被禁止启动。
使能防回滚功能:
通过以下命令读取当前值:
AT+OTP=RRAW,368,1
将读取到的值中的比特 6 置 0 后写回。例如读取到的值为 FF ,则写入 BF :
AT+OTP=WRAW,368,1,BF
OTP 配置说明:
防回滚版本号存储在芯片的 OTP 区域中:
OTP 的物理地址范围为 0x36E ~ 0x36F。
OTP 值中比特 0 的个数即为防回滚版本号。OTP 默认值为全 F ,对应的防回滚版本号为 0。
OTP 的比特位只能从 1 写为 0 ,且该地址范围共 16 位,因此最多支持 16 个防回滚版本号(版本号范围:1 ~ 16)。
启用防回滚:
启用防回滚功能需完成以下 2 个步骤:
设置 OTP 中的防回滚版本号:
通过以下命令读取当前的防回滚版本号:
AT+OTP=RRAW,36E,2
通过以下命令写入防回滚版本号:
AT+OTP=WRAW,36E,2,<Value_OTP>
其中
<Value_OTP>为目标版本号对应的 OTP 值,计算示例如下:例 1:写入
FFFC或FFCF均可。两个值中都有 2 个比特为 0 ,OTP 中的防回滚主版本号为 2 ,版本号小于(2 << 16)的固件将被禁止启动。例 2:写入
FFF0或0FFF均可。两个值中都有 4 个比特为 0 ,OTP 中的防回滚主版本号为 4 ,版本号小于(4 << 16)的固件将被禁止启动。
使能防回滚功能:
通过以下命令读取当前值:
AT+OTP=RRAW,368,1
将读取到的值中的比特 6 置 0 后写回。例如读取到的值为 FF ,则写入 BF :
AT+OTP=WRAW,368,1,BF
OTP 配置说明:
防回滚版本号存储在芯片的 OTP 区域中:
OTP 的物理地址范围为 0x36E ~ 0x36F。
OTP 值中比特 0 的个数即为防回滚版本号。OTP 默认值为全 F ,对应的防回滚版本号为 0。
OTP 的比特位只能从 1 写为 0 ,且该地址范围共 16 位,因此最多支持 16 个防回滚版本号(版本号范围:1 ~ 16)。
启用防回滚:
启用防回滚功能需完成以下 2 个步骤:
设置 OTP 中的防回滚版本号:
通过以下命令读取当前的防回滚版本号:
AT+OTP=RRAW,36E,2
通过以下命令写入防回滚版本号:
AT+OTP=WRAW,36E,2,<Value_OTP>
其中
<Value_OTP>为目标版本号对应的 OTP 值,计算示例如下:例 1:写入
FFFC或FFCF均可。两个值中都有 2 个比特为 0 ,OTP 中的防回滚主版本号为 2 ,版本号小于(2 << 16)的固件将被禁止启动。例 2:写入
FFF0或0FFF均可。两个值中都有 4 个比特为 0 ,OTP 中的防回滚主版本号为 4 ,版本号小于(4 << 16)的固件将被禁止启动。
使能防回滚功能:
通过以下命令读取当前值:
AT+OTP=RRAW,368,1
将读取到的值中的比特 6 置 0 后写回。例如读取到的值为 FF ,则写入 BF :
AT+OTP=WRAW,368,1,BF
OTP 配置说明:
防回滚版本号存储在芯片的 OTP 区域中:
OTP 的物理地址范围为 0x36E ~ 0x36F。
OTP 值中比特 0 的个数即为防回滚版本号。OTP 默认值为全 F ,对应的防回滚版本号为 0。
OTP 的比特位只能从 1 写为 0 ,且该地址范围共 16 位,因此最多支持 16 个防回滚版本号(版本号范围:1 ~ 16)。
启用防回滚:
启用防回滚功能需完成以下 2 个步骤:
设置 OTP 中的防回滚版本号:
通过以下命令读取当前的防回滚版本号:
AT+OTP=RRAW,36E,2
通过以下命令写入防回滚版本号:
AT+OTP=WRAW,36E,2,<Value_OTP>
其中
<Value_OTP>为目标版本号对应的 OTP 值,计算示例如下:例 1:写入
FFFC或FFCF均可。两个值中都有 2 个比特为 0 ,OTP 中的防回滚主版本号为 2 ,版本号小于(2 << 16)的固件将被禁止启动。例 2:写入
FFF0或0FFF均可。两个值中都有 4 个比特为 0 ,OTP 中的防回滚主版本号为 4 ,版本号小于(4 << 16)的固件将被禁止启动。
使能防回滚功能:
通过以下命令读取当前值:
AT+OTP=RRAW,368,1
将读取到的值中的比特 6 置 0 后写回。例如读取到的值为 FF ,则写入 BF :
AT+OTP=WRAW,368,1,BF
OTP 配置说明:
防回滚版本号存储在芯片的 OTP 区域中:
OTP 的物理地址范围为 0x36E ~ 0x36F。
OTP 值中比特 0 的个数即为防回滚版本号。OTP 默认值为全 F ,对应的防回滚版本号为 0。
OTP 的比特位只能从 1 写为 0 ,且该地址范围共 16 位,因此最多支持 16 个防回滚版本号(版本号范围:1 ~ 16)。
启用防回滚:
启用防回滚功能需完成以下 2 个步骤:
设置 OTP 中的防回滚版本号:
通过以下命令读取当前的防回滚版本号:
AT+OTP=RRAW,36E,2
通过以下命令写入防回滚版本号:
AT+OTP=WRAW,36E,2,<Value_OTP>
其中
<Value_OTP>为目标版本号对应的 OTP 值,计算示例如下:例 1:写入
FFFC或FFCF均可。两个值中都有 2 个比特为 0 ,OTP 中的防回滚主版本号为 2 ,版本号小于(2 << 16)的固件将被禁止启动。例 2:写入
FFF0或0FFF均可。两个值中都有 4 个比特为 0 ,OTP 中的防回滚主版本号为 4 ,版本号小于(4 << 16)的固件将被禁止启动。
使能防回滚功能:
通过以下命令读取当前值:
AT+OTP=RRAW,368,1
将读取到的值中的比特 6 置 0 后写回。例如读取到的值为 FF ,则写入 BF :
AT+OTP=WRAW,368,1,BF
OTP 配置说明:
防回滚版本号存储在芯片的 OTP 区域中:
OTP 的物理地址范围为 0x36E ~ 0x36F。
OTP 值中比特 0 的个数即为防回滚版本号。OTP 默认值为全 F ,对应的防回滚版本号为 0。
OTP 的比特位只能从 1 写为 0 ,且该地址范围共 16 位,因此最多支持 16 个防回滚版本号(版本号范围:1 ~ 16)。
启用防回滚:
启用防回滚功能需完成以下 2 个步骤:
设置 OTP 中的防回滚版本号:
通过以下命令读取当前的防回滚版本号:
AT+OTP=RRAW,36E,2
通过以下命令写入防回滚版本号:
AT+OTP=WRAW,36E,2,<Value_OTP>
其中
<Value_OTP>为目标版本号对应的 OTP 值,计算示例如下:例 1:写入
FFFC或FFCF均可。两个值中都有 2 个比特为 0 ,OTP 中的防回滚主版本号为 2 ,版本号小于(2 << 16)的固件将被禁止启动。例 2:写入
FFF0或0FFF均可。两个值中都有 4 个比特为 0 ,OTP 中的防回滚主版本号为 4 ,版本号小于(4 << 16)的固件将被禁止启动。
使能防回滚功能:
通过以下命令读取当前值:
AT+OTP=RRAW,368,1
将读取到的值中的比特 6 置 0 后写回。例如读取到的值为 FF ,则写入 BF :
AT+OTP=WRAW,368,1,BF
OTP 配置说明:
防回滚版本号存储在芯片的 OTP 区域中:
OTP 的物理地址范围为 0x378 ~ 0x37F。
OTP 值中比特 0 的个数即为防回滚版本号。OTP 默认值为全 F ,对应的防回滚版本号为 0。
OTP 的比特位只能从 1 写为 0 ,且该地址范围共 64 位,因此最多支持 64 个防回滚版本号(版本号范围:1 ~ 64)。
启用防回滚:
启用防回滚功能需完成以下 2 个步骤:
设置 OTP 中的防回滚版本号:
通过以下命令读取当前的防回滚版本号:
AT+OTP=RRAW,378,8
通过以下命令写入防回滚版本号:
AT+OTP=WRAW,378,8,<Value_OTP>
其中
<Value_OTP>为目标版本号对应的 OTP 值,计算示例如下:例 1:写入
FFFCFFFFFFFFFFFF或FFCFFFFFFFFFFFFF均可。两个值中都有 2 个比特为 0 ,OTP 中的防回滚主版本号为 2 ,版本号小于(2 << 16)的固件将被禁止启动。例 2:写入
FFF0FFFFFFFFFFFF或0FFFFFFFFFFFFFFF均可。两个值中都有 4 个比特为 0 ,OTP 中的防回滚主版本号为 4 ,版本号小于(4 << 16)的固件将被禁止启动。
使能防回滚功能:
通过以下命令读取当前值:
AT+OTP=RRAW,368,1
将读取到的值中的比特 6 置 0 后写回。例如读取到的值为 FF ,则写入 BF :
AT+OTP=WRAW,368,1,BF
OTP 配置说明:
防回滚版本号存储在芯片的 OTP 区域中:
OTP 的物理地址范围为 0x378 ~ 0x37F。
OTP 值中比特 0 的个数即为防回滚版本号。OTP 默认值为全 F ,对应的防回滚版本号为 0。
OTP 的比特位只能从 1 写为 0 ,且该地址范围共 64 位,因此最多支持 64 个防回滚版本号(版本号范围:1 ~ 64)。
启用防回滚:
启用防回滚功能需完成以下 2 个步骤:
设置 OTP 中的防回滚版本号:
通过以下命令读取当前的防回滚版本号:
AT+OTP=RRAW,378,8
通过以下命令写入防回滚版本号:
AT+OTP=WRAW,378,8,<Value_OTP>
其中
<Value_OTP>为目标版本号对应的 OTP 值,计算示例如下:例 1:写入
FFFCFFFFFFFFFFFF或FFCFFFFFFFFFFFFF均可。两个值中都有 2 个比特为 0 ,OTP 中的防回滚主版本号为 2 ,版本号小于(2 << 16)的固件将被禁止启动。例 2:写入
FFF0FFFFFFFFFFFF或0FFFFFFFFFFFFFFF均可。两个值中都有 4 个比特为 0 ,OTP 中的防回滚主版本号为 4 ,版本号小于(4 << 16)的固件将被禁止启动。
使能防回滚功能:
通过以下命令读取当前值:
AT+OTP=RRAW,368,1
将读取到的值中的比特 6 置 0 后写回。例如读取到的值为 FF ,则写入 BF :
AT+OTP=WRAW,368,1,BF
OTP 配置说明:
防回滚版本号存储在芯片的 OTP 区域中:
BOOT 固件防回滚版本号在 OTP 中的物理地址范围为 0x460 ~ 0x46F(
BL_VER_0~F,详见 OTP 配置区 )。ROM 会将 BOOT 固件的主版本号与该值比较。OTP 值中比特 0 的个数即为防回滚版本号。OTP 默认值为全 F ,对应的防回滚版本号为 0。
OTP 的比特位只能从 1 写为 0 ,且该地址范围共 128 位,因此最多支持 128 个防回滚版本号(版本号范围:1 ~ 128)。
启用防回滚:
启用防回滚功能需完成以下 2 个步骤:
在 OTP 中设置防回滚版本号:
使用以下命令读取当前的防回滚版本号(长度
10为十六进制,即 16 字节):AT+OTP=RRAW,460,10
使用以下命令写入防回滚版本号:
AT+OTP=WRAW,460,<Length>,<Value_OTP>
其中
<Value_OTP>为目标版本号对应的 OTP 值,<Length>为其字节长度(十六进制)。计算示例:示例 1:写入
FC或CF(<Length>为1)两个值都有 2 个比特为 0
OTP 中的防回滚主版本号为 2
版本号小于
(2 << 16)的固件禁止启动
示例 2:写入
F0或0F(<Length>为1)两个值都有 4 个比特为 0
OTP 中的防回滚主版本号为 4
版本号小于
(4 << 16)的固件禁止启动
启用防回滚功能:
防回滚功能由 OTP 地址 0x456 的 bit 2(
ANTIROLL_BACK_DIS)控制,该位为 0 时启用防回滚功能。使用以下命令读取当前值:
AT+OTP=RRAW,456,1
将读取到的值的 bit 2 置 0 后写回。例如,读取到的值为 FF 时,写入 FB:
AT+OTP=WRAW,456,1,FB
默认情况下, BOOT 固件和 APP 固件共用同一个防回滚版本号,该版本号从 OTP 中读取。
如需让 BOOT 固件和 APP 固件使用不同的防回滚版本号,可修改 bootloader\boot_ota_km4.c 或 bootloader\boot_ota_hp.c 中的函数 BOOT_OTA_GetCertRollbackVer() ,为 APP 固件自定义获取防回滚版本号的方式。
重要
OTP 为一次性可编程存储器,某一位一旦从 1 写为 0 ,就无法恢复。
防回滚功能一经启用便无法禁用,请谨慎操作。
建议在量产阶段先启用防回滚功能但不设置具体版本号,待 OTA 升级完成后再写入版本号。
如需在应用中修改防回滚版本号,请参考 OTP API 参考 中的接口,在代码中实现。
BOOT OTA
BOOT OTA 启用步骤
BOOT OTA 功能默认未启用。启用 BOOT OTA 需依次完成以下 3 个步骤,其中步骤 1、2 涉及 Flash 布局与设备 OTP 配置,步骤 3 仅影响编译产物,不涉及代码修改:
确认 BOOT OTA2 分区(按需修改):
SDK 已在 Flash 布局 中默认规划了 BOOT OTA2 分区。默认分区满足需求时可直接使用;如需调整,请修改分区范围,并确保地址 4K 对齐。
将步骤 1 中确认的 BOOT OTA2 分区起始地址写入 OTP :
RTL8721Dx:AT+OTP=WRAW,36C,2,<Value_OTP>
Value_OTP由 BOOT OTA2 起始地址计算得出,公式如下:Value_OTP = (IMG_BOOT_OTA2 >> 12 & 0xFF) << 8 | (IMG_BOOT_OTA2 >> 20 & 0xFF)
举例:当
IMG_BOOT_OTA2为0x08234000时,Value_OTP为3482,对应的写入命令为:AT+OTP=WRAW,36C,2,3482
RTL8720E:AT+OTP=WRAW,36C,2,<Value_OTP>
Value_OTP由 BOOT OTA2 起始地址计算得出,公式如下:Value_OTP = (IMG_BOOT_OTA2 >> 12 & 0xFF) << 8 | (IMG_BOOT_OTA2 >> 20 & 0xFF)
举例:当
IMG_BOOT_OTA2为0x08234000时,Value_OTP为3482,对应的写入命令为:AT+OTP=WRAW,36C,2,3482
RTL8710E:AT+OTP=WRAW,36C,2,<Value_OTP>
Value_OTP由 BOOT OTA2 起始地址计算得出,公式如下:Value_OTP = (IMG_BOOT_OTA2 >> 12 & 0xFF) << 8 | (IMG_BOOT_OTA2 >> 20 & 0xFF)
举例:当
IMG_BOOT_OTA2为0x08234000时,Value_OTP为3482,对应的写入命令为:AT+OTP=WRAW,36C,2,3482
RTL8726E:AT+OTP=WRAW,36C,2,<Value_OTP>
Value_OTP由 BOOT OTA2 起始地址计算得出,公式如下:Value_OTP = (IMG_BOOT_OTA2 >> 12 & 0xFF) << 8 | (IMG_BOOT_OTA2 >> 20 & 0xFF)
举例:当
IMG_BOOT_OTA2为0x08234000时,Value_OTP为3482,对应的写入命令为:AT+OTP=WRAW,36C,2,3482
RTL8713E:AT+OTP=WRAW,36C,2,<Value_OTP>
Value_OTP由 BOOT OTA2 起始地址计算得出,公式如下:Value_OTP = (IMG_BOOT_OTA2 >> 12 & 0xFF) << 8 | (IMG_BOOT_OTA2 >> 20 & 0xFF)
举例:当
IMG_BOOT_OTA2为0x08234000时,Value_OTP为3482,对应的写入命令为:AT+OTP=WRAW,36C,2,3482
RTL8730E:AT+OTP=WRAW,36C,2,<Value_OTP>
Value_OTP由 BOOT OTA2 起始地址计算得出,公式如下:Value_OTP = (IMG_BOOT_OTA2 >> 12 & 0xFF) << 8 | (IMG_BOOT_OTA2 >> 20 & 0xFF)
举例:当
IMG_BOOT_OTA2为0x08234000时,Value_OTP为3482,对应的写入命令为:AT+OTP=WRAW,36C,2,3482
RTL8721F:AT+OTP=WRAW,36C,2,<Value_OTP>
Value_OTP由 BOOT OTA2 起始地址计算得出,公式如下:Value_OTP = (IMG_BOOT_OTA2 >> 12 & 0xFF) << 8 | (IMG_BOOT_OTA2 >> 20 & 0xFF)
举例:当
IMG_BOOT_OTA2为0x08234000时,Value_OTP为3482,对应的写入命令为:AT+OTP=WRAW,36C,2,3482
RTL8720F:AT+OTP=WRAW,36C,2,<Value_OTP>
Value_OTP由 BOOT OTA2 起始地址计算得出,公式如下:Value_OTP = (IMG_BOOT_OTA2 >> 12 & 0xFF) << 8 | (IMG_BOOT_OTA2 >> 20 & 0xFF)
举例:当
IMG_BOOT_OTA2为0x08234000时,Value_OTP为3482,对应的写入命令为:AT+OTP=WRAW,36C,2,3482
RTL8735C:BOOT OTA2 起始地址存储在 OTP 物理地址 0x45E ~ 0x45F 中(
OTA_ADDR_0和OTA_ADDR_1,详见 OTP 配置区 ),写入命令如下:AT+OTP=WRAW,45E,2,<Value_OTP>
Value_OTP由 BOOT OTA2 起始地址计算得出,公式如下:Value_OTP = (IMG_BOOT_OTA2 >> 12 & 0xFF) << 8 | (IMG_BOOT_OTA2 >> 20 & 0xFF)
举例:当
IMG_BOOT_OTA2为0x08440000(SDK 默认值)时,Value_OTP为4084,对应的写入命令为:AT+OTP=WRAW,45E,2,4084
启用 BOOT OTA 打包选项:
参考 配置工程(menuconfig) ,进入
CONFIG OTA OPTION配置,启用Enable Bootloader OTA。该选项仅在编译时将 BOOT 固件集成到ota_all.bin中,供 OTA 升级使用,不会改变代码。CONFIG OTA OPTION ---> [*] Enable Bootloader OTA
重要
OTP 写入不可逆:BOOT OTA2 地址一经写入将永久生效且无法修改,请在写入前确认地址无误。
若 OTP 中的 BOOT OTA2 地址为
0xFFFF(即未配置),则:OTA 升级时将跳过 BOOT 固件更新;
设备始终从 BOOT OTA1 启动。
强烈建议在批量生产前完成 BOOT OTA2 地址的 OTP 配置,并启用 BOOT OTA 打包选项。
BOOT OTA 选择流程
芯片 ROM 中的引导程序根据 BOOT 固件头中的标签和版本号选择启动分区,流程如下图所示。
APP OTA
APP OTA 启用步骤
APP 固件支持 OTA 升级,可从 OTA1 或 OTA2 分区启动。APP OTA 功能默认启用,无需额外配置。
APP OTA 选择流程
BOOT 固件运行时,会根据 APP 固件的固件标签和版本号,选择从 OTA1 或 OTA2 分区启动。标签与版本号的含义请参考 固件标签和版本号,选择流程如下图所示:
OTA 压缩方案
启用 OTA 固件压缩功能后, APP OTA1 分区保持不变, APP OTA2 分区中的固件将以压缩形式存储,从而减小固件体积,节省 Flash 存储空间。
压缩算法采用 LZMA(Lempel-Ziv-Markov 链算法)。这是一种无损数据压缩算法,具有压缩比高、解压内存需求较低的特点,广泛应用于 .7z 格式文件及 7-Zip 软件中。
压缩效果用压缩率衡量,计算公式如下:
压缩率(%) = 压缩后固件大小 / 原始固件大小 × 100
压缩率受固件内容影响:原始固件内容越复杂,压缩率通常越高(即压缩效果越弱),一般为 50% ~ 70%。
启用 OTA 压缩功能后,启动流程具有以下特点:
固件标签和版本号的判断与普通流程一致。
仅 APP 固件支持压缩。
压缩固件在 OTA 过程中始终被下载到 OTA2 区域。
若判断需从 OTA2 中的压缩固件启动,BOOT 将先把固件解压并覆盖到 OTA1 区域,再从 OTA1 启动。
OTA 下载过程和启动时的解压过程均支持掉电保护。
压缩固件仅在下载完成后的首次启动时解压一次,后续启动不再解压。
启动选择流程如下图所示:
下面以一个示例说明压缩 OTA 的工作过程:
设备从 OTA1 启动并运行 OTA 应用。
压缩固件被下载到 OTA2。
下一次启动时,系统选择压缩固件,将其解压到 OTA1,然后从 OTA1 启动。
示意图如下:
启用 OTA 压缩功能需完成以下 2 个步骤:
启用 OTA 压缩选项:
参考 配置工程(menuconfig) ,进入
CONFIG OTA OPTION配置,启用Enable Compress APP image。CONFIG OTA OPTION ---> [*] Enable Compress APP image
编译生成压缩固件:
编译时, APP 固件会被压缩,生成以下文件:
压缩固件:
{SDK}\build_<soc>\build\project_xx\image\xxx_app_compress.bin包含压缩固件的
ota_all.bin,供 OTA 使用。
启用后,可通过烧录压缩固件来验证解压过程:
将以下文件烧录到对应区域:
{SDK}\build_<soc>\boot.bin:烧录到 BOOT OTA1 区域。{SDK}\build_<soc>\build\project_xx\image\xxx_app_compress.bin:烧录到 APP OTA2 区域。
重启设备。系统将选择 OTA2 中的压缩固件,解压到 OTA1 后从 OTA1 启动,即可验证压缩固件的解压过程。
重要
解压由 BOOT 固件完成,因此首次启用 OTA 压缩功能时,需同步更新并重新烧录 BOOT 固件。
建议在批量生产前就启用 OTA 压缩功能。
备注
对于 RTL8735C:
BOOT 固件为
{SDK}\build_RTL8735C\amebapro3_boot.bin,压缩固件为{SDK}\build_RTL8735C\build\project_np\image\amebapro3_app_compress.bin。压缩内容包含追加在 APP 固件之后的 AP FIP 固件。
仅当从 NOR Flash 启动时,BOOT 固件才会执行解压。
OTA 固件
OTA 固件格式
ota_all.bin 的文件格式如下图所示,其中 OTA 固件头部分为主头部和子头部,主头部包含版本号和子头部的数量,子头部包含升级固件的信息。
每增加一个升级固件,便增加对应的一个子头部。
项目 |
地址偏移 |
大小 |
描述 |
|---|---|---|---|
版本号 |
0x00 |
4 字节 |
OTA 固件主头部中的版本号,默认值是 0xFFFFFFFF |
数量 |
0x04 |
4 字节 |
OTA 固件子头部的数量,值为 1 或 2 |
标签 |
0x08 |
4 字节 |
OTA 固件子头部的标签,值为 |
长度 |
0x0C |
4 字节 |
OTA 固件子头部的长度,值为 0x18 |
校验和 |
0x10 |
4 字节 |
对应升级固件的校验和 |
固件长度 |
0x14 |
4 字节 |
对应升级固件的长度 |
固件偏移量 |
0x18 |
4 字节 |
在当前 OTA 固件中此升级固件的起始位置 |
固件 ID |
0x1C |
4 字节 |
对应升级固件的固件 ID
|
修改编译配置
生成 OTA 固件
在编译项目时, OTA 固件将自动生成。
OTA 固件内将包括如下内容
OTA 固件头
BOOT 固件 (参考 BOOT OTA )
APP 固件或者压缩的 APP 固件
VFS2 固件 (参考 APP 固件中的 VFS)
编译项目。OTA 固件 (
ota_all.bin) 将生成在{SDK}\build_<soc>目录下。
OTA 例程
本节提供了多种固件 OTA 升级示例,涵盖不同的传输协议和数据源:
示例 |
说明 |
|---|---|
HTTP 升级: 通过 HTTP 协议从远程服务器下载并升级固件 。 |
|
HTTPS 安全升级: 通过 HTTPS 协议安全下载并升级固件,支持 SSL/TLS 加密 。 |
|
用户自定义升级: 支持自定义数据源, SPI、UART 等 。 |
|
文件系统升级: 从虚拟文件系统(SD 卡、Flash 等)读取固件并升级 。 |