【BLE】CC2541之Large OAD

来源:互联网 发布:电力系统分析课本知乎 编辑:程序博客网 时间:2024/05/07 21:01

本篇博文最后修改时间:2016年11月11日,09:12。


一、简介

本篇以SimpleBLEPeripheral工程为例,介绍如何进行Large OAD升级。


二、实验平台

协议栈版本:BLE-CC254x-1.4.0

编译软件: IAR 8.20.2

硬件平台: Smart RF开发板

手机型号: 小米4S

安卓版本:安卓5.1

安卓app:BleSensorTag(解决了bug后的)


版权声明

博主:甜甜的大香瓜

声明:喝水不忘挖井人,转载请注明出处。

原文地址:http://blog.csdn.NET/feilusia

联系方式:897503845@qq.com

香瓜BLE之CC2541群:127442605

香瓜BLE之CC2640群:557278427

香瓜BLE之Android群:541462902

香瓜单片机之STM8/STM32群:164311667
甜甜的大香瓜的小店(淘宝店):https://shop217632629.taobao.com/?spm=2013.1.1000126.d21.hd2o8i

四、实验前提
1、在进行本文步骤前,请先阅读以下博文:
1)《CC2541之OAD》:http://blog.csdn.net/feilusia/article/details/50289371
2)TI官方资料:http://processors.wiki.ti.com/index.php/BLE_Large_Image_OAD
注:TI的资料写的并不详细,且有bug。


2、在进行本文步骤前,请先实现以下博文:
暂无


五、基础知识
1、Large OAD与普通OAD有什么区别?
答:

可以简单理解为代码量小于125K就用普通OAD,超过125K就用Large OAD。

2、Large OAD的升级原理是如何的?
答:工程中常驻代码为TI提供的BIM(2K)及Image A(90多K)代码。
BIM是芯片一上电便运行的代码,它会先判断代码里是否有ImageB,如果有则运行ImageB,否则接着判断是否有ImageA,如果有ImageA则运行ImageA,否则进入PM3睡眠模式。
ImageA在这里起到与主机通信的作用,也就是把ImageB接收下来,接收之后ImageA也就没什么用了,代码会从BIM跳转到ImageB启动。
当设备需要再次升级时,需要通过指令或者按键,使设备上电能跳转至ImageA,此时就可以像第一次一样升级ImageB。

3、BIM、ImageA、ImageB、snv是如何存放在flash中的?
答:起始2K存放BIM,末尾4K存放snv数据,
ImageA被分为两部分,紧接着BIM后面有14K,紧跟着snv前面有82K,ImageA的分布详情如下:

两块ImageA之间属于ImageB的存储空间,ImageB的分布详情如下:
-D_CODE_BEG=0x4030             // Last 10 pages of Bank 0.-D_CODE_END=0x7FFF//-D_BANK1_BEG=0x18000-D_BANK1_END=0x1FFFF//-D_BANK2_BEG=0x28000-D_BANK2_END=0x2FFFF//-D_BANK3_BEG=0x38000-D_BANK3_END=0x3FFFF//-D_BANK4_BEG=0x48000-D_BANK4_END=0x4FFFF//-D_BANK5_BEG=0x58000 // First 5 pages of 5-D_BANK5_END=0x5A7FF

4、BIM是通过什么判断有没有ImageA、ImageB的?
答:ImageA以及ImageB在写入flash之后,会分别有4个字节作为crc校验,分别写在0x0800(2K)起始处、0x4000(16K)起始处。
BIM一旦判断到0x4000(16K)位置有被写过crc,则说明有ImageB存在,则跳转到ImageB的代码处执行。
BIM一旦判断到0x0800(2K)位置有被写过crc,则说明有ImageA存在,则跳转到ImageA的代码处执行。

5、Large OAD使用过程中有什么注意的?
1)不需关闭参数更新:
在进行升级之前,不需要像普通OAD一样关闭ImageB工程的参数更新。因为ImageB不作为桥梁进行OAD升级,它是被升级一方。
2)需先跳转至ImageA:
再次进行升级之前,需要通过指令或者按键,使设备上电能跳转至ImageA,而不跳转至ImageB。
也就是再次升级前要使ImageB执行以下核心代码:
uint16 crc[2] = { 0x0000, 0xFFFF };uint16 addr = OAD_IMG_R_PAGE * ((uint16)(HAL_FLASH_PAGE_SIZE / HAL_FLASH_WORD_SIZE)) + OAD_IMG_CRC_OSET / HAL_FLASH_WORD_SIZE;HalFlashWrite(addr, (uint8 *)crc, 1);HAL_SYSTEM_RESET();
3)PC端软件、IOS软件进行升级大于128K的bin时,会出错。强烈推荐使用安卓app。
PS:感谢群友“星雨”(454086991)的经验分享,必须要大写的感谢,否则香瓜起码得在PC端软件上耗上好几天时间,香瓜实测PC端软件升级后crc错乱、不会跳转至ImageB。

6、下载完ImageB之后,不更新,如何知道crc是否正确呢?
答:这里有个小技巧,可以利用iar的“debug without download”方式仿真BIM工程,这样单步仿真既能看到ImageB的crc数值,又能不擦除代码。

六、实验步骤
1、下载TI的Large OAD的demo
下载地址:http://processors.wiki.ti.com/index.php/File:Large_OAD_Example.zip


2、拷贝demo中有用的部分到自己的工程中
1)将BIM、ImageA工程拷贝到自己的工程的ble文件夹下


2)将的ImageB工程中的xcl放到自己工程文件夹中,后面需要选中这个xcl的路径。


3)修改cc254x_f256_imgB_Large.xcl中的bug
-Z(CODE)CHECKSUM=0x3000-0x3001-Z(CODE)IMAGE_HEADER=0x3002-0x300F-Z(CODE)AES_HEADER=0x3010-0x302F
改成
-Z(CODE)CHECKSUM=0x4000-0x4001-Z(CODE)IMAGE_HEADER=0x4002-0x400F-Z(CODE)AES_HEADER=0x4010-0x402F

-J2,crc=8005,=3004-_BANK5_END
改成
-J2,crc=8005,=4004-_BANK5_END
由于BIM判断的CRC位置是0x4000(16K)起始处,因此ti提供的demo需要做如上修改。

3、修改工程中的批处理文件cc254x_ubl_pp.bat(……\BLE-CC254x-1.4.0\Projects\ble\common\cc2540\
@echo off  %~d1  chdir %1\..\..\common\cc2540  start cc254x_ubl_pp.js %2 %3 %4 %5  

通过文本编辑器编辑该批处理文件。

注:如果不做此步,很可能无法生成bin。

详情见http://e2e.ti.com/support/wireless_connectivity/f/538/t/314089


4、下载BIM工程
1)修改BIM代码为如下图

此处代码原本是注释掉的。

2)rebuild all,仿真下载。

5、下载ImageA工程


6、修改目标工程代码
PS:香瓜这里以SimpleBLEPeripheral工程作为目标工程举例
1)修改设备名(非必须,只是方便查看后续是否更新成功)(在simpleBLEperipheral.c中)
// GAP - SCAN RSP data (max size = 31 bytes)static uint8 scanRspData[] ={  0x07,     //自定义设备名的长度      GAP_ADTYPE_LOCAL_NAME_COMPLETE,      0x47,     //G      0x55,     //U      0x41,     //A      0x3A,     //:      0x30,     //0      0x31,     //1  // connection interval range  0x05,   // length of this data  GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE,  LO_UINT16( DEFAULT_DESIRED_MIN_CONN_INTERVAL ),   // 100ms  HI_UINT16( DEFAULT_DESIRED_MIN_CONN_INTERVAL ),  LO_UINT16( DEFAULT_DESIRED_MAX_CONN_INTERVAL ),   // 1s  HI_UINT16( DEFAULT_DESIRED_MAX_CONN_INTERVAL ),  // Tx power level  0x02,   // length of this data  GAP_ADTYPE_POWER_LEVEL,  0       // 0dBm};

2)增加切换到ImageA的指令(必须,但方式方法可自定义)(在simpleBLEperipheral.c中)
①增加宏

//GUA#include "hal_flash.h"//GUA

②增加指令处理进行切换ImageA(替换simpleProfileChangeCB函数)

//******************************************************************************            //name:             simpleProfileChangeCB//introduce:        特征值回调函数,往char1通道发送0x38指令,可切换至ImageA。          //parameter:        paramID :需处理的特征值                  //return:           none         //author:           甜甜的大香瓜                 //email:            897503845@qq.com     //QQ group          香瓜BLE之CC2541(127442605)                  //changetime:       2016.08.18                     //****************************************************************************** static void simpleProfileChangeCB( uint8 paramID ){  uint8 newValue;  uint16 nDelay = 10000;  switch( paramID )  {    case SIMPLEPROFILE_CHAR1:      SimpleProfile_GetParameter( SIMPLEPROFILE_CHAR1, &newValue );      //指令为0x38时擦除ImageB的crc      if(newValue == 0x38)      {        //断开连接        GAPRole_TerminateConnection();                   //擦除ImageB的crc        uint16 crc[2] = { 0x0000, 0xFFFF };        uint16 addr = OAD_IMG_R_PAGE * ((uint16)(HAL_FLASH_PAGE_SIZE / HAL_FLASH_WORD_SIZE)) + OAD_IMG_CRC_OSET / HAL_FLASH_WORD_SIZE;                HalFlashWrite(addr, (uint8 *)crc, 1);                //点个灯表示擦除了            P1SEL &= ~(1 << 0);   //设置为IO口            P1DIR |= (1 << 0);    //设置为输出         P1_0 =  1;            //亮LED1                //延时,为了看到led        while(nDelay--);                //复位        HAL_SYSTEM_RESET();              }      break;    default: break;  }}

7、生成目标工程的ImageB的bin文件

1)新建配置

Project->Edit Configurations->New



2)修改IAR配置1



也就是分别输入如下路径、宏:

$PROJ_DIR$\..\..\Profiles\OAD

FEATURE_OAD_BIMHAL_IMAGE_BFEATURE_OADOAD_KEEP_NV_PAGESOAD_IMG_A_PAGE=1OAD_IMG_A_AREA=47OAD_IMG_B_PAGE=8OAD_IMG_B_AREA=(124 - OAD_IMG_A_AREA)

3)修改IAR配置2


也就是加入如下路径:

"$PROJ_DIR$\..\..\common\cc2540\cc254x_sim2bin.exe" "$PROJ_DIR$\GUA-CC2541-LargeOAD-ImgB\Exe\SimpleBLEPeripheral.sim" "$PROJ_DIR$\GUA-CC2541-LargeOAD-ImgB\Exe\SimpleBLEPeripheral.bin"

4)修改IAR配置3


选择前面拷贝到自己工程文件夹下的ImageB的xcl。


5)修改IAR配置4



此步骤为了生成sim文件,后续可以将sim文件转换成bin文件。


6)修改代码1

将此三个文件编译进工程中。
编译方法:IAR中的文件都可以选择“编译”或“不编译”。打叉的文件是不编译的,如果工程中需要编译它,可以点击该文件右键——Options——把Exclude formbuild的勾去除。


7)修改代码2(SimpleBLEPeripheral.c中)

#if defined FEATURE_OAD    VOID OADTarget_AddService();                    // OAD Profile  #endif  

添加OAD服务的代码(协议栈默认已有)。


8)修改代码3(SimpleBLEPeripheral.c中)

#if defined FEATURE_OAD    #include "oad.h"    #include "oad_target.h"  #endif  

添加OAD服务的头文件(协议栈默认已有)。


9)修改代码(buildConfig.cfg)

// OAD Image Version (0x0000-0x7FFF)  -DOAD_IMAGE_VERSION=0x0001  

修改ImageB的版本号为0x0001。


10)rebuild all,此时,在自己的工程中就已经生成了bin文件



七、注意事项

手机可能缓存了之前的代码(在更新过CC2541的代码之后,都需要清除手机端的缓存!!!),因此要清除缓存,清除缓存的方法如下:

方法一:关闭app、关闭蓝牙总开关、打开蓝牙总开关、打开app。
方法二:手机重启。


八、实验结果

1、app升级ImageB的bin文件

注:网上的BleSensorTag代码均有bug,此处使用的是香瓜团队修改bug后的BleSensorTag.apk,有需要的可至香瓜淘宝店里购买:

https://shop217632629.taobao.com/?spm=2013.1.1000126.d21.hd2o8i

1)安装BleSensorTag.apk



2)手机连接电脑,将上面编译好的SimpleBLEperipheral.bin放到手机的Download文件夹下



3)断开手机与电脑,用手机的BleSensorTag下载SimpleBLEperipheral.bin







等待4分钟,结束之后依次执行:

1)蓝牙设备重新上电。

2)app清除缓存(关闭蓝牙app、关闭蓝牙开关、打开蓝牙开关、打开蓝牙app),代码有任何变更都需要清除缓存,切记!!

此时就能看到设备名由simpleBLEperipheral变成GUA:01


至此,代码即更新成功。


9、第N次更新的步骤(N大于等于2)

1)切换设备代码至ImageA

通过蓝牙app向设备的char1通道写指令“0x38”。

设备会断开连接、从ImageB跳转至ImageA、点亮P10端口的LED、重启设备。

此时再查看其广播时,设备名称又变回simpleBLEperipheral,说明跳转回了ImageA。



2)修改设备端目标工程的ImgeB工程代码

①修改设备名(非必须,只是方便查看后续是否更新成功)(在simpleBLEperipheral.c中)

static uint8 scanRspData[] ={  0x07,     //自定义设备名的长度      GAP_ADTYPE_LOCAL_NAME_COMPLETE,      0x47,     //G      0x55,     //U      0x41,     //A      0x3A,     //:      0x30,     //0      0x32,     //2  // connection interval range  0x05,   // length of this data  GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE,  LO_UINT16( DEFAULT_DESIRED_MIN_CONN_INTERVAL ),   // 100ms  HI_UINT16( DEFAULT_DESIRED_MIN_CONN_INTERVAL ),  LO_UINT16( DEFAULT_DESIRED_MAX_CONN_INTERVAL ),   // 1s  HI_UINT16( DEFAULT_DESIRED_MAX_CONN_INTERVAL ),  // Tx power level  0x02,   // length of this data  GAP_ADTYPE_POWER_LEVEL,  0       // 0dBm};
由“GUA:01”改为“GUA:02”。


②修改设备代码版本号(buildConfig.cfg中)

// OAD Image Version (0x0000-0x7FFF)-DOAD_IMAGE_VERSION=0x0002

③rebuild all,编译生成新的simpleBLEperipheral.bin

3)重复上面第8点的步骤,进行下载bin文件。更新之后的设备名称如下:


到此,Large OAD的更新步骤就介绍完了。


PS:从昨天下午一直工作到现在3:31,算上早上的上班时间,我已经连续工作了大约18小时了,腰酸背痛的厉害,真担心会猝死。

两篇OAD的文章都是在凌晨写好的,OAD是需要一鼓作气地实验的,否则时间可能要花多一倍。

祝大家一次就成功吧,GOOD LUCK。





1 0