|
由于工作和搬家的原因,很长一段时间没有更新《Zstack协议栈初窥》系列文章了,在此向大家表达我深深的歉意。
这一期我将继续顺着Zstack协议栈初窥(六)的脉络,主要讲述Zigbee路由设备是如何完成入网操作的。
我们之前曾经提到过,所有zigbee的设备只有在完成入网过程后才能够接收来自网络中其它设备发送的无线信息,因此入网操作是Zstack协议栈中非要重要的一项功能。
Zigbee路由设备在首次上电后需要做的最重要的事情就是加入网络,我们下面就根据具体程序代码来一步步理清这个过程。同协调器一样,路由设备的具体执行流程也是:Main()->osal_init_system()->osalInitTasks()->ZDApp_Init()。
ZDApp_Init首先检测SW1是否被按下,如果SW1被按下,设备将处于DEV_HOLD状态,不会进入组网状态,这里我们要特别注意。如果SW1没有被按下,那么程序将调用ZDOInitDevice来开启设备。
uint8 ZDOInitDevice( uint16 startDelay )
{
uint8 networkStateNV = ZDO_INITDEV_NEW_NETWORK_STATE;
uint16 extendedDelay = 0;
if ( devState == DEV_HOLD )
{
// Initialize the RAM items table, in case an NV item has been updated.
zgInitItems( FALSE );
}
ZDConfig_InitDescriptors();
//devtag.071807.todo - fix this temporary solution
_NIB.CapabilityFlags = ZDO_Config_Node_Descriptor.CapabilityFlags;
#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();
// clear NWK key values
ZDSecMgrClearNVKeyValues();
}
#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 the security for type of device
ZDApp_SecInit( networkStateNV );
if( ZDO_INIT_HOLD_NWK_START != startDelay )
{
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 )
{
// Set the NV startup option to force a "new" join.
zgWriteStartupOptions( ZG_STARTUP_SET, ZCD_STARTOPT_DEFAULT_NETWORK_STATE );
// Notify the applications
osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );
return ( ZDO_INITDEV_LEAVE_NOT_STARTED ); // Don't join - (one time).
}
// Trigger the network start
ZDApp_NetworkInit( extendedDelay );
}
// set broadcast address mask to support broadcast filtering
NLME_SetBroadcastFilter( ZDO_Config_Node_Descriptor.CapabilityFlags );
return ( networkStateNV );
}
上面的这段代码我们在Zstack协议栈初窥(六)中也曾经贴出过,这里再次把它拿出来是要更细致地来分析它的作用。我们假设if ( HalKeyRead() == SW_BYPASS_NV )判断结果为false,那么networkStateNV的状态将取决于ZDApp_ReadNetworkRestoreState()的返回值。
uint8 ZDApp_ReadNetworkRestoreState( void )
{
uint8 networkStateNV = ZDO_INITDEV_RESTORED_NETWORK_STATE;
// Look for the New Network State option.
if ( zgReadStartupOptions() & ZCD_STARTOPT_DEFAULT_NETWORK_STATE )
{
networkStateNV = ZDO_INITDEV_NEW_NETWORK_STATE;
}
return ( networkStateNV );
}
正常情况下,该返回值为ZDO_INITDEV_RESTORED_NETWORK_STATE。继续查看下面的代码,由于if ( networkStateNV == ZDO_INITDEV_RESTORED_NETWORK_STATE )为true,ZDApp_RestoreNetworkState()将被调用执行。
uint8 ZDApp_RestoreNetworkState( void )
{
uint8 nvStat;
// Initialize NWK NV items
nvStat = NLME_InitNV();
if ( nvStat != NV_OPER_FAILED )
{
if ( NLME_RestoreFromNV() )
{
// Are we a coordinator
ZDAppNwkAddr.addr.shortAddr = NLME_GetShortAddr();
if ( ZDAppNwkAddr.addr.shortAddr == 0 )
ZDO_Config_Node_Descriptor.LogicalType = NODETYPE_COORDINATOR;
devStartMode = MODE_RESUME;
osal_cpyExtAddr( ZDO_UseExtendedPANID, _NIB.extendedPANID );
}
else
{
nvStat = NV_ITEM_UNINIT;
}
if ( ZG_SECURE_ENABLED )
{
nwkFrameCounterChanges = 0;
if ( ZG_BUILD_COORDINATOR_TYPE && ZG_DEVICE_COORDINATOR_TYPE )
{
ZDApp_RestoreNwkKey();
}
}
// The default for RxOnWhenIdle is true for Routers and false for end devices
// [setup in the NLME_RestoreFromNV()]. Change it here if you want something
// other than default.
}
if ( nvStat == ZSUCCESS )
return ( ZDO_INITDEV_RESTORED_NETWORK_STATE );
else
return ( ZDO_INITDEV_NEW_NETWORK_STATE );
}
该函数负责从CC2530的NV存储器中读取设备之前保存的网络数据信息。由于我们的路由设备是全新的没有入网过的,因此NLME_RestoreFromNV()的返回值为flase,nvStat =将被赋值为NV_ITEM_UNINIT,ZDApp_RestoreNetworkState()函数的返回值为ZDO_INITDEV_NEW_NETWORK_STATE;如果设备之前曾经加入过网络,并且在预编译选项中我们启用了NV_RESTORE,那么NLME_RestoreFromNV()的返回值为true,程序将通过NLME_GetShortAddr()等函数获取保存在NV中的网络地址、PANID等信息,ZDApp_RestoreNetworkState()函数的返回值将为ZDO_INITDEV_RESTORED_NETWORK_STATE。
未完待续。
本文为与非网月光码头原创,未经允许谢绝转载。
更多内容请见:【深度分析Zigbee】Zigbee技术知多少?资深大牛对对碰
----------------------------
主讲嘉宾简 介:网名:月光码头。毕业于中国科学院电子学研究所,主要从事zigbee物联网方向的应用研究,尤其擅长TI RF芯片、和Silicon Lab MCU芯片的使用。现就职于上海理滋芯片设计公司,任研发部门经理,主要从事智能家居产品的设计开发,拥有5年多的zigbee软硬件开发经验。
------------------
推荐技术讲座:
听东北人讲天线:每周一个实例,个个经典!(CST仿真实践全包括)
【ADS学习小组】课程汇总(火烽主讲)
【HFSS学习小组】课程汇总(木木主讲)
|
|