CC2540 Large OAD实现程序无线升级

 

    CC254x代码量小于128K的可以使用ImageA和ImageB互切的方案,这个是TI比较标准的方案,但是有两个缺点:一是代码量限制的太小了,仅例程编译下来都要110K了,给用户可以扩展的空间太小;二是两个Image要分成不同的版本,每次升级要关注版本号,比较麻烦,也不符合常规升级习惯。


    对此TI又给出了CC2541的Large OAD方案,它把ImageA变成了只有BLE通讯的最小系统,用于无线对接升级ImageB,ImageA编译后只有96K,因此给用户留下150K的程序空间,这对于一般应用来讲还是差不多了,无线对接后每次只升级ImageB也就是用户程序,需要升级时在ImageB应用中写一个升级密码就会跳到ImageA中重新启动升级,这个比较符合常规升级习惯。


    这两种方案不是本文要讲内容,可以百度一下,按照例程一步步来就可以实现了。
    本文要讲的是,然而TI比较坑的在于,只给了CC2541的Large OAD例程(http://processors.wiki.ti.com/index.php/BLE_Large_Image_OAD
    但是没有CC2540的例程,所以要实现CC2540必须自己改例程。而因为CC2540的协议栈编译出来比CC2541要大几个KB导致程序放不下,所以如果直接把协议栈换掉,link的时候会出现以下错误:


Error[e104]: Failed to fit all segments into specified ranges. Problem discovered in segment BANKED_CODE. Unable to place 61 block(s)
(0x14ba9 byte(s) total) in 0x14638 byte(s) of memory. The problem occurred while processing the segment placement command
"-P(CODE)BANKED_CODE=_CODE_BEG-_CODE_END,_BANK5_BEG-_BANK5_END,_BANK6_BEG-_BANK6_END,_BANK7_BEG-_BANK7_END", where at the moment of
placement the available memory ranges were "CODE:2a24-3fff,CODE:5b7a4-5ffff,CODE:68000-6ffff,CODE:78000-7e7ff"
Error while running Linker


所以必须对代码进行裁剪。接下来详述怎样裁剪例程代码以实现CC2540的ImagA。


一、前提是CC2541的Large OAD已经实现并可以跑起来了,请参考香瓜的
http://blog.csdn.net/feilusia/article/details/52236140


二、接下来要Project->edit configurations,基于CC2541_OAD_ImgA新建一个CC2540_OAD_ImgA


三、工程上点右键,找到option打开工程选项,在C/C++ Complier标签的Preprocessor选项卡下的Defined symbols:下添加以下一行:
LIMIT_2540


在Extra options选项卡下修改配置文件名:
-f $PROJ_DIR$\buildConfig_2540.cfg


四、在工程的Lib组下右键Add上CC2540的协议栈,要注意的是这里要选用1.4.1协议栈,1.4.2的可能会出问题。然后在原来CC2541协议栈上点右键,勾选上从工程中排除的勾。


五、在电脑的工程所在目录中复制一下build_config.cfg文件,重命名为buildConfig_2540.cfg,打开将里面的-DCC2540改为-DCC2540


然后在IAR的工程下面TOOLS组中添加该文件,并将原文件右键从当前工程中排除。



六、修改代码,注意修改本工程内的文件,也就是APP组下的文件,不要修改库中涉及的其他文件:

1. SimpleBLEPeripheral_Main.c 文件


第一处:
#if !(defined LIMIT_2540) //尽量压缩2540代码
// Initialize board I/O
InitBoard( OB_COLD );
#endif
说明:增加宏编译语句#if !(defined LIMIT_2540),裁剪掉InitBoard( OB_COLD );语句。可以搜索该语句然后添加宏编译语句。后面裁剪手段与此相同,不再解释。


第二处:
#if !(defined LIMIT_2540) //尽量压缩2540代码
// Final board initialization
InitBoard( OB_READY );
#endif


2. peripheral_small.c 文件


第一处:
#if !(defined LIMIT_2540) //尽量压缩2540代码
static void gapRole_HandleParamUpdateNoSuccess( void );
#endif
第二处:


#if !(defined LIMIT_2540) //尽量压缩2540代码
case GAPROLE_IRK:
if ( len == KEYLEN )
{
......
break;
case GAPROLE_SRK:
if ( len == KEYLEN )
{
......
break;
case GAPROLE_SIGNCOUNTER:
......
break;
#endif
第三处:


#if !(defined LIMIT_2540) //尽量压缩2540代码
case GAPROLE_ADV_EVENT_TYPE:
......
case GAPROLE_ADV_DIRECT_TYPE:
......
case GAPROLE_ADV_DIRECT_ADDR:
if ( len == B_ADDR_LEN )
{
......
break;
case GAPROLE_ADV_CHANNEL_MAP:
if ( (len == sizeof ( uint8 )) && (*((uint8*)pValue) <= 0x07) )
{
......
break;
case GAPROLE_ADV_FILTER_POLICY:
if ( (len == sizeof ( uint8 )) && (*((uint8*)pValue) <= GAP_FILTER_POLICY_WHITE) )
......
break;
case GAPROLE_RSSI_READ_RATE:
......
break;
#endif


第四处:
#if !(defined LIMIT_2540) //尽量压缩2540代码
case GAPROLE_PARAM_UPDATE_REQ:
{
uint8 req = *((uint8*)pValue);
if ( len == sizeof ( uint8 ) && (req == TRUE) )
{
......
break;
#endif 

 
第五处:
if ( events & RSSI_READ_EVT )
{
#if !(defined LIMIT_2540) //尽量压缩2540代码
// Only get RSSI when in a connection
if ( gapRole_state == GAPROLE_CONNECTED )
{
// Ask for RSSI
VOID HCI_ReadRssiCmd( gapRole_ConnectionHandle );

// Setup next event
if ( gapRole_RSSIReadRate )
{
VOID osal_start_timerEx( gapRole_TaskID, RSSI_READ_EVT, gapRole_RSSIReadRate );
}
}
#endif


第六处:
if ( events & CONN_PARAM_TIMEOUT_EVT )
{
#if !(defined LIMIT_2540) //尽量压缩2540代码
// Unsuccessful in updating connection parameters
gapRole_HandleParamUpdateNoSuccess();
#endif


第七处:
#if !(defined LIMIT_2540) //尽量压缩2540代码
static void gapRole_HandleParamUpdateNoSuccess( void )
{
......
}
#endif


3. simpleBLEPeripheral.c 文件


第一处:
#if !(defined LIMIT_2540) //尽量压缩2540代码
static uint8 simpleBLEPeripheral_TaskID; // Task ID for internal task/event processing
#endif


第二处:
#if !(defined LIMIT_2540) //尽量压缩2540代码
static void simpleBLEPeripheral_ProcessOSALMsg( osal_event_hdr_t *pMsg );
static void performPeriodicTask( void );
#endif


第三处:
#if !(defined LIMIT_2540) //尽量压缩2540代码
simpleBLEPeripheral_TaskID = task_id;
#endif


第四处:
将原程序启动OSAL的代码修改成以下内容:
#if !(defined LIMIT_2540) //尽量压缩2540代码
// Setup a delayed profile startup
osal_set_event( simpleBLEPeripheral_TaskID, SBP_START_DEVICE_EVT );
#else //直接启动
// Start the Device
VOID GAPRole_StartDevice( &simpleBLEPeripheral_PeripheralCBs );
#endif


第五处:
注释掉函数内容:
uint16 SimpleBLEPeripheral_ProcessEvent( uint8 task_id, uint16 events )
{
#if !(defined LIMIT_2540) //尽量压缩2540代码
VOID task_id; // OSAL required parameter that isn't used in this function
......
#endif //LIMIT_2540
// Discard unknown events
return 0;
}


第六处:
#if !(defined LIMIT_2540) //尽量压缩2540代码
static void simpleBLEPeripheral_ProcessOSALMsg( osal_event_hdr_t *pMsg )
{
......
}
#endif


第七处:
static void peripheralStateNotificationCB( gaprole_States_t newState )
{
#if !(defined LIMIT_2540) //尽量压缩2540代码
switch ( newState )
{
......
}
}
#endif
gapProfileState = newState;
......


第八处:
#if !(defined LIMIT_2540) //尽量压缩2540代码
static void performPeriodicTask( void )
{
......
}
#endif

七、修改完成后编译代码,即可生成裁剪版的CC2540的ImagA程序,大小:


 95 963 bytes of CODE memory (+ 293 range fill )
50 bytes of DATA memory (+ 75 absolute )
5 590 bytes of XDATA memory
178 bytes of IDATA memory
8 bits of BIT memory
4 000 bytes of CONST memory
Errors: none
Warnings: none


八、对应的Large B文件也按前面步骤一至五完成即可,不需要第六步添加裁剪的代码。使用BLE Device Monitor即可完成升级(on-chip OAD)。

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值