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
终端和路由:CC2538
问题描述:
1、网络中有 60 个设备,网络中流通的数据不大。此时对一个终端节点进行 OTA 升级,“Image Block Response”发送 64 个字节,调用“relayCnt”为2的“zcl_SrcRtgSendCommand()”函数发送“Image Block Response”命令时返回“ZMemError(0x10)”,即申请内存失败。而此时查看内存管理器发现内存并未满,请问这是哪里出了问题?
2、此时对另一个路由节点进行 OTA 升级,也是“Image Block Response”发送 64 个字节,此时却可以升级成功。
3、即发送带 64 个字节数据的“Image Block Response”命令给终端设备是一定会出现“ZMemError(0x10)”的,我单步调试发现是调用 “APSDE_DataReq()” 函数时返回的“ZMemError(0x10)”。但是发送给路由设备却可以成功。
{
if (len > afDataReqMTU( &mtu ) )
{
if (apsfSendFragmented)
{
stat = (*apsfSendFragmented)( &req );
}
else
{
stat = afStatus_INVALID_PARAMETER;
}
}
else
{
stat = APSDE_DataReq( &req );
}
}
“zcl_SrcRtgSendCommand()”就只是在“zcl_SendCommand()”函数基础上添加了“uint8 relayCnt, uint16* pRelayList”形参,然后将函数里面的“AF_DataRequest()”改为“AF_DataRequestSrcRtg()”。
ZStatus_t zcl_SrcRtgSendCommand( uint8 srcEP, afAddrType_t *destAddr,
uint16 clusterID, uint8 cmd, uint8 specific, uint8 direction,
uint8 disableDefaultRsp, uint16 manuCode, uint8 seqNum,
uint16 cmdFormatLen, uint8 *cmdFormat, uint8 relayCnt, uint16* pRelayList )
{
endPointDesc_t *epDesc;
zclFrameHdr_t hdr;
uint8 *msgBuf;
uint16 msgLen;
uint8 *pBuf;
uint8 options;
ZStatus_t status;
epDesc = afFindEndPointDesc( srcEP );
if ( epDesc == NULL )
{
return ( ZInvalidParameter ); // EMBEDDED RETURN
}
#if defined ( INTER_PAN )
if ( StubAPS_InterPan( destAddr->panId, destAddr->endPoint ) )
{
options = AF_TX_OPTIONS_NONE;
}
else
#endif
{
options = zclGetClusterOption( srcEP, clusterID );
// The cluster might not have been defined to use security but if this message
// is in response to another message that was using APS security this message
// will be sent with APS security
if ( !( options & AF_EN_SECURITY ) )
{
afIncomingMSGPacket_t *origPkt = zcl_getRawAFMsg();
if ( ( origPkt != NULL ) && ( origPkt->SecurityUse == TRUE ) )
{
options |= AF_EN_SECURITY;
}
}
}
zcl_memset( &hdr, 0, sizeof( zclFrameHdr_t ) );
// Not Profile wide command (like READ, WRITE)
if ( specific )
{
hdr.fc.type = ZCL_FRAME_TYPE_SPECIFIC_CMD;
}
else
{
hdr.fc.type = ZCL_FRAME_TYPE_PROFILE_CMD;
}
if ( ( epDesc->simpleDesc == NULL ) ||
( zcl_DeviceOperational( srcEP, clusterID, hdr.fc.type,
cmd, epDesc->simpleDesc->AppProfId ) == FALSE ) )
{
return ( ZFailure ); // EMBEDDED RETURN
}
// Fill in the Maufacturer Code
if ( manuCode != 0 )
{
hdr.fc.manuSpecific = 1;
hdr.manuCode = manuCode;
}
// Set the Command Direction
if ( direction )
{
hdr.fc.direction = ZCL_FRAME_SERVER_CLIENT_DIR;
}
else
{
hdr.fc.direction = ZCL_FRAME_CLIENT_SERVER_DIR;
}
// Set the Disable Default Response field
if ( disableDefaultRsp )
{
hdr.fc.disableDefaultRsp = 1;
}
else
{
hdr.fc.disableDefaultRsp = 0;
}
// Fill in the Transaction Sequence Number
hdr.transSeqNum = seqNum;
// Fill in the command
hdr.commandID = cmd;
// calculate the needed buffer size
msgLen = zclCalcHdrSize( &hdr );
msgLen += cmdFormatLen;
// Allocate the buffer needed
msgBuf = zcl_mem_alloc( msgLen );
if ( msgBuf != NULL )
{
// Fill in the ZCL Header
pBuf = zclBuildHdr( &hdr, msgBuf );
// Fill in the command frame
zcl_memcpy( pBuf, cmdFormat, cmdFormatLen );
status = AF_DataRequestSrcRtg( destAddr, epDesc, clusterID, msgLen, msgBuf,
&APS_Counter, options, zcl_radius, relayCnt, pRelayList );
zcl_mem_free ( msgBuf );
}
else
{
status = ZMemError;
}
return ( status );
}
ZStatus_t zcl_SrcRtgSendCommand( uint8 srcEP, afAddrType_t *destAddr, uint16 clusterID, uint8 cmd, uint8 specific, uint8 direction, uint8 disableDefaultRsp, uint16 manuCode, uint8 seqNum, uint16 cmdFormatLen, uint8 *cmdFormat, uint8 relayCnt, uint16* pRelayList ) { endPointDesc_t *epDesc; zclFrameHdr_t hdr; uint8 *msgBuf; uint16 msgLen; uint8 *pBuf; uint8 options; ZStatus_t status; //add by alvin uint8 *Rtgbuf; zdoSrcRtg_t srcRtg; Rtgbuf=zcl_mem_alloc(sizeof(srcRtg)+relayCnt*sizeof(uint16)) if( Rtgbuf != NULL) { srcRtg.srcAddr=destAddr.shortAddr; srcRtg.relayCnt=relayCnt; srcRtg.pRelayList=pRelayList; } else{ status = ZMemError } epDesc = afFindEndPointDesc( srcEP ); if ( epDesc == NULL ) { return ( ZInvalidParameter ); // EMBEDDED RETURN } #if defined ( INTER_PAN ) if ( StubAPS_InterPan( destAddr->panId, destAddr->endPoint ) ) { options = AF_TX_OPTIONS_NONE; } else #endif { options = zclGetClusterOption( srcEP, clusterID ); // The cluster might not have been defined to use security but if this message // is in response to another message that was using APS security this message // will be sent with APS security if ( !( options & AF_EN_SECURITY ) ) { afIncomingMSGPacket_t *origPkt = zcl_getRawAFMsg(); if ( ( origPkt != NULL ) && ( origPkt->SecurityUse == TRUE ) ) { options |= AF_EN_SECURITY; } } } zcl_memset( &hdr, 0, sizeof( zclFrameHdr_t ) ); // Not Profile wide command (like READ, WRITE) if ( specific ) { hdr.fc.type = ZCL_FRAME_TYPE_SPECIFIC_CMD; } else { hdr.fc.type = ZCL_FRAME_TYPE_PROFILE_CMD; } if ( ( epDesc->simpleDesc == NULL ) || ( zcl_DeviceOperational( srcEP, clusterID, hdr.fc.type, cmd, epDesc->simpleDesc->AppProfId ) == FALSE ) ) { return ( ZFailure ); // EMBEDDED RETURN } // Fill in the Maufacturer Code if ( manuCode != 0 ) { hdr.fc.manuSpecific = 1; hdr.manuCode = manuCode; } // Set the Command Direction if ( direction ) { hdr.fc.direction = ZCL_FRAME_SERVER_CLIENT_DIR; } else { hdr.fc.direction = ZCL_FRAME_CLIENT_SERVER_DIR; } // Set the Disable Default Response field if ( disableDefaultRsp ) { hdr.fc.disableDefaultRsp = 1; } else { hdr.fc.disableDefaultRsp = 0; } // Fill in the Transaction Sequence Number hdr.transSeqNum = seqNum; // Fill in the command hdr.commandID = cmd; // calculate the needed buffer size msgLen = zclCalcHdrSize( &hdr ); msgLen += cmdFormatLen; // Allocate the buffer needed msgBuf = zcl_mem_alloc( msgLen ); if ( msgBuf != NULL ) { // Fill in the ZCL Header pBuf = zclBuildHdr( &hdr, msgBuf ); // Fill in the command frame zcl_memcpy( pBuf, cmdFormat, cmdFormatLen ); status = AF_DataRequestSrcRtg( destAddr, epDesc, clusterID, msgLen, msgBuf, &APS_Counter, options, zcl_radius, srcRtg.relayCnt, srcRtg.pRelayList ); //add by alvin zcl_mem_free(Rtgbuf); zcl_mem_free ( msgBuf ); } else { status = ZMemError; } return ( status ); }
我大致写了一些code出来,就是申请srcRtg,你去试试看,不行的话改一下,还没有验证过。
我将“uint16* pRelayList”形参单独申请内存保存之后就可以发送了,为什么会出现这个问题?有时候调用发送函数的时候也是会返回"ZMemError (0x10)",但是内存并没有满。
之前的函数:
ZStatus_t zcl_SrcRtgSendCommand( uint8 srcEP, afAddrType_t *destAddr, uint16 clusterID, uint8 cmd, uint8 specific, uint8 direction, uint8 disableDefaultRsp, uint16 manuCode, uint8 seqNum, uint16 cmdFormatLen, uint8 *cmdFormat, uint8 relayCnt, uint16* pRelayList ) { endPointDesc_t *epDesc; zclFrameHdr_t hdr; uint8 *msgBuf; uint16 msgLen; uint8 *pBuf; uint8 options; ZStatus_t status; epDesc = afFindEndPointDesc( srcEP ); if ( epDesc == NULL ) { return ( ZInvalidParameter ); // EMBEDDED RETURN } #if defined ( INTER_PAN ) if ( StubAPS_InterPan( destAddr->panId, destAddr->endPoint ) ) { options = AF_TX_OPTIONS_NONE; } else #endif { options = zclGetClusterOption( srcEP, clusterID ); // The cluster might not have been defined to use security but if this message // is in response to another message that was using APS security this message // will be sent with APS security if ( !( options & AF_EN_SECURITY ) ) { afIncomingMSGPacket_t *origPkt = zcl_getRawAFMsg(); if ( ( origPkt != NULL ) && ( origPkt->SecurityUse == TRUE ) ) { options |= AF_EN_SECURITY; } } } zcl_memset( &hdr, 0, sizeof( zclFrameHdr_t ) ); // Not Profile wide command (like READ, WRITE) if ( specific ) { hdr.fc.type = ZCL_FRAME_TYPE_SPECIFIC_CMD; } else { hdr.fc.type = ZCL_FRAME_TYPE_PROFILE_CMD; } if ( ( epDesc->simpleDesc == NULL ) || ( zcl_DeviceOperational( srcEP, clusterID, hdr.fc.type, cmd, epDesc->simpleDesc->AppProfId ) == FALSE ) ) { return ( ZFailure ); // EMBEDDED RETURN } // Fill in the Maufacturer Code if ( manuCode != 0 ) { hdr.fc.manuSpecific = 1; hdr.manuCode = manuCode; } // Set the Command Direction if ( direction ) { hdr.fc.direction = ZCL_FRAME_SERVER_CLIENT_DIR; } else { hdr.fc.direction = ZCL_FRAME_CLIENT_SERVER_DIR; } // Set the Disable Default Response field if ( disableDefaultRsp ) { hdr.fc.disableDefaultRsp = 1; } else { hdr.fc.disableDefaultRsp = 0; } // Fill in the Transaction Sequence Number hdr.transSeqNum = seqNum; // Fill in the command hdr.commandID = cmd; // calculate the needed buffer size msgLen = zclCalcHdrSize( &hdr ); msgLen += cmdFormatLen; // Allocate the buffer needed msgBuf = zcl_mem_alloc( msgLen ); if ( msgBuf != NULL ) { // Fill in the ZCL Header pBuf = zclBuildHdr( &hdr, msgBuf ); // Fill in the command frame zcl_memcpy( pBuf, cmdFormat, cmdFormatLen ); status = AF_DataRequestSrcRtg( destAddr, epDesc, clusterID, msgLen, msgBuf, &APS_Counter, options, zcl_radius, relayCnt, pRelayList ); zcl_mem_free ( msgBuf ); } else { status = ZMemError; } return ( status ); }
更改后的函数:
ZStatus_t zcl_SrcRtgSendCommand( uint8 srcEP, afAddrType_t *destAddr, uint16 clusterID, uint8 cmd, uint8 specific, uint8 direction, uint8 disableDefaultRsp, uint16 manuCode, uint8 seqNum, uint16 cmdFormatLen, uint8 *cmdFormat, uint8 relayCnt, uint16* pRelayList ) { endPointDesc_t *epDesc; zclFrameHdr_t hdr; uint8 *msgBuf; uint16 msgLen; uint8 *pBuf; uint8 options; ZStatus_t status; zdoSrcRtg_t srcrtg = {0}; srcrtg.srcAddr = destAddr->addr.shortAddr; srcrtg.relayCnt = relayCnt; srcrtg.pRelayList = NULL; if((relayCnt!=0)&&(pRelayList!=NULL)) { srcrtg.pRelayList = zcl_mem_alloc(relayCnt * sizeof(uint16)); if(srcrtg.pRelayList!=NULL) { osal_memcpy(srcrtg.pRelayList, pRelayList, relayCnt * sizeof(uint16)); } else { status = ZMemError; } } epDesc = afFindEndPointDesc( srcEP ); if ( epDesc == NULL ) { return ( ZInvalidParameter ); // EMBEDDED RETURN } #if defined ( INTER_PAN ) if ( StubAPS_InterPan( destAddr->panId, destAddr->endPoint ) ) { options = AF_TX_OPTIONS_NONE; } else #endif { options = zclGetClusterOption( srcEP, clusterID ); // The cluster might not have been defined to use security but if this message // is in response to another message that was using APS security this message // will be sent with APS security if ( !( options & AF_EN_SECURITY ) ) { afIncomingMSGPacket_t *origPkt = zcl_getRawAFMsg(); if ( ( origPkt != NULL ) && ( origPkt->SecurityUse == TRUE ) ) { options |= AF_EN_SECURITY; } } } zcl_memset( &hdr, 0, sizeof( zclFrameHdr_t ) ); // Not Profile wide command (like READ, WRITE) if ( specific ) { hdr.fc.type = ZCL_FRAME_TYPE_SPECIFIC_CMD; } else { hdr.fc.type = ZCL_FRAME_TYPE_PROFILE_CMD; } if ( ( epDesc->simpleDesc == NULL ) || ( zcl_DeviceOperational( srcEP, clusterID, hdr.fc.type, cmd, epDesc->simpleDesc->AppProfId ) == FALSE ) ) { return ( ZFailure ); // EMBEDDED RETURN } // Fill in the Maufacturer Code if ( manuCode != 0 ) { hdr.fc.manuSpecific = 1; hdr.manuCode = manuCode; } // Set the Command Direction if ( direction ) { hdr.fc.direction = ZCL_FRAME_SERVER_CLIENT_DIR; } else { hdr.fc.direction = ZCL_FRAME_CLIENT_SERVER_DIR; } // Set the Disable Default Response field if ( disableDefaultRsp ) { hdr.fc.disableDefaultRsp = 1; } else { hdr.fc.disableDefaultRsp = 0; } // Fill in the Transaction Sequence Number hdr.transSeqNum = seqNum; // Fill in the command hdr.commandID = cmd; // calculate the needed buffer size msgLen = zclCalcHdrSize( &hdr ); msgLen += cmdFormatLen; // Allocate the buffer needed msgBuf = zcl_mem_alloc( msgLen ); if ( msgBuf != NULL ) { // Fill in the ZCL Header pBuf = zclBuildHdr( &hdr, msgBuf ); // Fill in the command frame zcl_memcpy( pBuf, cmdFormat, cmdFormatLen ); status = AF_DataRequestSrcRtg( destAddr, epDesc, clusterID, msgLen, msgBuf, &APS_Counter, options, zcl_radius, srcrtg.relayCnt, srcrtg.pRelayList ); if(srcrtg.pRelayList!=NULL) { zcl_mem_free(srcrtg.pRelayList); } zcl_mem_free ( msgBuf ); } else { status = ZMemError; } return ( status ); }