天天看點

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中
uip0.9成功移植Z-STACK中

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中

      然後在相關檔案中做一些修改。在一個大工程項目中,條件編譯用的很多,為了和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 ()函數中添加如下代碼:(這個最好在開頭添加,因為網絡資料包處理要及時)

#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()){

                  //delay_sec(5);

          }else if(uip_connected()){

#if 1

                  uip_send(uip_appdata,sprintf((char*)uip_appdata,"%s",

                  "Hello,I connected to you! thanks."));

#endif

          }else if(uip_rexmit()){

#if 1

                  uip_send(uip_appdata,sprintf((char*)uip_appdata,"%s",

                  "this is retransmission packet"));

#endif

          }else if(uip_poll()){

#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()){

#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

                  uip_send(uip_appdata,sprintf((char*)uip_appdata,"%s",

                  "this is a second packet."));

#endif

          }else{

          }

          break;

  default:

          break;

}

}

#endif

上面代碼中有一個數組buf,這個是在SimpleCollector.c檔案中定義的,因為buf為zigbee網絡中的資料接收緩沖區,一旦接收到資料,就将這些資料發送以太網中。然後編譯連結,這其中不乏出現各種問題,需要自己去一一解決。

接下來看一下實驗運作的結果

                                      :

uip0.9成功移植Z-STACK中

這是一個ZigBee子產品打開時出現的結果,因為此時zigbee網絡中還沒有資料,是以此時buf一直為Battery:(我将buf初始化為Battery:),是以看到了以上結果。然後打開另一個zigbee子產品,可以看到這個運作結果:

uip0.9成功移植Z-STACK中

看到了麼,結果發生變化了,網絡調試助手接收到了從無線網絡中發過來的資料,這是cc2530内部溫度傳感器的資料!同時将序列槽助手打開看到:

uip0.9成功移植Z-STACK中

看到這個結果說明移植是成功的!哈哈!離完成項目又進了一步!

PS:在之前裸機移植uIP0.9到cc2530上,發現移植web伺服器時出了一個很怪異的問題!這個問題困擾了很久了!從理論上分析根本不會出現這個問題,但是實踐中可能會漏洞百出。等解決了這個問題再貼出來!相信很多同學都遇到了這個問題!