轉自:http://blog.csdn.net/yi412/article/details/45602929
我使用的協議棧版本及例子信息:
ZigBee2006\TexasInstruments\ZStack-1.4.3-1.2.1\Projects\zstack\Samples\SampleApp
以下爲系統處理來自AF層數據包的大致流程,
afIncomingData() ——afBuildMSGIncoming() ——osal_msg_send() —— osal_set_event()——
根據task_id調用事件處理函數(如SampleApp_ProcessEvent())——判斷具體事件類型調用相應回調函數(如SampleApp_MessageMSGCB())——實現具體現象
afIncomingData()函數用來從APS層傳遞一個ASDU到AF層;中間調用了afBuildMSGIncoming()函數,這個函數是用來爲APS層建立一個特定格式的消息包,然後再調用osal_msg_send()把消息(包含了ASDU)傳往AF層.
AF層規定接收的數據包的類型如下:
typedefstruct
{
osal_event_hdr_t hdr;
uint16 groupId;
uint16 clusterId;
afAddrType_t srcAddr;
byte endPoint;
byte wasBroadcast;
byte LinkQuality;
byte SecurityUse;
uint32 timestamp;
afMSGCommandFormat_t cmd;
}afIncomingMSGPacket_t;
首先看一下afIncomingData()函數
//傳輸數據:APS---->AF
void afIncomingData(aps_FrameFormat_t *aff, zAddrType_t*SrcAddress,
uint8 LinkQuality, byte SecurityUse, uint32 timestamp)
{
endPointDesc_t*epDesc = NULL;
uint16 epProfileID =0xFFFF; // Invalid ProfileID
epList_t*pList;
uint8grpEp;
//-----------
if (((aff->FrmCtrl &APS_DELIVERYMODE_MASK) == APS_FC_DM_GROUP))
{
// Find the first endpoint for thisgroup
grpEp = aps_FindGroupForEndpoint( aff->GroupID,APS_GROUPS_FIND_FIRST );
if ( grpEp == APS_GROUPS_EP_NOT_FOUND )
return; // No endpointfound,沒找到終端
epDesc = afFindEndPointDesc( grpEp); //找到終端,接着找終端描述符
if ( epDesc == NULL )
return; // Endpoint descriptor notfound,沒找到終端描述符
pList = afFindEndPointDescList( epDesc->endPoint); //找到終端描述符
} //pList指向終端列表中的元素
//-----------
else if (aff->DstEndPoint == AF_BROADCAST_ENDPOINT)
{
// Set thelist
if ( (pList = epList) )
{
epDesc = pList->epDesc;
}
}
//-----------
else if ( (epDesc =afFindEndPointDesc( aff->DstEndPoint )))
{
pList = afFindEndPointDescList( epDesc->endPoint);
}
//-----------
while ( epDesc)
{
if ( pList->pfnDescCB ) //如果有回叫函數
{
uint16 *pID = (uint16*)(pList->pfnDescCB(
AF_DESCRIPTOR_PROFILE_ID, epDesc->endPoint));
if ( pID )
{
epProfileID = *pID;
osal_mem_free( pID );
}
}
else if ( epDesc->simpleDesc ) //簡單描述符
{
epProfileID =epDesc->simpleDesc->AppProfId;
}
if ( (aff->ProfileID == epProfileID)||
((epDesc->endPoint == ZDO_EP)&& (aff->ProfileID== ZDO_PROFILE_ID)) ) //符合各條件
{
{
//建立信息傳遞,注意,這裏調用afBuildMSGIncoming()!!
afBuildMSGIncoming(aff, epDesc, SrcAddress, LinkQuality, SecurityUse, timestamp);
}
}
if ( ((aff->FrmCtrl &APS_DELIVERYMODE_MASK) == APS_FC_DM_GROUP))
{
// Find the next endpoint for thisgroup
grpEp = aps_FindGroupForEndpoint( aff->GroupID,grpEp );
if ( grpEp == APS_GROUPS_EP_NOT_FOUND )
return; // No endpointfound
epDesc = afFindEndPointDesc( grpEp );
if ( epDesc == NULL )
return; //Endpoint descriptor not found
pList = afFindEndPointDescList( epDesc->endPoint); //epDesc !=NULL
}
else if ( aff->DstEndPoint == AF_BROADCAST_ENDPOINT)
{
pList = pList->nextDesc;
if ( pList )
epDesc = pList->epDesc;
else
epDesc = NULL;
}
else
epDesc = NULL;
}
}
//----------------------------------------------------------------------------------------
afBuildMSGIncoming( aff, epDesc, SrcAddress,LinkQuality, SecurityUse, timestamp )
afBuildMSGIncoming( aps_FrameFormat_t *aff,endPointDesc_t *epDesc,
zAddrType_t *SrcAddress, uint8 LinkQuality, byteSecurityUse,
uint32 timestamp )
實參——形參
Aff——*aff
epDesc——*epDesc
SrcAddress——*SrcAddress
LinkQuality—— LinkQuality
SecurityUse—— SecurityUse
Timestamp—— timestamp
看一下afBuildMSGIncoming()函數
*********************************************************************
//Buildthe message for the app
static voidafBuildMSGIncoming( aps_FrameFormat_t *aff, endPointDesc_t*epDesc,
zAddrType_t*SrcAddress, uint8 LinkQuality, byteSecurityUse,
uint32 timestamp )
{
afIncomingMSGPacket_t*MSGpkt; //AF層需要接收這種結構體類型的信息包
//下面就通過本函數來爲接收到的信息構造這種類型
//信息包,從而可以發送到AF層去
const byte len =sizeof( afIncomingMSGPacket_t ) +aff->asduLength; //長度
byte *asdu =aff->asdu;
MSGpkt =(afIncomingMSGPacket_t *)osal_msg_allocate( len); //分配內存
if ( MSGpkt == NULL)
{
return;
}
MSGpkt->hdr.event = AF_INCOMING_MSG_CMD; //事件類型
MSGpkt->groupId =aff->GroupID; //組ID
MSGpkt->clusterId =aff->ClusterID; //簇ID
afCopyAddress(&MSGpkt->srcAddr, SrcAddress); //源地址
MSGpkt->srcAddr.endPoint =aff->SrcEndPoint;
MSGpkt->endPoint =epDesc->endPoint;
MSGpkt->wasBroadcast =aff->wasBroadcast; //廣播
MSGpkt->LinkQuality = LinkQuality; //鏈路質量
MSGpkt->SecurityUse = SecurityUse; //安全使能
MSGpkt->timestamp = timestamp; //時間
MSGpkt->cmd.TransSeqNumber = 0; //傳送序號
MSGpkt->cmd.DataLength =aff->asduLength; //長度
if (MSGpkt->cmd.DataLength ) //aff->asduLength
{
MSGpkt->cmd.Data = (byte *)(MSGpkt +1); //空間
//把長爲MSGpkt->cmd.DataLength數據從asdu賦給MSGpkt->cmd.Data
osal_memcpy( MSGpkt->cmd.Data, asdu,MSGpkt->cmd.DataLength );
}
else //無數據
{
MSGpkt->cmd.Data = NULL;
}
#if defined ( MT_AF_CB_FUNC)
// If MT has subscribed for this callback, don't send asa message.
ifAFCB_CHECK(MSGpkt->endPoint,*(epDesc->task_id),SPI_CB_AF_DATA_IND)
{
af_MTCB_IncomingData( (void *)MSGpkt );
// Release thememory.
osal_msg_deallocate( (void *)MSGpkt );
}
else
#endif
{
// Send message through taskmessage.
//數據包構造好後,就要發送到AF層,這裏調用osal_msg_send()
osal_msg_send( *(epDesc->task_id),(uint8 *)MSGpkt );
}
}
*********************************************************************
byte osal_msg_send( bytedestination_task, byte *msg_ptr )
{
//--------------------------------
if ( msg_ptr == NULL) //無消息
return (INVALID_MSG_POINTER );
//--------------------------------
if ( destination_task>= tasksCnt ) //不在任務條目範圍內???任務不合法
{
osal_msg_deallocate( msg_ptr );
return ( INVALID_TASK );
}
//--------------------------------
// Check the message header
if ( OSAL_MSG_NEXT(msg_ptr ) != NULL ||
OSAL_MSG_ID( msg_ptr ) != TASK_NO_TASK) //檢查到指針不合法
{
osal_msg_deallocate( msg_ptr ); //釋放這個消息內存
return ( INVALID_MSG_POINTER );
}
OSAL_MSG_ID( msg_ptr) = destination_task; //檢查到含有合法任務的消息,
//則把目的任務的ID賦給消息結構體的dest_id
//OSAL_MSG_ID()參見前面
//--------------------------------
// queue message 把當前消息(msg_ptr所指)加入到系統消息列表中
osal_msg_enqueue(&osal_qHead, msg_ptr );
//--------------------------------
// Signal the taskthat a message is waiting
osal_set_event(destination_task, SYS_EVENT_MSG ); //設置事件發生標誌函數!!
return ( ZSUCCESS);
}
*********************************************************************/
byte osal_set_event( byte task_id, UINT16event_flag )
{
if ( task_id< tasksCnt )
{
halIntState_t intState;
HAL_ENTER_CRITICAL_SECTION(intState); // Hold offinterrupts
tasksEvents[task_id] |= event_flag; // Stuff the event bit(s) 相應任務有事件發生
HAL_EXIT_CRITICAL_SECTION(intState); // Releaseinterrupts
}
else
return ( INVALID_TASK );
return ( ZSUCCESS);
}
//判斷OSAL層的消息類型
if ( events& SYS_EVENT_MSG )
{
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive(SampleApp_TaskID ); //接收屬於本用戶應用SampleApp的
消息(SampleApp_TaskID來標誌)
while ( MSGpkt ) //接收到着
{ //屬於這個應用的消息osal_msg_receive( MApp_TaskID);
switch ( MSGpkt->hdr.event ) //判斷數據包事件類型
{
// Received when a key ispressed
case AF_INCOMING_MSG_CMD: // #define AF_INCOMING_MSG_CMD 0x 1A --Incoming MSG typemessage
SampleApp_MessageMSGCB( MSGpkt );
break;
// Received whenever the device changes statein the network
case ZDO_STATE_CHANGE: //#define ZDO_STATE_CHANGE 0xD1 --ZDO has changed thedevice's network state
SampleApp_NwkState =(devStates_t)(MSGpkt->hdr.status);
if ( (SampleApp_NwkState ==DEV_ZB_COORD)
|| (SampleApp_NwkState == DEV_ROUTER)
|| (SampleApp_NwkState == DEV_END_DEVICE))
{
// Start sending the periodic message in aregular interval.
osal_start_timerEx( SampleApp_TaskID,
SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );
}
else
{
// Device is no longer in thenetwork
}
break;
default:
break;
}
// Release thememory
//釋放消息佔用的內存
osal_msg_deallocate( (uint8 *)MSGpkt );
// Next - if one isavailable
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive(SampleApp_TaskID );
} //end:while (MSGpkt )
// return unprocessed events
// 判斷是否有未處理的系統消息,有則接收返回沒有處理的事件
return (events ^ SYS_EVENT_MSG); //注意!這裏return到osal_start_system()下
}
//--------------------------
// Send a message out - This event is generated by atimer
// (setupin SampleApp_Init()).
if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT) //發送週期消息
{
// Send the periodicmessage
SampleApp_SendPeriodicMessage();
// Setup to send message again innormal period (+ a little jitter)
osal_start_timerEx( SampleApp_TaskID,SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
(SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand()& 0x00FF)) );
// return unprocessedevents
return (events ^SAMPLEAPP_SEND_PERIODIC_MSG_EVT);
}
// Discard unknownevents
return0;
}
//SampleApp_MessageMSGCB()功能是處理接收數據,函數
//的輸入爲接收到的數據,而輸出爲小燈閃爍的時間。
void SampleApp_MessageMSGCB(afIncomingMSGPacket_t *pkt )
{
uint16flashTime;
switch ( pkt->clusterId )//判斷簇ID
{
case SAMPLEAPP_PERIODIC_CLUSTERID: //periodic
break;
case SAMPLEAPP_FLASH_CLUSTERID: //flash
flashTime = BUILD_UINT16(pkt->cmd.Data[1],pkt->cmd.Data[2] );
HalLedBlink( HAL_LED_4, 4, 50, (flashTime / 4) ); //小燈閃爍四次
break;
}
}