升级工具链(BLE OTA / USB Dongle OTA)
本页介绍 fw-AC63_BT_SDK 的 OTA 升级工具链:以 USB Dongle(BLE 主机/GATT Client) 为桥接、以 PC 端工具为控制端的远端 BLE OTA 升级体系,以及设备端(从机侧)的 BLE OTA 消息处理与 RCSP 升级引擎。
Purpose and Scope
本页覆盖的内容:
- USB Dongle 固件侧 OTA 通道模型:PC ↔ Dongle(USB HID 自定义通道)↔ 远端 BLE 从机的三级透传架构(
apps/spp_and_le/examples/dongle/下的ota_dg_central.c、ble_dg_central.c、usb_hid_devices.c)。 - PC ↔ Dongle 的 USB 帧协议:
JL帧头、channel/cmd_type/长度字段、0xED帧尾、64 字节 HID 分片。 - 设备端(从机侧)BLE OTA 消息入口:
ble_ota_msg_handle()(LL Sync 协议)以及 RCSP 升级(rcsp_user_update)。 - 构建产物与 PC 端工具:
cpu/*/tools/下的ota.bin、uboot_no_ota.boot、download_app_ota.bat等。
有意留给兄弟页面、不在本页展开的内容:
- 具体的 BLE GATT 服务定义与 ATT 属性表 → 见 "GATT 服务与属性" 相关页面。
- 各云平台协议(Hilink / Tuya / Tencent LL)的 OTA 对接 → 见各云平台协议页面。
- Mesh DFU 组网升级 → 见 Mesh 相关页面。
- 配置工具(AC632N Config Tools)→ 见 "配置工具" 页面。
概述
在 AC63 系列(如 AC632N / BD19 / BD29 / BR23)蓝牙 SoC 方案中,OTA 升级有两条典型链路:
USB Dongle OTA(工具链主链路):PC 通过 USB 连接一个"Dongle"(本身就是一个以 GATT Client / BLE 主机 角色运行的 SoC,例如
apps/spp_and_le/examples/dongle/工程),Dongle 再通过 BLE 连接一个或多个远端从机设备。PC 工具发送的升级数据经 USB HID 通道进入 Dongle,Dongle 将其转发到对应的 BLE 连接(透传通道),远端设备收到后用自身的 OTA 引擎(RCSP / BLE OTA 消息处理)完成固件写入。这种方式让普通 PC(无 BLE 硬件或不想做 HCI 转发)也能批量、多设备地升级耳机/音箱等产品。BLE OTA(设备间/工具直连):手机或专用 BLE 工具直接连接从机设备,通过 LL Sync 或 RCSP 协议下发固件,从机侧由
ble_ota_msg_handle()(或rcsp_user_update中的处理函数)解析并执行升级。
本 SDK 中的升级工具链因此是"协议分层 + 通道复用"的架构:同一套 RCSP/BLE OTA 升级数据,既可以通过 BLE 直连下发,也可以通过 Dongle 的 USB 透传通道下发——Dongle 只负责透明转发(对远端连接进行 channel↔connection_handle 映射),不解析升级内容本身。
架构
flowchart TD
subgraph sg_PC["PC 端工具"]
PC["PC 升级工具 / 上位机"]
end
subgraph sg_USB["USB HID 链路"]
USBHID["custom_hid_tx_data<br/>64 字节 HID 分片"]
CMD["APP_CMD_* 命令通道<br/>JL 帧头 / 0xED 帧尾"]
end
subgraph sg_Dongle["USB Dongle 固件 (apps/spp_and_le/examples/dongle)"]
OTA_DG["ota_dg_central.c<br/>通道调度与转发"]
BLE_DG["ble_dg_central.c<br/>GATT Client 连接管理<br/>ota_is_support"]
HID_USB["usb_hid_devices.c<br/>自定义 HID 设备"]
end
subgraph sg_BLE["BLE 链路"]
CH_REMOTE["远端透传通道<br/>HID_RX_HANDLER_CHANNEL_REMOTE1~8"]
end
subgraph sg_Device["远端从机设备"]
LL_SYNC["ble_ota_msg_handle<br/>(LL Sync OTA 消息)"]
RCSP["rcsp_user_update<br/>RCSP 升级引擎"]
FLASH["固件写入 Flash"]
end
PC -->|"USB 串口/HID 指令"| USBHID
USBHID --> CMD
CMD --> OTA_DG
OTA_DG --> BLE_DG
BLE_DG --> CH_REMOTE
CH_REMOTE -->|"BLE GATT 通知/写"| LL_SYNC
CH_REMOTE -->|"RCSP 透传"| RCSP
LL_SYNC --> FLASH
RCSP --> FLASH
架构要点:
- PC ↔ Dongle:
ota_dg_central.c中的dongle_send_data_to_pc()/dongle_send_data_to_pc_2()/dongle_send_data_to_pc_3()负责把数据封装成统一的 USB 帧并回传 PC;custom_hid_tx_data()负责按 64 字节 HID report 分片发送。 - Dongle ↔ 远端设备:
ble_dg_central.c作为 BLE GATT Client 管理连接,每个连接 handle 通过trans_channel_set_to_connection_handle()/connection_handle_set_to_trans_channel()与一个透传通道号互转。 - 远端设备侧:从机收到数据后走 LL Sync 的
ble_ota_msg_handle()或 RCSP 升级引擎(rcsp_user_update),最终把固件写入 Flash。 - 设计意图:Dongle 侧刻意"只做通道、不做解析",使同一套上位机协议可以同时驱动多台设备(
HID_OTA_DEVICE_NUM = CONFIG_BT_GATT_CLIENT_NUM),且升级协议升级时无需改动 Dongle 固件。
通道模型与命令协议
通讯通道(Channel)定义
Dongle 与 PC 之间的所有数据都挂在"通道"上。ota_dg_central.c 用枚举把通道划分为命令、应答、USB 透传和最多 8 个远端升级透传通道:
//USB串口指令
enum {
//APP_BT_EVENT
APP_CMD_RCSP_DATA = 0,
APP_CMD_GET_DONGLE_MASSAGE,
APP_CMD_GET_CONNECT_DEVICE,//DONGLE_REPLY_SEARCH_DEVICE,
APP_CMD_RETURN_SUCC,
APP_CMD_RECONNECT_DEVICE,
APP_CMD_DISCONNECT_DEVICE,
APP_CMD_AUTH_FLAG,
//自定义命令
APP_CMD_CUSTOM = 0xFF,
};
//通讯通道
//-----channel_0: pc->dongle
//-----channel_1: dongle->pc
//-----channel_2: pc->usb透传
//-----channel_3~9: 远端升级透传
enum {
HID_RX_HANDLER_CHANNEL_COMMAND = 0x00 + DONGLE_OTA_VERSION,
HID_RX_HANDLER_CHANNEL_RESPONSE = 0x10 + DONGLE_OTA_VERSION,
HID_RX_HANDLER_CHANNEL_USB = 0x20 + DONGLE_OTA_VERSION,
HID_RX_HANDLER_CHANNEL_REMOTE1 = 0x30 + DONGLE_OTA_VERSION,
HID_RX_HANDLER_CHANNEL_REMOTE2 = 0x40 + DONGLE_OTA_VERSION,
HID_RX_HANDLER_CHANNEL_REMOTE3 = 0x50 + DONGLE_OTA_VERSION,
HID_RX_HANDLER_CHANNEL_REMOTE4 = 0x60 + DONGLE_OTA_VERSION,
HID_RX_HANDLER_CHANNEL_REMOTE5 = 0x70 + DONGLE_OTA_VERSION,
HID_RX_HANDLER_CHANNEL_REMOTE6 = 0x80 + DONGLE_OTA_VERSION,
HID_RX_HANDLER_CHANNEL_REMOTE7 = 0x90 + DONGLE_OTA_VERSION,
HID_RX_HANDLER_CHANNEL_REMOTE8 = 0xA0 + DONGLE_OTA_VERSION,
};
设计意图:通道号的高 4 位(0x30~0xA0)与 BLE 连接 handle 一一对应,低 4 位作为通道内子类型。DONGLE_OTA_VERSION 作为偏移量参与通道计算,意味着协议版本变化会整体迁移通道号,避免新旧上位机混淆。通道 0/1/2 固定用于命令、应答、USB 透传,通道 3~9 对应 8 路远端 BLE 连接(与 CONFIG_BT_GATT_CLIENT_NUM 相关)。
Channel ↔ Connection Handle 映射
远端透传通道号与 BLE connection_handle 之间的换算关系如下:
static u16 trans_channel_set_to_connection_handle(u16 trans_channel)
{
u16 connection_handle = trans_channel / 16 + BLE_FRIST_CONNECTION_CHANNEL - (HID_RX_HANDLER_CHANNEL_REMOTE1 / 16);
if (connection_handle < BLE_FRIST_CONNECTION_CHANNEL) {
log_info("trans_channel_set_to_connection_handle err!!");
return 0;
} else {
return connection_handle;
}
}
static u16 connection_handle_set_to_trans_channel(u16 connection_handle)
{
u16 trans_channel = (connection_handle + (HID_RX_HANDLER_CHANNEL_REMOTE1 / 16) - BLE_FRIST_CONNECTION_CHANNEL) * 16;
if (trans_channel < (HID_RX_HANDLER_CHANNEL_REMOTE1 / 16)) {
log_info("connection_handle_set_to_trans_channel err!!");
return 0;
} else {
return trans_channel;
}
}
换算公式可化简为:connection_handle = BLE_FRIST_CONNECTION_CHANNEL + (channel/16 - 3)。这里 BLE_FRIST_CONNECTION_CHANNEL = 0x50,即 Dongle 的第一个 BLE 连接 handle 从 0x50 起。两个函数互为逆运算,且都做了越界保护(非法值返回 0 并打印错误)。设计意图:用一次除法/乘法把"通道号→连接"的转换做成纯算术映射,避免查表,同时把合法性校验集中在转换边界,转发路径上无需再做一次查找。
USB 帧格式与 64 字节分片
Dongle 发往 PC 的数据统一由 dongle_send_data_to_pc() 组帧:帧头 {'J','L', channel, 0x00, len_hi, len_lo, cmd_type}(8 字节 tag 中的前 7 字节),数据区,帧尾 0xED,然后按每包 64 字节通过自定义 HID 上报:
static void dongle_send_data_to_pc(u16 channel, u8 *data, u16 len, u16 cmd_type)
{
len = len + 1;//加上cmd_type长度
u8 send_data_tag[HID_SEND_DATA_TAG_LONG - 1] = {'J', 'L', channel, 0x00, len / 256, len % 256, cmd_type};
len = len - 1;//去除cmd_type长度
u8 send_data[((len + HID_SEND_DATA_TAG_LONG - 1) / HID_USB_SEND_MAX + 1) * HID_USB_SEND_MAX];
memset(send_data, 0x00, sizeof(send_data));
memcpy(&send_data, &send_data_tag, HID_SEND_DATA_TAG_LONG - 1);
memcpy(&send_data[HID_SEND_DATA_TAG_LONG - 1], data, len);
send_data[HID_SEND_DATA_TAG_LONG + len - 1] = HID_RX_HANDLER_TAIL_TAG;
u8 i = (len + HID_SEND_DATA_TAG_LONG) / HID_USB_SEND_MAX;
i = ((len + HID_SEND_DATA_TAG_LONG) % HID_USB_SEND_MAX) ? (i + 1) : (i);
for (u8 j = 1; j <= i; j++) {
log_info("dongle send data to pc: %d", custom_hid_tx_data(0, &send_data[(j - 1) * 64], HID_USB_SEND_MAX));
put_buf(&send_data[(j - 1) * 64], HID_USB_SEND_MAX);
}
}
帧格式总结:
| 字段 | 长度 | 说明 |
|---|---|---|
'J' 'L' | 2 字节 | 帧头魔数(HID_RX_HANDLER_HEND_TAG 低字节) |
| channel | 1 字节 | 通讯通道号(0x00/0x10/0x20/0x30…) |
| 0x00 | 1 字节 | 保留 |
| len_hi / len_lo | 2 字节 | 数据区长度(大端) |
| cmd_type | 1 字节 | APP_CMD_* 命令类型 |
| data | len 字节 | 业务数据 |
0xED | 1 字节 | 帧尾(HID_RX_HANDLER_TAIL_TAG) |
数据先组入按 64 对齐的缓冲,再逐包调用 custom_hid_tx_data(0, ...) 发送——HID_USB_SEND_MAX = 64 与 USB HID report 最大负载一致。设计意图:帧尾 0xED 让上位机可以丢弃半包(例如 Dongle 重启导致的中断帧);cmd_type 在帧内单独成字节,便于上位机在不解业务数据的情况下区分 RCSP 数据与命令应答。
设备发现与在线列表
Dongle 维护一张远端设备信息表,供上位机查询"哪些设备在线、是否支持 OTA、认证标志":
typedef struct {
u8 auth_flag;//设备认证信息
u8 ota_support_flag;//设备是否支持ota
u8 conn_address[7];//连接地址
} device_massage;
ota_support_flag 由 ble_dg_central.c 在连接建立时按远端设备的 GATT 服务(是否包含 OTA 服务)置位,并通过 dg_central_get_ota_is_support(conn_handle) 暴露;ble_dg_central.c 中还维护全局 ota_is_support 标志。该表的更新入口是 dongle_return_online_list()(注释标明"在 ble_dg_central.c 中连接 or 断开时触发"),连接/断开事件发生后 Dongle 会把在线列表推给 PC,PC 据此决定对哪些设备发起升级。设备地址用 7 字节(type + 6 字节 BD_ADDR)存储,与 BLE 地址类型编码一致。
设备端 BLE OTA 消息处理
从机侧(如 LL Sync 示例 apps/spp_and_le/examples/ll_sync/ll_sync_demo.c)收到远端透传数据后,调用 OTA 消息处理器:
result = ble_ota_msg_handle(buffer, buffer_size);
if (result) {
...
}
ble_ota_msg_handle() 是设备端 BLE OTA 的协议解析入口:它从 BLE 数据通道取出 OTA 消息,按消息类型分发(升级开始、数据块、校验、重启等),并驱动底层 Flash 擦写。若返回非 0,上层继续做应答/错误处理。该函数与 Dongle 的透传逻辑解耦——设备端不关心数据是来自 BLE 直连还是经 Dongle 转发,这正是整个工具链能"一套协议、两种链路"的关键。
RCSP 升级引擎(远端设备侧)
除 LL Sync 外,SDK 的 RCSP(杰理私有蓝牙控制协议)也承载升级数据。Dongle 侧 dongle_send_data_to_pc_3() 专门把"RCSP 透传"数据原样转发给 PC:
void dongle_send_data_to_pc_3(u8 *data, u16 len)
{
dongle_send_data_to_pc(0x20, data, len, APP_CMD_RCSP_DATA);
}
RCSP 升级链路中,PC 工具(如杰理"蓝牙调试助手 / RCSP 升级工具")负责把固件切包并组 RCSP 升级指令,经 Dongle(或 BLE 直连)透传到设备;设备端由 apps/common/rcsp/ 下的 rcsp_user_update 模块解析 RCSP 升级指令,执行"进入升级模式 → 接收数据 → 写 Flash → 校验 → 重启"流程。Dongle 工程通过包含 rcsp_bluetooth.h / rcsp_user_update.h 并开启 RCSP_BTMATE_EN 宏来接入该引擎。
两种升级协议的取舍
| 维度 | LL Sync BLE OTA | RCSP 升级 |
|---|---|---|
| 消息入口 | ble_ota_msg_handle() | rcsp_user_update 处理函数 |
| 透传通道 | HID_RX_HANDLER_CHANNEL_REMOTE1~8 | 通道 0x20(USB 透传)+ RCSP 数据 |
| 典型场景 | 精简工具链、私有 OTA 服务 | 杰理生态工具、配套 App |
| Dongle 角色 | 纯转发(channel→handle 映射) | 纯转发(APP_CMD_RCSP_DATA) |
两者都遵循"上位机切包、设备端解析写 Flash、中间链路透明"的同一架构原则。
构建产物与 PC 端工具
cpu/*/tools/ 目录存放与升级相关的构建产物与脚本:
| 文件 | 用途 |
|---|---|
ota.bin | 供 OTA 升级用的固件镜像(升级包源文件) |
ota_debug.bin | 带调试信息的 OTA 镜像 |
uboot_no_ota.boot | 不带 OTA 引导段的 uboot,用于防止误入升级模式 |
uboot_no_ota.boot_debug | 对应调试版本 |
download_app_ota.bat | BR23 平台的 App+OTA 一键下载脚本 |
设计意图:ota.bin 由构建系统在编译时从 App 固件抽取生成;上位机工具把它切分成升级数据块后按上述帧格式下发。uboot_no_ota.boot 用于量产时关闭 OTA 引导,防止终端用户在未授权场景进入升级模式——这体现了"工具链"同时包含使能升级与禁用升级两条路径。
核心升级流程
sequenceDiagram
participant PC as PC 升级工具
participant DG as USB Dongle (ota_dg_central/ble_dg_central)
participant DV as 远端从机设备
PC->>DG: USB HID 帧: APP_CMD_GET_CONNECT_DEVICE
DG-->>PC: 在线列表 (device_massage: auth/ota_support/address)
PC->>DG: 选择设备, 下发 OTA 启动指令 (通道 REMOTE1)
DG->>DV: BLE GATT 写 (channel→connection_handle 映射)
DV-->>DG: 应答 (ota_support 校验/进入升级模式)
DG-->>PC: 应答帧经 channel 0x10 回传
loop 固件数据下发
PC->>DG: 数据块 (JL 帧头 + cmd_type + data + 0xED)
DG->>DV: 透传到远端连接
DV->>DV: ble_ota_msg_handle / rcsp_user_update 解析写 Flash
DV-->>DG: 每块 ACK / 进度
DG-->>PC: dongle_send_data_to_pc_2 转发 ACK
end
PC->>DG: 校验/结束指令
DV->>DV: 校验通过, 复位进入新固件
流程要点:
- 枚举:PC 发
APP_CMD_GET_CONNECT_DEVICE,Dongle 回调在线表生成接口dongle_return_online_list()回传设备信息(含ota_support_flag),PC 只对支持 OTA 的设备继续。 - 建链/选路:PC 按在线表选择设备并指定 REMOTE 通道;Dongle 用
trans_channel_set_to_connection_handle()定位 BLE 连接。 - 透传:升级数据在 Dongle 侧不做解析,仅组帧/分片转发;ACK 反向经
connection_handle_set_to_trans_channel()映射回原通道,PC 按 channel 区分是哪台设备的应答。 - 收尾:设备端写完并校验后重启;若中途断链,Dongle 支持按
ronn_massage(重连通道/地址/映射表)执行回连续传(APP_CMD_RECONNECT_DEVICE)。
配置选项
Dongle OTA 工具链由以下宏组合使能并配置(定义于 app_config.h / 工程配置):
| 配置项 | 类型 | 默认 | 说明 |
|---|---|---|---|
CONFIG_APP_DONGLE | 宏 | 关 | 使能 Dongle 应用工程 |
RCSP_BTMATE_EN | 宏 | 关 | 使能 RCSP 蓝牙配套协议(OTA 透传依赖) |
TCFG_PC_ENABLE | 宏 | 关 | 使能 PC 端通信(ota_dg_central.c 整体编译条件之一) |
TCFG_USB_CUSTOM_HID_ENABLE | 宏 | 关 | 使能自定义 HID 设备(custom_hid_tx_data 可用) |
CONFIG_BT_GATT_CLIENT_NUM | 数值 | 平台相关 | GATT Client 数量,即 HID_OTA_DEVICE_NUM,决定远端 OTA 设备路数 |
DONGLE_OTA_VERSION | 数值 | 0 | 协议版本偏移,参与所有 channel 号计算 |
HID_USB_SEND_MAX | 数值 | 64 | USB HID 单包最大字节数 |
BLE_FRIST_CONNECTION_CHANNEL | 数值 | 0x50 | 首个 BLE 连接 handle,channel↔handle 映射基准 |
设计意图:TCFG_PC_ENABLE && TCFG_USB_CUSTOM_HID_ENABLE && RCSP_BTMATE_EN && CONFIG_APP_DONGLE 四者同时成立时 ota_dg_central.c 才参与编译——把"Dongle 角色"做成纯编译期特性,同一 SDK 源码可同时支撑普通从机固件与 Dongle 固件,避免运行期分支。
失败模式、边界情况与并发
- 非法通道/句柄映射:
trans_channel_set_to_connection_handle()与反向函数都带有界检查,非法输入返回 0 并打印err日志。调用方必须把返回值 0 视为无效连接,否则可能向错误的 handle 发包。 - 断链与回连:升级中 BLE 断链会导致数据中断。Dongle 用
ronn_massage(reconn_channel、reconn_address[7]、reconn_map[HID_OTA_DEVICE_NUM])记录每路连接的通道与地址映射,配合reconn_timer与APP_CMD_RECONNECT_DEVICE命令实现断点回连。is_reconn_address_device用于标记是否正处于按地址回连状态,避免回连期间重复触发。 - 多设备并发:
HID_OTA_DEVICE_NUM路远端连接共用一条 USB HID 链路,因此 USB 帧必须携带 channel 字段区分设备;dongle_send_data_to_pc_2()通过reconn_map查找dongle_to_pc_handle决定应答走哪个 REMOTE 通道。若两台设备 channel 换算后落入同一reconn_map槽位,应答会串线——这是通道号与CONFIG_BT_GATT_CLIENT_NUM必须保持一致的原因。 - 半包/粘包:USB 帧以
0xED结尾,上位机应以帧尾对齐解析;Dongle 发送缓冲按 64 字节对齐分配并以memset清零,末包空余字节为 0,不携带有效信息。 - 设备不支持 OTA:
ota_support_flag为 0 的设备不应被下发升级数据;上位机应先查询在线列表(APP_CMD_GET_CONNECT_DEVICE)过滤。
性能与运维注意
- 吞吐瓶颈在 USB HID 与 BLE MTU:
custom_hid_tx_data每包 64 字节,BLE 侧受连接间隔与 ATT MTU 限制。升级大数据块应切分为与双方能力匹配的块,避免 Dongle 缓冲(usb_data_info_t为HID_USB_SEND_MAX * 9字节)溢出。 - 日志开销:
log_info在宏开关#if 1下开启,逐包打印会显著拖慢升级速率;量产/性能测试时可将#if 1改为#if 0关闭[BLE_DG_OTA]日志。 - 升级镜像管理:
ota.bin由构建产生,需与设备端 Flash 分区/引导(uboot)版本匹配;更换uboot_no_ota.boot可关闭量产机的 OTA 引导入口。
扩展点
- 新增远端路数:调整
CONFIG_BT_GATT_CLIENT_NUM并按HID_RX_HANDLER_CHANNEL_REMOTE1~8的规律扩展通道枚举。 - 新增 USB 命令:在
APP_CMD_*枚举中追加命令号(APP_CMD_CUSTOM = 0xFF预留自定义空间),并在 Dongle 的 USB 接收分发处增加分支。 - 更换升级协议:远端设备侧既支持
ble_ota_msg_handle()(LL Sync),也支持 RCSP(rcsp_user_update);Dongle 透传层无需改动,只需在上位机侧切换协议组包。
相关链接
- 源码入口:ota_dg_central.c、ble_dg_central.c、ll_sync_demo.c
- 构建产物:cpu/bd29/tools/、download_app_ota.bat
- 云平台 OTA(独立页面):Hilink OTA(
hilink_ota.c)、Tuya OTA(tuya_ota.c)、Tencent LL OTA(ble_qiot_llsync_ota.c) - Mesh DFU 组网升级(独立页面):
apps/mesh/mesh_dfu/mesh_target_node_ota.c