zigbee协议与开发-ZStack协议栈结构的初步解析

 

int main( void )
{
  // Turn off interrupts(关中断)
  osal_int_disable( INTS_ALL );

  // Initialization for board related stuff such as LEDs(初始化板上组件,如LED) HAL_BOARD_INIT();

  // Make sure supply voltage is high enough to run(电压检查)
  zmain_vdd_check();

  // Initialize board I/O(初始化I/O接口)
  InitBoard( OB_COLD ); 

  // Initialze HAL drivers(初始化HAL设备,在hal_drivers.c中实现)
  HalDriverInit();

  // Initialize NV System(初始化NV系统,即非易失设备,如Flash)
  osal_nv_init( NULL );

  // Initialize the MAC(初始化MAC)
  ZMacInit();

  // Determine the extended address(确定设备的长地址)
  zmain_ext_addr();

  // Initialize basic NV items(初始化ZStack的全局变量,如果在NV内存中不存在,则写入缺省值)
  zgInit();

#ifndef NONWK
  // Since the AF isn't a task, call it's initialization routine
  afInit();
#endif

  // Initialize the operating system(初始化操作系统)
  osal_init_system();

  // Allow interrupts(开中断)
  osal_int_enable( INTS_ALL );

  // Final board initialization(最后初始化板)
  InitBoard( OB_READY );

  // Display information about this device(显示设备信息,比如CollectorEB板的IEEE地址就是在这个函数里面显示出来的。)
  zmain_dev_info();

  /* Display the device info on the LCD */(显示LCD设备信息)
#ifdef LCD_SUPPORTED
  zmain_lcd_init();
#endif

#ifdef WDT_IN_PM1
  /* If WDT is used, this is a good place to enable it. */(开WatchDog)
  WatchDogEnable( WDTIMX );
#endif

  osal_start_system(); // No Return from here(启动操作系统,实际上进入一个死循环)

  return 0;  // Shouldn't get here.
} // main()

说明:以上初始化有的跟硬件相关,有的跟操作系统(以osal开头)相关,最后系统调用osal_start_system进入循环,然后在循环中处理消息,下面是这个函数的主体(见osal.c):

void osal_start_system( void )
{
#if !defined ( ZBIT ) && !defined ( UBIT )
  for(;;)  // Forever Loop (死循环)
#endif
  {
    uint8 idx = 0;

    osalTimeUpdate();  //更新时间
    Hal_ProcessPoll();  // This replaces MT_SerialPoll() and osal_check_timer().(轮询UART和Timer等设备消息)
   
    do {
      if (tasksEvents[idx])  // Task is highest priority that is ready.
      {
        break;
      }
    } while (++idx < tasksCnt);

    if (idx < tasksCnt)
    {
      uint16 events;
      halIntState_t intState;

      HAL_ENTER_CRITICAL_SECTION(intState);   //加锁防上访问事件队列充突
      events = tasksEvents[idx];
      tasksEvents[idx] = 0;  // Clear the Events for this task.
      HAL_EXIT_CRITICAL_SECTION(intState);

      events = (tasksArr[idx])( idx, events );                 //处理当前要处理的事件,并返回事件ID

      HAL_ENTER_CRITICAL_SECTION(intState);
      tasksEvents[idx] |= events;  // Add back unprocessed events to the current task.(更新事件状态)
      HAL_EXIT_CRITICAL_SECTION(intState);
    }
#if defined( POWER_SAVING )
    else  // Complete pass through all task events with no activity?
    {
      osal_pwrmgr_powerconserve();  // Put the processor/system into sleep(没有事件处理,进入休眠状态)
    }
#endif
  }
}

需要特别解析的是上面红色标注的行,这个地方看起来象是一个函数指针的形式,查看taskArr定义(见SAPI.c)如下:

#if OSAL_SAPI
// The order in this table must be identical to the task initialization calls below inosalInitTask.
const pTaskEventHandlerFn tasksArr[] = {
  macEventLoop,
  nwk_event_loop,
  Hal_ProcessEvent,
#if defined( MT_TASK )
  MT_ProcessEvent,
#endif
  APS_event_loop,
  ZDApp_event_loop,

  SAPI_ProcessEvent
};

上面基本上是***EventLoop,可以推测是处理不同层的信息,如mac, NWK, Hal, APS, ZDAPP的事件处理函数。以macEventLoop为例,可以在mac_api.h文件中找到这个函数的定义如下:

extern uint16 macEventLoop(uint8 taskId, uint16 events);
但是,没有跟踪到上述函数的实现在哪个文件中。但是对于温度监测应用DEMo来讲,上述的SAPI_ProcessEvent()函数在SAPI.c中实现如下:

UINT16 SAPI_ProcessEvent( byte task_id, UINT16 events )
{
  osal_event_hdr_t *pMsg;
  afIncomingMSGPacket_t *pMSGpkt;
  afDataConfirm_t *pDataConfirm;
 

  if ( events & SYS_EVENT_MSG )          //系统事件消息,只有定义了SAPI_CB_FUNC 的似乎才会被上层应用处理。
  {

    ...

case KEY_CHANGE:
#if ( SAPI_CB_FUNC )
          zb_HandleKeys( ((keyChange_t *)pMsg)->state, ((keyChange_t *)pMsg)->keys );
#endif
          break;

  ...
  // Return unprocessed events
    return (events ^ SYS_EVENT_MSG);
  }

  if ( events & ZB_ALLOW_BIND_TIMER )   //ZB_ALLOW_BIND_TIMER
  {
    afSetMatch(sapi_epDesc.simpleDesc->EndPoint, FALSE);
    return (events ^ ZB_ALLOW_BIND_TIMER);
  }

  if ( events & ZB_BIND_TIMER )  //ZB_BIND_TIMER
  {
    // Send bind confirm callback to application
    SAPI_BindConfirm( sapi_bindInProgress, ZB_TIMEOUT );
    sapi_bindInProgress = 0xffff;

    return (events ^ ZB_BIND_TIMER);
  }

  if ( events & ZB_ENTRY_EVENT )   //ZB_ENTRY_EVENT
  {
    uint8 startOptions;

    // Give indication to application of device startup
#if ( SAPI_CB_FUNC )
    zb_HandleOsalEvent( ZB_ENTRY_EVENT );
#endif

    // 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 );
  }

  // This must be the last event to be processed
  if ( events & ( ZB_USER_EVENTS ) )
  {
    // User events are passed to the application
#if ( SAPI_CB_FUNC )
    zb_HandleOsalEvent( events );
#endif

    // Do not return here, return 0 later
  }

  // Discard unknown events
  return 0;
}

上述代码中,只有黑色标注的才被上传到应用层APL进行处理,而这些代码正好是用户需要实现的,分别在DemoSensor.c和DemoCollector.c中实现。以路由器的代码为例,显示如下,其作用主要是对按键进行处理:

void zb_HandleKeys( uint8 shift, uint8 keys )
{
  static uint8 allowBind=FALSE;
  static uint8 allowJoin=TRUE;
  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 )     //Joystick Up key (Set as cordinator,设置为协调器)
    {
      if ( appState == APP_INIT  )
      {
        // Key 1 starts device as a coordinator
        logicalType = ZG_DEVICETYPE_COORDINATOR;
        zb_WriteConfiguration(ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType);
               
        // Reset the device with new configuration
        zb_SystemReset();
      }
    }
    if ( keys & HAL_KEY_SW_2 )    //Joystick Right key (Allow bind,允许绑定,一个网络中只有一个节点,即协调器有此设置。)
    {
      allowBind ^= 1;
      if (allowBind)
      {
        // Turn ON Allow Bind mode infinitly
        zb_AllowBind( 0xFF );
        HalLedSet( HAL_LED_2, HAL_LED_MODE_ON );
        //This node is the gateway node
        isGateWay = TRUE;
       
        // Update the display
        #if defined ( LCD_SUPPORTED )
        HalLcdWriteString( "Gateway Mode", HAL_LCD_LINE_2 );
        #endif
      }
      else
      {
        // Turn OFF Allow Bind mode infinitly
        zb_AllowBind( 0x00 );
        HalLedSet( HAL_LED_2, HAL_LED_MODE_OFF );
        isGateWay = FALSE;
       
        // Update the display
        #if defined ( LCD_SUPPORTED )
        HalLcdWriteString( "Collector", HAL_LCD_LINE_2 );
        #endif
      }
    }
    if ( keys & HAL_KEY_SW_3 )    //Joystick down key(路由器有效,用于定时向协调器报告事件,以生成拓扑图)
    {
      // Start reporting
      osal_set_event( sapi_TaskID, MY_REPORT_EVT );
    }
    if ( keys & HAL_KEY_SW_4 )      //Joystick Left key(用于禁止/允许节点加入,此功能用于协调器设置禁止或允许节点加入,但是不知为何无效!!?)
    {
      // Key 4 is used to control which routers
      // that can accept join requests
      allowJoin ^= 1;
      if(allowJoin)
      {
        NLME_PermitJoiningRequest(0xFF);
      }
      else {
        NLME_PermitJoiningRequest(0);
      }
    }
  }
}

对应的另一个处理函数如下:

void zb_HandleOsalEvent( uint16 event )
{
  uint8 logicalType;
 
  if(event & SYS_EVENT_MSG)  //系统消息,多数在底层已经处理,因此此处为空。
  {
   
  }
 
  if( event & ZB_ENTRY_EVENT )          //系统启动事件,需要做一些设置。
  { 
    // Initialise UART
    initUart(uartRxCB);
   
    // blind LED 1 to indicate starting/joining a network
    HalLedBlink ( HAL_LED_1, 0, 50, 500 );
    HalLedSet( HAL_LED_2, HAL_LED_MODE_OFF );
   
    // Read logical device type from NV
    zb_ReadConfiguration(ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType);
  
    // Start the device
    zb_StartRequest();
  }
 
  if ( event & MY_START_EVT )
  {
    zb_StartRequest();
  }
 
  if ( event & MY_REPORT_EVT )
  {
    if (isGateWay)
    {
      osal_start_timerEx( sapi_TaskID, MY_REPORT_EVT, myReportPeriod );
    }
    else if (appState == APP_BINDED)
    {
      sendDummyReport();
      osal_start_timerEx( sapi_TaskID, MY_REPORT_EVT, myReportPeriod );
    }
  }
  if ( event & MY_FIND_COLLECTOR_EVT )
  {
    // Find and bind to a gateway device (if this node is not gateway)
    if (!isGateWay)
    {
      zb_BindDevice( TRUE, DUMMY_REPORT_CMD_ID, (uint8 *)NULL );

    }
  }
 
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值