微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 无线和射频 > 射频无线通信设计 > UP智能家居之CC2530源码分析

UP智能家居之CC2530源码分析

时间:10-02 整理:3721RD 点击:

UP智能家居之CC2530源码分析


主要是为了记录学习博创的zigbee系统CC2530时的一些笔记.这是我第一次接触产品级的代码,确实在阅读源码时学到不少东西.
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发现主要在初始化时增加了一个函数.
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
/*********************************************************************
* @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读取节点类型和设备类型
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
   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();    }  
以及将串口事件注册到任务队列中
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
MT_UartRegisterTaskID( SampleApp_TaskID ); //add by 1305106  
然后进入事件循环:
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
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();<span style="white-space:pre">                         </span>  
      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网络-->
串口数据处理函数
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
void SampleApp_ProcessMTMessage(afIncomingMSGPacket_t *msg)  
{   
    Config_CmdProcessing((uint8*)msg);      //接收来自串口的 配置命令  
    NodeInfo_CmdProcessing((uint8*)msg);    //接收来自串口的 节点处理命令  
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
}  
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
//<span style="font-family: Arial, Helvetica, sans-serif;">afIncomingMSGPacket_t 结构体如下</span>  
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
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;  
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
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;  
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
<span style="white-space:pre">  </span>//最终调用了osal_nv_write 把接收数据保存到flash  
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
}  
其中 MT_RPC_POS_CMD1 的值为 2 .一开始很奇怪明明afIncomingMSGPacket_t 结构体的真正数据在最后一个,按一字节对齐来算怎么也不可能只是指针位置+2..我猜测可能是串口接收数据过程中,数据被保存到afIncomingMSGPacket_t 结构体,见此函数
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );  
每个事件数据分配的内存可能是不一样的.但是都统一当成afIncomingMSGPacket_t 指针来处理.最终处理时再强制转化为字节数组.
命令处理同理.
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
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;  
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
//...  
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
}  
在几个请求中,最重要的就是NODEINFO_CMD_GET_NWK_TOPO_REQ 了,在后面服务器端的代码分析中,服务器会开辟一个线程不断发送这个请求,以实时更新zigbee网络状态.
//这个函数从zigbee节点数据链表中提取每个节点短地址,并分别转发NODEINFO_CMD_GET_NWK_TOPO_REQ  请求.
//至于这个链表什么时候建立的  在后面的代码讲到
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
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);//建立发送请求(类似一个模板)  
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
            //Delay(5000);  
    }  
    // reset node's status  
    p->status = 0x00;  
}  
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
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 )  
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
//....  
[cpp] view plain copy print?在CODE上查看代码片派生到我的代码片
}  
协调器代码分析就到这吧

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top