OAD基础知识详解(For CC2640)
一、 概念
1. 缩写
- BIM
Boot Image Manager , the software bootloader - CRC
cyclic redundancy check
Client Characteristic Configuration Descriptor - SNV
Simple Non-Volatile storage - CCFG
Customer Configuration Area, contains lock-bits on flash page 31
2. OAD类型
1) On-chip
- Image存放在内部Flash中,是单芯片OAD解决方案
2) Off-chip
- Image存放在外部Flash中,是双芯片OAD解决方案
3. OAD元数据
1) CRC和CRC影子
CRC,即循环冗余校验,是一种检查image文件的方式,用以确保image文件完好无损。检查过程分作两步:首先,当映像文件从工具链生成的时候,必须计算CRC并将其存储在元数据向量区的CRC字段,这份初始的CRC将会通过OAD服务被发送出去;然后,目标机需要确认映像在传输的过程中没有发生错误,所以目标机会重新计算下载映像的CRC并将其存储在元数据向量区的CRC影子字段。
如果CRC和CRC影子的内容相同,目标机会认为映像在空中传输过程中没有损坏。
CRC计算使用的算法叫做CRC-16-CCITT,这是一种至少能够排查出99.9984%错误的16位CRC计算方法。
2) Version
image version字段用来追踪映像的版本并确保升级的兼容性,用户可以实现它们自己的版本管理方案。至于具体的版本检查是如何实现的,请参考Off-chip和On-chip的具体实例。
3) Length
Length字段用来描述image的长度,单位是words,关于word的具体长度,在On-chip中是EFL_OAD_ADDR_RESOLUTION,在Off-chip中是HAL_FLASH_WORD_SIZE.
使用不同外部Flash的OAD用户可能需要调整EFL_OAD_ADDR_RESOLUTION的长度来来匹配他们的器件,对于On-chip用户,CC2640的word是固定长度的。
4) UID
TI OAD配置没有用到该字段,但是如果用户想要添加他们自己的基于UID的映像验证的实现,这是很好的引子。
对于On-chip OAD,惯例是Image A嵌入‘A’, ‘A’, ‘A’, ‘A’,Image B嵌入‘B’,‘B’, ‘B’, ‘B’,Off-chip默认嵌入‘E’, ‘E’, ‘E’, ‘E’。
5) Start Address
Start Address是image在内部Flash中存储的首地址,和length字段相似,该字段用words计量。Off-chip的解决方案是根据映像的类型在start address处放置限制条件。
注意:对于On-chip的解决方案,该字段在元数据区被保留,因为它使用一种基于the internal flash memory map (OAD_IMG_D_PAGE)的混合起始地址。
6) Image Type
在带有外部Flash的Off-chip OAD系统中,有多种类型的image可以被上传,这些映像类型包括:App + Stack, App only, Network Processor, or Stack only.
注意:当使用Stack only设置时,用户必须确保在已有的image和上传的image之间App/Stack边界没有发生改变。因为在APP/Stack边界之间没有实时检查,如果Stack边界增长,就会覆盖已有的APP内容。在使用这项设置时用户尤其要注意。
如果需要改变边界(比如Stack增长或缩小),用户最好将App+Stack合并上传以确保image可以运行。
注意:对于On-chip的解决方案,该字段在元数据区被保留,因为它基于上面提到的image version字段的最小有效位(the least significant bit)来确定Image Type。
支持的映像类型如下:
7) Image State
Image state是只能在Off-chip解决方案中使用的一比特元数据区字段。该状态告诉BootLoader映像是否准备好运行或正在运行中。这避免了在每次引导程序启动时BootLoader会从外部Flash拷贝相同的image到内部Flash。
注意:对于On-chip的解决方案,该字段在元数据区被保留,因为the OAD reset service handles switching between images in the bootloader.
4. OAD特征值
1) Image Identify
映像识别特征值用来在下载器和目标机之间交换映像元数据。当下载器发送OAD映像的16比特元数据到目标机时,OAD过程开始。收到元数据之后,目标机会做一些计算来决定是否下载该映像。向该特征值的客户端特性配置描述符写“01:00”,拒绝元数据的通知将会启动。
注意:在On-chip和Off-chip两种方式之间,OAD是否被接收的条件是相似的,关于映像拒收条件的更多信息请参考各自相关部分。
如果目标机接收映像,它会通过向image Block特征值发送一个通知来请求第一块存储区的方式继续OAD传输。另外,目标机会通过发回部分现有映像元数据的方式来拒收映像。拒收元数据信息包括映像版本、长度和用户ID字段,关于这些字段的更多信息请参考元数据部分。
2) Image Block
映像区块特征值用来请求和传输OAD映像区块,向该特征值的客户端特性配置描述符写“01:00”,区块请求的通知将会启动。目标机通过向下载器发送一个带有区块请求序号的GATT通知来请求下一个映像区块,下载器会根据区块序号和16比特的OAD映像区块来发出响应信号。映像区块包含从OAD映像偏移区块序号个的真实的二进制数据。
3) Image Count
映像计数特征值用来设置将被下载的OAD映像的数量,这只在Off-chip方式中被用到,默认值是1。注意:On-chip方式在每次会话时只支持单次映像下载。
4) Image Status
映像状态特征值被用来标志OAD过程中可能发生的各种各样的错误,下载器可以利用这些信息判断出OAD失败的原因,然后纠正错误再次尝试。向该特征值的客户端特性配置描述符写“01:00”,状态更新的通知将会启动。默认情况下,定义了四种不同的状态信息,如果需要用户可以添加这些信息,并使用OAD_sendStatus()函数向下载器发送状态更新。
5. OAD过程
1) OAD过程的初始化
在建立新的连接之后,为了更快的进行OAD传输需要更新连接间隔,同时在OAD目标机上建立OAD映像识别和OAD映像区块特征值的通知服务,下载器将会向位于OAD目标机上的映像识别特征值写信息。这条信息就是将要下载的OAD映像信息的起始部分。
在收到向映像识别特征值写请求的前提下,OAD目标机会比较即将下载的OAD映像和已有的OAD映像。默认情况下,只有映像大小和标识映像类型(A/B)的版本号被检查后,才能决定新的映像是否被接收下载。
如果OAD目标机决定接收OAD映像,目标机会通过向下载器通知映像区块传输特征值来请求第一块新映像的方式对OAD过程进行初始化。相反,如果目标机发现新的映像不符合启动OAD过程的条件,它会通过使用它已有的映像头部数据作为拒收信号通知映像识别特征值的方式来响应。在这种情况下,OAD过程会在图11中画大X的地方停止。
2) 映像区块传输
映像区块传输特征值允许两个器件对OAD映像进行请求和回应,一次一个区块。映像区块大小被定义为16比特——see OAD_BLOCK_SIZE in oad.h. OAD目标机会通过使用相应的区块信号通知OAD映像区块特征值的方式向下载器请求映像区块,下载器会通过向OAD映像区块特征值写信息的方式对此作出回应,信息的内容是随后的相应16比特映像区块的被请求的区块序号。不过什么时候,只要OAD目标机准备好了接收OAD映像的另一个区块,它就会使用想要的映像区块序号来通知映像区块传输特征值,下载器随后就会响应。
3) OAD过程的完成
在OAD目标机接收完最后一个映像区块之后,会通过计算存储在OAD映像中的CRC来验证映像是否被正确接收和存储。OAD目标机接下来就会废除已有的映像然后重启,BIM引导程序会启动新的映像。接下来的重点在下载器上,它在验证和安装过程中会先失去跟OAD目标机的连接,然后重新开始扫描,重新建立连接,并验证新的映像是否正确运行。
二、 Off-chip OAD
1. Off-chip OAD的限制和要求
使用CC2640F128内部Flash的第一页和最后一页,或者说总共用了8KB,这部分是为了中断向量和BIM程序专门保留的。该Flash的第31页,或者说最后一页(起始地址0x1F000)是BIM程序和CCFG共享的。不管是第一页还是BIM程序都不是为Off-chip OAD上传而专门设计的。
如果要进行整个Flash区域的升级,需要一个至少拥有120KB以上空间的外部Flash器件来存储一个16比特的映像元数据区块。
被下载到外部Flash存储区的OAD映像可以是一个应用层映像、一个协议栈映像、一个应用层和协议栈混合的hex映像、一个为NP升级设计的映像或者任何其他类型的映像,只要该映像支持替换掉片上Flash 120KB区域(位于第一页和最后一页之间)的功能即可。在系统启动紧接着执行BIM引导程序把已经下载的映像从外部Flash存储区拷贝到内部Flash存储区之前,可以下载不止一份映像。
因为在外部Flash上第0页不能被更新,所以应用程序必须在Flash中包含他自己的TI-RTOS实例,而不是依赖于TI-RTOS存储在ROM中的实现(更多信息请参考10.3)。另外,应用程序还必须包含OAD配置,这是为了下一次在内部Flash上运行时的OAD升级做准备,因为外部Flash不需要任何类似于内部Flash上Image A的OAD应用程序。
任何时候都不要尝试对Flash的第一页和最后一页进行更新,因为对其中任何一页的更新操作都会使器件崩溃,除非对其进行重新编程(physically reprogrammed)。
On-chip OAD目标机只能接收一份应用层OAD映像,但是Off-chip OAD目标机可以接收多达3份OAD映像。通常情况下,下载器都会生成适合Off-chip OAD的映像元数据,但是Python脚本也能够嵌入元数据到映像中(详情见10.2),该元数据在传输时被嵌入到Off-chip OAD映像的开头处,在存储时被单独存储在外部Flash中。
2. OAD目标机
1) Off-chip OAD目标机的存储详情
Off-chip OAD目标机同时拥有内部Flash和外部Flash存储器件,内部Flash包含中断向量表、BLE协议栈、嵌入OAD配置的应用层程序、BLE协议栈映像、NV存储区、BIM引导程序和CCFG(用户配置区域)。
外部Flash包含高达3个OAD映像和相应的3个元数据区,每个OAD映像占用128KB的Flash空间,Off-chip OAD目标机的存储区域划分如上图所示。每一个OAD映像,如果既不是APP only也不是APP+Stack,就必须支持OAD Profile,这是为了以后的OAD升级做准备。
3. Off-chip OAD的BIM
OAD解决方案需要一个永久驻留的引导程序,BIM(Boot Image Manager)的存在提供了一个故障安全的机制,它可以决定是运行已有的映像程序还是从外部Flash拷贝一个新的映像文件/文件包到内部Flash。假设一个有效的存储在外部Flash上的映像文件准备好了被拷贝或者在任何给定的时间可以被转移到内部Flash上,基于该假设,内部Flash中初始的image文件在外部Flash中并不存在,所以它拥有无效的外部映像元数据,所以Boot-Loader会选择跳到已有映像的入口点。
一开始,BIM会检查外部Flash上的APP映像元数据的status字段来决定是否将image拷贝到内部Flash上。如果status = 0xFF,在发现有效CRC和CRC影子的情况下会拷贝映像;如果status != 0xFF,我们认为内部Flash上的应用程序正在运行中。如果发现一个两比特的值既不是0x0000也不是0xFFFF,而是0xFFFF的影子校验和,BIM会计算该映像的CRC,映像长度由元数据决定,也被存储在内部Flash紧邻CRC的区域,这些都在第一次从外部Flash写入映像时被拷贝过来了。
如果外部Flash中有一个坏掉的映像文件即将被上传,BIM程序就会被添加NO_COPY 标志来跳过映像检查,直接跳到已经被放到内部Flash上的image,内部image可以是坏掉映像的元数据无效,或者重新OAD一个新的映像文件放在坏掉映像的位置上。BIM不能够下载任何新的映像,除非在build的时候没有定义NO_COPY。
BIM只在启动时对APP映像的故障安全负责,这里的APP指的是APP only或者是APP+STACK,BIM只针对APP映像有一个入口。
BIM和CCFG共享Flash的最后一页,并且使用位于Flash第一页的中断向量表,该表有一个复位中断向量负责BIM程序的启动,以确保在启动之后BIM对系统的控制权。