安信可蓝牙模块TB系列实现远程OTA无线升级功能介绍,剖析整个实现原理和代码介绍。

[复制链接]
查看1092 | 回复8 | 2024-5-27 16:29:52 | 显示全部楼层 |阅读模式
一、BLE FOTA简介
BLE SLAVE设备除了有线升级(比如串口烧录)方式,还有通过BLE无线连接升级的方式。本篇博文,而深圳安信可科技的TB系列蓝牙模块能够实现这一功能,那么本篇文章带您简单了解 BLE SLAVE OTA实现的原理和流程。
适合模块:安信可TB-01\TB-02\TB-03F\TB-04

二、BLE SLAVE FOTA实现流程

在Telink BLE SDK中,已经实现了 BLE SLAVE FOTA,即BLE作为从机的ota升级。我们只需打开相关demo下的app_config.h文件里BLE_OTA_ENABLE这个宏定义即可。
1.png
在app_att.c文件中,Attribute Table中添加了OTA的相关内容,其中OTA数据Attribute的att_readwrite_callback_t r和att_readwrite_callback_t w分别设为otaRead和otaWrite,将属性设为Read和Write_without_Rsp(Master通过WriteCommand发数据,不需要slave回ack,速度会更快)。
  1. static const  u8 my_OtaUUID[16]                                            = TELINK_SPP_DATA_OTA;
  2. static const  u8 my_OtaServiceUUID[16]                                = TELINK_OTA_UUID_SERVICE;
  3. static u8 my_OtaData                                                         = 0x00;
  4. static const  u8 my_OtaName[]                                                 = {'O', 'T', 'A'};
  5. ...
  6. #if BLE_OTA_ENABLE
  7. OTA attribute values
  8. static const u8 my_OtaCharVal[19] = {
  9.         CHAR_PROP_READ | CHAR_PROP_WRITE_WITHOUT_RSP,
  10.         U16_LO(OTA_CMD_OUT_DP_H), U16_HI(OTA_CMD_OUT_DP_H),
  11.         TELINK_SPP_DATA_OTA,
  12. };
  13. #endif
  14. ...
  15. attribute_t my_Attributes[] = {
  16. ...
  17. #if BLE_OTA_ENABLE
  18. {4,ATT_PERMISSIONS_READ, 2,16,(u8*)(&my_primaryServiceUUID),        (u8*)(&my_OtaServiceUUID), 0},
  19. {0,ATT_PERMISSIONS_READ, 2, sizeof(my_OtaCharVal),(u8*)(&my_characterUUID), (u8*)(my_OtaCharVal), 0},                                //prop
  20. {0,ATT_PERMISSIONS_RDWR,16,sizeof(my_OtaData),(u8*)(&my_OtaUUID),        (&my_OtaData), &otaWrite, &otaRead},                        //value 读写属性
  21. {0,ATT_PERMISSIONS_READ, 2,sizeof (my_OtaName),(u8*)(&userdesc_UUID), (u8*)(my_OtaName), 0},  //OTA名字
  22. #endif
  23. ...
  24. };
复制代码
我们在使用支持BLE OTA的手机APP向BLE从机设备发送OTA数据时,实际是向上面{0,ATT_PERMISSIONS_RDWR,16,sizeof(my_OtaData),(u8*)(&my_OtaUUID), (&my_OtaData), &otaWrite, &otaRead},的Attribute写数据,手机APP需要知道这个Attribute在整个Attribute Table中的Attribute Handle。对于BLE从机设备来说, 手机APP端发送过来的写命令,是通过BLE协议栈自动解析并最终调用otaWrite函数来进行处理的。在otaWrite函数里,会对20字节的包的据进行解析,首先判断是OTA CMD还是OTA data,对OTA cmd进行相应的响应,对OTA数据进行CRC校验并烧写到flash对应位置。


1、收到OTA version命令固件版本,前两bytes为0xff00:OTA_FIRMWARE_VERSION命令)。
2、收到OTA start命令(前两bytes为0xff01):此时BLE从机设备进入OTA模式。若用户使用bls_ota_registerStartCmdCb函数注册了OTA start时的回调函数,则执行此函数,这个函数的目的是让用户在进入OTA模式后,修改一些参数状态等,比如将PM关掉(使得OTA数据传输更加稳定)。
另外BLE从机设备启动并维护一个slave_adr_index,初值为-1,记录最近一次正确OTA data的adr_index,用于判断整个OTA过程中是否有丢包。一旦丢包,认为OTA失败,退出OTA,MCU重启,master端由于收不到slave的ack包,也会由于OTA任务超时使得软件发现OTA失败。

其注册OTA start的回调函数:
  1. typedefvoid (*ota_startCb_t)(void);     
  2. void bls_ota_registerStartCmdCb(ota_startCb_t cb);
复制代码
用户需要注册这个回调,以便在OTA start的时候做一些操作,比如配置LED灯的特殊闪烁方式来指示OTA正在进行。



另外slave这端一旦收到OTA start开始OTA后,也会启动一个计时,目前SDK中默认是30s。如果30s之内OTA还没有完成,就认为超时失败。实际user最后需要根据自己的firmware大小(越大越耗时)和master端BLE数据带宽(太窄的话会影响OTA速度)来修改这个默认的30s,SDK提供修改的接口为:

  1. void bls_ota_setTimeout(u32 timeout_us);//单位:us
复制代码
3、收到有效的OTA数据(前两bytes为0~0x1000): 这个范围的值表示具体的OTA data。
这个范围的值表示具体的OTA data。


每次slave收到一个20 byte 的OTA data packet,先看adr_index是否等于slave_adr_index的值加1。若不等,说明丢包,OTA失败;若相等,更新slave_adr_index的值。


然后对前18 byte的内容进行CRC_16的校验。若不匹配,OTA失败;若匹配,则将16 byte的有效数据写到flash对应位置ota_program_offset+adr_index16 ~ ota_program_offset+adr_index16 + 15。在写flash的过程中,如果出错,OTA也失败。


4、收到OTA end(前两bytes为0xff02): 检查OTA end包中的adr_max和其取反校验值是否正确。若正确,则adr_max可以用来做double check。double check的时候,判断slave之前收到的master的数据index最大值与该包中的adr_max是否相等。若相等,认为OTA成功,若不等,认为丢掉了最后一笔或几笔数据,OTA不完整。


当OTA成功的时候,slave将老的firmware所在地址的flash启动标志设为0,将新的firmware所在地址的flash启动标志设为0x4b,将MCU reboot。


5、slave提供OTA状态的回调函数: slave端一旦启动OTA,不管OTA是成功还是失败,最会将MCU reboot: 若成功,会在reboot前设置flag告诉MCU再次启动后运行New_firmware; 若OTA失败,会将错误的新程序擦掉后重新启动,还是运行Old_firmware。
在MCU reboot前,根据user是否注册了OTA状态回调函数,来决定是否触发该函数。
  1. typedef void (*ota_resIndicateCb_t)(int result);
  2. enum{  OTA_SUCCESS = 0,     //success  OTA_PACKET_LOSS,     //lost one or more OTA PDU  OTA_DATA_CRC_ERR,     //data CRC err  OTA_WRITE_FLASH_ERR,  //write OTA data to flash ERR  OTA_DATA_UNCOMPLETE,  //lost last one or more OTA PDU  OTA_TIMEOUT,   // };
  3. void bls_ota_registerResultIndicateCb   (ota_resIndicateCb_t cb);
复制代码

用户也可以参考SDK demo “8258_ble_remote”中 debug OTA的code,其中使用了LED闪烁效果来判断OTA是否成功。


通过手机APP 完成BLE设备的OTA演示
1)先后编译两个新旧固件
2.png
2)烧录旧固件到TB系列模块
3.png
(注意:需使用V2.1.0版本的烧录工具,TB系列模组的RXD要短接SWS,然后再接USB转TTL到PC)
启动信息如下:

4.png
3)把新固件放在手机APP可访问的存储位置,打开手机APP进行扫描当前的蓝牙设备,如图:
5.png
连接蓝牙设备后,点击START开始OTA升级,直到如下图所示,完成升级。
6.png
升级前后串口打印如图:
7.png
OTA例程代码下载: https://gitcode.com/Ai-Thinker-Open/Telink_825X_SDK/tree/master/example/ota?utm_source=csdn_github_accelerator&isLogin=1
用心做好保姆工作
回复

使用道具 举报

lovzx | 2024-5-27 21:36:57 | 显示全部楼层
学习
回复

使用道具 举报

lovzx | 2024-5-27 21:38:00 | 显示全部楼层
代码地址打不开了
回复 支持 反对

使用道具 举报

爱笑 | 2024-5-28 08:50:47 | 显示全部楼层
lovzx 发表于 2024-5-27 21:38
代码地址打不开了

解决啦,是我放错了哈哈。
用心做好保姆工作
回复 支持 反对

使用道具 举报

WT_0213 | 2024-5-28 09:06:57 | 显示全部楼层
回复

使用道具 举报

djy876 | 2024-5-28 15:37:40 | 显示全部楼层
园长写这么好
回复 支持 反对

使用道具 举报

hahawen | 2024-11-1 16:38:16 | 显示全部楼层
github 里面的例子我烧录到TB03后,按reset开发版可以启动,再按reset就不能重新启动了,这是怎么回事?
而且OTA例子中有几个变量是缺失的。
回复 支持 反对

使用道具 举报

hahawen | 2024-11-2 21:41:15 | 显示全部楼层
研究了下发现OTA和安信可的bootloader 不可共存
回复 支持 反对

使用道具 举报

感谢分享,学习了
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则