OAD是TI在BLE协议栈基础上扩展的一种无线更新技术。OAD使用客户端-服务器的机制工作。需要固件更新的目标芯片叫做OAD Target/Client,用来管理OAD功能的一端叫做OAD Manager/Server。
配置OAD的目标设备,如果需要更新软件的话,不用连接仿真器,通过BLE无线就可以更新软件,方便用户升级。
有些人会觉得OAD很复杂,其实并不复杂,本质就是OAD Manager/Server端将需要升级的bin文件字节流取出来,然后按照特定的长度(因为BLE每个包的长度是受限的)通过write方法,将数据通过带有写权限的特征值发送给OAD Target/Client端,然后OAD Target/Client 端将收到的数据写到特定的flash地址上。
CC2640的OAD固件升级支持内置Flash和外置Flash两种,我们先来了解下内置Flash的OAD配置方式,至于外置Flash的情况,后期再继续更新。
1)首先了解一下Flash配置
2)编译imageA
首先导入工程:
BIM的作用如下图:
把三个程序依次编译,把hex文件烧录到CC2640R2 Launchpad,然后用BLE Device Monitor发现oad服务升级。
3)如何增加off-chip OAD到一个自己的工程
1.添加头文件:
1)oad 服务的头文件
目录 :\source\ti\ble5stack\profiles\oad\cc26xx
- oad.c
- oad.h
- oad_target.h
- oad_target_external_flash.c
2)添加外部flash头文件
- ExtFlash.c
- ExtFlash.h
3)添加cc26xx_app_oad.cmd以及打开预编译选项:
- FEATURE_OAD
- HAL_IMAGE_E
2.修改程序:
添加到应用程序中
#include "oad_target.h"
#include "oad.h"
// ...
#define OAD_PACKET_SIZE ((OAD_BLOCK_SIZE) + 2)
// ...
#define SBP_QUEUE_PING_EVT Event_Id_02
#define SBP_ALL_EVENTS (SBP_ICALL_EVT | \
SBP_QUEUE_EVT | \
SBP_PERIODIC_EVT | \
SBP_CONN_EVT_END_EVT | \
SBP_QUEUE_PING_EVT)
static Queue_Struct oadQ;
static Queue_Handle hOadQ;
void SimpleBLEPeripheral_processOadWriteCB(uint8_t event, uint16_t connHandle,
uint8_t *pData);\
// ...
static oadTargetCBs_t simpleBLEPeripheral_oadCBs =
{
SimpleBLEPeripheral_processOadWriteCB // Write Callback.
};
//增加Oad
VOID OAD_addService(); // OAD Profile
OAD_register((oadTargetCBs_t *)&simpleBLEPeripheral_oadCBs);
hOadQ = Util_constructQueue(&oadQ);
if (events & SBP_QUEUE_PING_EVT)
{
while (!Queue_empty(hOadQ))
{
oadTargetWrite_t *oadWriteEvt = Queue_get(hOadQ);
// Identify new image.
if (oadWriteEvt->event == OAD_WRITE_IDENTIFY_REQ)
{
OAD_imgIdentifyWrite(oadWriteEvt->connHandle, oadWriteEvt->pData);
}
// Write a next block request.
else if (oadWriteEvt->event == OAD_WRITE_BLOCK_REQ)
{
OAD_imgBlockWrite(oadWriteEvt->connHandle, oadWriteEvt->pData);
}
// Free buffer.
ICall_free(oadWriteEvt);
}
}
void SimpleBLEPeripheral_processOadWriteCB(uint8_t event, uint16_t connHandle,
uint8_t *pData)
{
oadTargetWrite_t *oadWriteEvt = ICall_malloc( sizeof(oadTargetWrite_t) + \
sizeof(uint8_t) * OAD_PACKET_SIZE);
if ( oadWriteEvt != NULL )
{
oadWriteEvt->event = event;
oadWriteEvt->connHandle = connHandle;
oadWriteEvt->pData = (uint8_t *)(&oadWriteEvt->pData + 1);
memcpy(oadWriteEvt->pData, pData, OAD_PACKET_SIZE);
Queue_put(hOadQ, (Queue_Elem *)oadWriteEvt);
// Post the application's event. For OAD, no event flag is used.
Event_post(syncEvent, SBP_QUEUE_PING_EVT);
}
}
3.如果不是TI的板子需要修改下面的文件,即对自己的flash进行驱动。
- ExtFlash.c
- ExtFlash.h
我的QQ群:639597049