UP智能家居系統之節點cc2530源碼分析(1)

本文爲這個系列文章的第一篇.

主要是爲了記錄學習博創的zigbee系統時的一些筆記.這是我第一次接觸產品級的代碼,確實在閱讀源碼時學到不少東西.

 

CC2530 特性
  • RF/Layout
    • 2.4-GHz IEEE 802.15.4 Compliant RF Transceiver
    • Excellent Receiver Sensitivity and Robustness to Interference
    • Programmable Output Power Up to 4.5 dBm
    • Very Few External Components
    • Only a Single Crystal Needed for Asynchronous Networks
    • 6-mm × 6-mm QFN40 Package
    • Suitable for Systems Targeting Compliance With Worldwide Radio- 
      Frequency Regulations: ETSI EN 300 328 and EN 300 440 (Europe), 
      FCC CFR47 Part 15 (US) and ARIB STD-T-66 (Japan)

 

ZStack 是一個片上系統,cc2530使用片內一個flash存儲這些代碼和數據.關於這個系統的OSAL(Operating System Abstraction Layer),網上已經有很多分析.我就不多說了,本文只關心osal的api的使用,不關心它的實現原理.附 osal API 中文版:

 

(竟然只找到了中文版,我在ti官方都找不到相關文件)

 

zStack從zmain.c開始運行.

用merge對比官方例程的zmain.c發現主要在初始化時增加了一個函數.

/*********************************************************************
 * @fn      zmain_ram_init
 * @brief   Initialize ram for stack "high-water-mark" observations.
 * @return  none
 *********************************************************************/
static void zmain_ram_init( void )
{
  uint8 *end;
  uint8 *ptr;

  // Initialize the call (parameter) stack
  end = (uint8*)CSTK_BEG;  // Lower end
  ptr = (uint8*)(*( __idata uint16*)(CSTK_PTR));  // Upper end
  while ( --ptr > end )
    *ptr = STACK_INIT_VALUE;

  // Initialize the return (address) stack
  ptr = (uint8*)RSTK_END - 1;  // Upper end
  while ( --ptr > (uint8*)SP )
    *(__idata uint8*)ptr = STACK_INIT_VALUE;
}


對比官方demo和up的sampleApp.c文件,up工程在SampleApp_Init 初始化中增加了從flash讀取節點類型和設備類型

    NodeHead = NULL;
    gSensorMode = 0x01;  //00 查詢模式 01 中斷模式,自動上報信息
    gIntFlag = 0x00;     //no interrupt
    
    gDevType = CheckDeviceType();
    gSensorType = CheckSensorType();  //在初始化的時候設置 "傳感器類型" 全局變量  //add by @wei
  
    if(gSensorType == (sensor_t)SENSOR_SHT11)
    {   Sht11Init();   }
    else if(gSensorType == (sensor_t)SENSOR_SET)
    {
        //HalLedBlink( HAL_LED_2, 4, 50, (1000 / 4) );
	//HalLedBlink( HAL_LED_3, 4, 50, (1000 / 4) );
        SensorSetIO();
    }
    else
    {   SensorIO_Init();    }

以及將串口事件註冊到任務隊列中

MT_UartRegisterTaskID( SampleApp_TaskID ); //add by 1305106


然後進入事件循環:
uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
{
    afIncomingMSGPacket_t *MSGpkt;
    (void)task_id;  // Intentionally unreferenced parameter
    
    if ( events & SYS_EVENT_MSG )
    {
        MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );
        while ( MSGpkt )
        {
            switch ( MSGpkt->hdr.event )
            { 
              // Received when a messages is received (OTA) for this endpoint
              case AF_INCOMING_MSG_CMD:
                HalLedBlink( HAL_LED_1, 4, 50, (1000 / 4) );     //receive message -> blink led //@wei zigbee網絡
                SampleApp_MessageMSGCB( MSGpkt );     //This function processes any incoming data - probably from other devices.
                break;
              
              case SPI_INCOMING_ZAPP_DATA:
                SampleApp_ProcessMTMessage(MSGpkt);               //receive uart data  重點
                MT_UartAppFlowControl (MT_UART_ZAPP_RX_READY);
                break;
      
              // Received whenever the device changes state in the network
              case ZDO_STATE_CHANGE:
                SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
                if ( (SampleApp_NwkState == DEV_ZB_COORD)
                    || (SampleApp_NwkState == DEV_ROUTER)
                    || (SampleApp_NwkState == DEV_END_DEVICE) )
                {
                    HalLedSet(HAL_LED_2, HAL_LED_MODE_ON);
                }
                else
                {
                    // Device is no longer in the network
                }
                break;
      
              default:
                break;
          }
          osal_msg_deallocate( (uint8 *)MSGpkt );                                   // Release the memory
          MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );   // Next - if one is available
      }
  
      return (events ^ SYS_EVENT_MSG);    // return unprocessed events
    }
    
   if ( events & SAMPLEAPP_SEND_SENSOR_INT_EVT )
    { 
      SampleApp_Process_SENSOR_INT();							
      return ( events ^ SAMPLEAPP_SEND_SENSOR_INT_EVT);
    }
  
    if ( events & SAMPLEAPP_CMD_RESET_RSP_EVT )
    { 
      SystemReset();  
      //return ( events ^ SAMPLEAPP_SEND_SENSOR_INT_EVT);
    }
    
    return 0;   // Discard unknown events
}

我們不按照代碼順序來分析.可以從數據的流向來看: 即 上位機-->串口-->下位機(zigbee協調器)-->zigbee網絡-->

串口數據處理函數

void SampleApp_ProcessMTMessage(afIncomingMSGPacket_t *msg)
{ 
    Config_CmdProcessing((uint8*)msg);      //接收來自串口的 配置命令
    NodeInfo_CmdProcessing((uint8*)msg);    //接收來自串口的 節點處理命令
}
//afIncomingMSGPacket_t 結構體如下
typedef struct
{
  osal_event_hdr_t hdr;     /* OSAL Message header */
  uint16 groupId;           /* Message's group ID - 0 if not set */
  uint16 clusterId;         /* Message's cluster ID */
  afAddrType_t srcAddr;     /* Source Address, if endpoint is STUBAPS_INTER_PAN_EP,
                               it's an InterPAN message */
  uint16 macDestAddr;       /* MAC header destination short address */
  uint8 endPoint;           /* destination endpoint */
  uint8 wasBroadcast;       /* TRUE if network destination was a broadcast address */
  uint8 LinkQuality;        /* The link quality of the received data frame */
  uint8 correlation;        /* The raw correlation value of the received data frame */
  int8  rssi;               /* The received RF power in units dBm */
  uint8 SecurityUse;        /* deprecated */
  uint32 timestamp;         /* receipt timestamp from MAC */
  afMSGCommandFormat_t cmd; /* Application Data */
} afIncomingMSGPacket_t;

void Config_CmdProcessing(uint8 *pBuf)
{
   uint16 cmd;
   uint8  *pData = pBuf+MT_RPC_POS_CMD1;
  
  /*************--cmd frame format--****************/
   /***  | sop | cmd | len | data | fcs |  ***/
   /***  |  1  |  2  |  1  | len  |  1  |  ***/
   cmd = BUILD_UINT16( pData[2], pData[1] );
   switch(cmd)
   {
   case CONFIG_CMD_SET_DEV_TYPE_REQ:
     Config_ProcessSetDevTypeReq(pData);          break;
	//最終調用了osal_nv_write 把接收數據保存到flash
}


其中 MT_RPC_POS_CMD1 的值爲 2 .一開始很奇怪明明afIncomingMSGPacket_t 結構體的真正數據在最後一個,按一字節對齊來算怎麼也不可能只是指針位置+2..我猜測可能是串口接收數據過程中,數據被保存到afIncomingMSGPacket_t 結構體,見此函數

MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );

每個事件數據分配的內存可能是不一樣的.但是都統一當成afIncomingMSGPacket_t 指針來處理.最終處理時再強制轉化爲字節數組. 


命令處理同理.

void NodeInfo_CmdProcessing(uint8 *pBuf)
{
   uint16 cmd;
   uint8  *pData = pBuf+MT_RPC_POS_CMD1;
  
  /*************--cmd frame format--****************/
   /***  | sop | cmd | len | data | fcs |  ***/
   /***  |  1  |  2  |  1  | len  |  1  |  ***/
   cmd = BUILD_UINT16( pData[2], pData[1] );
   switch(cmd)
   {
   case NODEINFO_CMD_NWK_CONNECT_REQ:
     NodeInfo_ProcessNwkConnectReq(pData);                  break;
     
   case NODEINFO_CMD_GET_NWK_DESP_REQ:
     NodeInfo_ProcessGetNwkDespReq(pData);                  break;
     
   case NODEINFO_CMD_GET_NWK_TOPO_REQ:
     NodeInfo_ProcessReportOutNode();                 //通過zigbee網絡傳遞請求
     NodeInfo_ProcessGetNwkTopoReq(pData);                  break;
//...
}

在幾個請求中,最重要的就是NODEINFO_CMD_GET_NWK_TOPO_REQ 了,在後面服務器端的代碼分析中,服務器會開闢一個線程不斷髮送這個請求,以實時更新zigbee網絡狀態.


 //這個函數從zigbee節點數據鏈表中提取每個節點短地址,並分別轉發NODEINFO_CMD_GET_NWK_TOPO_REQ  請求.

//至於這個鏈表什麼時候建立的  在後面的代碼講到

void NodeInfo_ProcessReportOutNode( void )
{
  pNode p;
  uint8 nwkaddr[2];
 
  for (p = NodeHead; p!=NULL ; p = p->next)
  {
      if(p->status == 0x00){
              p->times++; // out flag	
              //HalUARTWrite ( 0, "\r\nout\r\n", 7 );
      }
      if((p->status == 0x00)&&(p->times==3)){
              p->times=0;
              //MT report out node status.!!!
              nwkaddr[0] = HI_UINT16(p->nwkaddr);
              nwkaddr[1] = LO_UINT16(p->nwkaddr);
              SampleApp_BuildAndSendZToolResponse(NODEINFO_CMD_RPT_NODEOUT_RSP, 2, nwkaddr);//建立發送請求(類似一個模板)
              //Delay(5000);
      }
      // reset node's status
      p->status = 0x00;
  }
}

uint8 SampleApp_SendNwkData(uint16 nwkAddr, uint8 clusterId, uint8 *data, uint8 dataLen)
{
    if(nwkAddr == 0xFFFF)
      SampleApp_General_DstAddr.addrMode = (afAddrMode_t)AddrBroadcast;
    else 
      SampleApp_General_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
      SampleApp_General_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
      SampleApp_General_DstAddr.addr.shortAddr =nwkAddr;
    
    if ( AF_DataRequest( &SampleApp_General_DstAddr, &SampleApp_epDesc,//真正的發送函數.
                         clusterId,
                         dataLen,
                         data,
                         &SampleApp_TransID,// transfer id
                         AF_DISCV_ROUTE,
                         AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
//....
}

協調器代碼分析就到這吧
發佈了30 篇原創文章 · 獲贊 21 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章