【BLE】CC2541之Large OAD

本篇博文最后修改时间:2017年05月19日,03:33。


一、简介

本篇以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_BIM
HAL_IMAGE_B
FEATURE_OAD
OAD_KEEP_NV_PAGES
OAD_IMG_A_PAGE=1
OAD_IMG_A_AREA=47
OAD_IMG_B_PAGE=8
OAD_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。

注意这里是相对路径,每次移动文件夹、或者拿到别人的OAD工程时,需要重新选择一次!!!


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文件



七、注意事项

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

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

2、如果移动了工程,或者拿到别人的OAD工程,需重新选择xcl路径。(上方的“六——7——4)”步骤)

3、1.4.2协议栈版本比较特殊,须做以下操作

1)BIM和ImageA工程,使用协议栈1.4.0下载进板子。

2)B在1.4.2协议栈版本中生成。

3)当报错“Error[e16]: Segment ISTACK (size: 0xc0 align: 0) is too long for segment definition. ……”时,看字面意思是ISTACK段设置太长了,因此香瓜将iar设置中“General Options——Stack/Heap”的IDATA段从“0xC0”改成“0xB0”,即可编译通过。如果不这么做,会导致升级后连接不上!


八、实验结果

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。





评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值