This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
协议栈:Z-Stack 3.0.2
协调器:CC2538
路由器:EFR32
终端:EFR32
问题描述:
网络中有50个设备,44个路由器和6个终端设备。现在对其中一个终端设备进行OTA升级。升级到了80%的时候协调器会出现发送 image response 命令 会返回ZMemError(0x10),最后导致 OTA 设备发送终止命令,OTA 升级失败。
OTA升级期间没有别的设备进行应用层report之类的交互命令,只有MTO的route request 和 status link 这些维护网络的命令。请问 ZMemError(0x10) 呢?
zigbee网络测试-节点设备OTA升级中途停止-协调器内存分配失败-OTA失败-Abort.rar
我看了 route reply 只是别的设备发送给 coordinator 的而已,而且很少,你能帮我看下这个抓包吗?
前面 OTA 升级时非常顺利的,可是到了后面网络结构会变化,然后 coordinator 要进行 router request 过程修复链路。到最后面 coordinator 就出现zMemError(0x10),OTA 设备收不到 image response 就发送 abort 给 coordinator,升级失败。
/********************************************************************* * @fn AF_DataRequestSrcRtg * * @brief Common functionality for invoking APSDE_DataReq() for both * SendMulti and MSG-Send. * * input parameters * * @param *dstAddr - Full ZB destination address: Nwk Addr + End Point. * @param *srcEP - Origination (i.e. respond to or ack to) End Point Descr. * @param cID - A valid cluster ID as specified by the Profile. * @param len - Number of bytes of data pointed to by next param. * @param *buf - A pointer to the data bytes to send. * @param *transID - A pointer to a byte which can be modified and which will * be used as the transaction sequence number of the msg. * @param options - Valid bit mask of Tx options. * @param radius - Normally set to AF_DEFAULT_RADIUS. * @param relayCnt - Number of devices in the relay list * @param pRelayList - Pointer to the relay list * * output parameters * * @param *transID - Incremented by one if the return value is success. * * @return afStatus_t - See previous definition of afStatus_... types. */ afStatus_t AF_DataRequestSrcRtg( afAddrType_t *dstAddr, endPointDesc_t *srcEP, uint16 cID, uint16 len, uint8 *buf, uint8 *transID, uint8 options, uint8 radius, uint8 relayCnt, uint16* pRelayList )
这有点跑题了:
使用AF_DataRequestSrcRtg这个函数会在在发送控制指令前,添加relayList的,该函数最终也会调用AF_DataRequest实现控制指令的发送,会调用RTG_AddSrcRtgEntry_Guaranteed把relayList加入到source routing table里面,让协议栈按照这个添加的路径路径去发送,指令会更快的到达目的地址。
没跑题啊,现在不是在说可能是 route record 导致的内存激增吗。
我搜索了工程代码,没发现在哪里有利用 ZDO_SRC_RTG_IND_CBID 回调,底层有利用 ZDO_SRC_RTG_IND_CBID 回调来自动更新路由链路吗?从我上面发的那个抓包来看,协调器收到 OTA 设备的 route record 命令之后并没有任何反应,然后 OTA 设备就一直在发送 route record 给协调器了。
5.4.3 Route Record Command
For concentrator with no memory constraints, it can store all route record entries it receives and use them to send packets to the source devices in the future. Therefore, devices only need to send route record command once. However, for concentrator without source route caching capability, devices always need to send route record commands along with data packets. The concentrator will store the source route temporarily in the memory and then discard it after usage.
从 5.4.3 Route Record Command 里的这段话可以看出如果开了源路由缓存功能,设备只需要发送一次 route record 命令?
这个route record是设备更新了 route 路径然后上报的。 route record是客户自己要做的记录,底层只是传上来,用不用客户决定的。你可以试试在网络不做改变的情况下去OTA看看会不会失败。
其实工程中有例子:
/*************************************************************************************************** * @fn MT_ZdoSrcRtgCB * * @brief Handle Src Route from ZDO. * * @param pStr - pointer to the data structure for the src route * * @return void* */ void* MT_ZdoSrcRtgCB( void *pStr ) { uint8 len, *pBuf; zdoSrcRtg_t *pSrcRtg = pStr; // srcAddr (2) + relayCnt (1) + relayList( relaycnt * 2 ) len = 2 + 1 + pSrcRtg->relayCnt * sizeof(uint16); if (NULL != (pBuf = (uint8 *)osal_mem_alloc(len))) { uint8 idx, *pTmp = pBuf; uint16 *pRelay; // Packet payload *pTmp++ = LO_UINT16(pSrcRtg->srcAddr); *pTmp++ = HI_UINT16(pSrcRtg->srcAddr); *pTmp++ = pSrcRtg->relayCnt; // Relay List if( ( pRelay = pSrcRtg->pRelayList ) != NULL ) { for( idx = 0; idx < pSrcRtg->relayCnt; idx ++ ) { *pTmp++ = LO_UINT16(*pRelay); *pTmp++ = HI_UINT16(*pRelay); pRelay++; } } MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_AREQ | (uint8)MT_RPC_SYS_ZDO), MT_ZDO_SRC_RTG_IND, len, pBuf); osal_mem_free(pBuf); } return NULL; }
OK,我了解了,route record 命令是需要用户自己做应用的,AF_DataRequest() 是不会利用 route record 的对吧?
那么开启源路由缓存功能后:“CONCENTRATOR_ROUTE_CACHE=TRUE”、“MAX_RTG_SRC_ENTRIES=80”,协调器会自己缓存入网设备的源路由路径,然后在发送的时候会使用这些路径吗?如果会自己存储,那是独立开出80个源路由路径的内存吗?还是要占用“MAXMEMHEAP”的内存?
http://www.ti.com/tool/simplelink-cc13x2-26x2-sdk
注意3.10使用E版本芯片,如果你的芯片不是E版本,只能用2.30版本SDK
是不是设备复位后不知道协调器是带源路由缓存功能的设备,然后每上报一次数据给协调器都会自带一条“route record”?我是默认间隔 120 秒协调器广播一次“route request”命令的。