Z-Statk协调器 路由器 终端的确定---Simple例程(一)

BIOS更新后PIN不可用怎么办?从原理到实操的完整修复指南 在计算机维护中,BIOS更新是常见的固件升级操作,但其引发的登录异常却常让用户措手不及。Windows Hello PIN并非传统密码,它通过TPM芯片与设备启动环境(PCR状态)强绑定,一旦主板固件或安全启动配置改变,TPM便会拒绝释放密钥,导致“由于此设备上的更改,你的PIN不再可用”。理解这一原理后,恢复路径清晰可控:优先尝试密码登录,或通过WinRE替换utilman.exe创建临时管理员,必要时还需处理BitLocker恢复密钥。本文面向系统维护与数据安全场景,系统梳理PIN失效的恢复流程与避坑方 阅读详情

分类: 嵌入式

 
    当我们选择了终端、路由器、或者协调器的时候,来看一下程序中是怎么判断的。也就是如何作为其中的各个角色进行启动,是加入网络,还是形成网络。因为我们在这三个设备上使用的一套代码。首先,我们可以看到下面的三张图,这个是以 SampleApp例程为例子。从三幅图中我们可以看来,当选择不同的设备类型编译时,下面加载的配置文件是不一样的。

   下面是f8wCoord.cfg文件中的配置信息。这个协调器中的编译选项比路由器结点的编译选项相比多了一个-DZDO_COORDINATOR选项。
/* Common To All Applications */
-DCPU32MHZ                         // CC2430s Run at 32MHz
-DFORCE_MAC_NEAR                   // MAC code in NEAR
-DROOT=__near_func                 // MAC/ZMAC code in NEAR
 
-DMAC_CFG_APP_PENDING_QUEUE=TRUE
 
/* Coordinator Settings */
-DZDO_COORDINATOR                  // Coordinator Functions
-DRTR_NWK                          // Router Functions
 
/* Optional Settings */
-DBLINK_LEDS                       // LED Blink Functions
 
/* Compiler keywords */
-DCONST="const __code"
-DGENERIC=__generic                // Ptr declaration
下面是终端结点的配置信息。f8wEndev.cfg
/* Common To All Applications */
-DCPU32MHZ                         // CC2430s Run at 32MHz
-DFORCE_MAC_NEAR                   // MAC code in NEAR
-DROOT=__near_func                 // MAC/ZMAC code in NEAR
 
/* Optional Settings */
-DMAC_OPT_FFD=0                    // ZigBee RFD 应该是决定了是终端结点
-DBLINK_LEDS                       // LED Blink Functions
 
/* Compiler keywords */
-DCONST="const __code"
-DGENERIC=__generic                // Ptr declaration
下面是路由器结点的配置信息,f8wRouter.cfg,在这里没有协调器的编译选项
/* Common To All Applications */
-DCPU32MHZ                         // CC2430s Run at 32MHz
-DFORCE_MAC_NEAR                   // MAC code in NEAR
-DROOT=__near_func                 // MAC/ZMAC code in NEAR
 
-DMAC_CFG_APP_PENDING_QUEUE=TRUE
 
/* Router Settings */
-DRTR_NWK                          // Router Functions
 
/* Optional Settings */
-DBLINK_LEDS                       // LED Blink Functions
 
/* Compiler keywords */
-DCONST="const __code"
-DGENERIC=__generic                // Ptr declaration
    从上面的三个配置文件的内容,我们来看一下这三个配置文件的区别。其实区别就在上面红色标注的部分。协调器比路由结点多了-DZDO_COORDINATOR                  // Coordinator Functions
这句话,我们也可以看到就是在协调器结点中,也定义了路由器结点的选项,也就是   -DRTR_NWK                     // Router Functions,  
      其实这也说明了,在加载f8wCoord.cfg文件时,我们可以通过应用程序来决定配置成协调器,还是配置成路由器。还必须在配置了非自动启动模式HOLD_AUTO_START和软启动模式SOFT_START两个选项后,我们可以在SimpleControllerEB这个工程中和SimpleSwitchEB这个文件中,看到下面的编译选项,有什么不同点,也就是在作为协调器时,我们的编译选项多了一个非自动启动模式HOLD_AUTO_START模式。在这个选择设备的类型这个下拉框中,我们没有发现和SampleApp例程一样有三个选项,也就是协调器,路由器,终端,这里就两个选项一个是SimpleControllerEB,另一个是SimpleSwitchEB,我们知道SimpleSwitchEB是终端结点,SimpleControllerEB可作为协调器结点,那我们的路由结点在那里呢?从上面的分析可以看到一定是加载了  f8wCoord.cfg文件的,才可能成为路由器,其实协调器和路由器是通过程序中的按键来决定的,也就是用户的应用程序,其实这个工程和其它工程还有不同的地方就是协调器和路由器共用一个应用程序的文件,也就是SimpleController.c,而终端结点的应用在另一个文件SimpleSwitch.c。这个工程所有共用的代码是sapi.c文件,这也为我们应用程序的编写提供了另一种思路。开关设备SimpleSwitchEB无论按K1还是K2都是作为终端设备的,而灯设备SimpleControllerEB按键K1则作为协调器,按K2则作为路由器。那下面我们就看看应用程序中是怎么来实现这样一个功能的。下面首先是以协调器为例子。
                     
  图1 协调器的编译选项的配置
还是在ZDApp.c文件中,有下面的代码:
#if defined( HOLD_AUTO_START )
  devStates_t devState = DEV_HOLD;
#else
  devStates_t devState = DEV_INIT;
#endif
 
#if defined( ZDO_COORDINATOR ) && !defined( SOFT_START )
//定义了ZDO_COORDINATOR,没有定义SOFT_START执行下面的配置
  // Set the default to coodinator
  devStartModes_t devStartMode = MODE_HARD;
#else//其它情况
  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.
#endif
     在协调器中定义了编译选项非自动启动模式HOLD_AUTO_START和软启动模式SOFT_START,这里可以得知各个选项的值:devStates_t devState = DEV_HOLD; devStartModes_t devStartMode = MODE_JOIN;在Zglobals.h文件中可以看到。
#if defined ( SOFT_START )
  #define DEVICE_LOGICAL_TYPE ZG_DEVICETYPE_SOFT
#elif defined( ZDO_COORDINATOR )
  #define DEVICE_LOGICAL_TYPE ZG_DEVICETYPE_COORDINATOR
#elif defined (RTR_NWK)
  #define DEVICE_LOGICAL_TYPE ZG_DEVICETYPE_ROUTER
#else
  #define DEVICE_LOGICAL_TYPE ZG_DEVICETYPE_ENDDEVICE
#endif
 
// Values for ZCD_NV_LOGICAL_TYPE (zgDeviceLogicalType)
#define ZG_DEVICETYPE_COORDINATOR      0x00
#define ZG_DEVICETYPE_ROUTER           0x01
#define ZG_DEVICETYPE_ENDDEVICE        0x02
#define ZG_DEVICETYPE_SOFT             0x03
在AF.h文件中,
// Node Logical Types
#define NODETYPE_COORDINATOR    0x00
#define NODETYPE_ROUTER         0x01
#define NODETYPE_DEVICE         0x02
在ZDConfig.c文件中。
NodeDescriptorFormat_t ZDO_Config_Node_Descriptor =
{
#if defined( ZDO_COORDINATOR ) && !defined( SOFT_START )
  NODETYPE_COORDINATOR,
#elif defined (RTR_NWK)
       NODETYPE_ROUTER,
#else
  NODETYPE_DEVICE,          // Logical Type
#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 "Hold Auto Start"
 //打开电源时,检测到有手工设置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() */
我们首先看一下ZDO_Init( void )函数
void ZDO_Init( void )
{
  // Initialize ZD items
  #if defined ( REFLECTOR )
  ZDO_EDBind = NULL;
  #endif
 
  // Setup the device - type of device to create.
  ZDODeviceSetup();
}
static void ZDODeviceSetup( void )
{
#if defined( ZDO_COORDINATOR )
  NLME_CoordinatorInit(); //这个函数执行
#endif
 
#if defined ( REFLECTOR )//源绑定操作
  #if defined ( ZDO_COORDINATOR )
    APS_ReflectorInit( APS_REFLECTOR_PUBLIC );//这个函数执行
  #else
    APS_ReflectorInit( APS_REFLECTOR_PRIVATE );
  #endif
#endif
 
#if !defined( ZDO_COORDINATOR ) || defined( SOFT_START )
  NLME_DeviceJoiningInit();
#endif
}
    从上面的分析可知,由于编译了HOLD_AUTO_START选项后,devState == DEV_HOLD,所以不会进入ZDOInitDevice( 0 ); 函数,而是闪烁LED4,指示初始化设备。这时就应该到应用程序来处理的,决定来初始化为协调器,还是路由器了。
void SAPI_Init( byte task_id )
{
..............................................
if ( HalKeyRead () == HAL_KEY_SW_5)
  {
// If SW5 is pressed and held while powerup, force auto-start and nv-restore off and reset
//如果SW5按下,并且打开电源,强迫关闭自动启动,并且不从NV中读出参数,并重启
startOptions = ZCD_STARTOPT_CLEAR_STATE | ZCD_STARTOPT_CLEAR_CONFIG;
//把默认的启动选项写入到NV中
    zb_WriteConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );
    zb_SystemReset();//并重新启动系统
  }
#endif // HAL_KEY
 
  // Set an event to start the application
  osal_set_event(task_id, ZB_ENTRY_EVENT);
}
我们看了一下startOptions选项表示的是什么意思。下面的代码在ZComDef.h文件中,
#define ZCD_STARTOPT_DEFAULT_CONFIG_STATE  0x01
#define ZCD_STARTOPT_DEFAULT_NETWORK_STATE 0x02
#define ZCD_STARTOPT_AUTO_START            0x04
#define ZCD_STARTOPT_CLEAR_CONFIG   ZCD_STARTOPT_DEFAULT_CONFIG_STATE
#define ZCD_STARTOPT_CLEAR_STATE  ZCD_STARTOPT_DEFAULT_NETWORK_STATE
通过宏定义可以看出,他们都是默认的选项。可以看到在程序的最后启动了ZB_ENTRY_EVENT事件,
UINT16 SAPI_ProcessEvent( byte task_id, UINT16 events )
{
............................................
if ( events & ZB_ENTRY_EVENT )
  {
    uint8 startOptions;
 
    // Give indication to application of device startup 这里这个函数是一空函数
    zb_HandleOsalEvent( ZB_ENTRY_EVENT );
 
    // LED off cancels HOLD_AUTO_START blink set in the stack
    HalLedSet (HAL_LED_4, HAL_LED_MODE_OFF);
 //在上面当按下SW5按键后写入了默认的启动选项,这里进行了读取
    zb_ReadConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );
    if ( startOptions & ZCD_STARTOPT_AUTO_START )
    {
      zb_StartRequest();
    }
    else
    {
      // blink leds and wait for external input to config and restart
      HalLedBlink(HAL_LED_2, 0, 50, 500);
    }
 
    return (events ^ ZB_ENTRY_EVENT );
  }
............................................
}
     我们看一下ZCD_NV_STARTUP_OPTION的初始值是什么,在下面的函数中写入了ZCD_NV_STARTUP_OPTION的初始值,初始值为0.这个函数,在uint8 zgInit( void )中被调用。
uint8 zgReadStartupOptions( void )
{
  // Default to Use Config State and Use Network State
  uint8 startupOption = 0;
 
  // This should have been done in ZMain.c, but just in case.
  if ( osal_nv_item_init( ZCD_NV_STARTUP_OPTION,
                              sizeof(startupOption),
                              &startupOption ) == ZSUCCESS )
  {
    // Read saved startup control
    osal_nv_read( ZCD_NV_STARTUP_OPTION,
                  0,
                  sizeof( startupOption ),
                  &startupOption);
  }
  return ( startupOption );
}
    由于#define ZCD_STARTOPT_AUTO_START            0x04所以下面的判断语句不成立,也就是没有执行zb_StartRequest();函数。
if ( startOptions & ZCD_STARTOPT_AUTO_START )
    这时也就是网络没有形成,没有具体确定那个是协调器,还是作为路由器。下面就是通过应用程序的按键来确定。下面是灯设备,也就是SimpleController.c文件中的按键个事件的处理过程。
void zb_HandleKeys( uint8 shift, uint8 keys )
{
  uint8 startOptions;
  uint8 logicalType;
 
  // Shift is used to make each button/switch dual purpose.
  if ( shift )
  {
    if ( keys & HAL_KEY_SW_1 )
    {
    }
    if ( keys & HAL_KEY_SW_2 )
    {
    }
    if ( keys & HAL_KEY_SW_3 )
    {
    }
    if ( keys & HAL_KEY_SW_4 )
    {
    }
  }
  else
  {
    if ( keys & HAL_KEY_SW_1 )
    {
      if ( myAppState == APP_INIT  )
      {
        // In the init state, keys are used to indicate the logical mode.
        // Key 1 starts device as a coordinator
        //当按下按键1时,读取配置信息,通过读取NV中的ZCD_NV_LOGICAL_TYPE条目,判断设备的逻辑类型,
        zb_ReadConfiguration( ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType );
        if ( logicalType != ZG_DEVICETYPE_ENDDEVICE )
        {
          logicalType = ZG_DEVICETYPE_COORDINATOR;
          zb_WriteConfiguration(ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType);
        }
 
        // Do more configuration if necessary and then restart device with auto-start bit set
        // write endpoint to simple desc...dont pass it in start req..then reset
 
 
        zb_ReadConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );
        startOptions = ZCD_STARTOPT_AUTO_START;
        zb_WriteConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );
        zb_SystemReset();
 
      }
      else
      {
        // Initiate a binding
        zb_AllowBind( myAllowBindTimeout );
      }
    }
    if ( keys & HAL_KEY_SW_2 )
    {
      if ( myAppState == APP_INIT )
      {
        // In the init state, keys are used to indicate the logical mode.
        // Key 2 starts device as a router
 
        zb_ReadConfiguration( ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType );
        if ( logicalType != ZG_DEVICETYPE_ENDDEVICE )
        {
          logicalType = ZG_DEVICETYPE_ROUTER;
          zb_WriteConfiguration(ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType);
        }
 
        zb_ReadConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );
        startOptions = ZCD_STARTOPT_AUTO_START;
        zb_WriteConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );
        zb_SystemReset();
      }
      else
      {
      }
    }
    if ( keys & HAL_KEY_SW_3 )
    {
    }
    if ( keys & HAL_KEY_SW_4 )
    {
    }
  }
}
在  ZGlobals.c文件中,我们可以找到ZCD_NV_LOGICAL_TYPE的初始值是什么?
static CONST zgItem_t zgItemTable[] =
{
#if defined ( NV_INIT )
  {
    ZCD_NV_LOGICAL_TYPE, sizeof(zgDeviceLogicalType), &zgDeviceLogicalType
  },
  {
    ZCD_NV_POLL_RATE, sizeof(zgPollRate), &zgPollRate
  }
...............................,
}
在这个文件中我们还可以看到下面的这句话,
// Device Logical Type
uint8 zgDeviceLogicalType = DEVICE_LOGICAL_TYPE;
前面我们也有看到
#if defined ( SOFT_START )
  #define DEVICE_LOGICAL_TYPE ZG_DEVICETYPE_SOFT
#define ZG_DEVICETYPE_SOFT             0x03
     我们也可以看到在这个文件中的编译选项有 NV_INIT,并且在uint8 zgInit( void )函数中,对这个结构体数组进行了初始化。也就是说最后NV中的ZCD_NV_LOGICAL_TYPE条目被初始化了ZG_DEVICETYPE_SOFT值,所以if ( logicalType != ZG_DEVICETYPE_ENDDEVICE )判断不成功,执行下面的两条语句。也就是设置设备的逻辑类型为协调器,并且写入到ZCD_NV_LOGICAL_TYPE的条目中。
logicalType = ZG_DEVICETYPE_COORDINATOR;
zb_WriteConfiguration(ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType);
    下面的语句就是语句就是写入了自动启动项,并且最后重新启动了系统。我们看一下重新启动后的流程
在void SAPI_Init( byte task_id )函数中触发ZB_ENTRY_EVENT事件,进入UINT16 SAPI_ProcessEvent( byte task_id, UINT16 events )函数,对ZB_ENTRY_EVENT事件进行处理。
if ( events & ZB_ENTRY_EVENT )
  {
    uint8 startOptions;
 
    // Give indication to application of device startup
    zb_HandleOsalEvent( ZB_ENTRY_EVENT );
 
    // LED off cancels HOLD_AUTO_START blink set in the stack
    HalLedSet (HAL_LED_4, HAL_LED_MODE_OFF);
 
    zb_ReadConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );
    if ( startOptions & ZCD_STARTOPT_AUTO_START )//这时这个判断就是成立的
    {
      zb_StartRequest();
    }
    else
    {
      // blink leds and wait for external input to config and restart
      HalLedBlink(HAL_LED_2, 0, 50, 500);
    }
 
    return (events ^ ZB_ENTRY_EVENT );
  }
判断成立的话,就会进入zb_StartRequest()函数。下面重点看一下zb_StartRequest()
void zb_StartRequest()
{
  uint8 logicalType;
 
  // Start the device
  // start delay = min(NWK_START_DELAY, zgStartDelay) + rand() - only for fresh start, not restore
  if ( zgStartDelay < NWK_START_DELAY )
    zgStartDelay = 0;
  else
    zgStartDelay -= NWK_START_DELAY;
 
  /*check that bad combinations of compile flag definitions and device type 这时这里的ZCD_NV_LOGICAL_TYPE条目为ZG_DEVICETYPE_COORDINATOR
#define ZG_DEVICETYPE_COORDINATOR      0x00(协调器)
  #define ZG_DEVICETYPE_ROUTER           0x01(
路由器)
  #define ZG_DEVICETYPE_ENDDEVICE        0x02(
终端)
  #define ZG_DEVICETYPE_SOFT             0x03(
可选择类型)*/
  zb_ReadConfiguration( ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType );
   if (  ( logicalType > ZG_DEVICETYPE_ENDDEVICE )        ||
#if defined( RTR_NWK )
  #if defined( ZDO_COORDINATOR )
          // Only RTR or Coord possible
         ( logicalType == ZG_DEVICETYPE_ENDDEVICE )   ||
  #else
          // Only RTR possible
          ( logicalType != ZG_DEVICETYPE_ROUTER )     ||
  #endif
#else
  #if defined( ZDO_COORDINATOR )
          // Error
          ( 1 )                                     ||
  #else
          // only ED possible
          ( logicalType != ZG_DEVICETYPE_ENDDEVICE )  ||
  #endif
#endif
          ( 0 ) )
   {
     // error configuration
     SAPI_SendCback( SAPICB_START_CNF, ZInvalidParameter, 0 );
   }
   else
   {
     ZDOInitDevice(zgStartDelay);
   }
 
  return;
}
    经过一系列的错误检测,可以得出上面的if分支不成立,会执行else分支也就是ZDOInitDevice(zgStartDelay); 函数。这个函数,在上面的文章中也有分析到,这个函数中就分了NV_RESTORE编译选项的定义与否,由于这里没有定义这个选项,所以会直接执行ZDAppDetermineDeviceType();。
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 );
}
在ZDAppDetermineDeviceType();函数中,对设备进行了判断。
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编译选项,因为在按下S1按键后,把ZG_DEVICETYPE_COORDINATOR值写入了ZCD_NV_LOGICAL_TYPE条目中,在系统重新启动后,通过初始化zgDeviceLogicalType= ZG_DEVICETYPE_COORDINATOR所以这样就作为了一个协调器进行正常的启动了。后面的启动过程和前面分析是一样的形成网络,点亮绿色的灯。调用网络的初始化函数,触发ZDAppTaskID,任务中的ZDO_NETWORK_INIT事件处理。
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 );
  }
}

UINT16 ZDApp_event_loop( byte task_id, UINT16 events )
{
if ( events & ZDO_NETWORK_INIT )
  {
    // Initialize apps and start the network
    devState = DEV_INIT;
    ZDO_StartDevice( (uint8)ZDO_Config_Node_Descriptor.LogicalType, devStartMode,
                     DEFAULT_BEACON_ORDER, DEFAULT_SUPERFRAME_ORDER );
 
    // Return unprocessed events
    return (events ^ ZDO_NETWORK_INIT);
  }
}
从上面的分析可以得出ZDO_Config_Node_Descriptor.LogicalType = NODETYPE_COORDINATOR;
devStartMode = MODE_HARD;,
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 */
        scanCnf.hdr.Status = ZSUCCESS;
        scanCnf.ScanType = ZMAC_ORPHAN_SCAN;
        scanCnf.UnscannedChannels = 0;
        scanCnf.ResultListSize = 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 );
}
    其实路由器的判断形成过程于其极其的相似,也是这个文件,只是把按键改成了K2,也就改变了zgDeviceLogicalType变量的值。
保姆级教程:用YOLOv5s训练PCB缺陷检测模型(附北大公开数据集) 本文提供了一份基于YOLOv5s的PCB缺陷检测模型从零开始的完整实战教程。详细解析了如何使用北大公开数据集,涵盖环境搭建、数据处理、模型训练、性能评估及优化部署全流程,并针对工业场景中常见的类别不均衡问题给出了具体解决方案,旨在帮助开发者快速构建高精度的自动化质检系统。 阅读详情

相关推荐

NV 英伟达2022数字芯片笔试题

作者:数字IC打工人 链接:【开卷】第27期 NV 英伟达2022数字芯片笔试题_笔经面经_牛客网 来源:牛客网 1、Single Choice: Given thefollowing FIFO and rules, how deep does the FIFO need to be to preventunderflow or overflow? RULES: clk_A=25MHz; clk_B=100MHz; en_B is periodically asserted: period.

weixin_44072819的博客 6387

ZIGBEE 工程内区分终端与协调器

目前已知,工程中区分是终端还是协调器,与工程中Tolls文件夹中的.cfg文件有关: 从project->Edit Configuration进去可以删减左边栏Workspace下拉的项: 区别终端、路由器和协调器是通过Options.. -> C/C++ Compiler -> Extra Options 中添加不同的.cfg文件实现的: 协调器: 终端...

Rhiney_97的博客 4430

Ribo-seq数据解析:从翻译效率计算到动态可视化分析

本文系统介绍了Ribo-seq(核糖体印迹测序)数据分析全流程,从核心的P-site定位、翻译效率计算,到差异翻译分析和动态可视化。重点阐述了如何利用Ribo-seq高分辨率数据揭示基因表达在翻译层面的精细调控,并提供了从数据处理到生物学解读的实用工具与避坑指南。

weixin_28559803的博客 421

Z-stack开发指南

2.ZigBee 2.1 设备类型(Device Types) 在ZigBee网络中存在三种逻辑设备类型:Coordinator(协调器),Router(路由器)和End-Device(终端设备)。ZigBee网络由一个Coordinator以及多个Router和多个End_Device组成。 上图是一个简单的ZigBee网络示意图。其中黑色节点为Coordinator,红色节点为...

weixin_30357231的博客 707

基于LendingClub数据的信贷分析和建模报告

一:课题分析 二:数据获取 三:数据探索 3.1主要特征含义理解 3.2特征分布 3.2.1目标特征分布 3.2.2分类变量的分布 3.2.3连续数值特征分布 3.2.4时序特征分布 3.2.5文字特征分布 3.2.6两两特征的协方差 四:数据预处理 4.1数据集划分 4.2特征缺失值识别与处理 4.2.1严重缺失值的处理 4.2.2缺失值填充 4.3同值性特...

棒子皮蹦蹦床 2万+

MDK开发篇:基于立创逻辑派FPGA-G1与Cortex-M1软核的按键控制LED实战

本文详细介绍了基于立创逻辑派FPGA-G1开发板与高云Cortex-M1软核的完整开发流程。通过Gowin云源软件配置软核系统与GPIO外设,并在Keil MDK环境中编写按键控制LED的C程序,最终实现程序固化与上电自启动。教程涵盖硬件配置、软件开发、在线调试与固化部署全步骤,帮助STM32开发者快速上手FPGA软核开发。

weixin_42103128的博客 147

lesson7-1 Zigbee协议栈的使用

因此我们可以每个信道都或在一起(多个位取1),这样多个信道参数值就可以进行或操作,把结果作为宏的最终值,那么这样对于路由器和终端的意义:可以在这些信道上选择一个最佳的网络加入进去。这些宏值的不同会影响程序执行的流程,就会导致出现不同的功能,所以有了不同功能的代码版本:协调器、路由器和终端。因为Zigbee协议在发展过程中经历了3个版本,其中Zigbee在2007年推出了最新的规范,这个规范有2个版本,Zigbee2007和ZigbeePro,它们之间的区别是,PRO版本的功能在某方面更强。

qq_25218501的博客 1640

C# 操作Excel的时候,出现"被呼叫方拒绝接受呼叫的异常"的解决方案(参考官方给出的解决方案)

首先官方有对这个错误给出解释和解决方案,连接如下: https://docs.microsoft.com/zh-cn/previous-versions/ms228772(v=vs.120)#%E5%8F%AF%E9%9D%A0%E7%BC%96%E7%A8%8B 简单来说,貌似是线程问题,我猜。。。 之前我尝试着在代码中添加 Thread.Sleep(1000); 来进行解决,这种办...

Ck_Max的博客 5767

zigbee学习重点资料的摘录2

Zigbee的术语

mmcly的专栏 2457

YOLOv11改进策略【卷积层】| 引入注意力卷积模块RFAConv,关注感受野空间特征 助力yolov11精度提升

RFAConv:创新空间注意力和标准卷积运算感受野空间特征是针对卷积核设计的,根据卷积核大小动态生成。以3×3卷积核为例,它由非重叠滑动窗口组成,每个窗口代表一个感受野滑块。

Limiiiing的博客 1823

Couldn‘t agree a key exchange algorithm(available:curve25519-sha256,curve25519-sha256@libssh.org解决方案

本文主要介绍了Couldn’t agree a key exchange algorithm(available:curve25519-sha256,curve25519-sha256@libssh.org解决方案,希望能对使用winscp的同学们有所帮助。 文章目录 1. 问题描述 2. 解决方案 2.1 方案一 2.2 方案二

weixin_43178406的博客 4万+

学习zigbee入门-10

【转】学习zigbee入门-10 SimpleApp 例子解读-2 程序分析:         灯开关灯实验:开关设备通过发送命令切换控制设备的状态,并通过指示灯的状态变化反应操作是否成功。        在SimpleApp,SimpleController.c(灯管理器设备)按键处理函数zb_HandleKeys中,当SW1被按下,它将使设备作为协调器使用;期间按下S

xiao11xiang123的专栏 825

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Z-Statk协调器 路由器 终端的确定---Simple例程(二)

下面看一下终端结点的不同之处,下面这个图是终端结点的的编译选项,这里我们可以看到没有了编译选项SOFT_START。这里我们重点看一下不同之处。 #if defined( ZDO_COORDINATOR ) && !defined( SOFT_START ) // Set the default to coodinator devStar...

frankzfz的专栏 155

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

CC2530自动启动模式的流程

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

shjhuang的专栏 2676

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

zigbee协议栈雷达 硬件部分

声明:本人初学zigbee,很多代码引用自他人,因此本文仅作参考 文章目录前言一、协调器二、终端1.SampleApp.c2.舵机部分3.ZMain.c 前言 本人这学期课设,要求使用zigbee完成设计。在学习中颇有收获和心得,因此写下本文记录,并分享一些经验。 以下是硬件部分,包括一个协调器和两个终端,使用的传感器包括超声波模块,舵机,避障模块。 一、协调器 void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt ) { uin.

weixin_46256482的博客 1589

Z-stack 串口的使用

1、定义一个串口初始化函数,函数里面对串口进行配置 void initUart(halUARTCBack_t pf) { halUARTCfg_t uartConfig; uartConfig.configured = TRUE; uartConfig.baudRate = HAL_UART_BR_38400; uartConfig.flowControl = FALSE;

cucmakeit的专栏 1951

物联网之Zigbee系统开发三(无线传感器网络)

协议栈入门 内容概要: TI Z-Stack协议栈安装 串口通信 TI Z-Stack协议栈安装: • 我们用到的ZStack协议栈的版本为 2.3.0-1.4.0,找到相应安装软件并安装。 • 安装完成之后在C:\Texas Instruments下找到ZStack-CC2530-2.3.0-1.4.0文件夹,打开文件夹.可以看到文件的目录结构如下: 文件目录介绍: • Co...

许新天的博客 6089

ZigBee协调器和终端通信

本文主要记录了协调器和终端通信,完成LED灯的变化,具体为:协调器轮询接收终端发的数据,终端开不开发送都可以,协调器一定要开,终端才会收到。 #if defined(ZDO_COORDINATOR) //协调器收到"D1"后,返回"D1"给终端,让终端Led1也闪烁 SampleApp_SendPeriodicMessage(); #endif 即:以上代码,在通信时终端开不开都可以,...

苏某人的博客 9202

zigbee设备在Zstack中的体现

zigbee网络提供3种网络设备类型,分别是协调器、路由器和终端节点。 协调器是一个全功能设备,在整个网络中的权限最高,功能最强大。它是一个网络的建立者,维护整个zigbee网络。在协议栈中,每个源文件都可以定义多个功能设备的实现函数。它们都通过编译来实现各个设备的需要。 顺便说下,左边的那个EditConfigurations 可以增加或删除下图中Workspace下面下拉菜单里的内容 通过选择这个下拉菜单里的Router , EndDevice ,Coordinator,程序时怎样识别它们的? 首先说

Cool2050的博客 595

SimpleApp例子中网络的形成过程

SimpleApp例子中网络的形成过程    每个设备都有一组被配置的参数,整个配置参数在代码中已经定义了默认值(在f8wConfig.cfg)中,在同个网络中,所有设备的“网络细节”配置参数(如PANID,Channel等)应该被设置成一样的值。每个设备的“设备细节”配置参数(Coordinator,RouterEndDevice等)可能配置为不同的值。    但是,ZCD_NV_LOGIC

xiaoaide01的专栏 958

Zigbee-cc2530 笔记 z-tool的使用

Z-Stack的”Monitor and Test”功能为开发者提供了一个PC与协议栈运行状况进行通信的接口。方法就是利用TI提供的专用工具Z-tool,通过串口的方式与运行协议栈的设备进行信息的交互,下达指令 1.设置工程选项,打开option选项。 2.对一些宏定义进行修改,加入红框所示两个宏定义 3.修改代码部分 此处应与z-tool波特率对应 4.打开z-tool

P_xiaojia的博客 3294

ZigBee协议栈配置文件

文章目录f8w2530.xclf8config.cfgf8wCoord.cfgf8wEndev.cfgf8wRouter.cfg f8w2530.xcl   f8w2530.xcl包含CC2530单片机的链接控制指令(如定义堆栈大小、内存分配等),一般不需要改动: -D_XDATA_START=0x0001; 标明外部存储器的起始地址 -D_XDATA_END=0x1EFF ; 标明外部存储器的结束地址 f8config.cfg   f8config.cfg主要用于配置zigbee设备,是IAR编译的命

健身房 1008

详解在程序中怎样区分协调器 路由器 终端[转载]

原文地址:路由器 终端[转载]" style="text-decoration:none; color:rgb(33,128,36)">详解在程序中怎样区分协调器 路由器 终端[转载]作者:阿元 路由器 终端[转载]" title="[转载]详解在程序中怎样区分协调器 路由器 终端[转载]" style="margin:0px; padding:0px; border:0px; list

xiao11xiang123的专栏 1745

【转自小峰博客】协调器的启动【自动模式】

首先请让我向大家介绍下强人小峰,看完他写的多篇博客感悟颇多哦! 使用的协议栈版本信息: ZigBee2006\ZStack-1.4.3-1.2.1Zigbee网络设备启动流程—协调器(自启动模式)—以SampleApp的协调器为例.1、协调器预编译信息通过project->options->c/c++compiler->extraOptions可以看到协调器所带的配置文...

weixin_30655569的博客 299

zigbee网络设备启动流程

2)、预编译方式:project->options->c/c++compiler->preprocessor->defined symbols下编译选项:HOLD_AUTO_STARTSimpleApp例子里四种节点都预编译了HOLD_AUTO_START:非自动启动模式在ZDApp.c中:#if defined( HOLD_AUTO_START ) dev...

weixin_42030357的博客 905

. ZigBee节点——ZigBee协议栈Z-Stack开发指南

1.1设备类型(Device Types) 在ZigBee网络中存在三种逻辑设备类型:Coordinator(协调器),Router(路由器)和End-Device(终端设备)。ZigBee网络由一个Coordinator、多个Router(也可以没有)和多个End-Dev

skyxfire的专栏 2878
上一篇: Cover、Rational PureCoverage、BullseyeCoverage
下一篇: 协议栈中绑定流程的一点认识
linuxheik
博客等级 码龄15年 865粉丝 135原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值