这里参考了网上许多资料,但有些东西还是不同,记录在此,以备学习。
devState: DEV_INIT→DEV_COORD_STARTING->DEV_ZB_COORD
devStartMode :MODE_HARD
1:main()
2:osal_init_system()
3:osalinittasks()
4:zdapp_init()
主要完成以下初始化:
/*********************************************************************
* @fn ZDApp_Init
*
* @brief ZDApp Initialization function.
*
* @param task_id - ZDApp Task ID
*
* @return None
*/
void ZDApp_Init( uint8 task_id )
{
// Save the task ID
ZDAppTaskID = task_id;//初始化任务ID
// Initialize the ZDO global device short address storage
ZDAppNwkAddr.addrMode = Addr16Bit;//16位短地址
ZDAppNwkAddr.addr.shortAddr = INVALID_NODE_ADDR;//网络地址shortAddr无效
(void)NLME_GetExtAddr(); // Load the saveExtAddr pointer.保存64位IEEE地址
// 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 );
#if defined( ZDO_USERDESC_RESPONSE )
ZDApp_InitUserDesc();
#endif // ZDO_USERDESC_RESPONSE
// Start the device?
if ( devState != DEV_HOLD )
{//initial value of devState is DEV_INIT
ZDOInitDevice( 0 );ZDO初始化设备 ZDOInitDevice()
}
else
{// Init ZDO, but hold and wait for application to start the joining or
// forming network
ZDOInitDevice( ZDO_INIT_HOLD_NWK_START );
// Blink LED to indicate HOLD_START
HalLedBlink ( HAL_LED_4, 0, 50, 500 );
}
// Initialize the ZDO callback function pointers zdoCBFunc[]
ZDApp_InitZdoCBFunc();
ZDApp_RegisterCBs();//注册响应事件,比如64位IEEE地址,还有协调器的加入响应,端点节点绑定响应等
} /* ZDApp_Init() */
5:zdo_init()
ZDObject and ZDProfile initialization.
6:ZDODeviceSetup()
/*********************************************************************
* @fn ZDODeviceSetup()
*
* @brief Call set functions depending on the type of device compiled.
*
* @param none
*
* @return none
*/
static void ZDODeviceSetup( void )
{
if ( ZG_BUILD_COORDINATOR_TYPE )
{
NLME_CoordinatorInit();//协调器的初始化
}
#if defined ( REFLECTOR )
APS_ReflectorInit( (ZG_DEVICE_COORDINATOR_TYPE) ? APS_REFLECTOR_PUBLIC : APS_REFLECTOR_PRIVATE );
#endif//参考节点的初始化
if ( ZG_BUILD_JOINING_TYPE )
{
NLME_DeviceJoiningInit();//设备加入的初始化
}
}
7:ZDOInitDevice()
uint8 networkStateNV = ZDO_INITDEV_NEW_NETWORK_STATE;//这个变量用来决定是否网络处于了已经准备好等待应用程序加入的状态
,如果没有准备好,系统就会再次使用osal_set_event()函数通知系统在coordinator进行网络组建初始化时
没有初始化coordinator建网成功,否则,如果准备好了,就就继续为创建网络而进行网络初始化工作
#if defined( HOLD_AUTO_START )
devStates_t devState = DEV_HOLD;
#else
devStates_t devState = DEV_INIT;
#endif
8:ZDApp_NetworkInit()
/*********************************************************************
* @fn ZDApp_NetworkInit()
*
* @brief Used to start the network joining process
*
* @param delay - mSec delay to wait before starting
*
* @return none
*/
void ZDApp_NetworkInit( uint16 delay )
{
if ( delay )
{
// Wait awhile before starting the device
osal_start_timerEx( ZDAppTaskID, ZDO_NETWORK_INIT, delay );
}
else
{
osal_set_event( ZDAppTaskID, ZDO_NETWORK_INIT );
}
}
让ZDO任务事件函数ZDApp_event_loop去处理这些事件状态的变化,如何处理呢?(换句话,程序怎样才能找到ZDApp_event_loop?)
9:ZDApp_event_loop()
if ( events & ZDO_NETWORK_INIT )
{
// Initialize apps and start the network
devState = DEV_INIT;
osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );
ZDO_StartDevice( (uint8)ZDO_Config_Node_Descriptor.LogicalType, devStartMode,
DEFAULT_BEACON_ORDER, DEFAULT_SUPERFRAME_ORDER );
// Return unprocessed events
return (events ^ ZDO_NETWORK_INIT);
}
这里有一个关键的变量devStartMode
#if ( ZG_BUILD_RTRONLY_TYPE ) || ( ZG_BUILD_ENDDEVICE_TYPE )
devStartModes_t devStartMode = MODE_JOIN; // Assume joining
//devStartModes_t devStartMode = MODE_RESUME; // if already "directly joined"
// to parent. Set to make the device do an Orphan scan.
#else
// Set the default to coodinator,开始的时候肯定时作为coordinator,因为,这就是在分析coordinator的代码,并且前两个宏也肯定定义的!
devStartModes_t devStartMode = MODE_HARD;
#endif
10:ZDO_StartDevice()
相关代码如下所示:
startMode = devStartMode的值,通过调用ZDO_StartDevice()时的参数传递
if ( ZG_BUILD_COORDINATOR_TYPE && logicalType == NODETYPE_COORDINATOR )
{
if ( startMode == MODE_HARD )
{
devState = DEV_COORD_STARTING;
ret = NLME_NetworkFormationRequest( zgConfigPANID, zgApsUseExtendedPANID, zgDefaultChannelList,
zgDefaultStartingScanDuration, beaconOrder,
superframeOrder, false );
}
在调用NLME_NetworkFormationRequest()函数之后,如果成功会返回ZSuccess=ret,如果不成功的话,接着调用
if ( ret != ZSuccess )
{
osal_start_timerEx(ZDAppTaskID, ZDO_NETWORK_INIT, NWK_RETRY_DELAY );
}
会再次通知系统,让系统另外给一个网络初始化的事件,并为该事件另外设置一个定时器
11:NLME_NetworkFormationRequest()
/*********************************************************************
* NWK Management Service
* NLME-NETWORK-FORMATION//在此时使用的是这一条
* NLME-NETWORK-DISCOVERY
* NLME-PERMIT-JOINING
* NLME-JOIN
* NLME-DIRECT-JOIN
* NLME-ORPHAN-JOIN
* NLME-START-ROUTER
* NLME-SYNC
* NLME-LEAVE
* NLME-RESET
* NLME-GET
* NLME-SET
*/
/*
* This function allows the next higher layer to request that the device
* form a new network and become the ZigBee Coordinator for that network.
*
* @MT SPI_CMD_NLME_INIT_COORD_REQ
* (uint16 PanId,
* uint32 ScanChannels,
* byte BeaconOrder,
* byte ScanDuration,
* byte SuperFrameOrder,
* byte BatteryLifeExtension)
*
*/
extern ZStatus_t NLME_NetworkFormationRequest( uint16 PanId, uint8* ExtendedPANID, uint32 ScanChannels,
byte ScanDuration, byte BeaconOrder,
byte SuperframeOrder, byte BatteryLifeExtension );
对于这个函数的一些参数请参见:f8wConfig.Cfg配置文件
个域网ID号和默认通道号在f8wConfig.Cfg中定义:
-DZDAPP_CONFIG_PAN_ID=0xFFFF
-DDEFAULT_CHANLIST=0x00000800 // 11 - 0x0B
外扩个域网ID号在ZGlobals.c中定义:
zgApsUseExtendedPANID[Z_EXTADDR_LEN] = {00,00,00,00,00,00,00,00};
调用之后,剩下的工作就由MAC和PHY来完成了,这个过程应用是查询不到的,也即是形成网络的非常具体的过程查询不到,如果能查询到请共享一下
12:ZDO_NetworkFormationConfirmCB()
/*********************************************************************
* @fn ZDO_NetworkFormationConfirmCB
*
* @brief This function reports the results of the request to
* initialize a coordinator in a network.
*
* @param Status - Result of NLME_NetworkFormationRequest()
*
* @return none
*/
void ZDO_NetworkFormationConfirmCB( ZStatus_t Status )
{
nwkStatus = (byte)Status;
if ( Status == ZSUCCESS )
{
// LED on shows Coordinator started
HalLedSet ( HAL_LED_3, HAL_LED_MODE_ON );
// LED off forgets HOLD_AUTO_START
HalLedSet (HAL_LED_4, HAL_LED_MODE_OFF);
#if defined ( ZBIT )
SIM_SetColor(0xd0ffd0);
#endif
if ( devState == DEV_HOLD )//devState这个变量没有修改过,值没有改变到此处
{
// Began with HOLD_AUTO_START
devState = DEV_COORD_STARTING;//该设备将在网络中作为一个coordiantor来用
}
}
#if defined(BLINK_LEDS)
else
{
HalLedSet ( HAL_LED_3, HAL_LED_MODE_FLASH ); // Flash LED to show failure
}
#endif
osal_set_event( ZDAppTaskID, ZDO_NETWORK_START );//发起此事件到ZDO层,让ZDO层的事件处理函数来处理这一事件的状态变化
}
13:ZDApp_event_loop()
if ( events & ZDO_NETWORK_START )
{
ZDApp_NetworkStartEvt();
// Return unprocessed events
return (events ^ ZDO_NETWORK_START);
}
14:ZDApp_NetworkStartEvt()
这里注意到nwkStatus这个变量,它在之前调用ZDO_NetworkFormationConfirmCB( ZStatus_t Status )时,已经通过
nwkStatus = (byte)Status;把应该知道的值给保存了下来,因此,当成功的时候nwkStatus和ZSuccess肯定是相等的
if ( nwkStatus == ZSuccess )
{
// Successfully started a ZigBee network
if ( devState == DEV_COORD_STARTING )
{
devState = DEV_ZB_COORD;
}
osal_pwrmgr_device( PWRMGR_ALWAYS_ON );
osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );
}
经过这个函数之后,coordinator已经在网络中起作用了,并向系统发送事件ZDO_STATE_CHANGE_EVT
15:ZDApp_event_loop()
if ( events & ZDO_STATE_CHANGE_EVT )
{
ZDO_UpdateNwkStatus( devState );//转到这个更新函数
// At start up, do one MTO route discovery if the device is a concentrator
if ( zgConcentratorEnable == TRUE )
{
// Start next event
osal_start_timerEx( NWK_TaskID, NWK_MTO_RTG_REQ_EVT, 100 );
}
// Return unprocessed events
return (events ^ ZDO_STATE_CHANGE_EVT);
}
16: ZDO_UpdateNwkStatus
/**************************************************************************************************
* @fn ZDO_UpdateNwkStatus
*
* @brief This function sends a ZDO_STATE_CHANGE message to the task of every EndPoint
* registered with AF (except, of course, the ZDO_EP). Even if a single task has more
* than one registered EndPoint, it will only receive one notification per state
* change. Although the device may go through a sequence of state changes, the
* Application task may only receive notification of the final, steady-state state
* because it has the lowest priority and never even runs to receive the intermediate
* state change notifications.
*
* input parameters
*
* @param state - The current device state.
*
* output parameters
*
* None.
*
* @return None.
**************************************************************************************************
*/
void ZDO_UpdateNwkStatus(devStates_t state)
{
epList_t *pItem = epList;
while (pItem != NULL)
{
if (pItem->epDesc->endPoint != ZDO_EP)
{
zdoSendStateChangeMsg(state, *(pItem->epDesc->task_id));
}
pItem = pItem->nextDesc;
}
#if defined MT_ZDO_CB_FUNC
zdoSendStateChangeMsg(state, MT_TaskID);//主要关注这里, state=devState = DEV_ZB_COORD;转到此函数
#endif
ZDAppNwkAddr.addr.shortAddr = NLME_GetShortAddr();
(void)NLME_GetExtAddr(); // Load the saveExtAddr pointer.
}
17:zdoSendStateChangeMsg()
/**************************************************************************************************
* @fn zdoSendStateChangeMsg
*
* @brief Helper function for ZDO_UpdateNwkStatus.
*
* input parameters
*
* @param taskId - The OSAL task identifier to which to send the ZDO_STATE_CHANGE_EVT.
* @param state - The current device state.
*
* output parameters
*
* None.
*
* @return None.
**************************************************************************************************
*/
static void zdoSendStateChangeMsg(uint8 state, uint8 taskId)
{
osal_event_hdr_t *pMsg = (osal_event_hdr_t *)osal_msg_find(taskId, ZDO_STATE_CHANGE);
if (NULL == pMsg)
{
if (NULL == (pMsg = (osal_event_hdr_t *)osal_msg_allocate(sizeof(osal_event_hdr_t))))
{
// Upon failure to notify any EndPoint of the state change, re-set the ZDO event to
// try again later when more Heap may be available.
osal_set_event(ZDAppTaskID, ZDO_STATE_CHANGE_EVT);
}
else
{
pMsg->event = ZDO_STATE_CHANGE;
pMsg->status = state;
(void)osal_msg_send(taskId, (uint8 *)pMsg);//转到这个函数里面
}
}
else
{
// Modify in place the status of an existing ZDO_STATE_CHANGE message to the EndPoint.
pMsg->status = state;
}
}
18:osal_msg_send()
/*********************************************************************
* @fn osal_msg_send
*
* @brief
*
* This function is called by a task to send a command message to
* another task or processing element. The sending_task field must
* refer to a valid task, since the task ID will be used
* for the response message. This function will also set a message
* ready event in the destination tasks event list.
*
*
* @param uint8 destination task - Send msg to? Task ID
* @param uint8 *msg_ptr - pointer to new message buffer
* @param uint8 len - length of data in message
*
* @return SUCCESS, INVALID_TASK, INVALID_MSG_POINTER
*/
uint8 osal_msg_send( uint8 destination_task, uint8 *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;
// queue message
osal_msg_enqueue( &osal_qHead, msg_ptr );
// Signal the task that a message is waiting
osal_set_event( destination_task, SYS_EVENT_MSG );//这里向系统里发送一个事件SYS_EVENT_MSG,destination_task=MT_TaskID,MT_TaskID在zdoSendStateChangeMsg()函数里面
return ( SUCCESS );
}
20:main()->osal_start_system()->osal_run_system()->(tasksArr[idx])(idx,event)---->MT_ProcessEvent()
/*********************************************************************
* GLOBAL VARIABLES
*/
// The order in this table must be identical to the task initialization calls below in osalInitTask.
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
SampleApp_ProcessEvent
};
相关代码如下:
if ( events & SYS_EVENT_MSG )//SYS_EVENT_MSG这个事件已经被osal_set_event()函数在osal_msg_send里面发出来了
{
uint8 *msg_ptr = osal_msg_receive(task_id);
if (msg_ptr != NULL)
{
MT_ProcessIncomingCommand((mtOSALSerialData_t *)msg_ptr);//转到
osal_msg_deallocate(msg_ptr);
}
21:MT_ProcessIncomingCommand()
#ifdef MT_ZDO_CB_FUNC
case ZDO_STATE_CHANGE:
MT_ZdoStateChangeCB((osal_event_hdr_t *)msg);//协调器组网成功
break;