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

协调器代码分析就到这吧

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值