CC1310空中升级笔记04 WSN OAD Example

2020-04-17 14:41:31 浏览数 (1)

1. 前言

关于CC1310的空中升级,让我折腾了特别久,我几乎绝望了。仅有的两个参考资料都遇到了困难: 1.CC2640 OAD,其中的BIM部分,TI只提供了IAR的版本,这导致关键性的存储映射无从参考,缺少了最关键的资料。 2.CC1350 BLE OAD Project 0,只有一个开发文档。

但是,身负物联网世界振兴重任的我又怎么能说不行呢!IoT小能手的字典中从来就没有‘不行’这两个字,因为我连字典都没有。

你看,山重水复疑无路,柳暗花明又一村。TI给了我一个CC1310的内部例程WSN OAD Example。别问我怎么得到的。

本文作者twowinter,转载请注明作者:http://blog.csdn.net/iotisan/

2. 例程研究

这个工程包含了 rfWsnConcentratorOadServer_CC1350_LAUNCHXL_TI_CC1350F128 和 rfWsnNodeOadClient_CC1310_LAUNCHXL_TI_CC1310F128 projects,以及用来将hex转化成OAD bin,下载镜像的脚本。 例程中,集中器存储节点的OAD镜像,通过OAD方式发送给子节点,子节点将镜像存储到外部flash中,子节点BIM程序把固件拷贝到内部flash,之后运行新程序。

2.1 产生要求的二进制镜像

需要如下工具: - CCSv7 - simplelink_cc13x0_sdk_1_00_00_13 - Python 2.7 - Python intelhex-2.1 - Python crcmod-1.7

只有rfWsnNodeOadClient_CC1310_LAUNCHXL_TI_CC1310F128需要BIM。

2.2 如何使用OAD例程

为了第一次使用时正常工作,集中器和子节点的外部flash需要清空。给两个LP boards烧写bin和CC1350LaunchPad_ExtFlashErase.hex。当擦写时LED会闪烁,烧写完成时LED就停止闪烁。除非外部flash擦除,LED停止闪烁。

集中器的OAD Server和子节点的固件通过SmartRF Flash Programmer来下载。

集中器将在串口显示如下信息: *Available FW: None

代码语言:javascript复制
Nodes   FwVer   SW   RSSI

0xfe    0850    0    -025

Press BTN-2 to update available node FW

The "Available FW", or node selection is indicated by the '*'

子节点要用的OAD镜像可以使用oad_wrtie_bin.py 通过集中器的串口写入到外部flash。可用固件必须先按BTN-1来选中。

当”Available FW”被选中,BTN-2按下,则终端会显示:

代码语言:javascript复制
Waiting for Node FW update...

串口terminal立即关掉,然后运行脚本将bin写入。 升级完后,绿色LED会闪烁,之后就可以重新打开串口terminal。

现在使用BTN-1来选择节点,显示屏会显示节点来运行的程序: Available FW: rfWsnNode v02.00.00

代码语言:javascript复制
Nodes   Value   SW   RSSI

*0x7d    0850    0    -027

FW: rfWsnNode v01.00.00

Press BTN-2 to OAD node FW 

如果新上电一个节点,过几秒会显示出它的固件版本。

当选中节点后再按下BTN-2,则会开始向那个节点下发OAD。当节点接下来发送一个传感器读取,OAD就会启动,可以按下它自身的 BTN-1 来唤醒节点(它可能进入了50s的慢速上报)。节点固件会显示总包数和当前升级的包数:

代码语言:javascript复制
 Available FW: rfWsnNode v02.00.00

Nodes   Value   SW   RSSI

*0x7d    0850    0    -028

FW: Block 03f6/0ed8

Press BTN-2 to OAD node FW

一旦OAD完成,节点会自动重启。 集中器会显示一个新的节点,该新节点会显示更新的固件版本。

2.3 编译一个OAD固件

  1. Update the nodeFwVersion string in NodeTask.c
  2. Exclude the ccfg.c file from the project.
  3. Enable hex file conversion in Project->Properties Arm Hex Utility
  4. Set memory width to 8 in General options
  5. Set outut format to intel hex.
  6. build
  7. copy hex from the projects Debug dir to the bin folder
  8. convert to OAD bin:

python tools/oad_image_tool.py -v 0x[version] -i remoteapp bin/rfWsnNodeOadClient_CC1310_LAUNCHXL_tirtos_ccs.hex -ob bin/rfWsnNodeOadClient_CC1310_LAUNCHXL_TI_CC1310F128_app-[version].bin -m 0x1000

3. OAD 源码解析

3.1 关于OAD的空中交互部分

空中交互大致有6条,源码最主要体现在 sourcecommonwsnprotocol.h 底下

代码语言:javascript复制
WSNProtocol_sendFwVersionReq
WSNProtocol_sendFwVersionRsp
WSNProtocol_sendImgIdentifyReq
WSNProtocol_sendOadIdentifyImgRsp
WSNProtocol_sendOadImgBlockReq
WSNProtocol_sendOadImgBlockRsp

整体OAD的交互流程梳理如下:

Concentrator — fwVersionReq –> Node Concentrator <– fwVersionRsp — Node Concentrator — oadImgIdentifyReq –> Node Concentrator <– oadImgIdentifyRsp — Node Concentrator <– oadBlockReq — Node Concentrator — oadBlockRsp –> Node

3.2 关于镜像下载部分

空中交互之后就到了镜像下载部分,也是特别关键的一部分,每次下载16字节。每次在oadBlockRspCb()中收到镜像分包,然后进行写入,边下载边写入FLASH。下载完镜像之后,再做下CRC校验:

代码语言:javascript复制
/*********************************************************************
 * @fn      OAD_imgBlockWrite
 *
 * @brief   Process the Image Block Write.
 *
 * @param   pValue - pointer to data to be written
 *
 * @return  none
 */
void OAD_imgBlockWrite(uint8_t *pValue)
{
  // N.B. This must be left volatile.
  volatile uint16_t blkNum = BUILD_UINT16(pValue[0], pValue[1]);

  // Check that this is the expected block number.
  if (oadBlkNum == blkNum)
  {
    // Calculate address to write as (start of OAD range)   (offset into range)
    uint32_t addr = imageAddress   (oadBlkNum * OAD_BLOCK_SIZE);

    // If address starts a new page, erase that page first.
    if ((addr % flashPageSize) == 0)
    {
      OADTarget_eraseFlash(addr / flashPageSize);
    }

    // Write a 16 byte block to Flash.
    OADTarget_writeFlash(imagePage, (blkNum * OAD_BLOCK_SIZE), pValue 2,
                         OAD_BLOCK_SIZE);

    // Increment received block count.
    oadBlkNum  ;
  }
  else
  {
    // Overflow, abort OAD
    oadBlkNum = 0;
#ifndef FEATURE_OAD_ONCHIP
    flagRecord = 0;
#endif
    // Close the target device
    OADTarget_close();

    // Send status
    OAD_sendStatusCb(OAD_BUFFER_OFL);

    return;
  }

  // Check if the OAD Image is complete.
  if (oadBlkNum == oadBlkTot)
  {
#if FEATURE_OAD_ONCHIP
    // Handle CRC verification in BIM.
    OADTarget_systemReset();
#else // !FEATURE_OAD_ONCHIP
    // Run CRC check on new image.
    if (checkDL())
    {
      // Store the flag of the downloaded image.
      flagRecord |= getImageFlag();

      // Store the image information.
      saveImageInfo();

      // Indicate a successful download and CRC
      OAD_sendStatusCb(OAD_SUCCESS);
    }
    else
    {
      // CRC error
      OAD_sendStatusCb(OAD_CRC_ERR);
    }
    flagRecord = 0;
#endif //FEATURE_OAD_ONCHIP

    OADTarget_close();
    oadBlkNum = 0;
  }
  else
  {
    // Request the next OAD Image block.
    OAD_getNextBlockReqCb(oadBlkNum);
  }
}

4. End


0 人点赞