UWB OTA 固件升级方案文档¶
1. 方案概述¶
本文档描述了基于QN9090芯片的UWB OTA固件升级解决方案,支持App固件和SR150固件的串口升级/支持串口和蓝牙两种方式的升级,通过外部Flash存储和内部Flash运行的双重架构实现可靠的固件更新机制。
1.1 系统架构¶
1.1.1 整体架构概览¶
本系统支持两种OTA升级方式:串口OTA和蓝牙OTA,两种方式共享相同的存储架构和固件管理机制。 当前支持最大固件大小为512字节
┌───────────────────────────────────────────────────────────────────────────┐
│ OTA升级方案 │
├─────────────────────────────┬─────────────────────────────────────────────┤
│ 串口OTA方案 │ 蓝牙OTA方案 │
│ │ │
│ ┌─────────────────────┐ │ ┌─────────────────────┐ │
│ │ PC工具 │ │ │ Android App │ │
│ │ (固件升级工具) │ │ │ (OTA客户端) │ │
│ └─────────────────────┘ │ └─────────────────────┘ │
│ │ │ │ │
│ 串口连接 │ BLE连接 │
│ │ │ │ │
│ ┌─────────────────────┐ │ ┌─────────────────────┐ │
│ │ UART接口 │ │ │ BLE接口 │ │
│ └─────────────────────┘ │ └─────────────────────┘ │
└─────────────────────────────┴─────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────────┐
│ QN9090 UWB设备 │
├─────────────────┬───────────────────┬───────────────────┬───────────────────────┤
│ 外部Flash │ 内部Flash │ RAM │ 通信接口 │
│ (W25Q32JV) │ (QN9090) │ (QN9090) │ │
├─────────────────┤ ├─────────────────┤ ├─────────────────┤ ├─────────────────────┤
│ 0x00280000 │ │ 0x00000000 │ │ 0x04000000 │ │ • UART (串口OTA) │
│ ┌─────────────┐ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │ • BLE (蓝牙OTA) │
│ │App固件头部 │ │ │ │Bootloader │ │ │ │Stack │ │ │ • APDU协议处理 │
│ ├─────────────┤ │ │ │(100KB) │ │ │ ├─────────────┤ │ │ • 外部Flash操作 │
│ │App固件数据 │ │ │ └─────────────┘ │ │ │Heap │ │ │ • 固件验证 │
│ │(最大512KB) │ │ │ 0x00019000 │ │ ├─────────────┤ │ └────────────────────┘
│ └─────────────┘ │ │ ┌─────────────┐ │ │ │App Data │ │
│ 0x00300000 │ │ │Application │ │ │ │ │ │
│ ┌─────────────┐ │ │ │(540KB) │ │ │ └─────────────┘ │
│ │CRC+长度 │ │ │ └─────────────┘ │ └─────────────────┘
│ ├─────────────┤ │ └─────────────────┘
│ │SR150固件数据 │ │ ↑
│ └─────────────┘ │ Bootloader验证并加载
└─────────────────┘
1.1.2 两种OTA方案对比¶
| 特性 | 串口OTA | 蓝牙OTA |
|---|---|---|
| 连接方式 | UART串口线缆连接 | BLE无线连接 |
| 传输速率 | 460800 bps | ~2Mbps (BLE 2M PHY) |
| 客户端 | PC工具 | Android应用 |
| 适用场景 | 开发调试、工厂烧录 | 现场升级、用户自助升级 |
| 协议基础 | APDU协议 | APDU协议 (通过BLE传输) |
| 数据包大小 | 最大768字节/包 | 最大128字节/包 (MTU限制) |
| 可靠性 | 有线连接,稳定性高 | 无线连接,需重发机制 |
| 用户体验 | 需要连接线缆 | 无线操作,便捷性高 |
2. 存储布局设计¶
2.1 外部Flash布局 (W25Q32JV - 4MB)¶
| 地址范围 | 大小 | 用途 | 说明 |
|---|---|---|---|
| 0x000000 - 0x27FFFF | 2.5MB | 预留区域 | 可用于其他数据存储 |
| 0x280000 - 0x2FFFFF | 512KB | App固件存储区 | 存储应用程序固件 |
| 0x300000 - 0x3FFFFF | 1MB | SR150固件存储区 | 存储SR150固件 |
App固件存储区详细布局 (0x280000 - 0x2FFFFF)¶
0x280000 ┌────────────────────────────────┐
│ 固件头部 (32字节) │
│ - 魔数 (4字节): 0x12345678 │
│ - 版本号 (4字节) │
│ - 固件大小 (4字节) │
│ - CRC32校验值 (4字节) │
| - 更新标识 (1字节) |
│ - 预留字段 (15字节) │
0x280020 ├────────────────────────────────┤
│ │
│ App固件数据区 │
│ (最大 512KB - 32B) │
│ │
0x2FFFFF └────────────────────────────────┘
SR150固件存储区详细布局 (0x300000 - 0x3FFFFF)¶
0x300000 ┌────────────────────────────────┐
│ 配置信息页 (256字节) │
│ - CRC16校验值 (2字节) │
│ - 固件长度 (4字节) │
│ - 填充数据 (250字节,0xFF) │
0x300100 ├────────────────────────────────┤
│ │
│ SR150固件数据区 │
│ (最大 1MB - 256B) │
│ │
0x3FFFFF └─────────────────────────────────┘
2.2 内部Flash布局 (QN9090 - 640KB)¶
0x00000000 ┌─────────────────────────────────┐
│ Bootloader区域 │
│ (100KB = 0x19000) │
0x00019000 ├─────────────────────────────────┤
│ Application区域 │
│ (540KB = 0x87000) │
0x000A0000 └─────────────────────────────────┘
3. 固件头部结构¶
3.1 App固件头部结构¶
typedef struct {
uint32_t magic; // 魔数:0x12345678
uint32_t version; // 固件版本号
uint32_t size; // 固件大小(字节)
uint32_t crc32; // CRC32校验值
uint32_t reserved[4]; // 保留字段
} app_firmware_header_t;
3.2 SR150固件配置结构¶
typedef struct {
uint16_t crc16; // CRC16校验值(CRC-XMODEM)
uint32_t length; // 固件长度(字节)
uint8_t padding[250]; // 填充数据(0xFF)
} sr150_config_info_t;
4. 通信协议¶
4.1 基础APDU协议结构¶
4.1.1 协议帧结构¶
typedef struct __attribute__((packed)) {
uint8_t header; // 起始位 (0x00)
uint8_t preamble[2]; // 前导码 (0x00, 0xFF)
uint16_t length; // 数据长度
ApduPayload_t payload; // 协议负载
// DCS校验码 (1字节) - 动态计算
// 结束码 (1字节) - 0x00
} ApduProtocolFrame_t;
4.1.2 协议负载结构¶
typedef struct __attribute__((packed)) {
uint8_t SADDR[6]; // 源地址
uint8_t TADDR[6]; // 目标地址
uint8_t SNQ; // 序列号
uint8_t cmd_type; // 命令字
uint8_t result; // 结果状态
uint8_t apdu_count; // apdu数量
uint8_t data[1080]; // 数据域
} ApduPayload_t;
4.2 OTA协议扩展¶
4.2.1 命令定义¶
| 命令字 | 命令名称 | 功能描述 |
|---|---|---|
| 0xCA | RESET_MCU | 设备重启命令 |
| 0xCB | FIRMWARE_ERASE | 固件擦除命令 |
| 0xCC | FIRMWARE_PROGRAM | 固件写入命令 |
| 0xCD | FIRMWARE_READ_HEADER | 固件头部读取命令 |
4.2.2 固件擦除命令 (0xCB)¶
固件擦除BLE和COM方案是相同的,但响应不同,具体参考6
请求格式:
data[0-3]: 擦除起始地址 (32位小端序)
data[4]: 擦除块数 (0=整片擦除, 1-N=块数)
响应格式:
result: 0x00=成功, 0x01=失败
无数据域
说明:
- 每个块大小为64KB (W25Q32JV_BLOCK_64K)
- blocks = 0时执行整片擦除
- blocks > 0时从指定地址开始擦除指定数量的64KB块
4.2.3 固件写入命令 (0xCC)¶
COM请求格式:
data[0-3]: 写入起始地址 (32位小端序)
data[4]: 页数 (1-3页, 每页256字节)
data[5-N]: 固件数据 (最大768字节)
响应格式:
result: 0x00=成功, 0x01=失败
无数据域
BLE请求格式:
payload.result + payload.apdu_count:页号
data[0-3]: 写入起始地址 (32位小端序)
data[4]: 页数 (未使用,占位)
data[5-N]: 固件数据 (最大768字节)
BLE响应格式:
无响应.
说明:
- 支持1-3页写入,每页256字节
- 最大单次写入768字节
- 数据长度必须与页数匹配
- 使用多页写入接口优化性能
4.2.4 固件头部读取命令 (0xCD)¶
固件头部读取BLE和COM方案是相同的,但响应不同,具体参考6
请求格式:
data[0-3]: 读取起始地址 (32位小端序)
响应格式:
result: 0x00=成功, 0x01=失败
data[0-31]: 固件头部数据 (32字节)
说明:
- 固定读取32字节固件头部信息
- 默认从EXTERNAL_FLASH_APP_START地址读取
- 失败时不返回数据域
4.3.3 错误码定义¶
pass
5. 校验机制¶
5.1 App固件校验¶
- 算法: CRC32 (IEEE 802.3标准)
- 范围: 固件数据部分(不包含头部)
- 验证: Bootloader启动时验证
- 同串口方式一致
5.2 SR150固件校验¶
- 算法: CRC16 (CRC-XMODEM)
- 范围: 完整固件数据
- 验证: SR150芯片内部验证
6. 蓝牙OTA方案¶
6.1 方案概述¶
蓝牙OTA方案提供了一种无线固件升级解决方案,通过Android应用程序与UWB设备建立蓝牙连接,实现固件的无线传输和升级。该方案基于BLE (Bluetooth Low Energy) 技术,支持App固件和SR150固件(待定...)的远程升级。
6.2 系统架构¶
┌────────────────┐ BLE连接 ┌───────────────┐
│ Android App │ <----------> │ UWB设备 │
│ (OTA客户端) │ │ (QN9090) │
├────────────────┤ ├────────────────┤
│ • 固件选择 │ │ • BLE服务 │
│ • 设备扫描 │ │ • APDU协议处理 │
│ • 固件传输 │ │ • 外部Flash操作│
│ • 进度监控 │ │ • 响应发送 │
└────────────────┘ └────────────────┘
6.3 BLE通信协议¶
6.3.1 服务和特征定义¶
主服务UUID: D44BC439-ABFD-45A2-B575-925416129601
| 特征名称 | UUID | 属性 | 功能描述 |
|---|---|---|---|
| TX特征 | D44BC439-ABFD-45A2-B575-925416129603 |
Notify | 设备向App发送数据 |
| RX特征 | D44BC439-ABFD-45A2-B575-925416129602 |
Write | App向设备发送数据 |
6.3.2 数据传输格式¶
define gBleUseHSClock2MbpsPhy_c 1 //2Mbps PHY mode¶
APDU协议复用
- 蓝牙OTA完全复用串口OTA的APDU协议格式,确保协议层的一致性
- 每个BLE数据包都是完整的APDU帧结构,包含header、preamble、length、payload等字段
- 支持4种OTA命令:RESET_MCU(0xCA)、FIRMWARE_ERASE (0xCB)、FIRMWARE_PROGRAM (0xCC)、FIRMWARE_READ_HEADER (0xCD)
数据分块传输机制
- 单包限制: 受BLE MTU限制,每个数据包最大128字节固件数据
- 缓冲区管理: 设备端维护1KB缓冲区,采用8包聚合机制
- 拼接策略:
- 第1包:完整APDU帧,包含地址信息,初始化缓冲区
- 第2-8包:提取纯固件数据(跳过地址+pages字段),追加到缓冲区
- 第8包后:触发Flash写入操作,重置缓冲区状态
响应机制
- 简化响应: 设备端通过BLE Notification发送简化响应
[phase, status] - 阶段标识: phase值对应不同OTA阶段(1=擦除,2=编程,3=验证, 4=丢包)
- 状态码: status为0x00表示成功,0x01表示失败;
- CCCD要求: 客户端必须启用TX特征的通知功能才能接收响应
重发机制
- 包结构中的status和apdu_num这两个相邻字段被用来表示当前包序号
- 设备端监测包序号判断丢包,并向app发送丢包响应,通知重发
- 由于速率不匹配,app每秒仅接收一次相同序号的丢包响应
- 所有包发送完成后等待一秒,检查最后几包是否丢失,以免响应不及时导致异常
数据包结构示例
第1包 (初始化): [APDU Header][地址4B][Pages1B][固件数据123B]
第2包 (追加): [APDU Header][地址4B][Pages1B][固件数据123B] -> 仅提取128B数据
...
第8包 (触发): [APDU Header][地址4B][Pages1B][固件数据123B] -> 累计1KB写入Flash
6.4 Android应用架构¶
6.4.1 核心组件¶
┌─────────────────────────────────────────────────────────────┐
│ MainActivity │
├─────────────────────────────────────────────────────────────┤
│ • UI控制和用户交互 │
│ • 固件文件选择和管理 │
│ • 升级进度显示 │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ OtaManager │
├─────────────────────────────────────────────────────────────┤
│ • OTA流程控制和状态管理 │
│ • APDU协议封装和解析 │
│ • 固件数据分包和传输 │
│ • 错误处理和重试机制 │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ BleManager │
├─────────────────────────────────────────────────────────────┤
│ • BLE设备扫描和连接管理 │
│ • GATT服务发现和特征操作 │
│ • 数据收发和MTU协商 │
│ • 连接状态监控和异常处理 │
└─────────────────────────────────────────────────────────────┘
6.5 OTA升级流程¶
6.5.1 App固件升级流程¶
1. 设备扫描和连接
├── 扫描附近的UWB设备
├── 选择目标设备并建立BLE连接
├── 发现GATT服务和特征
└── 启用TX特征通知
2. 固件准备阶段
├── 选择App固件文件 (.bin)
├── 读取固件数据并计算CRC32
├── 构建固件头部信息
└── 准备传输数据包
3. 擦除阶段
├── 发送擦除命令 (0xCB)
├── 指定擦除地址和块数
├── 等待擦除完成确认
└── 验证擦除结果
4. 编程阶段
├── 分包发送固件数据 (0xCC)
├── 每包128字节固件数据
├── 实时进度更新
├── 错误检测和重试
└── 完成确认
5. 验证阶段
├── 读取固件头部 (0xCD)
├── 验证CRC32校验值
├── 确认固件完整性
└── 升级完成通知
6.5.2 SR150固件升级流程¶
pass
7 待办¶
7.1 串口OTA¶
- 缺少固件完整性验证
- 串口丢字节
- 串口接收数据后不触发回调
- 缺少重发机制
如果能解决2,3. 应该不用实现4
7.2 蓝牙OTA¶
添加了重发机制后,蓝牙OTA的成功率很高了(桌面环境).但还是缺少完整性验证兜底.