ZDO层的初使化在
void osalInitTasks( void )
{uint8 taskID = 0;
tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);
osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));
macTaskInit( taskID++ );
nwk_init( taskID++ );
Hal_Init( taskID++ );
#if defined( MT_TASK )
MT_TaskInit( taskID++ );
#endif
APS_Init( taskID++ );
#if defined ( ZIGBEE_FRAGMENTATION )
APSF_Init( taskID++ );
#endif
ZDApp_Init( taskID++ );
#if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )
ZDNwkMgr_Init( taskID++ );
#endif
Console_Init( taskID++ );
Comm_UartTaskInit (taskID++);
App_Init( taskID++);
}
ZDO层的循环事件函数
const pTaskEventHandlerFn tasksArr[] = {
macEventLoop,
nwk_event_loop,
Hal_ProcessEvent,
#if defined( MT_TASK )
MT_ProcessEvent,
#endif
APS_event_loop,
#if defined ( ZIGBEE_FRAGMENTATION )
APSF_ProcessEvent,
#endif
ZDApp_event_loop,
#if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )
ZDNwkMgr_event_loop,
#endif
Console_ProcessEvent,
Comm_UartTaskPro,
App_ProcessEvent
};
先看初使化函数
void ZDApp_Init( uint8 task_id )
{
// Save the task ID
ZDAppTaskID = task_id;
// Initialize the ZDO global device short address storage
ZDAppNwkAddr.addrMode = Addr16Bit;
ZDAppNwkAddr.addr.shortAddr = INVALID_NODE_ADDR;
(void)NLME_GetExtAddr(); // Load the saveExtAddr pointer.
// Check for manual "Hold Auto Start"
ZDAppCheckForHoldKey();
// Initialize ZDO items and setup the device - type of device to create.
ZDO_Init();
// Register the endpoint description with the AF
// This task doesn't have a Simple description, but we still need
// to register the endpoint.
afRegister( (endPointDesc_t *)&ZDApp_epDesc );//在这里和应用层一样,先通过端点描述符注册端点。这样,从APS层到ZDO层的数据首先到达 afIncomingData函数
#if defined( ZDO_USERDESC_RESPONSE )
ZDApp_InitUserDesc();
#endif // ZDO_USERDESC_RESPONSE
// Start the device?
if ( devState != DEV_HOLD )
{
ZDOInitDevice( 0 );
}
else
{
// Blink LED to indicate HOLD_START
HalLedBlink ( HAL_LED_4, 0, 50, 500 );
}
ZDApp_RegisterCBs();//这个函数下面讲
}
void ZDApp_RegisterCBs( void )//这个函数里注册ZDO从空中来的一些响应簇到ZDAppTaskID
{
#if defined ( ZDO_IEEEADDR_REQUEST ) || defined ( REFLECTOR )
ZDO_RegisterForZDOMsg( ZDAppTaskID, IEEE_addr_rsp );
#endif
#if defined ( ZDO_NWKADDR_REQUEST ) || defined ( REFLECTOR )
ZDO_RegisterForZDOMsg( ZDAppTaskID, NWK_addr_rsp );
#endif
#if ZG_BUILD_COORDINATOR_TYPE
ZDO_RegisterForZDOMsg( ZDAppTaskID, Bind_rsp );
ZDO_RegisterForZDOMsg( ZDAppTaskID, Unbind_rsp );
ZDO_RegisterForZDOMsg( ZDAppTaskID, End_Device_Bind_req );
#endif
#if defined ( REFLECTOR )
ZDO_RegisterForZDOMsg( ZDAppTaskID, Bind_req );
ZDO_RegisterForZDOMsg( ZDAppTaskID, Unbind_req );
#endif
}
ZStatus_t ZDO_RegisterForZDOMsg( uint8 taskID, uint16 clusterID )
//从函数的内容可以知道,注册一个簇实际就是在zdoMsgCBs链表中增加一个元素, typedef struct{void *next;uint8 taskID;uint16 clusterID;} ZDO_MsgCB_t;
{
ZDO_MsgCB_t *pList;
ZDO_MsgCB_t *pLast;
ZDO_MsgCB_t *pNew;
// Look for duplicate
pList = pLast = zdoMsgCBs;
while ( pList )
{
if ( pList->taskID == taskID && pList->clusterID == clusterID )
{
return ( ZSuccess );
}
pLast = pList;
pList = (ZDO_MsgCB_t *)pList->next;
}
// Add to the list
pNew = (ZDO_MsgCB_t *)osal_mem_alloc( sizeof ( ZDO_MsgCB_t ) );
if ( pNew )
{
pNew->taskID = taskID;
pNew->clusterID = clusterID;
pNew->next = NULL;
if ( zdoMsgCBs )
{
pLast->next = pNew;
}
else
{
zdoMsgCBs = pNew;
}
return ( ZSuccess );
}
else
{
return ( ZMemError );
}
}
在ZDApp_event_loop中的SYS_EVENT_MSG事件中会调用ZDApp_ProcessOSALMsg( (osal_event_hdr_t *)msg_ptr )函数。这个函数首先会对到来的消息做判断,如果消息是从APS层过来的(AF_INCOMING_MSG_CMD),则会调用ZDP_IncomingData( (afIncomingMSGPacket_t *)msgPtr ):
void ZDP_IncomingData( afIncomingMSGPacket_t *pData )
{
uint8 x = 0;
uint8 handled;
zdoIncomingMsg_t inMsg;
inMsg.srcAddr.addrMode = Addr16Bit;
inMsg.srcAddr.addr.shortAddr = pData->srcAddr.addr.shortAddr;
inMsg.wasBroadcast = pData->wasBroadcast;
inMsg.clusterID = pData->clusterId;
inMsg.SecurityUse = pData->SecurityUse;
inMsg.asduLen = pData->cmd.DataLength-1;
inMsg.asdu = pData->cmd.Data+1;
inMsg.TransSeq = pData->cmd.Data[0];
inMsg.macDestAddr = pData->macDestAddr;
handled = ZDO_SendMsgCBs( &inMsg );//这个函数会判断到来的消息对应的簇是否为response,并且是否已经在zdoMsgCBs链表中注册过,如果注册过,则把这条消息 // copy到ZDO_CB_MSG,再发给ZDApptask任务。
#if (defined MT_ZDO_CB_FUNC)
#if !defined MT_TASK
if (zgZdoDirectCB)
#endif
{
MT_ZdoDirectCB( pData, &inMsg );
}
#endif
while ( zdpMsgProcs[x].clusterID != 0xFFFF )
{
if ( zdpMsgProcs[x].clusterID == inMsg.clusterID )//判断这条消息是否为request消息,如果是request消息则在zdpMsgProcs结构体数组中通过指针调用对应簇ID的函数对其
//做出相应的响应,然后直接return函数
{
zdpMsgProcs[x].pFn( &inMsg );
return;
}
x++;
}
// Handle unhandled messages
if ( !handled ) //如果在zdoMsgCBs链表中没有这条消息的簇ID,并且在adpMsgProcs结构体数组中也没有发现这条消息对应的簇ID,那么就认为这条ZDO消息不被设备支持,
//即调用ZDApp_inMsgCB(&inMsg)函数做错误处理。
ZDApp_InMsgCB( &inMsg );
}
void ZDApp_ProcessOSALMsg( osal_event_hdr_t *msgPtr )
{
// Data Confirmation message fields
uint8 sentEP; // This should always be 0
uint8 sentStatus;
afDataConfirm_t *afDataConfirm;
uint8 tmp;
switch ( msgPtr->event )
{
// Incoming ZDO Message
case AF_INCOMING_MSG_CMD:
ZDP_IncomingData( (afIncomingMSGPacket_t *)msgPtr );
break;
case ZDO_CB_MSG: //从上面的注释可以知道,进入这个case的消息首先都会进入AF_INCOMING_MSG_CMD,只有ZDO在AF_INCOMING_MSG_CMD中发现从APS过来 // 的消息是在zdoMsgCBs链表中注册过的response簇,才会把这个消息通过OSAL机制设置为ZDO_CB_MSG事件COPY到这里。
ZDApp_ProcessMsgCBs( (zdoIncomingMsg_t *)msgPtr );
break;
.....