Chinaunix首页 | 论坛 | 博客
  • 博客访问: 483306
  • 博文数量: 285
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 629
  • 用 户 组: 普通用户
  • 注册时间: 2013-10-14 17:53
个人简介

相信自己,快乐每一天

文章分类

全部博文(285)

分类: 嵌入式

2014-08-21 13:24:40

这里参考了网上许多资料,但有些东西还是不同,记录在此,以备学习。
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;


阅读(4381) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~