微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 无线和射频 > TI Zigbee设计交流 > zigbee升级

zigbee升级

时间:10-02 整理:3721RD 点击:

cc2538出厂的时候自带uart升级boot吗?

好像没有,我这边最近也在做CC2538 OTA升级开发,遇到很多问题,其中多次升级同一个固件之后变砖就是致命的一个,目前还没有解决,@VV还在想办法帮忙分析原因,之前我在也在e2e上问了,TI工程师JasonB也还没给回复。

我的OTA升级,最多同时10个升级,多了升级不了,你用的是哪个版本的固件?

应该不止是十个,十个以上也是能升级的,因为每次只是请求offset,每次都不同,主机端负责读取文件,然后返回。

如果说设备多了,很可能会导致ota server 端处理不过来,这是有可能的。

源码里面定义的最大节点数是20个,我用ota同时更新2个cc2538都不行,感觉是znp的串口处理数据太慢导致的。

不是串口慢,而是znp自身处理速度慢,每次每个节点block request最多只有32byte,20个同时请求才多少数据,没多少;

我测试了3个节点同时block request OTA升级,是可以同时进行的,只是偶尔某个会卡一下又继续了,估计是znp处理没有响应block response,但是也没有超时失败。

你应该是用修改后的程序测试的吧,我用源码测试,同时ota2个,其中一个卡死,一个可以ota。

你需要分析zcl_otaserver_lnx.c文件里面的zclOTA_Srv_QueryNextImageReq函数,这里面处理版本判断是最佳位置;

说实话,server端的源码我都没看过,每次测试出现问题我们都怀疑是server端的问题,老大就是一口咬定server没问题,翻来覆去的改linux gateway的代码。日了狗了,浪费了好多时间。谢谢大神指导。

有个问题请教一下:zclOTA_Srv_QueryNextImageReq()函数中获取的filed应该是client传递过来的(也就是在sample_app_ota.cfg中写入的zigbee文件),从而可以获取field.version;改version跟cc2538中version(默认0x00000001)对比,但是我不知道这个值怎么获取。

在zcl_otaserver_linux.c中的zclOTA_Srv_QueryNextImageReq()中修改代码如上截图,测试发现不能避免重复ota,我这样改有什么问题?谢谢!

由于IAR编译出来的OTA firmware是BEBE-2538-AAAA0000.zigbee和BEBE-2538-BBBB1000.zigbee,对应的版本号分别是0xAAAA0000,和0xBBBB1000,所以不要修改,直接拿其做判断就可以了,参考下我的代码:

	zclOTA_FileID_t remoteFileId; 
	memset(&remoteFileId,0x00,sizeof(remoteFileId));
    memcpy(&remoteFileId,&pParam->fileId,sizeof(pParam->fileId));

    dbg_print(PRINT_LEVEL_INFO,"zclOTA_Srv_QueryNextImageReq: remote manufacturer: 0x%x type 0x%x file version 0x%x\n", 
        remoteFileId.manufacturer, remoteFileId.type, 
        remoteFileId.version);    

    // Request the next image for this device from image database 
    status = OtaServer_GetImage(&pParam->fileId, &imageSize, 
            pParam->hardwareVersion, NULL, options, pSrcAddr);

    dbg_print(PRINT_LEVEL_INFO,"zclOTA_Srv_QueryNextImageReq: Match image for manufacturer: 0x%x type 0x%x file version 0x%x returned with status 0x%x\n", 
        pParam->fileId.manufacturer, pParam->fileId.type, 
        pParam->fileId.version, status);

    //sanity check remote and will upgrade firmware version(Image A or Image B) prevent incorrect firmware
    if((remoteFileId.version == 0x1 && pParam->fileId.version == 0xAAAA0000)||
    (remoteFileId.version == 0xAAAA0000 && pParam->fileId.version == 0xAAAA0000) ||
    (remoteFileId.version == 0xBBBB1000 && pParam->fileId.version == 0xBBBB1000))
    {
    		//if remote version equal current version,we must be not upgrade firmware(ping-ponging for CC2538 soc)
    		queryRsp.status = ZOtaImageInvalid;
    		dbg_print(PRINT_LEVEL_INFO,"zclOTA_Srv_QueryNextImageReq: current firmware not suitable 0x%X ,upgrade abort\n",pSrcAddr->addr.shortAddr);
    		goto Ended;
    }else{
		//perfect
    }

2个问题:

1、memcpy(&remoteFileId,&pParam->fileId,sizeof(pParam->fileId)); 这样可以获取remoteFileID吗?

2、对于版本判断的逻辑,有个小错误,spec中规定ota本地更新版本必须要大于远程版本,假如更新版本为0xAAAABBBB,其值介于0xAAAA0000和0xBBBB1000之间,你的逻辑判断是可以进行ota的,但却与spec规定相悖;相当于人为引入了错误。

最后,非常感谢大神的无私分享!


   

1、首先,spec规定是死的,人是活的。CC2538由于使用了ping-ponging这种OTA升级方式,如果严格按照spec的来,每个新的版本号必须大于旧的,那么就会出现Image A 版本00,版本01,版本02..... 同样Image B也会出现版本01,版本02,版本03......,这给firmware的管理带来很大的难度,一定会出现这一次必须用Image B的02版本,下一次必须用Image A的03版本,02版本是不行的。

2、可能TI也认识到了这一点,所以在client接收“image response”的处理函数zclOTA_ProcessQueryNextImageRsp里面,并没有判断version版本号,而是只判断了type和manufacturer,这里的type无非是0x2538或者0x2530,manufacturer无非定义好的0xBEBE。

    // verify manufacturer id and image type
    if ( ( param.fileId.type == zclOTA_ImageType ) &&
         ( param.fileId.manufacturer == zclOTA_ManufacturerId ) )
    {
      // store file version and image size
      zclOTA_DownloadedFileVersion = param.fileId.version;
      zclOTA_DownloadedImageSize = param.imageSize;

      // initialize other variables
      zclOTA_FileOffset = 0;
      zclOTA_ClientPdState = ZCL_OTA_PD_MAGIC_0_STATE;

      // set state to 'in progress'
      zclOTA_ImageUpgradeStatus = OTA_STATUS_IN_PROGRESS;

      // store server address
      zclOTA_serverAddr = pInMsg->msg->srcAddr;

      // Store the file ID
      osal_memcpy ( &zclOTA_CurrentDlFileId, &param.fileId, sizeof ( zclOTA_FileID_t ) );

      // send image block request
      osal_start_timerEx ( zclOTA_TaskID, ZCL_OTA_IMAGE_BLOCK_REQ_DELAY_EVT, zclOTA_MinBlockReqDelay );
      status = ZCL_STATUS_CMD_HAS_RSP;

      // Request the IEEE address of the server to put into the
      // ATTRID_UPGRADE_SERVER_ID attribute
      ZDP_IEEEAddrReq ( pInMsg->msg->srcAddr.addr.shortAddr, ZDP_ADDR_REQTYPE_SINGLE, 0, 0 );

      osal_stop_timerEx ( zclOTA_TaskID, ZCL_OTA_IMAGE_QUERY_TO_EVT );
    }
  }

3.能不能获取到remoteFileID,我们随便找一个Z-Stack 3.0的 OTA dongle工程分析一下,找到MT_OTA.c文件,可以看到,OTA client发送给OTA server的“image request”一定让MT_OtaGetImage函数来处理,这个函数里面是添加了fileID这一项的,最后把请求发送Z-Tool控制台,这里我们认为Linux gateway扮演了控制台的角色,只是由于2014年释出的zigbee Linux geteway并不适应最新的Z-Stack 3.0 ZNP工程,所以我做了两件事情,一、不得不把OTA dongle里面的OTA移植到最新的Z-Stack 3.0 ZNP工程里面,而且让它工作,另外添加了“image notify”功能,默认是不带的;二、把zigbee Linux gateway里面的OTA server源码单独移植出来使用,这样就脱离了复杂且容易出bug的gateway代码。目前测试下来没有问题,已经实现了OTA server升级各个client。

uint8 MT_OtaGetImage(afAddrType_t *pAddr, zclOTA_FileID_t *pFileId, uint16 hwVer, 
                     uint8 *ieee, uint8 options)
{
  uint8   msgLen;
  uint8   *pBuf;
  uint8   *p;

  // Get length
  msgLen = MT_OTA_GET_IMG_MSG_LEN;
  
  // Allocate a buffer
  if ((p = pBuf = MT_TransportAlloc(0, msgLen)) != NULL)
  {
    // build header
    *p++ = msgLen;
    *p++ = (uint8) MT_RPC_CMD_AREQ | (uint8) MT_RPC_SYS_OTA;
    *p++ = MT_OTA_NEXT_IMG_REQ;
    
    // Add the file ID
    p = OTA_FileIdToStream(pFileId, p);

    // Add the device address 
    p = OTA_AfAddrToStream(pAddr, p);

    // Add the options
    *p++ = options;

    // Add the hardware ID (optional)
    *p++ = LO_UINT16(hwVer);
    *p = HI_UINT16(hwVer);
    
    if (ieee)
      osal_memcpy(p, ieee, Z_EXTADDR_LEN);
  
    // Send command to server
    MT_TransportSend(pBuf);
    
    return ZSuccess;
  }
  
  return ZMemError;
}

4.也许正如@VV所说,TI还在开发新的zigbee Linux gateway以适应最新的Z-Stack 3.0协议栈,但至少到目前为止,还没有释出任何代码,所以基本上还得依赖旧的版本来开发,或者使用简单的znp-host-framework代替多进程且容易出问题的zigbee Linux gateway,最后,理解了整个zigbee端的代码和gateway端的代码,做起来都得心应手。



1、仔细思考了下,感觉你这个设计思路很赞!本质就是固定2个更新版本,AAAA0000和BBBB1000,排除同一个版本重复更新的干扰,反复更新即可;相比于spec的规定,确实减少了很多版本命名方面的麻烦,perfect!

2、我还没有用Z-Stack 3.0,沿用老版本Z-Stack Home 1.2.2a.44539

3、对于获取remoteFileID问题,说一下我的理解:首先定位到zcl_otaserverlnc.c中zclOTA_Srv_QueryNextImageReq(),当app端没有执行“O”(OTA update)操作前,pParam->fileID.version获取的是远程clien端固件默认version(0x00000001),将值保存到remotefileID.version,当执行“O”操作时,pParam->fileID.version获取的是本地image database里面的固件version(0xAAAA0000或者0xBBBB1000);不知我这样理解是否正确?

另:你第3条中说的移植ota_dongle的ota到znp以及移植otaserver,不是太明白。

因为我想在最新的Z-Stack 3.0 ZNP工程上支持OTA更新,但是ZNP工程本身不带任何OTA的成分,所以需要移植,另外也要配置host的OTA server,我想让代码都放在ZNP端简单一些,如果都把AF过来的消息送到host端处理代码太繁琐。

我在zcl_otaserver_lnx.c中的zclOTA_Srv_QueryNextImageReq()函数里面,参考你的代码,添加对版本判断的内容,为什么编译后,重新执行./zigbeeHAgw,还是不能规避重复更新。

我是编译整个源码包,然后tar解包,使用新生成的zigbeeHAgw脚本。

ZStatus_t zclOTA_Srv_QueryNextImageReq(afAddrType_t *pSrcAddr,
    zclOTA_QueryNextImageReqParams_t *pParam)
{
  uint8 options = 0;
  uint8 status;
  uint32 imageSize;
  zclOTA_QueryImageRspParams_t queryRsp;

  /********************************************************************************/

  //获取remotefileID.version
  zclOTA_FileID_t remotefileID;
  memset(&remotefileID, 0, sizeof(remotefileID));
  memcpy(&remotefileID, &pParam->fileId, sizeof(pParam->fileId));

  uiPrintfEx(trDEBUG,"zclOTA_Srv_QueryNextImageReq: Remote image for manu 0x%x"
        " type 0x%x file version 0x%x",
        remotefileID.manufacturer, remotefileID.type, remotefileID.version);
 
  /********************************************************************************/

  //Respond to a "Query Next" only if Permit set to 0
  if (zclOTA_Permit == OTA_ENABLE_MODES__DOWNLOAD_ENABLE)
  {

    if (pParam->fieldControl)
    {
      options |= MT_OTA_HW_VER_PRESENT_OPTION;   //0x01
    }

    // Request the next image for this device from image database
 //获取Image,同时pImage->imageData->header.fileId.version给到 pParam->fileID.version
    status = OtaServer_GetImage(&pParam->fileId, &imageSize, pParam->hardwareVersion, NULL, options, pSrcAddr); 
 
    uiPrintfEx(trDEBUG,"zclOTA_Srv_QueryNextImageReq: Match image for manu 0x%x"
        " type 0x%x file version 0x%x returned with status 0x%x\n",
        pParam->fileId.manufacturer, pParam->fileId.type,
        pParam->fileId.version, status);

    if (status == OTASERVER_SUCCESS)
 {
  //Fill in the response parameters
     memcpy(&queryRsp.fileId, &pParam->fileId, sizeof(zclOTA_FileID_t));
     queryRsp.status = ZSuccess;
     queryRsp.imageSize = imageSize; //Get Filesize using fileId ?!

     uiPrintfEx(trDEBUG,"zclOTA_Srv_QueryNextImageReq: File size 0x%x\n", imageSize);

  // Send a success response to the client
  //zclOTA_SendQueryNextImageRsp(pSrcAddr, &queryRsp, ++zclOTA_SeqNo);
  
 /****************************************************************************************/

 //版本判断
  if((remotefileID.version = 0x01 && pParam->fileId.version == 0x1A) ||
   (remotefileID.version == 0x0B && pParam->fileId.version == 0x0B) ||
   (remotefileID.version == 0x1A && pParam->fileId.version == 0x1A)) 
  {
   queryRsp.status = ZOtaImageInvalid;
   printf("zclOTA_Srv_QueryNextImageReq: current firmware is not suitable 0x%x, upgrade abort\n", pSrcAddr->addr.shortAddr);
  }
  else
  {
   zclOTA_SendQueryNextImageRsp(pSrcAddr, &queryRsp, ++zclOTA_SeqNo);
  }
  //判断版本
  //0x0000000B > 0x01, 0x0000001A > 0x0000000B...
  //if(queryRsp.fileId.version > remotefileID.version)
  //{
  // zclOTA_SendQueryNextImageRsp(pSrcAddr, &queryRsp, ++zclOTA_SeqNo);
  //}
 /****************************************************************************************/
       return ZCL_STATUS_CMD_HAS_RSP;
    }
    else
  queryRsp.status = ZOtaNoImageAvailable;
  }
  else
  {
  
    //No image available, and not authorized. What should I use in case of
    //abort ?
    //queryRsp.status = ZOtaAbort;
    queryRsp.status = ZOtaNoImageAvailable;

    //Download status sent only on Upgrade End Req
    //sendDownloadStatus(appConnectionHandle, pSrcAddr, OTA_STATUS__ABORT);
  }

  // Fill in the response parameters
  memcpy(&queryRsp.fileId, &pParam->fileId, sizeof(zclOTA_FileID_t));
  queryRsp.imageSize = 0;

  //Send failure response
  zclOTA_SendQueryNextImageRsp(pSrcAddr, &queryRsp, ++zclOTA_SeqNo);

  return ZCL_STATUS_CMD_HAS_RSP;
}

Hi,

1、OTA调试又遇到了问题:2538原始固件为版本为0x01,我打算更新的固件版本为BEBE-2538-0000000B.zigbee,client端会发送request请求更新BEBE-2538-0000000B.zigbee,但是server端给client端的response却是BEBE-2538-0000001A.zigbee,这个通过sniffer已经抓到了解析的数据包;百思不得其解,求大神帮忙看看。

2、OTA重复更新问题,我参照你提供的代码进行修改,测试还是不行,这个也不知道原因在哪里。谢谢了!

问题已解决。不是代码问题,是源码有问题,编译生成的可执行文件的数目不够,重新换了干净的源码,测试ok。谢谢!

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top