2024年1月14日发(作者:)
1.
void ZDApp_Init( byte task_id )
{
uint8 capabilities;
// Save the task ID
ZDAppTaskID = task_id;
//设置任务id
// Initialize the ZDO global device short address storage
de = Addr16Bit;
ddr = INVALID_NODE_ADDR;
(void)NLME_GetExtAddr(); // Load the saveExtAddr pointer.
//函数的作用是返回指向64bitIEEE地址的指针,但这里有点奇怪,它好像没有接收这个指针
// Check for manual "Hold Auto Start"
ZDAppCheckForHoldKey();
//该函数的作用是如果HAL_KEY_SW_1键被按下,则not started automatically,如果不是自启动,则在自己的应用程序中要添加函数ZDOInitDevice( 0 )来启动建网过程,见Sample例子的应用程序
// 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
// set broadcast address mask to support broadcast filtering
NLME_GetRequest(nwkCapabilityInfo, 0, &capabilities);
//This function allows the next higher layer to get the value of a NIB (network information base)
attribute
NLME_SetBroadcastFilter( capabilities );
//This function sets a bit mask based on the capabilities of the device. It will be used to process
valid broadcast addresses
// 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();
} /* ZDO_Init() */
2.
void ZDApp_RegisterCBs( void )
{
#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 defined ( ZDO_COORDINATOR )
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
}
3.
ZStatus_t ZDO_RegisterForZDOMsg( uint8 taskID, uint16 clusterID )
{
ZDO_MsgCB_t *pList;
ZDO_MsgCB_t *pLast;
ZDO_MsgCB_t *pNew;
// Look for duplicate
pList = 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 );
}
该函数的作用是把新的ZDOMsg加入到这张表中。
4.
uint8 ZDOInitDevice( uint16 startDelay )
{
uint8 networkStateNV = ZDO_INITDEV_NEW_NETWORK_STATE;
uint16 extendedDelay = 0;
devState = DEV_INIT; // Remove the Hold state
// Initialize leave control logic
ZDApp_LeaveCtrlInit();
// Check leave control reset settings
ZDApp_LeaveCtrlStartup( &devState, &startDelay );
// Leave may make the hold state come back
if ( devState == DEV_HOLD )
return ( ZDO_INITDEV_LEAVE_NOT_STARTED ); // Don't join - (one time).
#if defined ( NV_RESTORE )
// Get Keypad directly to see if a reset nv is needed.
// Hold down the SW_BYPASS_NV key (defined in OnBoard.h)
// while booting to skip past NV Restore.
if ( HalKeyRead() == SW_BYPASS_NV )
networkStateNV = ZDO_INITDEV_NEW_NETWORK_STATE;
else
{
// Determine if NV should be restored
networkStateNV = ZDApp_ReadNetworkRestoreState();
}
if ( networkStateNV == ZDO_INITDEV_RESTORED_NETWORK_STATE )
{
networkStateNV = ZDApp_RestoreNetworkState();
}
else
{
// Wipe out the network state in NV
NLME_InitNV();
NLME_SetDefaultNV();
}
#endif
if ( networkStateNV == ZDO_INITDEV_NEW_NETWORK_STATE )
{
ZDAppDetermineDeviceType();
// Only delay if joining network - not restoring network state
extendedDelay = (uint16)((NWK_START_DELAY + startDelay)
+ (osal_rand() & EXTENDED_JOINING_RANDOM_MASK));
}
// Initialize device security
ZDApp_SecInit( networkStateNV );
// Trigger the network start
ZDApp_NetworkInit( extendedDelay );
return ( networkStateNV );
}
5.
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 );
}
}
6.
UINT16 ZDApp_event_loop( byte task_id, UINT16 events )
{
uint8 *msg_ptr;
if ( events & SYS_EVENT_MSG )
{
while ( (msg_ptr = osal_msg_receive( ZDAppTaskID )) )
{
ZDApp_ProcessOSALMsg( (osal_event_hdr_t *)msg_ptr );
// Release the memory
osal_msg_deallocate( msg_ptr );
}
// Return unprocessed events
return (events ^ SYS_EVENT_MSG);
}
if ( events & ZDO_STATE_CHANGE_EVT )
{
ZDO_UpdateNwkStatus( devState );
// Return unprocessed events
return (events ^ ZDO_STATE_CHANGE_EVT);
}
if ( events & ZDO_NETWORK_INIT )
{
// Initialize apps and start the network
devState = DEV_INIT;
ZDO_StartDevice( (uint8)ZDO_Config_Node_lType, devStartMode,
DEFAULT_BEACON_ORDER,
DEFAULT_SUPERFRAME_ORDER );
// Return unprocessed events
return (events ^ ZDO_NETWORK_INIT);
}
#if defined (RTR_NWK)
if ( events & ZDO_NETWORK_START )
{
ZDApp_NetworkStartEvt();
// Return unprocessed events
return (events ^ ZDO_NETWORK_START);
}
#endif //RTR_NWK
#if defined ( RTR_NWK )
if ( events & ZDO_ROUTER_START )
{
if ( nwkStatus == ZSuccess )
{
if ( devState == DEV_END_DEVICE )
devState = DEV_ROUTER;
osal_pwrmgr_device( PWRMGR_ALWAYS_ON );
}
else
{
// remain as end device!!
}
osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );
// Return unprocessed events
return (events ^ ZDO_ROUTER_START);
}
#endif // RTR
if ( events & ZDO_COMMAND_CNF )
{
// User defined logic
// Return unprocessed events
return (events ^ ZDO_COMMAND_CNF);
}
#if defined( ZDSECMGR_SECURE ) && defined( RTR_NWK )
if ( events & ZDO_NEW_DEVICE )
{
// process the new device event
if ( ZDSecMgrNewDeviceEvent() == TRUE )
{
osal_start_timerEx( ZDAppTaskID, ZDO_NEW_DEVICE, 1000 );
}
// Return unprocessed events
return (events ^ ZDO_NEW_DEVICE);
}
#endif // ZDSECMGR_SECURE && RTR
#if defined ( ZDSECMGR_COMMERCIAL )
if ( events & ZDO_SECMGR_EVENT )
{
ZDSecMgrEvent();
// Return unprocessed events
return (events ^ ZDO_SECMGR_EVENT);
}
#endif // defined( ZDSECMGR_COMMERCIAL )
#if ( SECURE != 0 )
if ( events & ZDO_DEVICE_AUTH )
{
ZDApp_DeviceAuthEvt();
// Return unprocessed events
return (events ^ ZDO_DEVICE_AUTH);
}
#endif // SECURE
if ( events & ZDO_NWK_UPDATE_NV )
{
ZDApp_SaveNetworkStateEvt();
// Return unprocessed events
return (events ^ ZDO_NWK_UPDATE_NV);
}
#if ( SECURE != 0 )
if ( events & ZDO_FRAMECOUNTER_CHANGE )
{
if ( nwkFrameCounterChanges++ > MAX_NWK_FRAMECOUNTER_CHANGES )
ZDApp_SaveNwkKey();
// Return unprocessed events
return (events ^ ZDO_FRAMECOUNTER_CHANGE);
}
#endif
if ( events & ZDO_DEVICE_RESET )
{
// The device has been in the UNAUTH state, so reset
// Note: there will be no return from this call
SystemReset();
}
// Discard or make more handlers
return 0;
}
7.
void ZDO_StartDevice( byte logicalType, devStartModes_t startMode, byte beaconOrder, byte
superframeOrder )
{
ZStatus_t ret;
ret = ZUnsupportedMode;
#if defined(ZDO_COORDINATOR)
if ( logicalType == NODETYPE_COORDINATOR )
{
if ( startMode == MODE_HARD )
{
devState = DEV_COORD_STARTING;
ret = NLME_NetworkFormationRequest( zgConfigPANID, zgDefaultChannelList,
zgDefaultStartingScanDuration, beaconOrder,
superframeOrder, false );
}
else if ( startMode == MODE_RESUME )
{
// Just start the coordinator
devState = DEV_COORD_STARTING;
ret = NLME_StartRouterRequest( beaconOrder, beaconOrder, false );
}
else
{
#if defined( LCD_SUPPORTED )
HalLcdWriteScreen( "StartDevice ERR", "MODE unknown" );
#endif
}
}
#endif // !ZDO_COORDINATOR
#if !defined ( ZDO_COORDINATOR ) || defined( SOFT_START )
if ( logicalType == NODETYPE_ROUTER || logicalType == NODETYPE_DEVICE )
{
if ( (startMode == MODE_JOIN) || (startMode == MODE_REJOIN) )
{
devState = DEV_NWK_DISC;
#if defined( MANAGED_SCAN )
ZDOManagedScan_Next();
ret = NLME_NetworkDiscoveryRequest( managedScanChannelMask,
BEACON_ORDER_15_MSEC );
#else
ret = NLME_NetworkDiscoveryRequest( zgDefaultChannelList,
zgDefaultStartingScanDuration );
#endif
}
else if ( startMode == MODE_RESUME )
{
if ( logicalType == NODETYPE_ROUTER )
{
ZMacScanCnf_t scanCnf;
devState = DEV_NWK_ORPHAN;
/* if router and nvram is available, fake successful orphan scan */
= ZSUCCESS;
pe = ZMAC_ORPHAN_SCAN;
nedChannels = 0;
ListSize = 0;
nwk_ScanJoiningOrphan(&scanCnf);
ret = ZSuccess;
}
else
{
devState = DEV_NWK_ORPHAN;
ret = NLME_OrphanJoinRequest( zgDefaultChannelList,
zgDefaultStartingScanDuration );
}
}
else
{
#if defined( LCD_SUPPORTED )
HalLcdWriteScreen( "StartDevice ERR", "MODE unknown" );
#endif
}
}
#endif //!ZDO COORDINATOR || SOFT_START
if ( ret != ZSuccess )
osal_start_timerEx(ZDAppTaskID, ZDO_NETWORK_INIT, NWK_RETRY_DELAY );
}
建立网络的过程大致是这样的:①在ZDApp_Init中调用ZDOInitDevice( 0 )这个函数;②在ZDOInitDevice中调用ZDApp_NetworkInit( extendedDelay )这个函数;③在ZDApp_NetworkInit( extendedDelay )中调用
osal_start_timerEx( ZDAppTaskID, ZDO_NETWORK_INIT, delay )这个函数来开启一个定时器;④定时时间到后在ZDApp_event_loop中的调用ZDO_StartDevice这个函数;⑤在ZDO_StartDevice这个函数中调用NLME_NetworkFormationRequest这个函数来建立网络;
如果不是自启动(是hold auto start),则在自己的应用程序中要添加函数ZDOInitDevice( 0 )来启动建网过程,见Sample例子的应用程序
协调器形成网络
osalInitTasks();
---->ZDApp_Init();
---->ZDOInitDevice();
---->ZDApp_NetworkInit();
---->osal_set_event( ZDAppTaskID, ZDO_NETWORK_INIT );
---->events & ZDO_NETWORK_INIT;
---->ZDO_StartDevice();
如果是协调器启动
---->NLME_NetworkFormationRequest();
如果是路由器或者终端设备第一次启动
---->NLME_NetworkDiscoveryRequest();
如果是路由器重新加入:
---->nwk_ScanJoiningOrphan();
如果是终端设备重新加入:
---->NLME_OrphanJoinRequest();
如果启动失败:
osal_start_timerEx(ZDAppTaskID, ZDO_NETWORK_INIT,
NWK_RETRY_DELAY );
*
*
*
*
---->ZDO_NetworkFormationConfirmCB();
---->osal_set_event( ZDAppTaskID, ZDO_NETWORK_START );
---->events & ZDO_NETWORK_START
---->ZDApp_NetworkStartEvt();
---->osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );
---->events & ZDO_STATE_CHANGE_EVT
---->ZDO_UpdateNwkStatus( devState );
---->osal_msg_send( *(epDesc->epDesc->task_id), (byte *)msgPtr );
//上面事件的作用是:向每个应用层任务注册一个ZDO_STATE_CHANGE事件
协调器(自启动模式)—以SampleApp的协调器为例,并假设初始化成功,网络建立成功.
程序大致流程:
main()->osal_init_system()->osalInitTasks()->ZDApp_Init()->ZDOInitDevice()->ZDApp_NetworkInit->触发ZDAppTaskID的ZDO_NETWORK_INIT->ZDO_StartDevice()->NLME_NetworkFormationRequest()->网络建立成功ZDO_NetworkFormationConfirmCB->触发ZDAppTaskID的ZDO_NETWORK_START->ZDApp_NetworkStartEvt()->触发ZDAppTaskID的ZDO_STATE_CHANGE_EVT->ZDO_UpdateNwkStatus()->触发SampleApp_TaskID的ZDO_STATE_CHANGE->开户周期信息发送的定时器.


发布评论