[置顶] uip0.9成功移植Z-STACK中

        之前将UIP0.9移植到CC2530上,是裸机移植的,由于项目需要,前几天将UIP0.9移植到Z-STACK中,并且系统能稳定运行,即实现了一个简单的TCP/IP+ZIGBEE的网关或者无线接入点。下面简要阐述下移植过程及运行结果。

       说明一下,我的Z-STACK版本ZStack-CC2530-2.2.2-1.3.0,用的是SimpleApp例程,在移植之前需要熟悉SimpleApp中的SimpleCollector和SimpleSensor实验,以及UIP0.9的cc2530裸机移植实验。最重要的是要熟悉

Z-STACK中事件驱动OSAL的运行机制和流程,这样才知道在哪些地方添加需要的代码。

       首先,在该项目的source目录里面添加uip和uip_app目录,并在这两个目录分别添加一下源文件


                   [置顶] uip0.9成功移植Z-STACK中_第1张图片

                   [置顶] uip0.9成功移植Z-STACK中_第2张图片

uip目录中的文件均为uip0.9源码包里面的文件,uip_app目录中两个文件自己添加,然后分别将这些文件添加到工程。enc28j60的驱动程序文件命名为hal_net.c,为了和Z-STACK中的驱动文件名字保持一致,相应添加一个头文件

hal_net.h,这两个文件在之前移植过程都有,只不过改了名字,略做修改而已。再分别将这两个文件添加进Z-STACK的驱动目录中,即driver目录中,相应路径为

C:\Texas Instruments\ZStack-CC2530-2.2.2-1.3.0\Components\hal\target\CC2530EB

   然后打开SimpleCollectorEB工程,如下图所示

                                                [置顶] uip0.9成功移植Z-STACK中_第3张图片

      然后在相关文件中做一些修改。在一个大工程项目中,条件编译用的很多,为了和Z-STACK中保持一致,在

hal_board_cfg.h添加如下代码

#ifndef HAL_NET
#define HAL_NET TRUE 
#endif


#ifndef UIP
#define UIP  TRUE
#endif

当不需要网络功能就可以将这写注释掉。

然后在sapi.c文件SAPI_Init函数添加如下代码

void SAPI_Init( byte task_id )
{
  uint8 startOptions;
#if (defined UIP)&&(UIP == TRUE)
  uip_init(); //uip初始化
  example1_init(); //uip应用程序初始化
#endif

  sapi_TaskID = task_id;


  sapi_bindInProgress = 0xffff;
  sapi_epDesc.endPoint = zb_SimpleDesc.EndPoint;
  sapi_epDesc.task_id = &sapi_TaskID;

  .....

}

当然别忘了添加头文件

#if (defined UIP)&&(UIP == TRUE)
   #include "uip.h"
   #include "app.h"
#endif

在hal_driver.c文件HalDriverInit()函数中末尾添加如下代码(记住是末尾添加,不能在开始添加,否则会有问题,我刚开始是放在开头的,结果出现调试不出结果,这个问题我也找了半天原因,先不说哈!)

#if (defined HAL_NET) && (HAL_NET == TRUE)
  HalNetInit();   //网络芯片驱动的初始化
#endif

需要在这个HalNetInit()中添加  HalSpiInit()函数,因为我用的是enc28j60网络芯片,其与cc2530的IO相连接,用的IO模拟SPI接口,所以这里面要初始化这几个IO。

同样在该文件 Hal_ProcessPoll ()函数中添加如下代码:(这个最好在开头添加,因为网络数据包处理要及时)

/* Net data Poll */

#if (defined HAL_NET) && (HAL_NET == TRUE)
  HalNetDataPoll();
#endif 
  

这个 HalNetDataPoll()函数是什么呢?我在里面添加了如下代码

    uint8 i;
    uint16 j;
    uip_len = dev_poll();
    for(j=0;j<500;j++);
    if(uip_len==0)
    {
      for(i = 0; i < UIP_CONNS; i++) 
      {
uip_periodic(i);
        if(uip_len>0)
        {
          uip_arp_out();
          dev_send();
        }
      }
      if(++arptimer == 20)
      {
        uip_arp_timer();
        arptimer = 0;
      }
    }
    else
    {
      if(BUF->type == htons(UIP_ETHTYPE_IP)) 
      {
        uip_arp_ipin();
        uip_input();
        if(uip_len > 0)
        {
          uip_arp_out();
          dev_send();
        }
      }
      else if(BUF->type == htons(UIP_ETHTYPE_ARP))
      {
        uip_arp_arpin();
        if(uip_len>0)
        {
          dev_send();
        }
      }
    }

   其实大家对这部分代码应该相当熟悉了,对!这就是移植uip到cc2530中main函数里面的大while(1)循环里面的代码。 因为Hal_ProcessPoll ()函数是系统轮询用的,每次for循环都会调用这个函数,所以HalNetDataPoll()每次都会得到调用以进行网络数据包的及时处理。这个是移植过程的关键部分。我之前试过用事件驱动机制将这个while循环的内容分解掉,将其放在Z-stack中的不同部分,但是发现效果极差,什么看不到想要的结果!可能是哪儿拆分的不合理!但是这种方式使能看到网络通信的结果的。

   另外就是数据类型的定义,在uip和z-stack中的定义是不同,这个很容易处理!还有就是头文件,这个在编译出错时进行相应添加!

最后就是uip.c文件,这个需要自己写,我的代码如下

void example1_init() 
{
   uip_listen(HTONS(1234));
}
#if 1
void example1_appcall()
{
  switch(uip_conn->lport) {

        case HTONS(1234):
          if(uip_timedout()||uip_aborted()||uip_closed()){
                  /*reconnect to server*/
                  //delay_sec(5);
          }else if(uip_connected()){
#if 1
                  /*is connected ok*/
                  uip_send(uip_appdata,sprintf((char*)uip_appdata,"%s",
                  "Hello,I connected to you! thanks."));
#endif
          }else if(uip_rexmit()){
#if 1
                  /*need retransmission last packet*/
                  uip_send(uip_appdata,sprintf((char*)uip_appdata,"%s",
                  "this is retransmission packet"));
#endif
          }else if(uip_poll()){
                  /*poll connecte is idle*/
#if 1
// uip_send(uip_appdata,sprintf((char*)uip_appdata,"%s",
// "Hi, we are idle"));
                  //uip_send("idle",4);
            uip_send(buf,32);
#endif
          }else if(uip_acked()){
                  /*get a ack for send packet ok*/
#if 0
                  uip_send(uip_appdata,sprintf((char*)uip_appdata,"%s",
                  "this is a second packet."));
#endif
                  if(uip_newdata()){
                          goto newdata_with_acked;
                  }
          }else if(uip_newdata()){
newdata_with_acked:
#if 1
                  /*receving a new data*/                
                  uip_send(uip_appdata,sprintf((char*)uip_appdata,"%s",
                  "this is a second packet."));
#endif
          }else{
                  /*error*/
          }
          break;
  default:
          /*discard packet*/
          break;
}
}
#endif

上面代码中有一个数组buf,这个是在SimpleCollector.c文件中定义的,因为buf为zigbee网络中的数据接收缓冲区,一旦接收到数据,就将这些数据发送以太网中。然后编译链接,这其中不乏出现各种问题,需要自己去一一解决。

接下来看一下实验运行的结果

                                      :[置顶] uip0.9成功移植Z-STACK中_第4张图片

这是一个ZigBee模块打开时出现的结果,因为此时zigbee网络中还没有数据,所以此时buf一直为Battery:(我将buf初始化为Battery:),所以看到了以上结果。然后打开另一个zigbee模块,可以看到这个运行结果:

                                         [置顶] uip0.9成功移植Z-STACK中_第5张图片

看到了么,结果发生变化了,网络调试助手接收到了从无线网络中发过来的数据,这是cc2530内部温度传感器的数据!同时将串口助手打开看到:

[置顶] uip0.9成功移植Z-STACK中_第6张图片



看到这个结果说明移植是成功的!哈哈!离完成项目又进了一步!

PS:在之前裸机移植uIP0.9到cc2530上,发现移植web服务器时出了一个很怪异的问题!这个问题困扰了很久了!从理论上分析根本不会出现这个问题,但是实践中可能会漏洞百出。等解决了这个问题再贴出来!相信很多同学都遇到了这个问题!

你可能感兴趣的:(zigbee,zigbee,CC2530,Z-Stack,Z-Stack,uip)