03-OTA (SPI-nand Flash) 在线升级方案
【1】说明
本文档编辑时间:2026-10-12
本文以 X2000 Halley5 SPI-NAND 为例介绍 OTA 升级方案,SDK 中的目录也以 X2000 Halley5 环境为例,其他平台可根据实际目录和配置进行调整。
SPI-NAND OTA 分为两种模式:
recovery OTA:先升级并启动
kernel_recovery,进入 recovery ramdisk 后再升级 U-Boot、kernel 和 system 等镜像。该模式需要制作 recovery 镜像和 ramdisk,完整流程见本文【3】至【8】章节。A/B OTA:将 kernel 和 system 划分为 A、B 两组,设备运行过程中把升级内容写入当前未启动的备用分区,再切换启动分区完成升级。该模式不需要
kernel_recovery,具体配置、制作、部署和测试方法见本文【9】和【10】章节。两种 OTA 模式共用版本检测、升级包制作、服务器部署、下载和校验等基础流程;分区布局、镜像准备、设备端升级入口和回滚机制存在差异,使用时应选择与产品配置对应的 OTA 模式。
【2】OTA升级简介
【2.1】OTA介绍
OTA: 是一整套的设备在线升级方案,支持升级uboot,kernel,recovery,system分区。
【2.2】升级策略
在服务器端升级包路径下存放VERSION文件,记录升级包的版本;设备端在
/usr/data/VERSION文件中记录设备当前的系统版本。检测升级时,设备通过
/usr/data/ota_res/recovery.conf配置文件中的url得到current_version_full.conf。解析这个文件得到升级包路径,获取升级包版本,与当前系统版本做比较,如果升级包版本大于当前系统版本,则启动升级程序进行升级。升级成功后,更新本地/usr/data/VERSION文件,否则不进行升级。
【2.3】OTA升级时序图

【3】OTA服务器的搭建
在《01_OTA简介与docker服务器搭建.md》中介绍了一个通过nginx+python实现的https服务器,该服务器使用docker方式搭建,如果需要可以参考。在服务器搭建完成之后,需要在指定的OTA升级目录(以上述搭建服务器为例,该目录为$DOCK_SERVER_PATH/ota)下存放一个current_version_full.conf文件,在这个文件中保存着OTA升级包在服务器中的存放位置,可以参考device/x2000halley5/ota-overlay/package_config/current_version.conf文件示例进行修改,示例如下:
{
"server":{
"ip":"10.1.4.187",
"url":"https://10.1.4.187/version3"
}
}
其中ip是OTA服务器的IP地址,url是升级包在服务器的存放位置,上述示例中指定的OTA升级包路径为$DOCK_SERVER_PATH/ota/versions(以上述搭建服务器为例)。
【4】开发板初始环境搭建
对于下载的SDK,首先需要在SDK顶层目录下执行source build/envsetup.sh配置环境变量,然后在执行lunch,如下(以Halley5 V30开发板为例,基于NAND介质的OTA升级为例):

修改device/x2000halley5/ota-overlay/package_config/recovery.conf文件来配置服务器中current_version_full.conf文件的存放位置,以【3】OTA服务器的搭建中配置的环境为例,recovery.conf内容如下:
{
"server":{
"ip":"10.1.4.187",
"url":"https://10.1.4.187",
"rpt_url":""
}
}
其中ip是OTA服务器的IP地址,url是current_version_full.conf文件在服务器上的存放位置,在此处的环境配置下也就是$DOCK_SERVER_PATH/ota/,rpt_url为上报升级状态的服务器地址,如果没有,设置为空。
然后执行make命令编译镜像,编译出来的镜像如下:
test@user:~/release/x2000$ ll out/product/x2000halley5.v30_nand_6.6_ota-eng/image/ total 64096 drwxr-xr-x 2 test sw 4096 Nov 18 15:47 ./ drwxr-xr-x 4 test sw 4096 Nov 18 15:44 ../ -rw-r--r-- 1 test sw 6058048 Nov 18 15:45 kernel -rw-r--r-- 1 test sw 9781312 Nov 18 15:46 kernel_recovery -rw-r--r-- 1 test sw 49393664 Nov 18 15:47 system.ubifs -rw-r--r-- 1 test sw 381360 Nov 18 15:47 uboot
执行cat out/product/x2000halley5.v30_nand_6.6_ota-eng/system/etc/ota_res/recovery.conf验证配置的recovery是否正确,如果正确则将编译出来的镜像拷贝到PC上,用于后续的烧录操作。
【5】OTA升级包制作
【5.1】修改分区表信息配置
修改device/x2000halley5/ota-overlay/package_config/partition_nand.conf文件配置NAND的大小和分区情况,具体的分区情况应与烧录工具保持一致(即与产品NAND的实际分区情况保持一致):


【5.2】修改升级信息配置
修改device/x2000halley5/ota-overlay/package_config/customization_nand.conf文件配置升级信息,参考如下:

上述提供的文档先升级kernel_recovery,启动kernel_recovery(ramdisk)之后再升级uboot、kernel、system,具体所需升级的文件可根据实际情况进行修改。
【5.3】待升级镜像文件制作
【5.3.1】kernel_recovery升级镜像文件制作
【5.3.1.1】ramdisk的制作
因为编译生成kernel_recovery时需要ramdisk,ramdisk的制作是根据ramdisk_nand.conf文件(以NAND为例,文件位置为:device/x2000halley5/ota-overlay/ramdisk_config/ramdisk_nand.conf)中列出的文件列表信息从out/product/x2000halley5.v30_nand_6.6_ota-eng/obj/buildroot-intermediate/target目录(即target目录)下进行抽取的。如果需要修改ramdisk中的文件,则可以通过修改ramdisk_nand.conf文件进行添加和删除。
下面看一下ramdisk_nand.conf文件的内容:

每一行的内容都是文件在target目录下的相对路径,以./lib/firmware和./etc/init.d/S21mount为例(参见下图),因为./lib/firmware是一个目录,其在制作ramdisk的时候会将这个目录抽取出来,而./etc/init.d/S21mount是一个文件,则只会抽取这一个文件,若当前行以#开头,则不进行抽取。

如果想要验证抽取的ramdisk是否是自己所需要的,可以在编译完kernel_recovery之后到out/product/x2000halley5.v30_nand_6.6_ota-eng/obj/kernel_recovery-intermediate/ramdisk目录(根据实际情况修改路径)下进行查看,如下图:

【5.3.1.2】kernel_recovery的defconfig配置
以X2000 Halley5 NAND OTA升级为例,其所需要的默认配置文件是halley5_v30_linux_sfc_nand_recovery_defconfig文件,具体开发板所对应的是哪个配置可参见device/x2000halley5/kernel-recovery.mk文件(以halley5开发板为例),如下图所示:

如果需要修改kernel_recovery的配置,可以在SDK顶层目录下执行make kernel_recovery-menuconfig命令,需要注意必须配置CONFIG_BLK_DEV_INITRD并且将CONFIG_INITRAMFS_SOURCE配置为ramdisk.cpio.gz,如下图所示(必须配置):

【5.3.1.3】kernel_recovery文件的编译生成
在SDK顶层目录下执行make kernel_recovery命令单独编译kernel_recovery,执行make命令时进行整体编译的过程中会编译kernel_recovery,生成的镜像文件存储在out/product/x2000halley5.v30_nand_6.6_ota-eng/image/目录下。
如果生成的kernel_recovery不能启动到ramdisk环境,请转到【8】OTA升级测试常见问题。
【5.3.2】uboot升级镜像文件制作
和uboot编译相关的文件可参考device/x2000halley5/uboot.mk,对于Halley5 V30 Nand介质的开发板其对应的config为halley5_xImage_sfc_nand_ota,如下图所示:

需要注意halley5_uImage_sfc_nand和halley5_xImage_sfc_nand_ota的主要区别是halley5_xImage_sfc_nand_ota增加了SPL_OS_BOOT和OTA_VERSION30选项(Option)。
在SDK顶层目录下执行make uboot可单独编译uboot,生成的文件在out/product/x2000halley5.v30_nand_6.6_ota-eng/image/目录下,然后将生成的uboot镜像文件拷贝到本地PC上用烧录工具合成镜像并填充分区表信息,必须确保与产品分区保持一致,其操作如下:


然后在将要编译生成OTA升级包之前将生成的image.bin拷贝到out/product/x2000halley5.v30_nand_6.6_ota-eng/image目录下(根据实际情况进行修改),并重新命名为uboot。
【5.3.3】kernel升级镜像文件制作
和产品的kernel制作方法一致,生成的镜像文件在out/product/x2000halley5.v30_nand_6.6_ota-eng/image目录下。
【5.3.4】rootfs升级镜像文件制作
【5.3.4.1】buildroot的defconfig配置
X2000 Halley5 OTA升级时buildroot的默认配置文件是halley5_linux_ota_defconfig,具体开发板对应的是哪个配置可参见device/x2000halley5/device.mk文件(以halley5开发板为例),如下图所示:

如果需要修改,必须配置BR2_PACKAGE_CJSON(编译recovery等依赖的库)和BR2_PACKAGE_HOST_PYTHON3(制作升级镜像包时使用)。
【5.3.4.2】rootfs-overlay的使用
在device/x2000halley5目录下的rootfs-overlay用于存储最基本的一些文件供开发板使用,对于NAND OTA升级时所需要的文件则存储在device/x2000halley5/ota-overlay/rootfs_nand_overlay目录下,比如挂载usrdate分区、拷贝/etc/ota_res/到/usr/data/目录下等相关的脚本文件等:

【5.4】编译生成升级镜像包
上述镜像文件制作完成之后都在out/product/x2000halley5.v30_nand_6.6_ota-eng/image目录下,如下:
test@user:~/release/x2000/out/product/x2000halley5.v30_nand_6.6_ota-eng/image$ ls -l total 64088 -rw-r--r-- 1 test sw 6058048 Nov 18 15:45 kernel -rw-r--r-- 1 test sw 9781312 Nov 18 16:47 kernel_recovery -rw-r--r-- 1 test sw 49393664 Nov 18 15:47 system.ubifs -rw-r--r-- 1 test sw 381360 Nov 18 17:26 uboot
需要注意此处的uboot镜像文件是在PC上使用烧录工具填充分区表信息之后再拷贝到服务器上的(详见【5.3.2】uboot升级镜像文件制作)。然后在SDK顶层目录下执行make ota_mkpackage命令来制作OTA升级镜像包,其结果如下图所示:


【6】升级包部署
在【3】OTA服务器的搭建中提到的current_version_full.conf文件中保存着OTA升级包在服务器中的存放位置,以上述配置为例,我们则需要将OTA升级包上传到服务器的$DOCK_SERVER_PATH/ota/versions目录下,上传完之后$DOCK_SERVER_PATH/ota/versions目录内容如下所示:
. ├── global.xml ├── nand │ ├── update000.zip │ ├── update001.zip │ ├── ...... ├── ota-package.7z └── sha1Tab
然后在服务器存放升级包的位置处执行mkdir full ; 7zr x ota-package.7z -ofull命令解压升级包,解压后服务器存放升级包的目录下内容如下所示:
. ├── full │ ├── global.xml │ ├── nand │ │ ├── update000.zip │ │ ├── update001.zip │ │ ├── ...... │ └── sha1Tab ├── global.xml ├── nand │ ├── update000.zip │ ├── update001.zip │ ├── ....... ├── ota-package.7z └── sha1Tab
然后在服务器升级包路径下创建VERSION文件并写入版本号,例如echo 16 > VERSION。
【7】OTA升级测试
将制作OTA升级包时升级的zero文件拷贝到PC上和【4】开发板初始环境搭建中生成的镜像文件一起烧录到开发板上,烧录工具配置参考下图:

启动到system后需要配置网络连接服务器,下面分别介绍WIFI和以太网的网络配置方法:
WIFI网络配置方法:
方法一 —— 在编译builroot时直接将其打包在根文件系统中的:
修改buildroot/package/wpa_supplicant/wpa_supplicant.conf文件来配置要连接的WIFI或者在device/x2000halley5/rootfs-overlay/etc目录下添加wpa_supplicant.conf文件
方法二 —— 开发板启动后动态配置:
在开发板启动之后可以使用wpa_passphrase命令动态配置要连接的WIFI,比如wpa_passphrase "ssid" "passphrase" | tee -a /etc/wpa_supplicant.conf。也可以手动修改/etc/wpa_supplicant.conf文件进行配置。
配置完wpa_supplicant.conf文件后执行wifi_download_fw_and_up.sh启动WIFI。
以太网网络配置方法:
对于通过以太网升级的目前还没有提供配置IP地址的脚本,如果需要可自行添加。
配置好网络后,使用ping命令来确认是否与服务器成功连接。ping通之后执行ota_update_script.sh检验是否有更新待升级,如果需要进行升级,输入y,如下图所示:

输入y之后开始进行OTA升级,系统先升级recovery,然后启动ramdisk升级uboot、kernel和system(具体的根据上面配置的升级信息),最后再次启动,本地VERSION被更新。(详细的升级流程参见【2.3】OTA升级时序图)
【8】OTA升级测试常见问题
【8.1】升级包制作失败,出现如下错误信息
Could not find the main class: com.android.signapk.SignApk. Program will exit. adding: update008/ (stored 0%) adding: update008/xImage_003 (deflated 0%) Exception in thread "main" java.lang.UnsupportedClassVersionError: com/android/signapk/SignApk : Unsupported major.minor version 51.0 at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631) at java.lang.ClassLoader.defineClass(ClassLoader.java:615) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
由于升级包制作程序中有提前编译好的jar包,编译jar包时的java版本和您当前制作升级包的服务器java版本不匹配导致。解决办法,执行如下命令:
/* 以halley5为例 */ cd packages/updater/ota_package_maker/otapackage/depmod/signature/signapk rm -f signapk.jar ./build.sh cd - rm out/product/halley5/obj/ota/ -rf rm out/product/halley5/image/ota/ -rf make ota_mkpackage
【8.2】升级开始解析sha1Tab出错
每次制作升级包前需要删除之前升级包的sha1Tab
rm out/product/"板级"/image/ota/ -rf make ota_mkpackage
【8.3】无法启动recovery,Uncompressing Linux...后无打印
可能由于recovery镜像太大(通常为10M左右),内核自解压覆盖了自解压程序,可以通过配置CONFIG_XIMAGE_LDADDR(比如将0x80F00000改为0x81000000)或者裁剪ramdisk或recovery内核来解决。
【8.4】recovery启动失败:Failed to execute /linuxrc (error -2)
错误信息如下:

可能的原因是缺少了busybox所需的库,首先通过readelf -d busybox确定busybox所依赖的库,如下:

如果ramdisk中缺少库,则将其补上,重新编译测试。如果还不能启动ramdisk,则看是否缺少必要的C库。
【9】SPI-NAND A/B OTA升级方案
前面的【3】至【8】章节介绍的是 SPI-NAND recovery OTA,原有 recovery OTA 的流程图、配置、镜像制作和常见问题保持不变。本章补充 SPI-NAND A/B OTA。两种模式共用 OTA 服务器、版本检查、升级包制作、下载和校验流程,只有分区布局、镜像准备和设备端写入目标不同。
ab partition OTA 提供一种双缓存OTA机制,该模式上存在两个 kernerl 分区 和 两个system 分区分别为 kernelA、systemA、kernelB、systemB,该模式不需要组建 recovery kernel,第一次默认烧录在 A 区(kernelA , squashfsA),OTA 升级在 B 区(kernelB , squashfsB),自此之后 OTA 升级在 A/B 区域轮换(由 NV 分区特定位决定)。
此模式相比recovery OTA 模式需要占用更多的 flash 空间,但可以保留上一个可用版本,在更新后出现任何问题可以进行版本回退。
【9.1】两种OTA模式说明
X2000 Halley5 的 OTA 模式由 TARGET_EXT2_SUPPORT 选择:
设置为
ota时使用RECOVERY_OTA,需要制作kernel_recovery和 recovery ramdisk。设置为
abota时使用AB_OTA,不制作kernel_recovery,由设备端执行recovery -m ab,将升级内容写入当前未启动的备用分区。
两种模式的共同点如下:
使用相同的 OTA 服务器、
recovery.conf、版本检查和版本更新策略。使用相同的
make ota_mkpackage命令制作 OTA 升级包。使用
global.xml、分片update*.zip、sha1Tab和签名对升级包进行描述和校验。设备端都需要先检查服务器版本,再下载、校验并写入升级镜像。
服务器部署、网络配置和升级包目录结构可直接参考本文【3】、【4】、【6】和【7】章节,不在 A/B 章节中重复说明。
两种模式的主要差异如下:
| 项目 | recovery OTA | A/B OTA |
|---|---|---|
| 升级环境 | recovery ramdisk | 当前运行的 Linux 系统 |
| recovery 镜像 |
需要 kernel_recovery 和 ramdisk | 不需要 |
| system 写入位置 | 配置指定的 system 分区 | 当前未启动的 systemA 或 systemB |
| 分区布局 | 单组 kernel/system | 两组 kernel/system |
| 完成升级后 | 通常由 recovery 重启 | 设置下一次启动分区后重启 |
| 回滚 | 依赖 recovery 流程 |
依赖 U-Boot 启动状态和 ota_rollback |
【9.2】A/B OTA工作原理
SPI-NAND A/B OTA 将 kernel 和 system 分为 A、B 两组。设备从其中一组启动时,升级程序选择另一组作为目标分区,先写入目标组并完成校验,再更新 NV 分区中的启动状态。设备重启后由 U-Boot 选择新的启动分区。
以当前 Halley5 配置为例:
从 A 组启动时,第一次升级写入
kernelB和systemB。从 B 组启动时,下一次升级写入
kernelA和systemA。uboot和nv是公共分区,不属于 A/B 轮换的系统分区。userdata不参与升级,升级过程中应保留用户数据。
A/B OTA 的核心是“先升级备用分区,再切换启动分区”,因此不会覆盖当前正在运行的 system 分区。目标分区下载失败、校验失败或写入失败时,不应切换到不完整的目标分区。
【10】SPI-NAND A/B OTA开发和使用
【10.1】A/B分区规划
当前 X2000 Halley5 SPI-NAND A/B OTA 的分区配置文件为:
device/x2000halley5/ota-overlay/package_config/partition_nand_ab.conf
当前分区表如下:
[storageinfo] mediumtype=nand capacity=128MB [partition] item1=uboot,0x0,0x100000,mtdblock0 item2=nv,0x100000,0x100000,mtdblock1 item3=kernelA,0x200000,0x800000,mtdblock2 item4=systemA,0xa00000,0x2800000,mtdblock3 item5=kernelB,0x3200000,0x800000,mtdblock4 item6=systemB,0x3a00000,0x2800000,mtdblock5 item7=userdata,0x6200000,0x1e00000,mtdblock6
kernel 镜像必须小于 0x800000(8 MiB),system.ubifs 必须小于 0x2800000(40 MiB)。分区起始地址和大小必须与烧录工具、U-Boot 实际使用的 MTD 分区表一致;修改 A/B 分区时需要同步检查这三处配置。
【10.2】A/B升级信息配置
A/B OTA 的升级信息配置文件为:
device/x2000halley5/ota-overlay/package_config/customization_nand_ab.conf
当前配置如下:
[update] mediumtype=nand imgcnt=3 [image1] name=uboot type=normal offset=0x0 bootmode=normal updatemode=slice [image2] name=kernel type=normal offset=0x200000 bootmode=normal updatemode=slice [image3] name=system.ubifs type=ubifs offset=0xa00000 bootmode=normal updatemode=slice
kernel 和 system.ubifs 是逻辑镜像名称,offset 使用 A 组分区的基准地址;实际写入 A 还是 B 由当前启动分区和设备端升级逻辑决定,不能理解为永远只写 A 分区。
【10.3】A/B模式编译配置
NAND A/B OTA 使用以下配置:
TARGET_EXT2_SUPPORT=abota转换为OTA_MODE=AB_OTA。Buildroot 使用
x2000_halley5_linux_abota_defconfig,生成 A/B OTA 所需的裁剪文件系统。U-Boot 使用
x2000_halley5_xImage_sfc_nand_abota配置。A/B OTA 不编译
kernel_recovery和 recovery ramdisk。设备端保留
recovery、libupdater、libsysutils和ota_rollback;NAND 在线下载不依赖本地getpackage流程。
【10.4】A/B镜像制作和升级包生成
A/B OTA 不需要制作 kernel_recovery,需要准备以下镜像:
out/product/<NAND A/B产品目录>/image/ ├── kernel ├── system.ubifs └── uboot
确认镜像大小满足【10.1】的分区限制,且 uboot 与产品实际 A/B 分区布局匹配后,在 SDK 顶层目录执行:
make ota_mkpackage
NAND A/B 的 ota.mk 会将 A/B 专用配置转换为 OTA 工具默认读取的配置:
customization_nand_ab.conf -> <输出目录>/ota/package_config/customization_nand.conf partition_nand_ab.conf -> <输出目录>/ota/package_config/partition_nand.conf
生成目录如下:
out/product/<NAND A/B产品目录>/image/ota/ ├── global.xml ├── nand/ │ ├── update000.zip │ ├── update001.zip │ └── ... ├── ota-package.7z └── sha1Tab
如果在 recovery OTA 和 A/B OTA 之间切换过,建议清理对应产品的 OTA 中间目录后重新制作:
rm -rf out/product/<NAND A/B产品目录>/obj/ota rm -rf out/product/<NAND A/B产品目录>/image/ota make ota_mkpackage
【10.5】A/B设备端升级流程
NAND A/B OTA 使用在线下载流程,设备端执行:
update recovery -m ab
升级过程如下:
update根据/usr/data/ota_res/recovery.conf连接 OTA 服务器,读取版本信息。设备比较服务器版本与
/usr/data/VERSION,确认有新版本后进入升级流程。recovery -m ab下载并校验global.xml、sha1Tab和各个update*.zip。解析 NAND 分区表和升级信息,识别当前活动分区。
选择另一组 kernel、system 分区作为目标分区。
下载并写入 U-Boot、kernel 和 system 镜像,其中 system 使用 UBIFS 方式处理。
校验目标分区,调用
ota_rollback设置下一次启动分区。重启后由 U-Boot 从新分区启动,启动成功后更新版本信息。
升级过程中如果下载失败、镜像校验失败或目标分区写入失败,不应切换到不完整的目标分区;设备应保留当前启动分区,便于重新执行升级。
【10.6】A/B启动分区和回滚
NAND A/B OTA 升级完成后,设备会通过 U-Boot 的启动状态切换到新升级的分区;如果新分区启动失败,则由 ota_rollback 根据启动检测结果执行回退。当前工程的具体回滚机制和使用方法请参考 Gitee 文档:AB OTA rollback。
验证 A/B OTA 时,建议至少完成一次 A 到 B 和一次 B 到 A 的升级,并确认启动分区切换和 userdata 数据保持正常。
【10.7】A/B OTA远程部署
【10.7.1】服务器目录结构
NAND A/B OTA 推荐使用远程 HTTP/HTTPS 部署。当前 recovery 程序会根据 recovery.conf 的 url 进入版本目录,再选择 full 或 difference 目录,并逐个下载 global.xml、sha1Tab 和 nand/update*.zip。
服务器目录建议如下:
ota/ ├── current_version_full.conf └── version3/ └── full/ ├── global.xml ├── sha1Tab └── nand/ ├── update000.zip ├── update001.zip └── ...
current_version_full.conf 示例:
{
"server":{
"ip":"10.1.4.187",
"url":"https://10.1.4.187/version3"
}
}
在 version3/full 目录下创建版本号文件:
echo 17 > VERSION
如果使用本工程前面介绍的 ota-package.7z,应先解压到版本目录,而不是直接把 7z 文件地址填写到 recovery.conf:
mkdir -p version3/full 7zr x ota-package.7z -oversion3/full
解压后必须确认以下文件存在:
version3/full/global.xml version3/full/sha1Tab version3/full/nand/update000.zip
【10.7.2】设备端远程升级检查
在设备端确认资源和网络配置:
cat /usr/data/ota_res/recovery.conf ping 10.1.4.187 cat /usr/data/VERSION update
设备检测到新版本后执行:
recovery -m ab
日志中应看到类似信息:
OTA mode is AB OTA Downloading .../full/sha1Tab Downloading .../full/global.xml Updating device: "nand" Downloading .../full/nand/update000.zip
如果日志仍然出现 /storage/update/update.zip,通常说明当前产品仍编译了 OTA_LOCAL_PACKAGE,或实际运行的 recovery 不是当前 A/B 产品生成的版本,需要检查 OTA_MODE、编译产物和设备端 /usr/data/ota_res/ 文件。
【10.8】A/B OTA本地升级包部署
本地部署适合无网络环境或快速验证。NAND A/B 的本地升级包应放在设备可访问的本地存储目录中,推荐使用 file: URL 复用在线升级流程。与 EMMC 的单个 mmc/update.zip 不同,NAND A/B 使用 global.xml、sha1Tab 和多个 nand/update*.zip 分片文件。
【10.8.1】本地 recovery.conf
将设备端 recovery.conf 配置为 file: 路径:
{
"server":{
"ip":"127.0.0.1",
"url":"file:/storage/ota_download",
"rpt_url":""
}
}
修改后重新编译对应产品,或在测试设备上临时替换 /usr/data/ota_res/recovery.conf。file: 后面必须填写设备端的绝对路径,不能填写 PC 端路径,也不能填写 ota-package.7z 文件路径。
【10.8.2】本地目录结构
本地目录示例:
/storage/ota_download/ ├── current_version_full.conf └── version3/ ├── VERSION └── full/ ├── global.xml ├── sha1Tab └── nand/ ├── update000.zip ├── update001.zip └── ...
current_version_full.conf 示例:
{
"server":{
"ip":"127.0.0.1",
"url":"file:/storage/ota_download/version3"
}
}
其中,recovery.conf 中的 URL 用于获取 current_version_full.conf,current_version_full.conf 中的 URL 用于获取版本号和升级包。设备端实际读取的路径如下:
/storage/ota_download/current_version_full.conf /storage/ota_download/version3/VERSION /storage/ota_download/version3/full/global.xml /storage/ota_download/version3/full/sha1Tab /storage/ota_download/version3/full/nand/update000.zip /storage/ota_download/version3/full/nand/update001.zip
准备目录后,将 VERSION 写入大于设备当前版本的升级版本号:
echo 17 > /storage/ota_download/version3/VERSION
【10.8.3】本地升级包导入设备
先在 PC 端将 ota-package.7z 解压到 version3/full 目录:
mkdir -p ota_download/version3/full 7zr x out/product/<NAND A/B产品目录>/image/ota/ota-package.7z \ -oota_download/version3/full echo 17 > ota_download/version3/VERSION
确认目录内容完整后,可以使用 adb 导入整个目录:
adb push ota_download /storage/
或者通过业务程序、U 盘或其他方式将文件复制到设备的 /storage/ota_download。导入后检查:
ls -l /storage/ota_download/current_version_full.conf ls -l /storage/ota_download/version3/VERSION ls -l /storage/ota_download/version3/full/global.xml ls -l /storage/ota_download/version3/full/sha1Tab ls -l /storage/ota_download/version3/full/nand/update000.zip
【10.8.4】本地部署注意事项
/storage必须已经挂载,并且剩余空间能够容纳全部nand/update*.zip分片文件。current_version_full.conf中的路径必须与recovery.conf中的路径和设备实际目录一致。VERSION位于current_version_full.conf的 URL 指向目录下,即本例中的/storage/ota_download/version3/VERSION。NAND A/B 的
global.xml、sha1Tab和全部nand/update*.zip必须来自同一次make ota_mkpackage,不能只复制update000.zip。使用
file:时,recovery 通过/bin/cp读取本地文件,因此路径必须存在,并且文件权限必须允许 recovery 读取。当前 NAND A/B 默认使用多分片流程,设备端不需要开启
OTA_LOCAL_PACKAGE,也不能将多分片包改名为/storage/update/update.zip。如果日志仍然读取
/storage/update/update.zip,应检查运行中的 recovery 是否为 A/B 版本,以及产品是否误开启了OTA_LOCAL_PACKAGE。本地部署仍会执行版本、设备类型、分区匹配、SHA1 和签名校验。
本地目录准备完成后,执行下面的命令进行升级:
update recovery -m ab
【10.8.5】本地部署和远程部署对比
| 项目 | 远程部署 | 本地部署 |
|---|---|---|
recovery.conf URL | https://服务器地址 | file:/storage/ota_download |
| 升级包来源 | OTA 服务器 | 设备本地存储 |
| NAND A/B 包路径 | version3/full/nand/update*.zip | /storage/ota_download/version3/full/nand/update*.zip |
| 是否需要网络 | 需要 | 不需要 |
| 主要限制 | 网络、HTTPS 和服务器连通性 | 本地存储空间、目录层级和文件权限 |
【10.9】A/B OTA完整测试清单
建议按照下面顺序验证,避免只验证“包能下载”而遗漏分区切换:
编译检查:确认使用 A/B lunch 目标,生成
kernel、system.ubifs、uboot和ota-package.7z,且没有依赖kernel_recovery。包结构检查:确认服务器存在
VERSION、global.xml、sha1Tab和完整的nand/update*.zip。配置检查:确认生成的
partition_nand.conf是由partition_nand_ab.conf转换而来,分区地址与烧录工具一致。网络检查:设备能够 ping 通服务器,
recovery.conf的 URL 可访问current_version_full.conf。A 到 B 升级:从 partitionA 启动,执行
update和recovery -m ab,确认写入 B 组并从 B 组启动。B 到 A 升级:再次制作更高版本或部署下一版本,确认写入 A 组并从 A 组启动。
回滚检查:使用
ota_rollback -i验证主动切换;模拟目标系统启动失败,确认自动回退逻辑符合预期。数据检查:确认
userdata中的用户文件、/usr/data/VERSION和 OTA 资源符合预期。
常见问题定位时,优先区分以下阶段:
| 现象 | 优先检查内容 |
|---|---|
下载不到 global.xml | recovery.conf、current_version_full.conf、服务器目录和网络 |
下载不到 update001.zip |
服务器是否完整解压、global.xml 中的包索引是否与文件一致 |
image can not mapped in partition | 镜像大小、分区偏移和 A/B 配置是否匹配 |
| UBIFS 写入失败 | systemA/systemB 容量、坏块/ECC、烧录工具分区和镜像大小 |
| 升级后仍从旧分区启动 | ota_rollback、NV 启动状态和 U-Boot A/B 启动逻辑 |
【10.10】NAND A/B OTA与recovery OTA差异
两种模式的通用配置和流程见本文前面的 recovery OTA 章节,本节只列出 NAND 下的差异:
recovery OTA 使用
partition_nand.conf和customization_nand.conf;A/B OTA 使用partition_nand_ab.conf和customization_nand_ab.conf作为源配置。recovery OTA 需要
kernel_recovery、ramdisk 和 recovery 启动过程;A/B OTA 不需要这些镜像。recovery OTA 通常将系统镜像写入固定的 system 分区;A/B OTA 根据当前启动状态写入备用 system 分区。
recovery OTA 使用单组
kernel/system;A/B OTA 必须配置kernelA/systemA和kernelB/systemB,且两组容量应一致。两种模式都使用 NAND、UBIFS、分片升级包和相同的服务器部署方式,但 A/B OTA 需要额外验证启动分区切换和回滚。