升级通道:UART / 测试盒 / BLE OTA / USB / SD
AW30N BLE SDK 的固件升级子系统支持五类升级通道:UART 串口、测试盒 UART、测试盒 BLE、App BLE OTA(RCSP 协议)以及存储设备(USB/SD)。所有通道均由 app_config.c 中的 CONFIG_UPDATE_* 宏统一使能,并通过 sdk/apps/app/bsp/common/update/ 目录下的通道实现与预编译的 update_lib.a 协作完成固件传输、loader 下载与 Flash 写入。
Purpose and Scope
本页系统讲解 AW30N 固件升级子系统的通道架构:各升级通道的使能开关、实现文件、适用场景与数据流向,以及它们在统一升级框架中的角色。内容包括:
- 升级使能宏的配置语义与默认值;
update模块的文件布局与分层关系;- 五类通道(UART / 测试盒 UART / 测试盒 BLE / App BLE OTA / USB+SD)各自的实现入口;
- 升级流程、配置项、已知的边界问题与扩展方式。
不覆盖的内容:JL_rcsp 协议本身的完整报文格式与命令字定义(属于 RCSP 协议页范畴);测试盒端(PC 工具)的实现;具体芯片 Flash 分区规划(由 update.ld 与链接配置决定)。本页聚焦于 SDK 侧的通道使能与分发机制。
Overview
嵌入式设备的固件升级是产品量产与售后维护的核心能力。AW30N SDK 在应用层提供了统一的升级入口,并把"通道传输"与"固件写入"解耦:
- 通道层负责把固件数据从外部介质/工具传输到芯片:UART 串口、测试盒(UART/BLE)、手机 App(BLE OTA,走 RCSP 私有协议)、USB 或 SD 卡(存储设备)。
- 框架层(
update.c及预编译库update_lib.a)负责升级状态机、数据校验、loader 下载与重启后的固件搬移。 - 配置层通过
CONFIG_UPDATE_*宏决定编译进固件的通道集合,既可用于功能裁剪(例如量产只保留测试盒通道),也可用于内存优化(参见仓库中"裁剪到 256KB 以内"的补丁包)。
从源码证据看,主工程 sdk/apps/app/src/mbox_flash/app_config.c 中四个通道宏全部默认为 1(全通道使能),且各通道分别有独立实现文件(dev_update.c、testbox_uart_update.c、testbox_update.c)与 RCSP 侧的 rcsp_user_update.c,说明该 SDK 采用"统一入口 + 按通道分文件实现 + 编译期裁剪"的设计。
Architecture
下图展示了升级子系统的分层架构与通道分发关系(节点均对应仓库中真实存在的文件/模块):
flowchart TD
subgraph sg_Config["配置层 app_config.c"]
CFG["CONFIG_UPDATE_* 使能宏"]
end
subgraph sg_Update["升级框架 sdk/apps/app/bsp/common/update/"]
ENTRY["update.c 统一入口"]
DEV["dev_update.c 存储设备通道"]
TBOX_UART["testbox_uart_update.c 测试盒UART"]
TBOX_BLE["testbox_update.c 测试盒BLE"]
end
subgraph sg_RCSP["BLE OTA App 通道 RCSP 协议"]
RCSP["rcsp_user_update.c / .h"]
end
subgraph sg_Lib["预编译库与链接"]
LIB["update_lib.a 升级核心库"]
LOADER["update_loader_download.h loader下载"]
LD["update.ld 链接脚本"]
end
subgraph sg_Media["升级介质/工具"]
M_UART["UART 串口工具"]
M_USB["USB 设备"]
M_SD["SD 卡"]
M_BLE["BLE 空中链路"]
end
CFG -->|"编译期使能"| ENTRY
ENTRY --> DEV
ENTRY --> TBOX_UART
ENTRY --> TBOX_BLE
ENTRY --> RCSP
DEV --> M_USB
DEV --> M_SD
TBOX_UART --> M_UART
TBOX_BLE --> M_BLE
RCSP --> M_BLE
ENTRY --> LOADER
LOADER --> LIB
LIB --> LD
分层职责说明:
- 配置层:
app_config.c第 71–75 行集中定义四个通道使能宏,是裁剪升级功能的唯一开关,也是本页所有通道的"总闸门"。 - 框架层:
update.c是升级模块的 C 源码总入口;核心升级算法(校验、搬移、状态机)封装在预编译库update_lib.a(面向bd49/mbox_flash平台),通过update.ld链接进固件。 - 通道层:每个物理通道一个实现文件,
dev_update.c同时服务 USB 与 SD 两种存储介质;testbox_uart_update.c与testbox_update.c分别对接测试盒的 UART 与 BLE 两种连接方式。 - RCSP 层:App 发起的 BLE OTA 复用杰理 RCSP 私有协议(
JL_rcsp/rcsp_update/),属于应用协议栈的一部分,向上对接update框架。 - loader 机制:
update_loader_download.h表明升级采用"先下载升级 loader,再重启执行固件搬移"的两段式架构,这是嵌入式 OTA 常见的抗断电失败设计。
升级使能开关(配置层)
主工程配置文件 sdk/apps/app/src/mbox_flash/app_config.c 用一段集中注释 "update control" 声明了全部升级通道开关:
////////////////////////////update control///////////////////////////////////////////
const int CONFIG_UPDATE_STORAGE_DEV_EN = 1;
const int CONFIG_UPDATE_TESTBOX_UART_EN = 1;
const int CONFIG_UPDATE_APP_OTA_EN = 1;
const int CONFIG_UPDATE_TESTBOX_BLE_EN = 1;
Source: app_config.c
四个宏的语义与默认值如下:
| 宏 | 默认值 | 通道 | 说明 |
|---|---|---|---|
CONFIG_UPDATE_STORAGE_DEV_EN | 1 | USB / SD | 存储设备升级:从 USB 或 SD 卡读取升级文件 |
CONFIG_UPDATE_TESTBOX_UART_EN | 1 | 测试盒 UART | 测试盒通过 UART 下发固件 |
CONFIG_UPDATE_APP_OTA_EN | 1 | App BLE OTA | 手机 App 通过 BLE(RCSP 协议)升级 |
CONFIG_UPDATE_TESTBOX_BLE_EN | 1 | 测试盒 BLE | 测试盒通过 BLE 下发固件 |
设计意图:把通道开关集中放在配置文件而非散落在各驱动中,便于产品线按量产/售后场景一键裁剪。仓库中的补丁包(如"裁剪到 256KB 以内的补丁包")正是基于这些开关做功能与内存裁剪。
升级模块文件布局
升级子系统在 SDK 中按"源码 + 预编译库 + 头文件 + 链接脚本"四部分组织,路径集中在三处:
| 类别 | 文件 | 职责 |
|---|---|---|
| 通道实现 | update.c | 升级模块 C 源码总入口 |
| 通道实现 | dev_update.c | 存储设备(USB/SD)升级实现 |
| 通道实现 | testbox_uart_update.c | 测试盒 UART 升级实现 |
| 通道实现 | testbox_update.c | 测试盒 BLE 升级实现 |
| BLE OTA | rcsp_user_update.c / .h | App BLE OTA 的 RCSP 协议封装 |
| 头文件 (v2) | update.h、dev_update.h、testbox_uart_update.h、uart_update.h、update_loader_download.h | 升级接口声明(第二版升级框架) |
| 头文件 (v1) | update_v1.h | 旧版升级框架接口(兼容保留) |
| 预编译库 | update_lib.a | 升级核心算法(校验/搬移/状态机),面向 bd49/mbox_flash 平台预编译 |
| 链接脚本 | update.ld | 升级代码段的链接布局 |
| 协议配置 | lib_update_config.c(及 bt_common/hid/config/ 同名单文件) | 不同蓝牙 profile(HID / SPP+LE)下的升级库配置 |
设计意图分析:头文件区分为 code_v1 与 code_v2 两套,表明升级框架经历过一次大版本演进;code_v2 中 update_loader_download.h 独立成头,进一步印证"loader 下载"被抽象为独立阶段。核心算法以 .a 预编译库形式提供,应用层只保留通道相关源码——这既保护了算法实现,也保证了所有使用该 SDK 的产品升级行为一致。
各通道详解
UART 串口通道
UART 通道是最直接的调试/量产升级途径:PC 工具通过串口把固件分包发给芯片。接口声明位于 uart_update.h(code_v2)。该通道通常用于产线烧录与开发调试,配合杰理 PC 端升级工具使用。注意 SDK 中 UART 通道与"测试盒 UART"通道是两个独立文件(uart_update.h 与 testbox_uart_update.h),说明普通串口工具与测试盒虽然物理介质相同,但握手/协议流程不同,因此分开实现。
测试盒 UART 通道
由 CONFIG_UPDATE_TESTBOX_UART_EN 使能,实现位于 testbox_uart_update.c,接口见 testbox_uart_update.h。测试盒(TestBox)是杰理产测生态的硬件工具,量产时由测试盒通过 UART 与设备握手并下发固件。该通道与普通 UART 通道并存,体现 SDK 对"产线自动化"场景的一等支持。
测试盒 BLE 通道
由 CONFIG_UPDATE_TESTBOX_BLE_EN 使能,实现位于 testbox_update.c。与测试盒 UART 相比,该通道走 BLE 空中链路,适合设备已装入外壳、无法插线的产测/售后场景。测试盒通过 BLE 连接设备后以私有协议传输固件,传输路径复用 BLE 协议栈,因此实现文件独立于 RCSP 侧的 App 升级。
App BLE OTA 通道
由 CONFIG_UPDATE_APP_OTA_EN 使能,是面向终端用户的核心通道。与"测试盒 BLE"不同,App 升级复用杰理 RCSP(Remote Control & Smart Profile) 私有协议,实现在 rcsp_user_update.c 与 rcsp_user_update.h:
- 位置位于
third_party_profile/jieli/JL_rcsp/rcsp_update/,说明它是 RCSP 协议栈的一个子模块(update 子功能),由 RCSP 的命令分发驱动; - 用户在手机 App 中选择固件文件后,App 通过 BLE GATT 通道把固件按 RCSP 协议分包下发;
rcsp_user_update作为协议与应用升级框架之间的适配层,把 RCSP 报文翻译为update框架可消费的数据流。
USB / SD(存储设备)通道
由 CONFIG_UPDATE_STORAGE_DEV_EN 使能,实现位于 dev_update.c,接口见 dev_update.h。该通道的特点:
- 无需外部工具:用户把升级文件(如
update.bin)拷入 U 盘或 SD 卡,插入设备后触发升级; - 单一实现服务两种介质:
dev_update.c同时处理 USB 与 SD,因为两者对上层呈现的都是"块存储/文件系统"抽象,差异集中在底层驱动; - 该通道的日志标签为
DEV_UPDATE(见下节),与通用UPDATE标签区分,便于定位存储介质相关故障。
日志标签
升级模块在配置文件里注册了独立的调试日志开关,按日志级别拆分为 UPDATE 与 DEV_UPDATE 两组(i/d/e/c 对应 info/debug/error/... 级别):
const char log_tag_const_i_UPDATE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIBS(1);
const char log_tag_const_d_UPDATE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIBS(1);
const char log_tag_const_e_UPDATE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIBS(1);
const char log_tag_const_c_UPDATE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIBS(1);
const char log_tag_const_i_DEV_UPDATE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIBS(1);
Source: app_config.c
调试建议:排查升级失败时,先用 i_UPDATE / e_UPDATE 观察升级状态机推进,再用 DEV_UPDATE 组定位存储介质(USB/SD)读写问题。
Core Flow(升级核心流程)
尽管各通道的物理介质不同,升级主流程统一为"通道传输 → loader 下载 → 重启 → 校验 → 写入 Flash"。该流程由 update.c 入口、update_loader_download.h 声明的 loader 下载接口与预编译库 update_lib.a 协作完成,应用层只负责把数据送入框架:
sequenceDiagram
participant U as 用户/工具
participant C as update.c 统一入口
participant CH as 通道实现
participant L as Loader 下载
participant F as Flash 存储
U->>C: 触发升级请求(串口/测试盒/App/存储设备)
C->>C: 检查 CONFIG_UPDATE_* 通道使能
C->>CH: 按通道分发
CH->>CH: 接收固件数据流(分包/文件)
CH->>L: 下载升级 loader
L->>F: 保存 loader 并请求重启
Note over F: 重启进入升级模式
F->>F: 校验固件完整性(长度/校验和)
F->>F: 擦写 Flash 并搬移固件
F-->>U: 升级完成,重启进入新固件
分步说明:
- 触发:不同通道触发方式各异——UART/测试盒由工具主动握手;App 由用户在 RCSP 会话中发起;USB/SD 则检测到插入的升级文件。
- 使能检查与分发:
update.c依据编译期宏决定哪些通道可用,并按来源把数据流路由到对应通道实现。 - 数据接收:通道实现负责协议细节——串口/测试盒按帧接收,存储设备按文件读取,BLE 按 RCSP 报文重组。
- loader 下载:数据收齐后进入 loader 阶段(
update_loader_download),先把升级引导程序写入安全区域。 - 重启与搬移:复位后由 loader 主导,先校验固件完整性再擦写 Flash;校验失败可回退到旧固件,避免"半砖"。
- 收尾:搬移成功后重启进入新固件,升级会话结束。
Usage Examples
示例 1:使能/裁剪升级通道
量产固件若只保留测试盒 UART 通道,可将其他三个宏改为 0,同时可节省对应通道的代码与内存占用:
////////////////////////////update control///////////////////////////////////////////
const int CONFIG_UPDATE_STORAGE_DEV_EN = 0; // 关闭 USB/SD 通道
const int CONFIG_UPDATE_TESTBOX_UART_EN = 1; // 保留测试盒 UART
const int CONFIG_UPDATE_APP_OTA_EN = 0; // 关闭 App BLE OTA
const int CONFIG_UPDATE_TESTBOX_BLE_EN = 0; // 关闭测试盒 BLE
Source: app_config.c(默认全使能,按需修改)
仓库中"裁剪到 256KB 以内的补丁包"即在此基础上进一步裁剪,证明该开关组合是内存优化的第一落点。
示例 2:按蓝牙 profile 配置升级库
同一份升级库配置在 bt_common 下按 profile 分目录维护(HID 与 SPP+LE 各一份 lib_update_config.c)。开发时若更换蓝牙应用场景(如从 HID 键盘改为 SPP 透传),需同步确认对应目录下的升级配置被正确编译链接,避免通道使能与实际蓝牙链路不一致。
示例 3:定位升级故障(日志标签)
升级失败时按标签过滤日志,快速区分问题层级:
# 查看升级状态机与校验错误
# 日志 tag:i_UPDATE / d_UPDATE / e_UPDATE / c_UPDATE
# 存储介质(USB/SD)相关:DEV_UPDATE 组
Source: app_config.c
Configuration Options
升级子系统的全部配置集中在 app_config.c 的 "update control" 段落,属于编译期常量(const int),编译后不可热修改:
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
CONFIG_UPDATE_STORAGE_DEV_EN | const int | 1 | USB / SD 存储设备升级通道使能 |
CONFIG_UPDATE_TESTBOX_UART_EN | const int | 1 | 测试盒 UART 升级通道使能 |
CONFIG_UPDATE_APP_OTA_EN | const int | 1 | App BLE OTA(RCSP)通道使能 |
CONFIG_UPDATE_TESTBOX_BLE_EN | const int | 1 | 测试盒 BLE 升级通道使能 |
log_tag_const_{i,d,e,c}_UPDATE | const char | CONFIG_DEBUG_LIBS(1) | 升级框架日志开关(info/debug/error/...) |
log_tag_const_{i,d,e,c}_DEV_UPDATE | const char | CONFIG_DEBUG_LIBS(1) | 存储设备升级日志开关 |
设置说明:
- 值为
1表示通道编译进固件;0表示裁剪。修改后需重新编译,无法运行时切换。 - 日志开关由
CONFIG_DEBUG_LIBS(1)宏控制,量产固件可统一关断以减少日志段占用。 - 配置同时存在于主工程
sdk/apps/app/src/mbox_flash/app_config.c与各补丁包副本中,升级/打补丁时注意以实际使用的源码目录为准。
API Reference
升级接口以头文件形式提供给应用层,分 code_v1(旧)与 code_v2(新)两套。本页编写时未逐行展开头文件内容,具体函数签名、参数与返回值请直接查阅下列头文件,此处给出接口模块与用途对照:
| 头文件(code_v2) | 接口主题 | 对应通道 |
|---|---|---|
| update.h | 升级框架总接口(状态机、数据输入) | 所有通道共用 |
| uart_update.h | UART 串口升级接口 | UART |
| testbox_uart_update.h | 测试盒 UART 升级接口 | 测试盒 UART |
| dev_update.h | 存储设备升级接口(文件触发、读取) | USB / SD |
| update_loader_download.h | 升级 loader 下载接口 | 所有通道共用 |
| update_v1.h | 旧版升级接口(兼容) | 历史代码迁移用 |
典型调用方式(概念性):应用检测到升级触发源后,调用 update.h 暴露的入口注册通道数据回调,按通道持续喂入固件分片;框架内部在数据完整后调用 loader 下载并重启。RCSP 侧 rcsp_user_update.h 则是 App OTA 报文的解析与回调声明,具体命令字需对照 RCSP 协议文档。
Failure Modes、边界情况与并发
升级中断电/校验失败
升级写入 Flash 前先下载 loader 并校验固件(长度、校验和),失败时不进入擦写流程,设备可继续运行旧固件。该机制由预编译库实现,应用层无需干预——这是"loader 两段式"架构的核心收益。
复位源问题(已修复案例)
仓库中 补丁包/v1.1.1软关机复位源问题补丁/ 专门修复了软关机后的复位源问题,且该补丁同时携带完整的 app_config.c(含全部 CONFIG_UPDATE_* 宏与 UPDATE 日志标签)。这提示:升级模块对复位源(reset source)敏感——软关机后若复位源判断错误,可能影响升级重启流程的正确性。涉及升级与重启逻辑时,应确保应用复位源处理与此补丁保持一致。
内存/Flash 空间受限
补丁包/AW30N_v1.2.0_SDK裁剪到256KB以内的补丁包_20240815/ 表明升级模块会占用可观代码空间。裁剪通道(将对应宏置 0)可回收空间,但需注意:App BLE OTA(RCSP)与蓝牙协议栈耦合,裁剪时需一并评估 RCSP 依赖。
蓝牙版本升级联动
补丁包/v1.2.0升级至v1.3.0蓝牙补丁/ 同时更新了 app/src/mbox_flash/app_config.c 中的升级宏,说明蓝牙协议栈升级可能带来升级接口(code_v2 头文件)的兼容性变化。跨版本升级 SDK 时,应核对升级头文件与 update_lib.a 的配套关系。
并发与竞态
升级过程本质上是"独占系统资源"的操作:固件搬移期间设备处于升级模式、蓝牙/音频等服务停止。应用层应保证升级入口的幂等性(重复触发不产生并发写入),并避免在升级期间响应其他数据通道。SDK 通过重启进入 loader 模式天然串行化该过程,应用侧不应绕过该机制自行并发写 Flash。
性能与运维考虑
- 预编译库保证一致性:升级核心以 update_lib.a 形式发布(面向
bd49/mbox_flash平台),不同产品使用同一套校验/搬移逻辑,降低兼容性风险;升级 SDK 版本时必须同步替换该库,不能只更新头文件。 - 链接脚本约束:update.ld 规定升级代码段的放置与对齐,改动 Flash 分区时必须同步评估,否则可能出现链接冲突或搬移越界。
- 存储介质通道(USB/SD):
DEV_UPDATE日志组是排查"文件未识别/读取失败"的第一入口;升级文件需放在设备可枚举的存储根目录/约定路径(以dev_update.c实际实现为准)。 - 量产裁剪:产线固件通常只保留测试盒 UART/BLE 通道,终端固件保留 App OTA + 存储设备通道;在
app_config.c中按产品形态配置,兼顾 Flash 空间与维护便利。 - 打补丁流程:官方补丁包(如 v1.1.1 复位源、v1.2.0 裁剪、v1.3.0 蓝牙)均会携带或引用
app_config.c的升级宏段落,打补丁后应核对最终编译所用配置与日志开关是否与预期一致。
扩展点
- 通道裁剪:通过四个
CONFIG_UPDATE_*宏任意组合启用/禁用通道,是官方支持的扩展方式(有裁剪补丁包佐证)。 - 新增通道:若需接入自有升级工具,可参照
testbox_uart_update.c/dev_update.c的模式:新写一个通道实现文件,向上复用update.h框架接口,向下对接新介质驱动,再新增一个使能宏接入app_config.c的 "update control" 段落。 - RCSP 扩展:App OTA 的命令字与流程在
rcsp_user_update.c中适配,RCSP 协议本身由JL_rcsp目录承载;如需扩展升级命令(如查询版本、回滚),从该文件入手。 - 日志开关:
CONFIG_DEBUG_LIBS()宏统一控制UPDATE/DEV_UPDATE日志段的编译,量产与调试版本可分别配置。
测试覆盖
仓库未发现独立的升级单元测试工程;升级功能的验证主要依赖:
- 官方补丁包作为回归依据(复位源、蓝牙兼容、内存裁剪三方面);
- 各通道实现在
sdk/apps/app/bsp/common/update/下与主应用一同编译,通过真机产测(测试盒)与 App OTA 实测验证; - 建议的自测矩阵:每通道至少覆盖"正常升级成功、固件校验失败、升级中断电重启、重复触发升级"四类用例。
Related Links
- 配置源头:app_config.c(升级控制段)
- 升级框架入口:update.c
- 存储设备通道(USB/SD):dev_update.c
- 测试盒 UART 通道:testbox_uart_update.c
- 测试盒 BLE 通道:testbox_update.c
- App BLE OTA(RCSP):rcsp_user_update.c
- 接口头文件(code_v2):update.h / dev_update.h / uart_update.h / update_loader_download.h
- 预编译升级库:update_lib.a
- 链接脚本:update.ld
- 相关补丁包(升级相关已知问题与裁剪):v1.1.1 软关机复位源补丁、256KB 裁剪补丁、v1.3.0 蓝牙补丁