04-OTA (EMMC) 在线升级方案

【1】说明

  1. 本文档用于介绍板级关于OTA升级模式,分为recovery OTA和A/B partition OTA两种模式

  2. recovery OTA升级过程以X2600 Halley7V10 EMMC为例进行,SDK中的目录以X2600 Halley7V10 的SDK环境为例,其他SDK环境依据这个进行参考

  3. A/B partition OTA升级过程以x2000_halley5_v30板级为例进行介绍,SDK目录以x2000_halley5的SDk为准,其他的板级可参考此x2000_halley5板级

【2】整体介绍

【2.1】功能框图

该框图为 Manhattan 平台提供的 OTA 功能模块,以及资源配置和环境部署原则。

img_01.png


【2.2】recovery OTA升级简介

【2.2.1】OTA介绍

recovery OTA: 是一整套的设备在线升级方案,支持升级uboot,kernel,recovery,system分区。

【2.2.2】升级策略

  • 在服务器端升级包路径下存放VERSION文件,记录升级包的版本;设备端在/usr/data/VERSION文件中记录设备当前的系统版本。

  • 检测升级时,设备通过/usr/data/ota_res/recovery.conf配置文件中的url得到current_version_full.conf。解析这个文件得到升级包路径,获取升级包版本,与当前系统版本做比较,如果升级包版本大于当前系统版本,则启动升级程序进行升级。升级成功后,更新本地/usr/data/VERSION文件,否则不进行升级。

【2.2.3】OTA升级时序图

img_02.png

【3】OTA服务器的搭建

在《01_OTA简介与docker服务器搭建.md》中介绍了一个通过nginx+python实现的https服务器,该服务器使用docker方式搭建,如果需要可以参考。在服务器搭建完成之后,需要在指定的OTA升级目录(以上述搭建服务器为例,该目录为$DOCK_SERVER_PATH/ota)下存放一个current_version_full.conf文件,在这个文件中保存着OTA升级包在服务器中的存放位置,可以参考device/x2600halley7/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,如下(以Halley7 V10开发板为例,基于EMMC介质的OTA升级为例):

img_03.png

修改device/x2600halley7/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/x2600/out/product/x2600halley7.v10_msc_6.6_ota-eng/image$ ls -l
total 95576
-rw-r--r-- 1 test sw   5988416 Nov 19 14:16 kernel
-rw-r--r-- 1 test sw   9199680 Nov 19 14:18 kernel_recovery
-rw-r--r-- 1 test sw 209715200 Nov 19 14:19 system.ext2
-rw-r--r-- 1 test sw    233528 Nov 19 14:18 uboot

执行cat out/product/x2600halley7.v10_msc_6.6_ota-eng/system/etc/ota_res/recovery.conf验证配置的recovery是否正确,如果正确则将编译出来的镜像拷贝到PC上,用于后续的烧录操作。

【5】OTA升级包制作

【5.1】修改分区表信息配置

修改device/x2600halley7/ota-overlay/package_config/partition_mmc.conf文件配置EMMC的大小和分区情况,具体的分区情况应与uboot中配置的分区表保持一致(即与EMMC的实际分区情况保持一致)。以X2600 Halley7V10为例,OTA升级时EMMC的分区表配置文件为u-boot/board/ingenic/x2600_halley7/partitions_mmc_ota.tab(可根据实际情况进行适当地修改),那么partition_mmc.conf文件中配置的分区信息就应该与此文件中的保持一致,如下图所示:

img_04.png

img_05.png

【5.2】修改升级信息配置

修改device/x2600halley7/ota-overlay/package_config/customization_mmc.conf文件配置升级信息,参考如下:

img_06.png

上述提供的文档先升级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_mmc.conf文件(以EMMC为例,文件位置为:device/x2600halley7/ota-overlay/ramdisk_config/ramdisk_mmc.conf)中列出的文件列表信息从out/product/x2600halley7.v10_msc_6.6_ota-eng/obj/buildroot-intermediate/target/目录(即target目录)下进行抽取的。如果需要修改ramdisk中的文件,则可以通过修改ramdisk_mmc.conf文件进行添加和删除。

下面看一下ramdisk_mmc.conf文件的内容:

img_07.png

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

img_08.png

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

img_09.png

【5.3.1.2】kernel_recovery的defconfig配置

以X2600 Halley7 V10 EMMC OTA升级为例,其所需要的默认配置文件是x2600_halley7_v1.0_mmc_recovery_defconfig文件,具体开发板所对应的是哪个配置可参见device/x2600halley7/kernel-recovery.mk文件(以Halley7V10开发板为例),如下图所示:

img_10.png

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

img_11.png

【5.3.1.3】kernel_recovery文件的编译生成

在SDK顶层目录下执行make kernel_recovery命令单独编译kernel_recovery,执行make命令时进行整体编译的过程中会编译kernel_recovery,生成的镜像文件存储在out/product/x2600halley7.v10_msc_6.6_ota-eng/image/目录下。

如果生成的kernel_recovery不能启动到ramdisk环境,请转到【8】OTA升级测试常见问题。

【5.3.2】uboot升级镜像文件制作

和uboot编译相关的文件可参考device/x2600halley7/uboot.mk,对于Halley7 V10 EMMC(msc0)介质的开发板其对应的config为x2600_halley7_xImage_msc0_ota,如下图所示:

img_12.png

需要注意x2600_halley7_uImage_msc0和x2600_halley7_xImage_msc0_ota的主要区别是x2600_halley7_xImage_msc0_ota增加了SPL_OS_BOOT、GPT_TAB_BUILT_IN和OTA_VERSION30选项(Option)。

在SDK顶层目录下执行make uboot可单独编译uboot,生成的文件在out/product/x2600halley7.v10_msc_6.6_ota-eng/image/目录下,然后将生成的uboot镜像文件拷贝到本地PC上用烧录工具合成镜像并填充分区表信息,必须确保与产品分区保持一致,其操作如下:

img_13.png

然后在将要编译生成OTA升级包之前将生成的image.bin拷贝到out/product/x2600halley7.v10_msc_6.6_ota-eng/image目录下(根据实际情况进行修改),并重新命名为uboot。


【5.3.3】kernel升级镜像文件制作

和产品的kernel制作方法一致,生成的镜像文件在out/product/x2600halley7.v10_msc_6.6_ota-eng/image/目录下。

【5.3.4】rootfs升级镜像文件制作

【5.3.4.1】buildroot的defconfig配置

X2600 Halley7 OTA升级时buildroot的默认配置文件是x26xx_linux_defconfig,具体开发板对应的是哪个配置可参见device/x2600halley7/device.mk文件(以Halley7V10开发板为例),如下图所示:

img_14.png

如果需要修改,必须配置BR2_PACKAGE_CJSON(编译recovery等依赖的库)和BR2_PACKAGE_HOST_PYTHON3(制作升级镜像包时使用)。

【5.3.4.2】rootfs-overlay的使用

在device/x2600halley7目录下的rootfs-overlay用于存储最基本的一些文件供开发板使用,对于EMMC OTA升级时所需要的文件则存储在device/x2600halley7/ota-overlay/rootfs_mmc_overlay目录下,比如挂载usrdate分区、挂载storage分区(用于存储下载的OTA升级包)、拷贝/etc/ota_res/到/usr/data/目录下等相关的脚本文件等,例如:

img_15.png

在上述在EMMC OTA升级时所需的最基本文件中,etc/init.d/S12storage启动脚本文件用于在系统启动时通过解析/etc/ota_res/partition_mmc.conf文件来实现自动挂载storage分区到/storage目录,etc/init.d/S21data启动脚本文件则用于在系统启动时通过解析/etc/ota_res/partition_mmc.conf文件来实现自动挂载usrdate分区到/usr/data目录,需要注意这两个启动脚本文件都是通过调用mount_mmc_partition.sh脚本实现的挂载操作,在mount_mmc_partition.sh脚本主要就是通过mount命令来实现挂载操作。

【5.4】编译生成升级镜像包

上述镜像文件制作完成之后都在out/product/x2600halley7.v10_msc_6.6_ota-eng/image目录下,如下:

test@user:~/release/x2600/out/product/x2600halley7.v10_msc_6.6_ota-eng/image$ ls -l
total 95576
-rw-r--r-- 1 test sw   5988416 Nov 19 14:16 kernel
-rw-r--r-- 1 test sw   9199680 Nov 19 14:18 kernel_recovery
-rw-r--r-- 1 test sw 209715200 Nov 19 14:19 system.ext2
-rw-r--r-- 1 test sw    233528 Nov 19 14:18 uboot

然后在SDK顶层目录下执行make ota_mkpackage命令来制作OTA升级镜像包,其结果如下图所示:

img_16.png

img_17.png

【6】升级包部署

在【3】OTA服务器的搭建中提到的current_version_full.conf文件中保存着OTA升级包在服务器中的存放位置,以上述配置为例,我们则需要将OTA升级包上传到服务器的$DOCK_SERVER_PATH/ota/versions目录下,上传完之后$DOCK_SERVER_PATH/ota/versions目录内容如下所示:

user@user-HP-Compaq-8200-Elite-USDT-PC:~/ota/docker_server/ota/version3$ tree
.
├── mmc
│   └── update.zip
├── ota-package.7z
└── sha1Tab

1 directory, 3 files

需要注意,此处上传OTA升级包到服务器之后不再需要解压升级包并将解压的升级包存储到full目录下,这是与NAND OTA升级在升级包部署过程中一个最大的不同之处。

然后在服务器升级包路径下创建VERSION文件并写入版本号,例如echo 16 > VERSION。

【7】OTA升级测试

将制作OTA升级包时升级的zero文件拷贝到PC上和【4】开发板初始环境搭建中生成的镜像文件一起烧录到开发板上,烧录工具配置参考下图:

img_18.png

启动到system后需要配置网络连接服务器,下面分别介绍WIFI和以太网的网络配置方法:

WIFI网络配置方法:

方法一 —— 在编译builroot时直接将其打包在根文件系统中的:

修改buildroot/package/wpa_supplicant/wpa_supplicant.conf文件来配置要连接的WIFI或者在device/x2600halley7/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,如下图所示:

img_19.png

输入y之后开始进行OTA升级,系统先升级recovery,然后启动ramdisk升级uboot、kernel和system(具体的根据上面配置的升级信息),最后再次启动,本地VERSION被更新。(详细的升级流程参见【2.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)

错误信息如下:

img_20.png

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

img_21.png

如果ramdisk中缺少库,则将其补上,重新编译测试。如果还不能启动ramdisk,则看是否缺少必要的C库。

【9】EMMC A/B OTA升级方案

【9.1】OTA模式选择

SDK 支持 recovery OTA 和 A/B partition OTA 两种模式,使用前先根据 EMMC 分区空间和产品可靠性需求进行选择。

对比项 recovery OTA A/B OTA
系统分区 一组 kernel、system 分区 两组 kernelA/systemA、kernelB/systemB 分区
升级目标 recovery 环境中写入配置指定的系统分区 当前未运行的备用分区
kernel_recovery 必须制作并作为升级入口 通常不参与升级,需以当前 SDK 实现为准
EMMC 空间 占用空间相对较少 需要额外保存一套系统分区,空间占用较大
升级中断影响 依赖 recovery 升级流程保证系统可恢复 当前运行分区保留,可从另一分区启动
升级后动作 recovery 升级成功后通常自动重启 通常需要设置启动分区后再重启,是否自动重启以设备实现为准
版本回退 依赖 recovery 和设备端实现 可利用保留的旧分区和启动状态实现回退

【9.1.1】recovery OTA适用场景

EMMC recovery OTA 的完整配置和操作方法见本文【2】至【8】章节。其典型流程是:下载升级包,先写入 kernel_recovery,重启进入 recovery ramdisk,再由 recovery 写入 uboot、kernel、system 等分区。

【9.1.2】A/B OTA适用场景

A/B OTA 适用于需要保留上一版本系统、支持系统启动失败回退,或者不希望升级过程直接覆盖当前运行系统的产品。A/B OTA 需要在产品设计阶段预留两套系统分区,并让 uboot 能够识别和切换 A、B 启动分区。

【9.2】两种OTA的通用内容

以下内容在 recovery OTA 和 A/B OTA 中保持一致,文档中只保留一份共用说明:

  1. 升级包制作命令:在 SDK 顶层目录执行 make ota_mkpackage。

  2. 升级包类型:当前使用全包升级,暂不支持差分包升级。

  3. 升级包校验:升级包包含 sha1Tab,用于校验升级资源完整性;如启用 OTA key,还需要使用公钥验证升级包。

  4. 版本检测:服务器升级包目录下的 VERSION 与设备端 /usr/data/VERSION 比较,只有服务器版本更高时才进行升级。

  5. 升级包位置获取:设备端通过 /usr/data/ota_res/recovery.conf 获取 current_version_full.conf,再解析实际升级包路径。

  6. 升级包下载:两种模式均支持远程服务器下载和本地导入设备;EMMC 远程部署通常直接使用 mmc/update.zip 等内容,不需要按 NAND 方案部署到 full 目录。

  7. 设备端工具:先执行 update 获取升级包和版本信息,再执行 recovery;A/B 模式在当前 SDK 中使用 recovery -m ab,但应以板级代码实际支持的参数为准。

  8. 升级成功标志:升级成功后更新 /usr/data/VERSION;失败时不应更新版本号。

【9.3】通用内容索引

两种 OTA 共用版本检查、升级包下载、校验、服务器目录和设备端升级入口,不再分别维护两套说明。为避免同一条命令或配置在多个章节重复,相关内容统一放在以下章节:

  • OTA 资源目录、recovery.conf、版本文件和本地升级包路径,见本文【11】设备端配置定制。

  • 远程下载、本地导入和下载方式选择,见本文【12】下载方式定制。

  • 编译目标、网络配置、服务器部署和设备端检查,见本文【13】OTA 环境部署。

  • recovery OTA 的完整制作、部署和测试流程,仍见本文【3】至【8】,其中原有流程图、时序图和截图保持不变。

  • A/B OTA 专属的分区、升级配置、镜像准备和启动切换,见本文【10】。

因此,A/B OTA 不需要重新设计版本检测、服务器目录或下载流程;只需在相同的通用流程中,使用 A/B 对应的编译目标、分区配置和设备端升级命令。

【10】EMMC A/B OTA开发和使用

【10.1】A/B OTA工作原理

A/B partition OTA 提供一种双缓存 OTA 机制。x2000halley5 的 EMMC 中包含两组 kernel 和 system 分区,分别为 kernelA、systemA、kernelB、systemB。设备从当前活动分区启动,升级时将新版本写入另一组分区,升级完成后由 uboot 根据 NV 中的启动状态选择下一次启动分区。

当前 x2000halley5 的 A/B OTA 不编译 kernel_recovery,而是由用户态 recovery -m ab 直接将升级内容写入备用分区。首次烧录通常从 A 分区启动,第一次 OTA 写入 B 分区;后续 OTA 在 A、B 分区之间交替进行。

与 recovery OTA 相比,A/B OTA 需要额外保留一组系统分区,但升级时可以保留当前正在运行的系统,且可以结合 ota_rollback 回退到上一版本。

【10.2】A/B EMMC分区规划

下面是 x2000halley5.v30_msc_5.10_abota-eng 使用的EMMC 分区情况,来源: device/x2000halley5/ota-overlay/package_config/partition_mmc_ab.conf。

分区名称 起始地址 大小 作用 设备节点
uboot0x0(0 MiB)0x300000(3 MiB) U-Boot、SPL 和 GPT 区域/dev/mmcblk2
kernelA0x300000(3 MiB)0x900000(9 MiB) A 组 kernel/dev/mmcblk2p1
kernelB0xc00000(12 MiB)0x900000(9 MiB) B 组 kernel/dev/mmcblk2p2
nv0x2500000(37 MiB)0x1000000(16 MiB) OTA 状态、启动分区和 NV 数据/dev/mmcblk2p3
reserved10x3500000(53 MiB)0x400000(4 MiB) 预留分区/dev/mmcblk2p4
reserved20x3900000(57 MiB)0x4000000(64 MiB) 预留分区/dev/mmcblk2p5
resource0x7900000(121 MiB)0xc800000(200 MiB) 资源分区/dev/mmcblk2p6
userdata0x14100000(321 MiB)0x6400000(100 MiB) 用户数据/dev/mmcblk2p7
systemA0x1a500000(421 MiB)0x1f400000(500 MiB) A 组 system/dev/mmcblk2p8
systemB0x39900000(921 MiB)0x1f400000(500 MiB) B 组 system/dev/mmcblk2p9
storage0x58d00000(1421 MiB)0x80000000(2048 MiB) OTA 下载包和用户存储/dev/mmcblk2p10

uboot 生成 GPT 时使用的分区表文件为:

u-boot/board/ingenic/x2000_halley5/partitions_mmc_ab_ota.tab

OTA 打包使用的配置文件为:

device/x2000halley5/ota-overlay/package_config/partition_mmc_ab.conf

两者的分区名称、起始地址和大小必须保持一致。修改 EMMC 分区时,必须同时检查 uboot 分区表、partition_mmc_ab.conf 和烧录工具配置。

【10.3】A/B分区配置

partition_mmc_ab.conf 描述 EMMC 容量、分区偏移、分区大小和设备节点。A/B OTA 构建时,device/x2000halley5/ota.mk 会将该文件复制为 OTA 工具默认读取的 partition_mmc.conf:

customization_mmc_ab.conf -> <输出目录>/ota/package_config/customization_mmc.conf
partition_mmc_ab.conf     -> <输出目录>/ota/package_config/partition_mmc.conf

当前实际配置如下:

[storageinfo]
mediumtype=mmc
capacity=4096MB

[partition]
item1=uboot,0x0,0x300000,mmcblk2
item2=kernelA,0x300000,0x900000,mmcblk2p1
item3=kernelB,0xc00000,0x900000,mmcblk2p2
item4=nv,0x2500000,0x1000000,mmcblk2p3
item5=reserved1,0x3500000,0x400000,mmcblk2p4
item6=reserved2,0x3900000,0x4000000,mmcblk2p5
item7=resource,0x7900000,0xc800000,mmcblk2p6
item8=userdata,0x14100000,0x6400000,mmcblk2p7
item9=systemA,0x1a500000,0x1f400000,mmcblk2p8
item10=systemB,0x39900000,0x1f400000,mmcblk2p9
item11=storage,0x58d00000,0x80000000,mmcblk2p10

其中 mmcblk2 是整块 EMMC 设备,mmcblk2p1 至 mmcblk2p10 是 GPT 分区设备节点。不要仅根据分区序号写死 NV 设备节点;当前ota_rollback 会根据 GPT 分区名 PARTNAME=nv 查找 NV 分区。

【10.4】A/B升级信息配置

A/B OTA 的升级信息配置文件为:

device/x2000halley5/ota-overlay/package_config/customization_mmc_ab.conf

当前实际配置如下:

[update]
mediumtype=mmc
imgcnt=3

[image1]
name=uboot
type=normal
offset=0x0
bootmode=normal
updatemode=slice

[image2]
name=kernel
type=normal
offset=0x300000
bootmode=normal
updatemode=slice

[image3]
name=system.ext2
type=normal
offset=0x1a500000
bootmode=normal
updatemode=slice

这里的 offset 是 A 组分区的基准地址,A/B 模式下实际写入 A 还是 B 由当前启动分区和升级程序决定,不应把配置中的 kernel、system.ext2 理解为只写 A 分区。当前配置中 kernel、system.ext2 必须分别与 partition_mmc_ab.conf 中的 kernelA/kernelB、systemA/systemB 容量和布局匹配。

【10.5】A/B模式变量和资源配置

【10.5.1】lunch目标和OTA_MODE

x2000halley5 通过 TARGET_EXT2_SUPPORT 选择 OTA 模式:

A/B OTA 环境初始化和编译示例:

source build/envsetup.sh
lunch
  [x2000halley5]
        1. x2000halley5.v20_msc_5.10-eng
        2. x2000halley5.v20_nand_5.10-eng
        3. x2000halley5.v20_nor_5.10-eng
        4. x2000halley5.v30_msc_5.10_abota-eng *
        5. x2000halley5.v30_msc_5.10-eng
        6. x2000halley5.v30_msc_5.10_ota-eng
        7. x2000halley5.v30_nand_5.10-eng
        8. x2000halley5.v30_nand_5.10_ota-eng
        9. x2000halley5.v30_nor_5.10-eng

Which would you like? [x2000halley5.v30_msc_5.10_abota-eng] 4
make

【10.5.2】A/B模式资源和模块

AB OTA 仍使用 recovery、libupdater、libsysutils、getpackage 和 ota_rollback;但不编译 recovery OTA 所需的 kernel_recovery 和 recovery ramdisk。

板级 OTA 资源目录为:

device/x2000halley5/ota-overlay/
├── package_config/
│   ├── customization_mmc_ab.conf
│   ├── partition_mmc_ab.conf
│   ├── recovery.conf
│   └── current_version.conf
├── ramdisk_config/
└── rootfs_mmc_overlay/

【10.6】A/B镜像准备和打包

A/B OTA 与 recovery OTA 使用相同的升级包制作流程,通用命令见【9.2】;本节只说明 A/B OTA 特有的镜像准备要求:

  1. 编译 A/B uboot 配置对应的 uboot 和 kernel xImage。

  2. 编译 system.ext2,其大小必须小于 systemA 和 systemB 的 0x1f400000 分区大小。

  3. 确认 kernel 镜像小于 kernelA 和 kernelB 的 0x900000 分区大小。

  4. 确认 customization_mmc_ab.conf 的 uboot、kernel、system 偏移与分区表一致。

执行通用打包命令后,在 out/product/<板级产品目录>/image/ota/ 下生成 mmc、ota-package.7z 和 sha1Tab。

【10.7】A/B设备端升级命令和流程

设备端操作顺序如下:

update
recovery -m ab

升级流程:

  1. update 获取服务器端版本和升级包路径。

  2. 检查版本号,确认服务器版本高于 /usr/data/VERSION。

  3. 下载升级包并校验 sha1Tab 和 OTA key。

  4. 读取当前活动分区。

  5. 选择另一组分区作为目标分区。

  6. 将 kernel、system 等升级内容写入目标分区。

  7. 校验目标分区内容。

  8. ota_rollback 设置下一次启动分区。

  9. 新分区启动成功后确认 /usr/data/VERSION 已更新。

当前 x2000halley5 的 uboot 通过 NV 分区的 partition 字段保存启动分区:0 表示 partitionA,0xa5 表示 partitionB。启动时可看到:

The startup area for this time is partitionA !!!
The startup area for this time is partitionB !!!

第一次 OTA 通常从 A 升级到 B,后续 OTA 在 A/B 之间交替。A/B OTA 升级成功后通常需要手动执行 reboot

【10.8】A/B OTA rollback介绍

A/B OTA 的可靠性依赖启动状态和回滚机制,具体使用可参考:AB OTA rollback

【10.9】A/B OTA与recovery OTA差异总结

两种模式的版本检测、升级包下载、校验、服务器部署和版本更新策略相同,具体见本文【9.2】及【11】至【13】章节。本节只保留模式差异:

  • recovery OTA 需要制作 kernel_recovery 和 recovery ramdisk;A/B OTA 通常不需要。

  • recovery OTA 在 recovery 环境中写入配置指定的系统分区;A/B OTA 写入当前未运行的备用分区。

  • recovery OTA 完成后通常自动重启;A/B OTA 需要设置下一次启动分区,再按设备实现重启。

  • recovery OTA 的完整流程、流程图和截图保留在本文【3】至【8】章节;A/B OTA 的专属配置和流程见本章。

【11】设备端配置定制

【11.1】设备端 OTA 资源目录

x2000halley5 的板级 OTA 资源位于:

device/x2000halley5/ota-overlay/
├── package_config/
│   ├── current_version.conf
│   ├── customization_mmc.conf
│   ├── customization_mmc_ab.conf
│   ├── partition_mmc.conf
│   ├── partition_mmc_ab.conf
│   └── recovery.conf
├── ramdisk_config/
└── rootfs_mmc_overlay/
    ├── etc/init.d/S12storage
    ├── etc/init.d/S21data
    ├── etc/init.d/S40copy_ota_res
    └── usr/bin/ota_update_script.sh

编译后,板级 OTA 资源会进入系统的 /etc/ota_res/。设备启动时由 S40copy_ota_res 等启动脚本将资源复制到 /usr/data/ota_res/,升级程序实际优先读取 /usr/data/ota_res/ 中的资源。

默认资源位于:

tools/updater/default_ota_res/

板级 overlay 中同名文件会覆盖默认资源,因此可以通过板级目录定制 recovery.conf、ota_config.xml、公钥、提示音、图片和下载插件。

【11.2】recovery.conf 配置

recovery.conf 文件名固定,源文件位于:

device/x2000halley5/ota-overlay/package_config/recovery.conf

当前配置为:

{
  "server":{
    "ip":"10.1.187.xx",
    "url":"https://10.1.187.xx",
    "rpt_url":""
  }
}

字段说明:

  • ip:OTA 服务器 IP 地址,主要用于显示或设备端网络处理。

  • url:版本查询根地址,设备端通过该地址获取 current_version_full.conf 和 VERSION。

  • rpt_url:升级结果上报地址;不使用上报功能时保持为空。

修改配置后需要重新编译 SDK,并通过以下命令检查编译产物:

cat out/product/x2000halley5.v30_msc_5.10_abota-eng/system/etc/ota_res/recovery.conf

recovery OTA 只需将输出产品目录替换为 recovery OTA 的产品目录。A/B OTA 与 recovery OTA 使用相同的 recovery.conf 格式。

【11.3】升级版本配置文件

设备执行 update 后,会从 recovery.conf 中的 url 获取服务器端的 current_version_full.conf,并将其保存到:

/usr/data/current_version_full.conf

设备端版本文件包括:

文件 作用
/usr/data/current_version_full.confupdate 从服务器获取的升级包路径配置
/usr/data/VERSION_NEW 服务器端当前可用版本
/usr/data/VERSION 设备当前系统版本
/usr/data/VERSION_OLD 升级前的版本备份

服务器端 current_version_full.conf 示例:

{
  "server":{
    "ip":"10.1.187.xx",
    "url":"https://10.1.187.xx/version3"
  }
}

EMMC 单包下载规则要求版本目录下存在:

<版本目录>/mmc/update.zip

【11.4】OTA 相关编译变量

PriceTag 文档中的设备端配置变量在当前 x2000halley5 中对应如下:

变量 当前 x2000halley5 行为
OTA_MODE 由 TARGET_EXT2_SUPPORT=ota 或 abota 转换为 RECOVERY_OTA 或 AB_OTA
OTA_OVERLAY_PATH 默认使用 device/x2000halley5/ota-overlay/package_config
PACKAGE_CONFIG recovery OTA 直接使用板级配置;A/B OTA 使用输出目录中的复制配置
OTA_UPDATER_GETPACKAGE MSC 产品配置为 ON,但 A/B 的 libupdater 构建分支需结合编译日志确认是否传入该宏
OTA_LOCAL_PACKAGE MSC 产品配置为 ON,允许 recovery 从本地包路径读取升级包

【11.5】本地升级包路径配置

当前 MSC EMMC 配置中:

  • getpackage 将升级包下载到 /storage/update/update.zip。

  • recovery 的 ota_config.xml 用于将本地升级包路径设置为 /storage/update。

  • storage 分区挂载到 /storage,由 S12storage 和 mount_mmc_partition.sh 完成。

  • usrdata 分区挂载到 /usr/data,用于保存版本文件和 OTA 资源。

目前测试可以将 ota_config.xml 内容设置为如下,具体可以根据实际情况进行修改

<?xml version="1.0" encoding="UTF-8"?>
<ota_config>
    <prefix_local_update_path>/storage/update</prefix_local_update_path>
</ota_config>

因此,getpackage 和 recovery 必须使用同一个 /storage/update 路径,不能让下载器写入 /storage/update 而让 recovery 仍从当前默认路径 /tmp/update 读取。

【12】下载方式定制

【12.1】默认 wget 下载

当 recovery.conf 或 current_version_full.conf 中的 URL 使用 https 协议时,设备端使用默认网络下载方式。远程升级需要保证:

  • 开发板可以连接 OTA 服务器。

  • 开发板能够解析服务器地址并访问 HTTPS 服务。

  • 服务器版本目录存在 current_version_full.conf、VERSION 和 mmc/update.zip。

【12.2】默认 cp 本地下载

当 URL 使用 file: 协议时,可以通过本地文件路径进行升级。示例:

{
  "server":{
    "ip":"127.0.0.1",
    "url":"file:/storage/ota_download",
    "rpt_url":""
  }
}

本地目录需要与配置保持一致,并包含:

/storage/ota_download/
├── current_version_full.conf
├── VERSION
└── mmc/
    └── update.zip

【13】OTA环境部署

【13.1】部署前准备

【13.1.1】选择编译目标

recovery OTA:

source build/envsetup.sh
lunch x2000halley5.v30_msc_5.10_ota-eng
make

A/B OTA:

source build/envsetup.sh
lunch x2000halley5.v30_msc_5.10_abota-eng
make

生成 A/B OTA 后,重点检查:

out/product/x2000halley5.v30_msc_5.10_abota-eng/image/uboot
out/product/x2000halley5.v30_msc_5.10_abota-eng/image/kernel
out/product/x2000halley5.v30_msc_5.10_abota-eng/image/system.ext2
out/product/x2000halley5.v30_msc_5.10_abota-eng/image/ota/ota-package.7z

A/B OTA 不应要求 kernel_recovery 作为升级入口;recovery OTA 则必须检查 kernel_recovery 是否生成。

【13.1.2】配置网络

WIFI 配置可以放在 buildroot 的公共配置中:

buildroot/package/wpa_supplicant/wpa_supplicant.conf

也可以放在板级 rootfs overlay:

device/x2000halley5/rootfs-overlay/etc/wpa_supplicant.conf

板级 overlay 的配置会覆盖公共配置。示例:

ctrl_interface=/var/run/wpa_supplicant
update_config=1
country=CN

network={
    ssid="ssid"
    scan_ssid=1
    psk="password"
    priority=1
}

启动设备后使用 ping 确认 OTA 服务器连通:

ping 10.1.187.xx

【13.2】远程部署

【13.2.1】远程服务器搭建

远程部署适用于在线升级。服务器搭建方法参考本文【3】章节的 Docker、nginx 和 Python 服务器方案。

服务器需要提供 HTTPS 访问,并保证开发板可以访问服务器的版本目录。

【13.2.2】远程升级包部署

  1. 在 SDK 端配置板级 recovery.conf,使 url 指向服务器根目录。

  2. 在服务器 OTA 根目录创建版本配置 current_version_full.conf:

{
  "server":{
    "ip":"10.1.187.xx",
    "url":"https://10.1.187.xx/version3"
  }
}
  1. 将 EMMC 单包部署到版本目录的 mmc/update.zip。如果 SDK 输出的是 ota-package.7z,先按 EMMC OTA 方案解压或提取其中的 mmc/update.zip。

  2. 在版本目录创建 VERSION:

echo 10 > VERSION

远程目录示例:

ota/
├── current_version_full.conf
└── version3/
    ├── VERSION
    └── mmc/
        └── update.zip

当前 x2000halley5 的 getpackage 下载规则是:

<current_version_full.conf 中的 url>/mmc/update.zip

【13.2.3】远程部署检查

设备端检查:

cat /usr/data/ota_res/recovery.conf
ping 10.1.187.xx
update
ls -l /usr/data/current_version_full.conf /usr/data/VERSION_NEW

如果开启 getpackage,检查:

ls -l /sbin/getpackage /storage/update/update.zip

【13.3】本地部署

本地部署适合无网络环境或快速验证。当前 EMMC 的本地升级包应放在 storage 分区挂载的 /storage 目录中。

【13.3.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。

【13.3.2】本地目录结构

本地目录示例:

/storage/ota_download/
├── current_version_full.conf
├── VERSION
└── mmc/
    └── update.zip

current_version_full.conf 示例:

{
  "server":{
    "ip":"127.0.0.1",
    "url":"file:/storage/ota_download"
  }
}

准备目录后,将 VERSION 写入升级版本号:

echo xxx > /storage/ota_download/VERSION

【13.3.3】本地升级包导入设备

可以使用 adb 导入完整目录:

adb push ota_download /storage/

或者通过业务程序、U 盘或其他方式将文件复制到设备的 /storage/ota_download。导入后检查:

ls -l /storage/ota_download/current_version_full.conf
ls -l /storage/ota_download/VERSION
ls -l /storage/ota_download/mmc/update.zip

也可以直接将已下载的升级包放入:

/storage/update/update.zip

但仍需保证 update 能够获取匹配的版本配置和版本号。

【13.3.4】本地部署注意事项

  • /storage 对应 EMMC 的 storage 分区,当前大小为 0x80000000(2 GiB),需要确保能够容纳升级包。

  • current_version_full.conf 中的路径必须与 recovery.conf 中的路径一致。

  • 使用 file: 时填写设备端绝对路径,不能填写 PC 端路径。

  • A/B OTA 和 recovery OTA 可以共用本地部署目录,但升级包内容必须与当前编译的 OTA 模式匹配。

  • 如果只替换了 recovery.conf,还需要确认设备端已有对应的 current_version_full.conf、VERSION 和 mmc/update.zip。

【13.4】远程部署和本地部署对比

项目 远程部署 本地部署
recovery.conf URLhttps://服务器地址file:/storage/ota_download
升级包来源 OTA 服务器 EMMC storage 分区
EMMC 包路径<版本目录>/mmc/update.zip/storage/ota_download/mmc/update.zip
是否需要网络 需要 不需要
主要限制 网络、HTTPS 和服务器连通性 本地存储空间和目录配置

【14】OTA A/B 分区切换测试

【14.1】升级成功信息

recovery -m ab

xxxxxxxxxxxxxx
xxxxxxxxxxxxxx
xxxxxxxxxxxxxx
+++ UPDATING 90
I/Recovery--->ota_manager 1176: Updating "/storage/update/update/update205/system.ext2_198"
E/Recovery--->mmc 52: mmc write: infile=/storage/update/update/update205/system.ext2_198,outfile=/dev/mmcblk2p9,offset=206569472,length=1048576
E/Recovery--->mmc 72: mmc write cmd: dd if=/storage/update/update/update205/system.ext2_198 of=/dev/mmcblk2p9 bs=1048576 skip=0 seek=197 count=1 conv=fsync
1+0 records in
1+0 records out
1048576 bytes (1.0MB) copied, 0.144387 seconds, 6.9MB/s
D/Recovery--->block_manager 147: =============================
D/Recovery--->block_manager 148: Dump bm event
D/Recovery--->block_manager 149: operation: Write
D/Recovery--->block_manager 150: progress:  99
D/Recovery--->block_manager 151: =============================
D/Recovery--->ota_manager 659: *********cmd: /usr/data/ota_res/update_stage.sh UPDATING 99
in update_stages:param:UPDATING,99
+++ UPDATING 90
I/Recovery--->ota_manager 1176: Updating "/storage/update/update/update206/system.ext2_199"
E/Recovery--->mmc 52: mmc write: infile=/storage/update/update/update206/system.ext2_199,outfile=/dev/mmcblk2p9,offset=207618048,length=1048576
E/Recovery--->mmc 72: mmc write cmd: dd if=/storage/update/update/update206/system.ext2_199 of=/dev/mmcblk2p9 bs=1048576 skip=0 seek=198 count=1 conv=fsync
1+0 records in
1+0 records out
1048576 bytes (1.0MB) copied, 0.186523 seconds, 5.4MB/s
D/Recovery--->block_manager 147: =============================
D/Recovery--->block_manager 148: Dump bm event
D/Recovery--->block_manager 149: operation: Write
D/Recovery--->block_manager 150: progress:  99
D/Recovery--->block_manager 151: =============================
D/Recovery--->ota_manager 659: *********cmd: /usr/data/ota_res/update_stage.sh UPDATING 99
in update_stages:param:UPDATING,99
+++ UPDATING 90
I/Recovery--->ota_manager 1176: Updating "/storage/update/update/update207/system.ext2_200"
E/Recovery--->mmc 52: mmc write: infile=/storage/update/update/update207/system.ext2_200,outfile=/dev/mmcblk2p9,offset=208666624,length=1048576
E/Recovery--->mmc 72: mmc write cmd: dd if=/storage/update/update/update207/system.ext2_200 of=/dev/mmcblk2p9 bs=1048576 skip=0 seek=199 count=1 conv=fsync
1+0 records in
1+0 records out
1048576 bytes (1.0MB) copied, 0.164693 seconds, 6.1MB/s
D/Recovery--->block_manager 147: =============================
D/Recovery--->block_manager 148: Dump bm event
D/Recovery--->block_manager 149: operation: Write
D/Recovery--->block_manager 150: progress:  100
D/Recovery--->block_manager 151: =============================
D/Recovery--->ota_manager 659: *********cmd: /usr/data/ota_res/update_stage.sh UPDATING 100
in update_stages:param:UPDATING,100
+++ UPDATING 100
I/Recovery--->ota_manager 1347: Updating package finish. Updating NV...I/Recovery--->ota_manager 1367: finish. 
D/Recovery--->ota_manager 659: *********cmd: /usr/data/ota_res/update_stage.sh UPDATE_SUCCESS 0
in update_stages:param:UPDATE_SUCCESS,0
+++ UPDATE_SUCCESS
# 

#

【14.2】切换分区测试

# ota_rollback -i
AB OTA MMC: NV partition=/dev/mmcblk2p3
AB OTA MMC: reading NV, size=1116 bytes
AB OTA MMC: read NV success
AB OTA MMC: current partition=partitionB
AB OTA MMC: target partition=partitionA
AB OTA MMC: writing NV, size=1116 bytes
AB OTA MMC: write NV success
AB OTA MMC: reading NV, size=1116 bytes
AB OTA MMC: read NV success
AB OTA MMC: NV write and reread verification success
Modify the startup section to partitionA !

# ota_rollback -i
AB OTA MMC: NV partition=/dev/mmcblk2p3
AB OTA MMC: reading NV, size=1116 bytes
AB OTA MMC: read NV success
AB OTA MMC: current partition=partitionA
AB OTA MMC: target partition=partitionB
AB OTA MMC: writing NV, size=1116 bytes
AB OTA MMC: write NV success
AB OTA MMC: reading NV, size=1116 bytes
AB OTA MMC: read NV success
AB OTA MMC: NV write and reread verification success
Modify the startup section to partitionB !
#

【14.3】显示当前分区信息

# ota_rollback -d
AB OTA MMC: NV partition=/dev/mmcblk2p3
AB OTA MMC: reading NV, size=1116 bytes
AB OTA MMC: read NV success
current startup section is partitionB !
NV FLAGS:
 nv->boot       0
 nv->step       0
 nv->start      0
 nv->end        a5a5a5a5
 nv->needfullpkg        0
 nv->rot_angle  0
 nv->partition  a5
 
# ota_rollback -i
AB OTA MMC: NV partition=/dev/mmcblk2p3
AB OTA MMC: reading NV, size=1116 bytes
AB OTA MMC: read NV success
AB OTA MMC: current partition=partitionB
AB OTA MMC: target partition=partitionA
AB OTA MMC: writing NV, size=1116 bytes
AB OTA MMC: write NV success
AB OTA MMC: reading NV, size=1116 bytes
AB OTA MMC: read NV success
AB OTA MMC: NV write and reread verification success
Modify the startup section to partitionA !

# ota_rollback -d
AB OTA MMC: NV partition=/dev/mmcblk2p3
AB OTA MMC: reading NV, size=1116 bytes
AB OTA MMC: read NV success
current startup section is partitionA !
NV FLAGS:
 nv->boot       0
 nv->step       0
 nv->start      0
 nv->end        a5a5a5a5
 nv->needfullpkg        0
 nv->rot_angle  0
 nv->partition  0
#

AB partition内容参考来自:OTA开发和介绍,如有疑问可进一步查阅该文档介绍