1.OAD概述
OAD是一种设备固件升级方法,允许使用蓝牙低功耗连接通过无线方式更新设备上运行的固件映像,同时提供断电保护。OAD分为片外OAD(off-chip OAD)和片内OAD(on-chip OAD),在CC2640R2F蓝牙5.0中,BLE5-Stack仅支持片外OAD。本文就是介绍如何在CC2640R2F蓝牙5.0的环境中实现片外OAD升级。要实现OAD需要两个支持BLE的设备,笔者选择的是两块CC2640R2F开发板,作为OAD目标设备和OAD下载设备。
OAD目标设备(OAD Target)即我们要更新的外围设备。OAD Target使用启动映像管理器也就是BIM工程来帮助固件升级,BIM在设备重置时执行,并确定是否应用固件更新。如果没有应用更新,则BIM就将程序执行转移到主应用程序映像。
OAD下载设备(OAD Downloader)提供可供OAD升级的固件更新映像,将需要升级的映像文件写入OAD Target。过程大体情况如下图所示
2.片外OAD介绍
片外OAD支持分离镜像片外OAD(Split Image Off-Chip OAD)和堆栈库片外OAD(Library Off-Chip OAD)。也就是片外OAD支持Stack和Stack_library图像类型。
2.1分离镜像片外OAD(Split Image Off-Chip OAD)
分离镜像片外OAD支持app、stack单独升级,如果开发人员想要以额外的传输时间为代价升级应用程序以及堆栈,则也可以生成App + Stack OAD Image,进行app+stack升级。
其中在SimpleLink CC2640R2 SDK中存在着一个分离镜像OAD的实例,叫做simple_peripheral_oad_offchip项目,具有App片外OAD的实现,被称为开箱即用。笔者使用的是simplelink_cc2640r2_sdk_1_40_00_45版本,该项目存放在C:\ti\simplelink_cc2640r2_sdk_1_40_00_45\examples\rtos\CC2640R2_LAUNCHXL\ble5stack。请注意BIM工程也是位于该地址。
下面我用开箱即用为例,介绍如何将OAD升级移植到自己的产品中去。
2.1.1开箱即用
实验环境:
协议栈版本:simplelink_cc2640r2_sdk_1_40_00_45
编译软件:IAR8.11 \CCS7.2.0
硬件平台:CC2640R2F LaunchPad
仿真器:XDS110
2.1.1.1用IAR来实现
要实现片外OAD,需要三个工程文件,BIM、APP、STACK。在C:\ti\simplelink_cc2640r2_sdk_1_40_00_45\examples\rtos\CC2640R2_LAUNCHXL\ble5stack路径下就可以找到三个工程,bim_oad_offchip(BIM工程),simple_peripheral_oad_offchip(其中包含了STACK和APP工程)。
对BIM工程进行处理
BIM要求在OAD升级中驻留在FLASH中,以便提供一个故障检测机制,用于确定时候运行现有的应用程序镜像还是从外部flash中拷贝新的镜像到内部flash中。当有新的镜像存在在外部FLASH中,BIM对镜像进行CRC校验,如果CRC校验通过,并且没有定义NO_COPY宏,BIM将新的镜像复制到内部flash中,如果定义了NO_COPY宏,BIM将不会加载任何新镜像。
打开bim_oad_offchip项目后开始修改BIM,请确定是否有将NO_COPY宏删除,如果没有请将该宏前面加上x。具体操作如下:点击project,选中Options,选择C/C++ Compiler,点击Preprocessor,在Defined symbols中找到NO_COPY,在前面加上x,变成xNO_COPY。接下来请在Application文件下找到startup_iar.c,在这个函数文件中找到void ResetISR(void)中的SetupTrimDevice()。请将SetupTrimDevice()屏蔽,如果没有屏蔽掉,调试下会出现问题,官方给定的工程下会有bug,将这一句屏蔽掉即可。
接下来修改外部flash引脚,找到Board文件下的bsp.h,这步可以根据自己需求来设置引脚
**//** Board external flash defines
#define BSP_IOID_FLASH_CS IOID_20
#define BSP_SPI_MOSI IOID_9
#define BSP_SPI_MISO IOID_8
#define BSP_SPI_CLK_FLASH IOID_10
请注意:修改后的引脚不要和其它引脚重复定义,如果有重复,比如若"BSP_IOID_LED_2"也被定义为IOID_20,请将"BSP_IOID_LED_2"定义为“PIN_UNASSIGNED”
接下来增加flash芯片型号的定义
在Middleware的ExtFlash文件下找到ext_flash.c,默认支持四种型号的Flash,如果自己的Flash型号不在这四种内,在文件中增加自己的flash定义,如下图所示
即在
{
.manfId = 0x0,
.devId = 0x0,
.deviceSize = 0x0
}
前增加
{
.manfId = 0xEF, //add our flash
.devId = 0x13,
.deviceSize = 0x100000 //1 MByte(8 Mbit)
}
其中manfId、devId、deviceSize的值要根据自己产品中使用的外部flash型号来定义。下面提供方法来查询自己的Flash型号。
打开相关手册的W25Q80芯片手册_EN,输入“Device ID”查询,在10.2.1 Manufacturer and Device Identification,如下图
可以看到自己的Flash的信息,W25Q80的manfld是0xEF,devId是0x13,也可以在CC2640R2的外设教程中看到自己的Flash型号和大小。
对APP工程进行处理
打开simple_peripheral_oad_offchip项目,选中cc2640r2lp_app-FlashROM_OAD_Offchip(APP工程),在Middleware的ExtFlash文件下找到ExtFlash.c,和在BIM工程中处理的一样,加入自己的Flash型号。接下来在Startup文件的board.c下找到CC2640R2_LAUNCHXL.c,将Flash对应的SPI的引脚定义为和BIM工程的bsp.h一样,如图
这里也请注意,不要将引脚重复定义,将重复的引脚定义为“PIN_UNASSIGNED”即可,如同BIM工程一样处理。
2.1.1.2用CCS来实现
同样需要三个工程文件,BIM、APP、STACK。将bim_oad_offchip(BIM工程)和simple_peripheral_oad_offchip(其中包含了STACK和APP工程)导入CCS中。
点击BIM工程,变为ble5_bim_oad_offchip_cc2640r2lp_app[Active-FlashOnly],右键点击Properties,选择ARM Compiler的Predefined Symbols,在右边的Pre-define NAME(–define,-D)加入xNO_COPY。接下来找到Application文件的startup_ccs.c,将Setup TrimDevice()屏蔽。在bsp.h文件中,修改外部flash引脚定义,在ext_flash.c文件中,加入Flash型号,和在IAR中配置的一样,这里就不在赘述。
点击APP工程,找到CC2640R2_LAUNCHXL.h和ExtFlash.c修改外部flash引脚定义和增加flash芯片型号定义,和上面用IAR实现的步骤一样。
2.1.1.3将工程烧录进开发板
运行Setup_SmartRF_Flash_Programmer_2.exe,安装SmartRF Flash Programmer 2。将开发板插入PC端,打开SmartRF Flash Programmer 2,右边的Connected devices显示当前连接的开发板,右键连接,这个开发板是作为OAD Target设备。将BIM、stack、app工程编译生成三个hex文件,点击Multiple,将三个hex文件烧录进OAD Target设备
2.1.1.4用BLE Device Monitor和BTOOL来帮助片外OAD升级
网上有的人说BLE Device Monitor可以实现OAD升级,但笔者自己试了几次,发现CC2640R2F蓝牙5.0的升级存在问题,因此建议大家用官方自带的BTOOL。
BTOOL是一个用于蓝牙设备调试的PC软件工具,可以在C:\ti\simplelink_cc2640r2_sdk_1_40_00_45\tools\ble5stack\btool路径下找到它,打开即可。现在就需要用到OAD Downloader设备,该设备必须要烧写运行主机测试示例应用程序cc2640r2lp_host_test.hex,这个文件可以在C:\ti\simplelink_cc2640r2_sdk_1_40_00_45\examples\rtos\CC2640R2_LAUNCHXL\ble5stack\hexfiles下找到,利用SmartRF Flash Programmer烧写进OAD Downloader设备即可。将OAD Downloader设备插入PC端,这样打开BTOOL后就可以接收广播到的设备信息。端口等信息按下图设置即可。
下面点击Scan按键,搜索现在正在广播的设备,选中OAD Target设备的地址,点击Establish,界面右边就会显示连接的OAD Target设备地址,这样就说明已经连接上了。有关步骤可参见下图。
如若不知道自己的OAD Target设备地址,可以通过SmartRF Flash Programmer 2进行检查,打开它,连接设备,在界面上方选择MAC Address,在Primary address中“read”BLE MAC address,就可以显示自己的设备地址。
选择BTOOL中的OAD选项并启动OAD过程。
在这个过程中,为了验证OAD是否成功 ,可以通过更改蓝牙设备的名称来确定。可以在APP工程中的simple_peripheral.c找到,如下图所示。
可以更改图中蓝色字符来改变蓝牙设备广播名称,注意,如若删除增加字符,请相应的将长度也改变。将生成的bin文件放入BTOOL中,发送。
OAD的流程继续如下
当显示如下则说明OAD升级已然成功。
当然,这里只是BTOOL说明OAD升级成功了,自己还要进行验证。将OAD Target设备从PC端拔下(如若单单按下重启按键会出现HIB现象,所以笔者建议拔电重启),拔电重启后打开BLE Device Monitor,搜索正在广播的设备,可以发现搜索到的蓝牙设备中有自己命名的OAD Target就说明OAD真正成功了。
2.2堆栈库片外OAD(Library Off-Chip OAD)
支持APP+STACK的升级,由于蓝牙5项目大部分都是堆栈库项目,下面来介绍如何在现有项目里加入OAD功能。
以下所有的更改都是基于APP工程,对STACK工程不需要更改。
1.bim_oad_offchip工程按原样使用项目,不需要更改。
2.将OAD配置文件代码添加到应用程序项目:
可以在C:\ti\simplelink_cc2640r2_sdk_1_40_00_45\source\ti\ble5stack\profiles\oad\cc26xx找到所需文件。
oad.c
oad.h
oad_target.h
oad_target_external_flash.c
方法如下,下同。
3.将外部flash中间件添加到应用程序项目
可以在C:\ti\simplelink_cc2640r2_sdk_1_40_00_45\source\ti\mw\extflash找到。
ExtFlash.c
ExtFlash.h
4.为项目添加必要的包含路径:
点击"Options",选择C/C++Compiler,在Preprocessor中的Additional include directories,增加C:\ti\simplelink_cc2640r2_sdk_1_40_00_45\source\ti\ble5stack\profiles\oad\cc26xx路径。
5.使用适当的片外OAD链接器文件并正确配置它。
IAR项目应该使用:
cc26xx_app_oad.icf
CCS项目应使用:
cc26xx_app_oad.cmd
在IAR的项目中修改cc26xx_app_and_stack.icf
5.1.定义应用程序和堆栈代码和数据的位置
将//Code and RO Data
place in FLASH_ALL {readonly};
改为
place in FLASH {readonly};
5.2.接下来重新定义FLASH,使得它从未定义的符号OAD_FLASH_START到FLASH_END,OAD_FLASH_START表示应用程序/堆栈代码可以开始的位置。
define region FLASH = men:[from OAD_FLASH_START to FLASH_END];
5.3.定义OAD元数据的符号:
//OAD specific
define symbol OAD_HDR_SIZE = 16;//size of metadata vector
define symbol OAD_HDR_START = FLASH_START;
define symbol OAD_HDR_END = OAD_HDR_START+OAD_HDR_SIZE-1
5.4.定义OAD_FLASH_START,计算元数据向量以及中断表:
define symbol OAD_FLASH_START = INT_VEC_START + INT_VEC_SIZE;
注意:要完全定义OAD_FLASH_START需要考虑中断向量表,请接下一步。
5.5.需要放置中断向量表,以使应用程序正常运行。通常,表格会在闪存开始时开始; 但是,由于元数据向量,需要移动表。
首先定义符号来表示表:
define symbol INT_VEC_SIZE = 64;
define symbol INT_VEC_START = OAD_HDR_START + OAD_HDR_SIZE;
define symbol INT_VEC_END = INT_VEC_START + INT_VEC_SIZE - 1;
最后,对于内存放置,需要添加以下内容,以便.intvec正确放置该部分:
// Interrupt Vector Table
place at start of INT_VEC { readonly section .intvec };
keep { readonly section .intvec };
注意:添加后删除原有的代码
5.6.删除以下行
// CCFG
place at end of FLASH_LAST_PAGE { readonly section .ccfg };
keep { section .ccfg };
6.在应用程序中添加预处理器定义:
FEATURE_OAD
HAL_IMAGE_E
7.在pre-build中添加OAD_IMAGE_E
您可能需要更改OAD_IMG_E=1为OAD_IMG_A=1或OAD_IMG_B=1根据您的使用的版本情况
8.更改外部FLASH的引脚分配情况,这个根据自己情况设定,因为在分离镜像中已经叙述,这里不再重复。
9.更新OAD图像工具构建步骤,生成带有校验的bin文件
在Post-build command line中更改为cmd /C "$TOOLS_BLE_DIR$\output_converter\output_converter.exe $EXE_DIR$\$TARGET_BNAME$.bin -a 0x10 & $TOOLS_BLE_DIR$\oad\oad_image_tool.exe $EXE_DIR$\$TARGET_BNAME$.hex -t offchip -i app --imgVer 0 -ob $EXE_DIR$\$TARGET_BNAME$.bin -m 0x0000 --r 0x0000"
经过上述步骤就完成了在现有项目中加入OAD的功能,编译后将hex和BIM的hex文件一起烧录进OAD Target设备。接下来进行OAD升级,方法和开箱即用的相同,这里不再叙述。
参考文档:file:///C:/ti/simplelink_cc2640r2_sdk_1_40_00_45/docs/ble5stack/ble_user_guide/html/oad/oad_offchip.html