语音芯片OTA V4.1.X使用和协议说明¶
概述¶
本文档适用于通过串口对启英泰伦语音芯片sdk固件进行OTA升级的方案;升级方式为串口升级,默认升级串口号、波特率和语音通信协议一致。
功能特性说明¶
- 支持全量固件升级:支持全量升级(usercode2、asr、dnn、voice、userfile)。
- 支持部分分区升级:升级固件只打包部分分区,只升级这些分区。
- 支持跳过无差异分区:升级时自动跳过不需要升级的分区,减少数据传输。
- 断点续传:支持分区级别断点续传,若升级过程中发生异常中断,下次从异常发生的分区开始升级。
- 运行自恢复:进入OTA模式超过一定时间没有收到主端OTA命令,若主程序有效,清除OTA标志,跳转执行主程序。
- 固件校验:支持主端定义校验内容(通过协议设置哪些需要校验),非法固件禁止升级。
- 产品编号
- 芯片型号
- 软件版本号
- 硬件版本号
- CRC错误固件
- 固件大小
- 分区版本号
- 断电保护:升级过程中若发生断电或通信中断,重新上电后能自动识别固件无效,重新进入OTA模式,避免设备变砖。
- 超时重传:升级过程中命令、数据在超时时间内未收到响应或者下一包数据,进行重传。
- 有限重试:超时重传只执行三次,三次内不能成功则认为OTA失败,语音端和主端重新执行OTA流程。
- OTA模式通告:若设备异常进入OTA模式,将会重复发送通告消息(进入OTA模式响应)给主端。
固件烧写工具说明(使用4.0.5 1.0及以上版本)¶
ota需修改firmware文件夹下面config.ini文件:firmware_version=FW_V4。
修改好后,重启启动sdk自带的烧写工具,工具里面合成固件的code1(OTA_code)和code2(user_code)地址可配置,表示修改成功,如下图所示(备份code1不勾选):

SDK配置说明¶
OTA在SDK里面user_config.h文件有使能选项可选,宏定义如下:
#define CI_OTA_ENABLE 0 //使能OTA功能,0:不使能 ,1:使能
术语表¶
| 术语 | 解释 |
|---|---|
| OTA | Over-The-Air,空中升级,本文特指通过串口进行固件更新 |
| 主程序 | 由正常功能的用户使用程序 |
| OTA程序 | 执行OTA功能的程序 |
| 主端 | OTA流程中主控端,负责下发固件,控制OTA流程,如主端、PC工具 |
| 语音端 | OTA流程中从端,负责接收固件并写入Flash,本文指我司语音芯片模块 |
| dev | 下挂在语音端串口上的电控或其他mcu |
特性说明¶
主端可以配置OTA的波特率和校验内容,参考主端工程配置文件:
| 宏定义 | 取值 | 意义 |
|---|---|---|
| OTA_UART_BAUDRATE | 921600 | OTA串口波特率 |
| OTA_PACK_LENGTH | 4096 | 每包数据长度 |
| OTA_CHECK_SOFT_VER | 1 | 是否检查固件软件版本号 |
| OTA_CHECK_HARD_VER | 1 | 是否检查固件硬件版本号 |
| OTA_CHECK_FLASH_SIZE | 1 | 是否检查硬件Flash大小 |
| OTA_CHECK_PID | 1 | 是否检查产品编号 |
| OTA_CHECK_CHIP_TYPE | 1 | 是否检查芯片类型 |
| OTA_CHECK_PART_VER | 0 | 是否检查固件分区版本号 |
| OTA_UART_UPDATE_BAUDRATE | 921600 | OTA固件传输波特率0~2M(0表示使用默认波特率) |
系统通信及协议设计¶
交互流程¶

备注:在OTA之前,主端可以先查询语音端版本号,版本号符合升级需求再下发进入OTA模式命令
交互说明:
1. 主端发送协议,语音端进入OTA模式
2. 语音端收到协议后,写OTA的标记信息到NV,然后复位芯片进入OTA模式,发送语音端OTA状态给主端。
3. 主端发送OTA版本及参数设置(0xA0)命令,设置语音端的校验参数和固件传输波特率(0表示使用默认波特率)参数。
4. 语音端回复ACK是否允许OTA。
5. 主端收到允许OTA则下发开始OTA消息,否则下发结束OTA消息。
6. 语音端开始OTA后,设置波特率(如果要设置),回复语音端OTA状态,然后发送获取OTA数据的消息。
7. 主端收到后,回复语音端OTA数据。
8. 语音端收到OTA数据,做数据校验,并写入到flash。
9. 主端收到请求包大于固件总包数,发送结束OTA消息。
10. 语音端校验分区表和分区信息,判断OTA是否成功。若成功,擦除OTA使能标记,回复OTA成功,否则回复OTA失败,然后复位系统。
OTA特性:
1. 进入OTA模式后,不支持语音识别
2. OTA时,语音端异常断电,需要主端重新发起OTA
3. 开始进入OTA,OTA升级未完成或异常失败,程序停留在OTA模式,必须OTA成功后,才能切换回正常模式,进行语音识别
4. 语音端在升级之前,做了如下的逻辑检查:
(1) updater分区校验:若updater程序大小超过updater分区大小,语音端回复错误,拒绝OTA。
(2) 固件软件版本号校验:主端开启了固件软件版本号校验,若版本号一致,语音端回复错误,拒绝OTA。
(3) 固件硬件版本号校验:主端开启了固件硬件版本号校验,若版本号不一致,语音端回复错误,拒绝OTA。
(4) FLASH大小校验:主端开启了FLASH大小校验。若FLASH大小错误,语音端回复错误,拒绝OTA。
(5) 产品号校验:主端开启了产品号检查,若产品号不符,语音端回复错误,拒绝OTA。
(6) 芯片型号校验:主端开启了芯片型号检查,若芯片型号不符,语音端回复错误,拒绝OTA。
上述情况,OTA异常,主端收到错误后,需发送OTA结束指令,语音端收到后复位,版本信息不更新。
语音端开始擦除分区,并写入新的OTA固件信息后,会做如下检查:
(1) 收到消息帧crc校验错误,或者长时间未收到主端发送的OTA固件消息,语音端重复发送获取OTA数据协议(0xA1)。若重试次数超过设置次数,语音端复位后重新进行OTA模式。
(2) 语音端写入每个分区完成后,会做分区完整信息的crc16校验,若校验不通过,语音端回复错误。主端需要检查OTA固件信息是否正确,重新发起OTA。
上述情况,OTA异常,主端收到错误后,需检查OTA固件信息或者传输过程是否有误,重新发起OTA。语音端进入OTA模式后,升级成功前一直处于OTA模式。
通信接口说明¶
OTA通信串口,使用和主端通信使用同一个串口和串口波特率,默认参数由串口号宏:UART_PROYTOCOL_NUMBER和波特率宏:UART_PROTOCOL_BAUDRATE决定。主端在版本及参数设置命令中可以更改串口波特率。
通信协议¶
进入OTA模式命令,不同的sdk命令不同,支持用户自定义:
| 主端发送到语音端进入OTA模式命令 | |
|---|---|
| 算法sdk | 0xA5 0xFC 0x00 0x00 0xA1 0x97 0x00 0x38 0x01 0xFB |
| AIOT sdk | 0xA5 0xA5 0x5A 0x5A 0x00 0x00 0x01 0x05 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 |
其中0x97和0x0501是sdk中进入OTA模式的判断字段。 OTA通信协议如下,分为主端(pc或者app)发送的协议和语音芯片发送的协议: 注意:
- 帧长为帧类型+帧数据+CRC+结束符的长度。
- CRC校验为帧头+帧长+帧类型+帧数据的CRC16。
- 中继下发和中继上传的数据需要与协议帧格式一致,crc校验失败会丢弃。
| 主端发送到语音芯片 | ||||||
|---|---|---|---|---|---|---|
| 帧头 (2字节) | 帧长(2字节) | 帧类型 (1字节) | 帧数据 | crc16校验(2字节) | 结束符号(1字节) | |
| 版本及参数设置命令 | 0xA50F | 帧类型长度+数据长度+crc长度+结束符 | 0xA0 | 是否校验软件版本(1字节)+是否校验硬件版本(1字节)+是否校验产品型号(1字节)+是否校验芯片型号(1字节)+是否校验nv地址(1字节)+是否校验分区版本号(1字节)+固件版本号(3字节)+波特率(4字节) | XXXX | 0xFF |
| 发送OTA升级固件数据 | 0xA50F | 帧类型长度+数据长度+crc长度+结束符 | 0xA1 | 包序号(2字节)+每包有效数据 | XXXX | 0xFF |
| 发送OTA结束指令 | 0xA50F | 帧类型长度+数据长度+crc长度+结束符 | 0xA2 | 0字节 | XXXX | 0xFF |
| 发送OTA开始指令 | 0xA50F | 帧类型长度+数据长度+crc长度+结束符 | 0xA3 | 升级对象(1字节):0x00=OTA语音端,0x01=OTA下挂设备 | XXXX | 0xFF |
| 中继参数设置 | 0xA50F | 帧类型长度+数据长度+crc长度+结束符 | 0xA4 | 串口号(1字节)+波特率(4字节,高字节在前) | XXXX | 0xFF |
| 中继下发 | 0xA50F | 帧类型长度+数据长度+crc长度+结束符 | 0xA5 | 中继数据 | XXXX | 0xFF |
| 语音芯片发送到主端 | ||||||
| 帧头 (2字节) | 数据长度 (2字节) | 帧类型 (1字节) | 帧数据 | crc16校验(2字节) | 结束符号(1字节) | |
| 版本及参数设置响应 | 0xA50F | 帧类型长度+数据长度+crc长度+结束符 | 0xA0 | 校验结果(1字节):0x00=拒绝OTA,0x01=允许OTA +版本信息(3字节)+拒绝原因(1字节,参考下方拒绝升级原因表) | XXXX | 0xFF |
| 固件请求 | 0xA50F | 帧类型长度+数据长度+crc长度+结束符 | 0xA1 | 响应状态(1字节)+附加数据(4字节),具体参考下方固件传输响应状态表 | XXXX | 0xFF |
| OTA状态响应 | 0xA50F | 帧类型长度+数据长度+crc长度+结束符 | 0xA2 | 升级状态(1字节,参考下方OTA状态码表)+原因(1字节,参考下方对应原因表) | XXXX | 0xFF |
| 中继参数设置响应 | 0xA50F | 帧类型长度+数据长度+crc长度+结束符 | 0xA4 | 响应结果(1字节):0x00=拒绝OTA,0x01=允许OTA(串口或波特率错误) | XXXX | 0xFF |
| 中继上报 | 0xA50F | 帧类型长度+数据长度+crc长度+结束符 | 0xA6 | 中继数据最大长度4KB+10 | XXXX | 0xFF |
OTA状态码¶
| 状态值 | 含义 |
|---|---|
| 0x00 | 升级失败 |
| 0x01 | 升级成功 |
| 0x02 | 等待升级 |
| 0x03 | 升级语音芯片中 |
| 0x04 | 升级下挂设备中 |
拒绝升级原因(错误码)¶
| 错误码 | 原因 |
|---|---|
| 0x01 | 软件版本号错误 |
| 0x02 | 硬件版本号错误 |
| 0x03 | 波特率错误 |
| 0x04 | NV地址错误 |
| 0x05 | 产品型号错误 |
| 0x06 | 芯片型号错误 |
| 0x07 | 分区CRC错误 |
| 0x08 | 分区表CRC错误 |
| 0x09 | 固件头信息错误 |
| 0x0A | 固件大小错误 |
| 0x0B | ota code大小错误 |
| 0x0C | 变化分区未升级 |
| 0x0D | 分区版本号错误 |
| 0x0E | 消息超时 |
| 0x0F | 保留 |
等待升级原因¶
| 原因码 | 含义 |
|---|---|
| 0x01 | 主端主动发起OTA升级 |
| 0x02 | 语音端分区错误 |
| 0x03 | 加载用户code失败 |
| 0x04 | 保留 |
固件传输响应状态¶
| 状态值 | 含义 | 附加数据 |
|---|---|---|
| 0x00 | 写入失败 | 失败原因(1字节,参考上表拒绝升级原因) |
| 0x01 | 写入成功 | 当前包序号(2字节)+ 下一包包序号(2字节) |
windows测试工具使用说明¶
updater参数配置¶
通过该程序可以配置ota过程中的串口号、波特率、芯片型号、用户协议的帧结构、用户协议的帧类型等参数,方便客户使用自己的协议来完成ota适配。
- 源固件,ota code源码生成的ota程序
- 目标固件,使用ota code生成的带配置的updater程序
- ota参数设置,设置ota过程中的串口号、波特率、芯片型号
- 帧结构设置,勾选此选项可以开启用户协议与标准协议的转换,大小端影响帧长、crc的读取,帧长最大支持4字节,crc只支持标准协议中的crc16;
- 配置帧类型,勾选配置帧类型可以开启用户协议帧类型与标准协议帧类型的映射,若帧类型未修改不用勾选。

OTA固件制作¶
原始固件¶
原始由sdk中的固件打包工具打包完生成,如下图;

包含boot、分区表、备份分区表、ota程序、主程序等,OTA程序暂时不可升级;内容如下表:
| 分区起始地址 | 分区 |
|---|---|
| 0x000 | Boot |
| 0x6000 | 分区表 |
| 0x8000 | 备份分区表 |
| 0xA000 | ota程序固件 |
| 0xA000+OTA程序固件大小 | use_code2分区 |
| user_code2起始地址+user_code2大小 | asr分区 |
| asr起始地址+asr大小 | dnn分区 |
| dnn起始地址+dnn大小 | voice分区 |
| voice起始地址+voice大小 | userfile分区 |
| 0xFC000/3FC000 | NV分区或其他自定义值 |
OTA固件¶
- OTA固件通过OTA工具裁剪生成,推荐使用自动检查修改分区来选择升级分区,如下图;

- OTA固件包含固件头信息、分区表(必须升级)、可选升级分区内容(user_code2、asr、dnn、voice、userfile)。
OTA固件头信息用于记录需要升级的内容,大小为4kB,大端格式。 头信息格式如下:
| 长度(2字节) | 分区数(2字节) | 可选升级分区 | 可选升级分区 | 可选升级分区 | 可选升级分区 | 可选升级分区 | CRC |
|---|---|---|---|---|---|---|---|
| 有效数据长度(不包含crc,高字节在前) | 要升级的分区个数(高字节在前) | user_code2 | asr | dnn | voice | user_file | crc16校验(校验内容包含分区数和可选升级分区) |
OTA固件格式如下:
| 固件起始地址 | 内容 |
|---|---|
| 0x0000 | 固件头信息 |
| 0x1000 | 分区表 |
| 0x2000 | 可选升级分区内容(user_code2、asr、dnn、voice、userfile) |
OTA升级测试¶
通过工具可以测试OTA功能,支持设置串口、传输波特率、等参数,操作步骤如下:
- 设置串口和波特率,连接串口。
- 设置ota流程中的参数。
- 设置进入ota模式的方法。
- 选择升级文件。
- 点击开始ota,等待运行。
- 运行中会打印各种流程信息。
- 工具目录下会自动保存对应时间戳的升级log。

如何使用OTA?¶
生成updater原始bin文件¶
通过源码生成¶
通过ota_code源码生成ota_code.bin;这里可能涉及到芯片型号、日志串口和OTA串口;编译方法与其他sdk一致;通过修改user_config.h文件配置参数,工具中执行编译;
芯片型号:
串口:

编译完成后会在projects\offline_asr_sample\firmware\user_code生成user_code.bin,这个bin文件就是updater参数配置中需要的源固件;
使用资料包中自带的¶
资料包中已经有了基于源码生成的ota_code.bin,如果没有特殊需求可以使用资料包中自带的,其中log0代表日志使用串口0。如下:

配置updater参数¶
参考updater参数配置。
生成固件包¶
编译算法或者离在线的sdk,通过sdk中的pack工具生成固件包;需设置pack工具的配置文件中projects\offline_asr_alg_pro_sample\firmware\config.ini为firmware_version=FW_V4; 如下图,红框中需要选择第2.1.2章节中配置过参数的updater固件;

制作OTA固件¶
参考OTA固件制作。
升级测试¶
参考ota升级测试;如果主端已经适配完成,可以使用主端工程来联调。
用户协议转换¶
当用户使用固定帧格式的消息且校验方式与我司一致时,可以使用协议转换功能,快速完成协议适配;
备注:用户协议中帧类型与标准协议要有相对应的,中继不使用时可以没有;
界面如下:

以下是一个适配例子,用户协议如下:
| 帧头 | 版本 | 帧序号 | 帧类型 | 帧长 | 帧数据 | crc |
|---|---|---|---|---|---|---|
| A5 0F | 02 | 1字节 | 2字节 | 2(n字节+crc长度) | n字节 | 2字节 |
帧类型定义: 备注:上报帧与上报帧、下发帧与下发帧不允许相同,中继相关如果没用到可以设置为不使用的值; 数据长度补充是协议字段中帧长与数据长度之间的差值,当前例子中帧长是数据长度n字节+crc2字节,所以数据长度补充就是2;
| 主端到语音端 | 主端到语音端 |
|---|---|
| 版本参数设置 | 1111 |
| 开始OTA | 2222 |
| 升级固件请求响应 | 3333 |
| 结束OTA | 4444 |
| 中继参数响应 | FFF1 |
| 中继下发 | FFF2 |
| 语音端到主端 | 语音端到主端 |
| OTA状态 | 5555 |
| 版本及参数响应 | 6666 |
| 升级固件请求 | 7777 |
| 中继参数设置响应 | FFF3 |
| 中继上报 | FFF4 |
配置如下:

主端参考demo说明¶
主端demo可以参考OTA_V4.1_主端参考代码linux工程;
enter_ota_mode()¶
主端发送进入ota模式命令到语音端,发送后等待语音端回复OTA状态响应(等待升级状态)。收到响应说明语音端进入OTA模式。具体命令参考第1.7.3通信协议章节。
ota_check_version()¶
主端发送ota版本及参数设置命令到语音端,语音端保存设置参数,并校验版本是否正确。返回校验结果给主端。主端根据返回结果决定继续ota还是结束ota。
ota_start()¶
主端发送开始ota命令给语音端,语音端收到命令后,更新通信波特率为版本及参数设置命令中的值(波特率为0时,不设置),然后回复OTA状态响应(升级语音端状态或升级下挂设备状态)
ota_transport_firmware()¶
发送OTA升级固件有效数据命令,包含两段参数: 1:包序号,第一次发送时为0,后续的包序号,从语音端回复的ACK里面解析得出。 2:有效数据,从待升级固件OTA_INVALID_HEAD_LENGTH开始,加上包序号乘以每包有效数据长度(OTA_PACK_LENGTH),开始读固件并取出。 主端发送数据到收到语音端的超时时间需要设置高一点,至少大于5S(语音端擦除falsh比较耗时)。默认的策略是发送第一次超时未收到ACK,重发一次,重发也未收到ACK,程序判断OTA失败。 语音端返回的固件传输ACK消息有两个状态。 1:如果状态是0,表示写入失败。后续第一个字节表示写入固件失败的原因,有如下值:-1,当前系统内存不足导致不能继续OTA;-2,下发固件不是OTA固件;-3,下发的固件分区表信息校验不通过;-4,下发的固件硬件版本信息不一致;-5,下发固件后校验分区的crc不正确。 2:如果返回状态是1,表示写入成功,解析返回数据的下一包包序号字段,确认发送的下一包数据内容。特别注意,如果返回的下一包包序号大于了主端计算的数据包总包数,表示固件全部传输完成,主端程序判断OTA成功,发送OTA结束指令。
ota_end()¶
发送OTA结束指令,语音端收到后会回复OTA状态响应(OTA成功或失败)并立即软件复位重启。主端结束OTA逻辑回到语音协议交互逻辑。
OTA适配重点¶
流程如何设计?¶
- 主端通过语音协议先获取语音端软件版本号,校验版本号是否需要升级;满足升级需求再下发进入OTA命令;这样可以避免语音端重复进入OTA模式。
- 语音端OTA成功后会将其中标志设为OTA成功,如果有要求OTA成功后正常进入语音识别模式进行播报或者上报消息,可以通过读取标志位来实现。
- 语音端默认接收消息和发送都会有3s超时,重试3次;主端在发送消息时可以参考demo实现超时(4s和3次)和重试;
- 语音端在收到切换波特率命令时,会在50ms之后发出数据,主端可以在数据发送后延迟10ms等待发送完成再切换波特率等地啊接收语音端消息;
- 若用户已有协议,通过第2.1章节的协议转换,可以实现协议转换通信。标准OTA流程中的协议若用户没有需要新增。
- 使用ota_code源码编译出user_code文件;可以直接使用ota_code_bin目录下的bin文件,选择串口对对应的版本即可。如下图:

- 使用步骤3得到的ota_code.bin生成ota_updater.bin,串口号、波特率、芯片型号需要配置与实际一致,参考updater参数配置。

- 使用打包工具打包程序,打包工具配置文件要设为FW4,user_code1选择步骤4生成的文件。

- 路径:projects\offline_asr_alg_pro_sample\firmware\config.ini
- 烧写测试。
设备未进入OTA模式¶
进入OTA模式需要通过flash中的标记来判断,应用层需要在消息处理时写入flash标记;
通过向语音端发送串口协议(可以自定义),接收到消息时调用write_ota_mcu_status函数即可使设备进入OTA模式。 调用时:
// OTA_STA_ENTER进入ota模式
write_ota_mcu_status(OTA_STA_ENTER);
语音执行此函数进入使设备下次重启后,进入OTA模式,其中NVDATA_ID_OTA_MCU_STATUS为NV区OTA标记的地址,默认0x80000001。不可修改; OTA标志枚举如下:
typedef enum
{
OTA_STA_FAIL = 0x00, // OTA失败
OTA_STA_SUC = 0x01, // OTA成功
OTA_STA_WAITING = 0x02, // 等待OTA
OTA_STA_CI = 0x03, // OTA语音端
OTA_STA_DEV = 0x04, // OTA下挂设备中
OTA_STA_ENTER = 0x05, // 进入OTA
} ota_state_t;
函数实现如下:
cinv_item_ret_t write_ota_mcu_status(uint8_t status)
{
uint8_t flag = status;
return cinv_item_write(NVDATA_ID_OTA_MCU_STATUS, sizeof(uint8_t), &flag);
}
OTA升级失败¶
OTA升级流程中发生错误,语音设备都有详细的错误类型上报,可以查看通信协议中的失败原因列表。
低波特率OTA¶
使用较低的波特率OTA时,需要调整传输的超时时间和单包大小,例如9600波特率时,若使用4k单包来传输,必然发生超时,理论速率传输完4k报文,需要5s多时间;不建议使用较低波特率,升级时间较长。
OTA阶段log和升级串口使用同一个¶
不建议使用同一个,如果一定要使用同一个,需要保证log打印和消息发送时的时序;多任务运行时可能冲突导致消息发送失败;
使用自定义的串口引脚¶
如果需要使用自定义串口引脚,需要在ota_code源码中修改板级配置文件;语音code和ota code同步修改;ota code固定加载driver\boards\CI-D06GT01D.c 修改其中函数void pad_config_for_uart(UART_TypeDef *UARTx)中对应串口的引脚即可。
修改超时时间和次数¶
由于主端可能通过wifi或ble来执行升级流程,交互需要经过云端、主端、语音端,此时3s的超时时间就不太够用,可以通过修改源码中的配置来设置更长的超时时间。修改user_config中的OTA_TIMEOUT和OTA_RETRY_TIME:

主端参数说明¶
可选配置参数如下图:

升级固件制作说明¶
升级固件建议选择所有分区,升级时会自动判断哪些分区需要升级,升级时间与部分分区升级差异不大;如果受限于资源或场景等条件需要升级固件比较小可以选择打包部分分区。