最近完成了CC1350的蓝牙空中升级功能,在开始写这个功能之前,我在网上找过很多相关资料,结果大多是零零碎碎的信息,然后英文资料偏多,因此也走了不少弯路,好在最终还是完成了这个功能,在此做个笔记,希望能帮助到其他使用TI蓝牙模块的童鞋们在做空中升级时少走些弯路。
流程说明:
1、 app从服务器上下载固件至本地沙盒
说明:固件文件由设备端工程师制作,导出文件为hex格式,需要转换为bin格式的二进制文件供移动端下载(TI的文档里面会有相关的转换说明)
2、app利用蓝牙通讯将固件传输至蓝牙设备
说明:按照TI的文档要求,需要将固件分片发送至蓝牙设备,每一片数据的长度为取镜像文件中连续的16个字节,在头部拼接2字节的序列编号共18个字节。
整个升级方案分为以上两个流程模块,第一个模块主要为app准备固件。 第二个模块为app将固件传输至设备 。这里主要讲解第二个模块功能的流程。
升级使用到的服务与特征
//===在线升级服务搜索特征===
#define UUID_UPGRADE_SERVER @"F000FFC0-0451-4000-B000-000000000000"
//===在线升级数据交互特征===
//头特征,用于发送固件头数据,通知设备开始升级,头数据长度为16个字节
#define UUID_UPGRADE_Identify @"F000FFC1-0451-4000-B000-000000000000"
//block特征,用于分片发送固件数据,长度为2+16字节
#define UUID_UPGRADE_Block @"F000FFC2-0451-4000-B000-000000000000"
//状态特征,返回0时 代表升级成功
#define UUID_UPGRADE_Status @"F000FFC4-0451-4000-B000-000000000000"
流程介绍:
UUID_UPGRADE_Identify 以下简称Identify
UUID_UPGRADE_Block 以下简称Block
UUID_UPGRADE_Status 以下简称Status
注意:以上3个特征皆需要订阅通知
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
1、App写入头数据(CRC共16个Byte)至Identify特征开启设备的升级模式
2、Block特征返回要求发送的片数据编号(2个字节)
3、根据返回的数据编号a取对应的第a片数据,将编号(2Byte)+片数据(16Byte)以Block特征发送数据
4、Block特征返回下一片数据的编号
5、重复Block过程直到固件全部发送至设备
6、Status特征返回<00>表示升级成功
数据说明:
CRC---Identify特征开启升级模式的头数据,也是Block特征发送的第一片数据。数据长度为16个字节,在block特征中需要拼接2字节的编号至头部。(数据来源为固件中的第一片16字节数据)
来自TI文档的CRC头数据说明表
在TI的升级规则中,我们不能将高版本的固件升级为低版本固件,当我们如此操作时,Identify特征会直接返回相应的数据信息,而不触发block特征的通知,这样升级的流程就无法再进行。在CRC数据中,我们可以解析出相应的版本号,数据长度等信息。
来自TI文档的Status特征状态说明表
整个升级过程中,只有当Status特征返回值为0时才表示升级成功。
踩过的坑和需要注意的地方
在TI的升级过程中,我们可能因为总总原因导致升级失败或者需要中断升级,这时如果没有相应的处理,我们往往无法再次进入升级流程。
1、在正常连接状况下当app中断升级时,需要给Block特征发送错误的数据编号和长度,此时设备会自动擦除Flash中已接收的数据,Status特征返回相应状态,否则无法再次进入升级流程。
2、断开连接状态下导致的升级中断,需要设备端自行检测并擦除数据,否则无法再次进入升级流程。
以上为TI蓝牙模块空中升级大略的讲解,关于具体的文件数据分片和代码实例可以留言问我。