自动启动模式分析 - -以SampleApp例程协调器为例

2020-02-21 22:50

自动启动模式分析----以SampleApp例程协调器为例 (2010-12-23 13:38) 分类: ZigBee 技术学习

在上一篇文章中,分析了一下定义了HOLD_AUTO_START编译选项后,程序的流程,这里分析一下在没有定义这个编译选项后,程序的启动流程,也就是自动启动模式的流程。SampleApp例程为例。 在ZDApp.c文件中,可以看到下面的定义: #if defined( HOLD_AUTO_START )

devStates_t devState = DEV_HOLD; // 初始化-不会自动启动 #else

devStates_t devState = DEV_INIT; //初始化-没有连接到任何东西 #endif

不管什么样的启动方式,都会在ZDApp_Init()函数中得到体显,下面是这个函数的源代码。因为这个函数是必须要被执行到。也就是在用户的初始化函数之前被初始化。

void ZDApp_Init( byte task_id ) {

uint8 capabilities; // 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. 加载IEEE地址 // Check for manual \

//打开电源时,检测到有手工设置SW_1则会设置devState = DEV_HOLD,从而不进行网络初始化

ZDAppCheckForHoldKey();

// Initialize ZDO items and setup the device - type of device to create.

ZDO_Init(); //初始化ZDO条目,并设置设备的启动方式是协调器,还是别的 // 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); NLME_SetBroadcastFilter( capabilities );

// Start the device? 是否启动设备?如果devState不是DEV_HOLD时,则启动设备,在上面的代码分析中,也可以看到,如果定义了HOLD_AUTO_START宏,则devState等于DEV_HOLD,不会启动设备。如果按下了SW_1键devState也

等于DEV_HOLD,也不会启动网络。也就是说有两种方式可以设置非自动启动模式,一种是通过按键,一种通过宏定义 if ( devState != DEV_HOLD ) {

ZDOInitDevice( 0 ); //在本例程中没有定义HOLD_AUTO_START所以这个会成功执行 } else {

//如果定义了HOLD_AUTO_START,则等待延时或外部事件启动网络,并且LED4灯,也就是蓝色的灯闪烁

// Blink LED to indicate HOLD_START HalLedBlink ( HAL_LED_4, 0, 50, 500 ); }

ZDApp_RegisterCBs(); } /* ZDO_Init() */

其中ZDOInitDevice()函数是最重要的,也是设备的初始化。下面是ZDOInitDevice()函数的源代码。

uint8 ZDOInitDevice( uint16 startDelay ) {

//初始化设备网络状态为ZDO_INITDEV_NEW_NETWORK_STATE:新的网络状态.可能意味着ZCD_NV_STARTUP_OPTION不能恢复,或没有任何网络状态恢复 uint8 networkStateNV = ZDO_INITDEV_NEW_NETWORK_STATE; uint16 extendedDelay = 0;

devState = DEV_INIT; // Remove the Hold state 重新设置设备状态 // Initialize leave control logic

//函数读取NV项目ZCD_NV_LEAVE_CTRL的值,ZDApp_LeaveCtrl指向这个值 ZDApp_LeaveCtrlInit();

// Check leave control reset settings

//设备的断开会造成DEV_HOLD状态,这里面设置的. ZDApp_LeaveCtrlStartup( &devState, &startDelay ); // Leave may make the hold state come back

//以上两个函数设置了对设备离开时的控制,如果有延时则延时,没有则 //把设备状态设为DEV_HOLD

//ZDO_INITDEV_LEAVE_NOT_STARTED:该设备没有在网络中,下次调用才启用. 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 )

//SW_BYPASS_NV按键处于按下状态时,则避开网络层的NV存储

networkStateNV = ZDO_INITDEV_NEW_NETWORK_STATE; //设备网络状态为新的网络状态 else {

// Determine if NV should be restored

//函数返回的设备网络状态要么是新的网络状态;要么是恢复的网络状态;以此 //来确定要不要读取NV里相应条目来恢复网络先前状态 networkStateNV = ZDApp_ReadNetworkRestoreState(); }

//如果设备的网络状态为恢复的网络状态

if ( networkStateNV == ZDO_INITDEV_RESTORED_NETWORK_STATE ) {

networkStateNV = ZDApp_RestoreNetworkState(); } else {

// Wipe out the network state in NV //恢复设备先前的网络状态参数

//设置devStartMode = MODE_RESUME 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 ); }

在这里又分了两种情况,一种是定义了编译选项NV_RESTORE,另一种就是没有定义该编译选项。

下面首先看一下没有定义该选项的情况: (1) NV_RESTORE编译选项定义 首先,判断按键HAL_KEY_SW_5是否按下,如果HAL_KEY_SW_5按键按下,则设置networkStateNV = ZDO_INITDEV_NEW_NETWORK_STATE; 如果没有

按下,通过调用ZDApp_ReadNetworkRestoreState()函数设置networkStateNV的值,通过读取ZCD_NV_STARTUP_OPTION项的值,来决定networkStateNV选项的值。如果这个函数的返回值为

ZDO_INITDEV_RESTORED_NETWORK_STATE。则调用ZDApp_RestoreNetworkState();函数,该函数的源代码如下: uint8 ZDApp_RestoreNetworkState( void ) {

byte nvStat;

#if ( SECURE != 0 )

nwkActiveKeyItems keyItems; #endif

// Initialize NWK NV items nvStat = NLME_InitNV();

//如果设备的状态为恢复的网络状态,即

ZDO_INITDEV_RESTORED_NETWORK_STATE状态,则进行这个函数进行恢复。如果短地址为0x0000则为协调器结点,然后设备逻辑设备的类型为

NODETYPE_COORDINATOR,并设置devStartMode = MODE_RESUME;说明设备为恢复状态。

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; } else

nvStat = NV_ITEM_UNINIT; #if ( SECURE != 0 )

nwkFrameCounterChanges = 0;

osal_memset( &keyItems, 0, sizeof( nwkActiveKeyItems ) );

osal_nv_item_init( ZCD_NV_NWKKEY, sizeof(nwkActiveKeyItems), (void *)&keyItems );

#if defined ( ZDO_COORDINATOR ) ZDApp_RestoreNwkKey();

#endif // ZDO_COORDINATOR #endif // SECURE

// The default for RxOnWhenIdle is true for RTR_NWK 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 ); }

//如果networkStateNV=ZDO_INITDEV_NEW_NETWORK_STATE,则会调用下面的函数

void ZDAppDetermineDeviceType( void ) {

if ( zgDeviceLogicalType == ZG_DEVICETYPE_ENDDEVICE ) return;

#if defined ( SOFT_START )

if ( zgDeviceLogicalType == ZG_DEVICETYPE_COORDINATOR ) {

devStartMode = MODE_HARD; // Start as a coordinator

ZDO_Config_Node_Descriptor.LogicalType = NODETYPE_COORDINATOR; } else {

if ( zgDeviceLogicalType == ZG_DEVICETYPE_ROUTER ) {

softStartAllowCoord = FALSE; // Don't allow coord to start 如果是路由器则不充许作为协调器启动

continueJoining = TRUE; }

devStartMode = MODE_JOIN; // Assume joining }

#endif // SOFT_START }

可以看到,如果编译等式SOFT_START也有定义的话,设备的类型为协调器,则会设置devStartMode = MODE_HARD;也就是说设备为开始状态。如果是不是协调器而是路由器的话,devStartMode = MODE_JOIN; 设备为重新加入的状态。 在ZDOInitDevice()函数的最后,通过调用ZDApp_NetworkInit( extendedDelay );进行网络的初始化操作。

(2)void ZDApp_NetworkInit( uint16 delay ) {

if ( delay ) {

// Wait awhile before starting the device

osal_start_timerEx( ZDAppTaskID, ZDO_NETWORK_INIT, delay ); } else {


自动启动模式分析 - -以SampleApp例程协调器为例.doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:泉州资格证考试高中美术试讲教案:中国民间美术

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: