首页 资讯 应用 高压 设计 行业 低压 电路图 关于

嵌入式

旗下栏目: PLC 嵌入式 单片机 DCS

BLE空中升级—BIM工程代码分析

嵌入式 | 发布时间:2017-11-26 | 人气: | #评论# |本文关键字:BLE,BIM工程
摘要:凡是涉及到升级功能的,都一定会有一段BootLoader代码!BLE的空中升级自然也不例外,它的BootLoader工程为BLE-CC254x-1.3.2\ble\util\BIM目录下的BIM(ImageBootManager)工程。BIM工程管理着两段代码空间,分别

凡是涉及到升级功能的,都一定会有一段BootLoader代码!BLE的空中升级自然也不例外,它的BootLoader工程为BLE-CC254x-1.3.2\ble\util\BIM目录下的BIM(Image Boot Manager)工程。BIM工程管理着两段代码空间,分别是ImageA与ImageB的这两段固件运行空间,它默认会先运行ImageB的代码,如发现ImageB不存在或无效,再去运行ImageA的代码,如发现ImageA不存在或无效,则让系统进入睡眠状态。下面就来分析下BIM的工程代码。

1、固件文件相关定义

(1)ImageA在flash空间的布局

  a.ImageA的起始位置为flash的page1。

#define BIM_IMG_A_PAGE 1

  b.分配给ImageA的空间大小为62个页。

#define BIM_IMG_A_AREA 62

(2)ImageB在flash空间的布局

  a.ImageB的起始位置为flash的page8。

#define BIM_IMG_B_PAGE 8

  b.分配给ImageB的空间大小为62个页。

#define BIM_IMG_B_AREA (124 - BIM_IMG_A_AREA)

(3)CRC及固件信息首部在页中的偏移

  a.CRC在页中的偏移

#define BIM_CRC_OSET 0x00

  b.固件首部在页中的偏移

#define BIM_HDR_OSET 0x00

2.固件信息首部结构定义

typedef struct {

  uint16 crc0;       /*CRC must not be 0x0000 or 0xFFFF*/

  uint16 crc1;       /*CRC-shadow must be 0xFFFF.*/

  uint16 ver;          /*User-defined Image Version Number*/

  uint16 len;          /*Image length in 4-byte blocks*/ 

  uint8  uid[4];       /*User-defined Image Identification bytes.*/

  uint8  res[4];     /*Reserved space for future use.*、

} img_hdr_t;

其中crc0实际上不属于固件信息的首部,但是由于它的位置紧挨着固件首部的crc1,为了代码方便,这才将它包含进来。crc0是独立存在的,由编译器编译时计算得到的。在编译固件ImageA与ImageB工程时,在对应的链接文件cc254x_f256_imgA.xcl与cc254x_f256_imgB.xcl的最后分别有一句:-J2,crc=8005,0804-_BANK7_END和-J2,crc=8005,4004-_BANK4_END,这两句表示在编译这两个固件工程时计算固件的CRC16值,这里的crc0就是用于保存编译器计算得到的crc值。

crc1才是真正属于固件信息首部的crc成员,它是在代码中计算的,通过比较由代码中计算得到的crc1与由编译器得到的crc0,就可以判断当前固件是否有效。

ver用于保存当前固件的版本,在空中升级时,就是判断ver来决定是否要升级。

len用于保存固件的大小,需要注意的是,它以字HAL_FLASH_WORD_SIZE为单位。

uid[4]用来标志固件身份,如对于ImageA,用uid[4]={’A’,’A’,’A’,’A’}来标志ImageA的身份;对于ImageB来说,用uid[4]={’B’,’B’,’B’,’B’}来标志ImageB的身份。

res[4]保留给以后拓展用。

3、定义缓冲数组pgbuf,可以用于缓冲一个页的数据

__no_init uint8 pgBuf[HAL_FLASH_PAGE_SIZE];

4、定义用于保存当前运行固件种类的变量

__no_init __data uint8 JumpToImageAorB @ 0x09;

当JumpToImageAorB = 0时,表示当前正运行ImageA代码。

当JumpToImageAorB = 1时,表示当前正运行ImageB代码。

注意:__no_init __data表示不让编译器布局这个变量位置;而@ 0x09则指定这个变量放到IDATA的0x09地址处。

 halSleepExec()  让系统进入睡眠

在这函数之前,有句#pragma optimize=none表示不对这个函数进行优化。要进入睡眠很简单,只要设置电源的供电模式寄存器PCON强让设备进入睡眠模式。

PCON = 0x01;

 crcCalc() 计算crc值

参数:

page-要计算的起始页

1、读取起始页的数据,因为这个页包含固件信息的首部。

HalFlashRead(page, 0, pgBuf, HAL_FLASH_PAGE_SIZE);

2、读取固件信息首部

const img_hdr_t *pImgHdr = (const img_hdr_t *)(pgBuf + BIM_HDR_OSET);

3、获取固件的结束位置

(1)如果是ImageB

uint8 pageBeg = page;

uint8 pageEnd = pImgHdr->len / (HAL_FLASH_PAGE_SIZE / HAL_FLASH_WORD_SIZE); /*固件所占的页个数*/

uint16 osetEnd = (pImgHdr->len - (pageEnd * (HAL_FLASH_PAGE_SIZE / HAL_FLASH_WORD_SIZE)))*HAL_FLASH_WORD_SIZE;/*结束位置在最后一页的偏移*/

pageEnd += pageBeg;/*结束位置所在页*/

(2)如果是ImageA,则还需要跳过ImageB的区域。

if (pageBeg == BIM_IMG_A_PAGE)

{

  pageEnd += BIM_IMG_B_AREA;

}

4、配置随机数发生器为计算CRC用

ADCCON1 &= 0xF3; /*随机数发生器配置成16为的线性反馈以为计寄存器(LFSR)*/

RNDL = 0x00;

RNDL = 0x00;/*通过连续两次写入RNDL寄存器来产生CRC需要的种子数*/

5、开始计算固件的 CRC值。

(1)读取每个页的值,写入RNDH开始计算

for (uint16 oset = 0; oset < HAL_FLASH_PAGE_SIZE; oset++)

{

...

RNDH = pgBuf[oset];

}

HalFlashRead(page, 0, pgBuf, HAL_FLASH_PAGE_SIZE);

(2)开始计算时,跳过固件首部与CRC相关的4个字节(上面的crc0与crc1)

if ((page == pageBeg) && (oset == BIM_CRC_OSET))

{

  oset += 3;  // Skip the CRC and shadow.

}

(3)如果到了结束为止在,则计算出最后的CRC16的值

else if ((page == pageEnd) && (oset == osetEnd))

{

  uint16 crc = RNDH;

  crc = (crc << 8) | RNDL;

  return crc;

}

责任编辑:BLE工程
首页 | 资讯 | 应用 | 高压 | 设计 | 行业 | 低压 | 电路图 | 关于

Copyright 2017-2018 电气自动化网 版权所有 辽ICP备17010593号-1

电脑版 | 移动版

Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。