前言¶
概述
本文档详细的描述了BS2XV100升级流程以及相关工具的操作指导,同时提供了常见的问题解答及故障处理方法。
BS2X系列包含BS21/BS21E/BS22/BS26,本文档以BS21为例。
产品版本
与本文档对应的产品版本如下。
产品名称 |
产品版本 |
|---|---|
BS2X |
V100 |
读者对象
本文档主要适用以下工程师:
技术支持工程
软件开发工程师
符号约定
在本文中可能出现下列标志,它们所代表的含义如下。
符号 |
说明 |
|---|---|
|
表示如不避免则将会导致死亡或严重伤害的具有高等级风险的危害。 |
|
表示如不避免则可能导致死亡或严重伤害的具有中等级风险的危害。 |
|
表示如不避免则可能导致轻微或中度伤害的具有低等级风险的危害。 |
|
用于传递设备或环境安全警示信息。如不避免则可能会导致设备损坏、数据丢失、设备性能降低或其它不可预知的结果。 “须知”不涉及人身伤害。 |
|
对正文中重点信息的补充说明。 “说明”不是安全警示信息,不涉及人身、设备及环境伤害信息。 |
修改记录
文档版本 |
发布日期 |
修改说明 |
|---|---|---|
06 |
2025-08-07 |
|
05 |
2025-05-30 |
更新“BLE传输”章节内容。 |
04 |
2025-01-14 |
文档名称由《BS2XV100 星闪&BLE OTA升级方案 指导书》更改为《BS2XV100 升级方案 使用指南》
|
03 |
2024-08-29 |
|
02 |
2024-07-04 |
|
01 |
2024-05-24 |
第一次正式版本发布。 更新“升级包传输”章节内容。 |
00B01 |
2024-02-28 |
第一次临时版本发布。 |
概述¶
功能描述¶
固件升级功能可用于对单板芯片的固件进行更新。
BS2X的固件包含分区表、二级引导程序(Flashboot)、用户固件镜像(Application)、NV镜像,支持二级引导程序、用户固件镜像,目前升级方式包括全镜像升级、压缩升级。
全镜像升级:新的固件镜像不做处理,直接打包到固件升级包(以下简称为“升级包”)中,在单板上直接将其更新至目标位置。
压缩升级:新的固件镜像经过压缩处理后,打包到升级包中,首先在设备上解压恢复,再更新至目标位置。
固件升级流程¶
从端到端来看,整个芯片固件的升级操作包括以下过程。如图1所示。
升级包制作:固件开发完成后,根据实际情况,将要升级的固件镜像打包生成固件升级包文件的过程。
升级包传输:将升级包传输到单板上。根据实际情况,可能有多种传输方式,如BLE、星闪、串口、USB等。
升级包保存:将传输到单板的固件升级包保存至本地存储器。在BS2X中,固件升级包存储在Flash中。
升级包本地校验:升级程序替换前,在单板上校验升级包的完整性和合法性。
升级包本地升级:在单板上将新的固件更新至目标位置。在BS2X中,Flashboot程序负责升级Flashboot自身以及APP镜像。
图 1 固件升级流程图

升级包制作¶
流程原理¶
图 1 升级包制作流程

升级包的制作流程示意图如图1所示,具体操作步骤如下:
编译生成带签名的明文新镜像。
对新镜像进行处理。处理方式包含场景如下:
将新镜像压缩,生成压缩的新镜像。
新镜像不做处理。
对步骤2中生成的镜像添加升级镜像头。
将生成的所有带升级镜像头的升级镜像文件合并到最终升级包中,并对整包添加升级包头,进行数字签名。
说明: BS2X不支持安全升级,步骤5中不添加数字签名。
升级包格式¶
升级包格式如图1所示,主要分为升级秘钥区、升级信息区、镜像表头区、镜像区,各区保持16字节对齐。相应的结构体见include/middleware/utils/upg.h。
图 1 升级包结构图

开发流程¶
升级包可以在所有镜像编译完成后,通过执行“build/config/target_config/bs21/build_bs21_update.py”来制作,在“build_bs21_update.py”文件中配置各个镜像的路径以及其他脚本所需的参数,并调用升级包制作脚本“build/script/build_upg_pkg.py”。“build_bs21_update.py”配置的各个路径可以根据实际路径修改。脚本及配置文件说明如下:
BS2X在编译生成新固件时,会自动将生成固件打包成升级包,用户只需选择需要升级的固件。配置升级固件的文件路径:build/config/target_config/bs21/config.py。如图1所示,在upg_pkg选项中选择需要升级的固件,支持升级的固件:flashboot,application。
图 1 升级包添加升级镜像

升级包路径:output/bs21/acore/bs21-sle-ble-central-peripheral/fota.fwpkg。
升级包制作脚本为:build/script/build_upg_pkg.py,升级包制作脚本的调用参数说明如表1所示。
配置文件为:build/config/target_config/bs21/fota/1M_flash/fota.cfg(外置flash版本为build/config/target_config/bs21/fota/extern_flash/fota.cfg),配置文件的各个字段说明如表2所示。
配置文件“fota.cfg”中可配置升级镜像模式,如表2中的升级镜像模式标记DecompressFlag所示,支持两种升级模式压缩、全量。
生成fota包时,会根据芯片类型及用户配置的特征码插入版本特征码,升级时将进行一致性检查。特性宏配置如下图所示。若一致性检查失败,则停止升级并删除当前存储的升级包。

表 1 build_upg_pkg.py参数说明
参数 |
参数值 |
说明 |
|---|---|---|
-app_name |
文件名 |
生成的升级包文件名称,以及部分中间文件的名称前缀。 |
-upg_format_path |
升级包结构配置文件 |
升级包的包头结构,包含“fota_key_area”和“fota_info_area”两部分。 |
-base |
基础配置文件路径 |
基础配置文件路径,参考表2。 升级包制作过程中,会根据该文件生成中间配置文件,或直接使用该配置文件中的配置值。 |
-temp_dir |
临时文件存放目录 |
存放中间文件的路径。 |
-new_images |
新镜像列表 |
要升级的镜像的路径和类型,每个镜像的格式为: “镜像路径:镜像类型”,镜像之间用“|”进行分割。其中镜像类型与base参数所指定的文件中各个镜像的类型一一对应。 列表格式举例: “镜像1路径:镜像类型1|镜像2路径:镜像类型2|...|镜像N路径:镜像类型N” |
-output_dir |
升级文件存放目录 |
base参数所指定的文件中若未指定升级镜像和签名镜像的路径,则会放入该目录中,并以“app_name”作为前缀进行命名。 |
表 2 fota.cfg主要内容说明
标签 |
属性 |
说明 |
|---|---|---|
[SIGN_CFG] |
- |
签名相关属性。 |
SignSuite |
签名密钥类型。
|
|
UpgImagePath |
升级包文件路径和名称。 |
|
UpgSignedImagePath |
升级包签名后的路径和名称。 |
|
RootKeyFile |
根密钥文件路径。 |
|
SubKeyFile |
二级秘钥文件路径。 |
|
[TOOLS] |
- |
制作工具配置属性。 |
UpgToolPath |
升级工具路径和名称(升级工具可用作制作差分文件和签名文件)。 |
|
LzmaToolPath |
压缩工具路径和名称。 |
|
[FOTA_KEY_AREA] |
- |
升级包Key区属性。 |
ImageId |
升级包Key区镜像ID,固定为0xCB8D154E。 |
|
KeyAlg |
升级包Key区域密钥算法类型。
|
|
KeyVersion |
升级包Key区版本号。 |
|
KeyVersionMask |
升级包Key区版本号掩码。 |
|
Msid |
市场区域ID。 |
|
MsidMask |
市场区域ID掩码。 |
|
[FOTA_INFO_AREA] |
- |
升级包INFO区属性。 |
ImageId |
升级包INFO区镜像ID,固定为0xCB8D154E。 |
|
HardwareID |
硬件版本号。 |
|
Msid |
市场区域ID。 |
|
MsidMask |
市场区域ID掩码。 |
|
[flashboot/application] |
- |
镜像类型名称。 |
HeaderMagic |
头结构魔术字,固定为0x464F5451。 |
|
ImageId |
升级镜像ID,与原始镜像的ImageId相同,镜像ID请参考middleware/chips/bs2x/update/include/upg_definitions_porting.h。 |
|
DecompressFlag |
升级镜像模式标记。
|
|
ReRncFlag |
升级镜像加密标记。
|
说明:
外置Flash版本只支持全量升级,内置Flash版本支持全量升级、压缩升级。
升级包最大size请参考“Flash分区”中分区表配置文件中的fota_data(0x26)区,其size减去4K升级标记区即为升级包最大size。
升级包配置文件fota.cfg配置了升级过程需要校验的字段,用户如需要在升级包中添加字段,需要对build_upg_pkg.py做二次开发。升级包结构与字段可参见“升级包格式”和include/middleware/utils/upg.h。
升级包传输¶
升级包的传输,由应用程序实现,可以有多种方式,包括蓝牙、星闪、USB、UART。以下介绍各种传输方式的基本流程以及相关工具的使用。
BLE传输¶
BS2X BLE端到端升级交互流程如图1所示。Server端使能BLE OTA升级,需要先注册BLE OTA通道,如图2,然后注册BLE OTA服务,如图3。可参考BLE UART Sample,代码路径application/samples/products/ble_uart。
图 1 升级流程图

图 2 注册BLE OTA通道

图 3 注册BLE OTA服务

采用DebugKits工具把升级包通过蓝牙传输到单板上,操作流程如下。
星闪传输¶
星闪端到端升级交互流程与BLE传输一致。

注册星闪OTA通道,如图1。
注册星闪OTA服务,如图2。
注册星闪OTA钩子,如图 注册OTA钩子函数。
具体可参考RCU Sample,代码路径application/samples/products/rcu。
图 1 注册星闪OTA通道

图 2 注册星闪OTA服务

图 3 注册OTA钩子函数

星闪升级工具的具体操作流程如下。注:工具名称:SleOta_时间.apk
单击SCAN开始扫描设备。
图 4 扫描设备

单击STOPSCAN停止扫描设备。
图 5 停止扫描

单击配网进入该设备的升级界面。
图 6 单击配网

升级界面:设备状态为connected表示已连接,disconnected表示未连接。
图 7 SLE OTA升级界面

单击BROWSER选择升级文件,若连接状态为disconnected,则无法选择文件。测试时一般将文件放在sdcard/Download目录下(仅供参考)。
图 8 选择文件

选择好升级文件后,单击START即可开始升级,开始成功后进度条便会前进
图 9 开始升级

说明:
如果配对失败,可以重新打开星闪开关以及重新启动APK来进行配对。
进入到OTA升级界面后需要查看设备连接状态是否为connected。若选中bin文件后会跳转至权限界面,需要手动允许apk访问所有文件。
星闪Dongle传输¶
星闪协议要求从机与主机侧交互时,从机和主机侧都搭配星闪芯片。由于芯片外销时,市面大部分产品的主SOC不支持星闪功能。为了快速铺开星闪生态,考虑主机侧增加内置星闪芯片的Dongle来实现与从机侧的星闪交互。实现流程如图1所示,具体参考SLE OTA Dongle Sample,路径:application/samples/products/sle_ota_dongle。Dongle与从机的交互协议具体可参考文档《BS2XV100 星闪应用层SLE-Link协议》。
图 1 SLE Dongle传输流程图

星闪Dongle工具分为安卓版本和Windows版本,安卓工具版本为Debugkits,操作流程如下。
设置对端目标设备SLE地址,如图2所示。
图 2 设置对端地址

单击CONNUSB按键,与Dongle USB建立连接,如图3所示。
图 3 连接USB

再次单击CONNUSB按键,使能SLE并获取Client端地址,再单击CONNSLE按键,扫描并连接目标设备,如图4所示。若显示目标设备地址和版本号(0),则连接成功。
图 4 连接目标设备

选择升级包路径并开始传输,如图5
图 5 传输升级包

Windows工具为Burntool工具,在Option选项中选择Change chip,选择BS2X-SLE模块,进入界面后的操作流程如下。
DFU升级¶
通过DFU升级交互流程如图1所示,升级传输第一包数据为升级准备流程,工具发送一包数据描述升级包信息,包括起始标记、升级包地址、升级包大小等,详见dfu_packge_header_t,文件路径为application/samples/products/sle_mouse_with_dongle/mouse_usb/usb_dfu.c。Dongle侧收到第一包数据后,根据文件长度擦除fota区。从第二包开始,工具下发升级包数据,每包长度4KB,直至升级包数据传完。待升级包传输结束,dongle侧写升级标记位,本地重启。
图 1 DFU升级交互流程

DFU相关代码实现可参考SLE Mouse Sample,代码路径application/samples/products/sle_mouse_with_dongle。工具的操作流程如下。
使用管理员权限打开程序(右键单击应用程序,单击以管理员身份运行,如图2所示。
图 2 Burntool运行

Burntool的option选项选择“BS2X-USB”。
在BurnTool界面的USB处选择所需的USB设备。如图3所示。
图 3 Burntool界面选项

在BurnTool界面中单击“Select file”按钮,选择产品编译生成的固件包,并单击“打开”。
在表格中选中需要烧写的文件。
单击“Start burn”按钮(单击后“Start burn”变为“Stop burn”)。
等待传输完成后结束烧写,烧写完成会出现“All images burn successfully”。烧写完成效果,如图4所示。
图 4 DFU烧录完成

UART升级¶
产线一般通过UART对空片烧录固件,一般会在烧录商用版本之前烧录产测版本,用于测试、校准等。为了减少烧录商用版本的步骤,可以将商用固件以升级包的形式,和产测固件一并烧录到芯片Flash上,在完成产测测试后写升级标记位并复位芯片,进入Flashboot本地升级流程将产测固件升级为商用固件。UART传输升级包,由Loaderboot程序实现,具体适配流程如下。
打包产测固件和商用固件¶
修改产测固件的打包脚本,将商用固件的升级包与产测固件一并打包成一个fwpkg,产线烧录时烧录该固件即可,打包脚本路径:tools/pkg/chip_packet/bs2x/packet.py。修改如图1所示。图中升级包路径根据实际情况修改,本文只做示例。
图 1 烧录的固件中添加升级包

产测固件升级到商用固件¶
在完成产线测试后,需要执行写升级标记位的操作,并进入本地升级流程。升级标记区位于升级包区域最后4KB空间,格式如下,升级标记的结构体详见middleware/utils/update/inner_include/upg_definitions.h。
typedef struct fota_upgrade_flag_area {
uint32_t head_magic;
uint32_t head_before_offset;
uint32_t package_length;
uint32_t firmware_num;
uint8_t firmware_flag[UPG_FIRMWARE_MAX_NUM][UPG_FLAG_RETYR_TIMES];
uint8_t nv_flag[UPG_FLAG_RETYR_TIMES];
uint8_t ver_change_flag;
uint32_t update_result;
uint32_t nv_data_offset;
uint32_t nv_data_len;
uint32_t nv_hash_offset;
uint32_t nv_hash_len;
uint32_t complete_flag;
uint32_t head_end_magic;
} fota_upgrade_flag_area_t;
以下为写使能标记位代码示例,供参考:
fota_upgrade_flag_area_t fota_flag;
memset_s((uint8_t *)&fota_flag, sizeof(fota_upgrade_flag_area_t), 0xff, sizeof(fota_upgrade_flag_area_t));
fota_flag.head_magic = 0x55aa55aa;
fota_flag.head_before_offset = 0;
fota_flag.package_length = fota_len; // 升级包大小
fota_flag.firmware_num = fw_num; // 升级包中固件个数
fota_flag.head_end_magic = 0xaa55aa55;
partition_information_t info;
uapi_partition_init();
errcode_t ret_val = uapi_partition_get_info(PARTITION_FOTA_DATA, &info);
uint32_t flag_address = info.part_info.addr_info.addr + info.part_info.addr_info.size - 0x1000;
uint32_t status = (uint32_t)osal_irq_lock();
uapi_sfc_reg_erase(flag_address, 0x1000);
uapi_sfc_reg_write(flag_address, (uint8_t *)&fota_flag, sizeof(fota_upgrade_flag_area_t));
// uapi_flash_block_erase(0, flag_address, 0x1000); // 外置flash版本
// uapi_flash_write_data(0, flag_address, (uint8_t *)&fota_flag, sizeof(fota_upgrade_flag_area_t)); // 外置flash版本
osal_irq_restore(status);
upg_reboot(); // 复位单板
说明: 以上代码,用户需要调整变量fota_len和fw_num,fota_len为升级包大小,fw_num为升级包中固件个数,比如升级包中只包含Application.bin,则fw_num = 1。
HID升级¶
以BS26为例,SDK共提供三个flashboot,即:
flashboot-bs26-n1200:支持OTA升级,即会在OTA升级完成后将FOTA区数据解压拷贝到APP主区
flashboot-bs26-n1200-usb:支持USB HID升级,但不支持OTA升级后的拷贝
flashboot-bs26-n1200-usb-with-ota:支持USB HID升级,并支持OTA升级后的拷贝
所以如果需要flashboot带HID升级功能,需要使用flashboot-bs26-n1200-usb或flashboot-bs26-n1200-usb-with-ota,即在对应config.py中将'flashboot_cfg'配置成所需的flashboot。
带USB HID升级功能的flashboot镜像要更大,划分分区时需注意。
USB HID升级需要额外4K分区用来作为升级标志判断,即分区ID为0x26的fota data,和其他OTA升级方式不同的是,HID升级只是要fota data的最后4k用来存储升级标志信息,其他OTA升级方式需要在fota区域存储升级镜像。
另外,USB HID升级需要分区表中额外添加ID 0x29,用来存储vid、pid和io检测信息。

示例如下:

如下图所示,配合vid和pid后,单击Start burn,之后插拔/重启后级开始下载。

上位机控制HID升级¶
HID升级在上电时(插拔USB)会初始化USB并且等待burntool发送USB升级指令,所以会增加上电时长,为了减少上电时长,故增加一个上位机控制HID升级的flashboot版本。以BS26为例,即
flashboot-bs21e-1100e-usb-with-control 和 flashboot-bs21e-1100e-usb-with-ota-with-control。
打包fwpkg的时候选择带'-with-control'的flashboot版本,默认上电不进行HID升级,需要上位机发送命令控制bs2x写HID升级标志寄存器和软复位寄存器,软复位后进行HID升级。
HID升级标志寄存器:0x5702C010写0x5A。
软复位寄存器:0x57004600写0。
升级包保存¶
在BS2X中,升级包保存在Flash中,包括内置Flash以及外挂Flash,用户可根据产品的需求选择不同方案。Flash的内存分布如下(内置Flash基地址:0x90100000)。
Flash分区¶
在BS2X中,客户可根据需要划分Flash分区。在版本的sector_cfg选项中修改相应的分区,分区表的路径位于build/config/target_config/bs21/flash_sector_config。如图1。
图 1 分区表配置

512KB内置Flash分区,如图2。具体配置见build/config/target_config/bs21/flash_sector_config/bs21-standard-512k.json。
图 2 512KB内置Flash分区图

1M内置Flash分区,如图3。具体配置见build/config/target_config/bs21/flash_sector_config/bs21-standard-1m.json。
图 3 1M内置Flash分区图

512K内置Flash,外挂Flash(外挂Flash大小可根据用户需要调整,不小于512K),如图4。具体配置见build/config/target_config/bs21/flash_sector_config/bs21-extern-flash.json。
图 4 512KB内置Flash与外挂Flash分区图

外置Flash适配¶
外置Flash选型
目前BS2X支持的外置Flash选型,详见include/driver/flash/flash_common_config.h,如图1。其他头文件未列出的Flash类型,用户需自行适配。
图 1 Flash驱动支持的外置Flash选型

外置Flash适配
图 2 Flash初始化

图 3 Flash驱动添加manufacturer id

图 4 修改Flash驱动info

升级包本地升级¶
在BS2X中,本地升级程序主要在Flashboot程序中运行。可升级的镜像为Flashboot、Application。
Flashboot程序升级Flashboot自身时,会将Flashboot拷贝到Flashboot备份区,避免掉电异常。在更新完所有镜像后,单板会自动复位,复位后进入Application镜像。
FAQ¶
问题一:手机与Server端连接正常,但是单击Start无法传输
定位思路:
可以先打开OTA业务的Log开关,如图1。排查一下版本是否注册OTA业务,DFX是否注册OTA通道,具体参考“BLE传输”、“星闪传输”。例如DFX未注册OTA通道时,Client端(手机apk或星闪Dongle)读取对端版本号会失败,如图2所示。若是OTA业务未注册,升级界面无法进入,如图3所示。
图 1 打开Server端OTA日志

图 2 OTA读取版本号失败

图 3 APK升级界面进入失败

升级包太大,超过FOTA分区大小。日志如图4所示。
图 4 升级包超出FOTA分区

问题二:升级包传输过程进度条卡住或者传输时间超过10分钟
定位思路:
可能是传输过程出现丢包,或者Client发包速度太慢,导致Server端不断向Client端发重传请求。如果是星闪dongle升级,可以排查一下Dongle是否日志加太多影响传输速率。
问题三:升级包传输完成后Server端不复位
定位思路:
升级包格式不对,排查下升级包版本是否不对,升级包版本路径如图5所示。
图 5 Server端传输结束后复位失败

问题四:升级包传输完成并更新固件复位后变砖
定位思路:
防串货机制导致,与Flashboot版本相关,需更新Flashboot版本。Flashboot版本与Application版本需来自同个SDK。
问题五:升级包更新搬运固件的过程掉电,复位后变砖
定位思路:
BS2X有本地升级掉电保护机制,如果掉电后重新上电后变砖,可能是防串货机制导致,需更新Flashboot版本。Flashboot版本与Application版本需来自同个SDK。
问题六:如何升级分区表
旧版本分区表升级至新版本分区表,需要升级两次才能完全更新。
须知:
升级分区表的流程有变砖风险,用户需谨慎操作,升级过程保证不掉电。
BS2X启动与升级流程都依赖分区表,原则上分区表不应升级。在产品生产前分区表需固化,后续不应再修改。以上升级分区表的方法不推荐在量产阶段使用。
具体步骤如下:
基于旧版本添加下列修改,编译中间版本。
此中间版本在Application初始化分区表之前,修改旧版本分区表升级区的信息,使其与新版本一致,代码修改如图6。
图 6 初始化分区表之前修改分区表升级区信息


代码示例:
static uint32_t g_partition[0x400] = { // 分区表镜像头,不需要修改 0x4b87a52d, 0x00010000, 0x00000000, 0x000c001c, 0x26252301, 0x30292827, 0x00333231, // 0x00 0x00001000, 0x00008000, // 0x01 0x00009000, 0x00008000, // 0x23 0x00011000, 0x0008c000, // 0x25 0x000FE000, 0x00002000, // 0x26 0x0009d000, 0x00061000, // 0x27 0x00000000, 0x00000000, }; errcode_t ret = osal_irq_lock(); uapi_sfc_reg_erase(0x0, 0x1000); uapi_sfc_reg_write(0x0, (uint8_t *)g_partition, 0x400); osal_irq_restore(ret);
在升级的传输流程结束后、单板复位前,修改旧版本分区表其他区域区,使分区表与新版本分区表保持一致。DFU升级的代码修改如图7,OTA升级的代码修改如图8。
图 7 DFU升级传输流程结束后更新分区表

图 8 OTA升级传输流程结束后更新分区表

基于上述修改,编译中间版本。旧版本升级该中间版本,完成分区表升级区的更新,然后再升级新版本固件(包括新版本Flashboot、App镜像),即可完成分区表的更新。














