TinyOS、NesC程序開發經驗談

1、 nesC的語法
       NesC是標準C的擴展,應用背景是傳感器網絡這樣的嵌入式系統,這類系統的特色是內存有限,存在任務和中斷兩類操做。NesC的語法和標準C基本沒有區別(NesC應該不能動態分配內存)。NesC程序的基本組成是Component,一個Component是一個*.nc文件。每一個Component 能夠完成必定的工做,一個app通常有一個稱爲「Main」的Component做爲程序的執行體(相似於C的main函數),「Main」調用其餘的 component以實現程序的功能。「Main」調用其餘Component,以及一個Component調用其餘的Component的方式是 「interface」的鏈接,Component 「uses」的interface鏈接到其餘component 「provides」的interface。Interface能夠看做函數聲明的一種封裝,一個interface的內容是幾個函數的聲明(沒有函數的定義),TinyOS系統提供了一系列interface(interface應該是由系統提供,不用本身寫的)。能夠理解爲Interface是 Component的屬性,函數是interface的屬性。Component分爲兩類,「configuration」用來完成component之間的鏈接,「module」用來完成該Component的功能(內容是「provides」的interface中函數的定義)。NesC定義了兩類特殊的函數,「command」和「event」。函數調用時,Command用「call」,event用「signal」,在一個component 中,provides的interface中的command函數必須被實現(在implementation中定義),uses的interface中的event函數必須被實現。「async」指出這個command或者event能夠在有中斷時使用。爲了協調任務和中斷的執行,nesC使用 「atomic」指出該段代碼「不可被打斷」。另外定義了「task」封裝一些代碼來完成一個任務,系統有FIFO的task隊列。不一樣的Task之間沒有優先級,但task能夠被interrupt handler打斷。爲防止全局變量等公用數據被非正常修改,nesC規定只在task中進入公共的數據部分。
2、 學習nesC比較有效的過程
      在系統附帶的文檔裏../tinyos/cygwin/opt/tinyos-1.x/doc/tutorial 提供了8個lesson,是用來熟悉nesC語法用的。把lesson1(Blink)和lesson2(sense)看懂,而且按照後面練習中的要求修改程序。作完以後,對於nesC的語法就比較熟悉了。以後看別的程序差很少就能夠直接看源代碼了。
3、 生成程序的結構圖
      頗有用的功能,在程序的文件夾裏,鍵入「make micaz docs」命令,能夠在../doc/nesdoc/micaz目錄下生成這個程序的結構圖。經過看結構圖來了解程序比較直觀。另外,在編寫程序的時候,有一個問題,就是調試程序很困難。所以在編寫完程序而且編譯經過以後,能夠先生成它的結構圖,檢查是否正確,做爲調試程序的一個步驟。
4、 調試方法
在程序中儘可能多得使用三個指示燈,是比較有效的調試方法。程序寫完以後能夠生成程序的結構圖以及用listen命令讀取消息包的類型。
5、 有用的連接
TinyOS tutorial: http://www.tinyos.net/tinyos-1.x/doc/tutorial/
TinyOS FAQ:     http://www.tinyos.net/faq.html#SEC-43
TinyOS Programming, NesC Tutorial(這些網上能夠下載到,沒有找到的話,留下Email我給你發,對了我這也有TinyOS中文版和NesC中文版,但我建議仍是英文原版的好,翻譯過來的實在是...)
6、 一個程序示例
(實現RSSI信號的16個Node節點採集,請注意對應的文件名,燒製時注意節點ID號。如下是完整的 Node節點程序,PC程序爲之前說的SNICI軟件系統,這個程序加以修改能夠獲得聲音定位程序,實驗室如今在作視頻無線傳感器網絡的是在 starget上實現的。)

/********************************************************************
        Copyright (C), 2006-2007, by Enoch.
        FileName:       Rssi.h
        Description:    Hardware specific definitions for the MTS300/310.
*********************************************************************/

enum
{
    INITIAL_TIMER_RATE      = 1000,
    INITIAL_TIMER_REAE_STEP = 8,
    INITIAL_TIMER_DELAY     = 1500
};

enum
{
    BASE_NODE = 0,
    MOVE_NODE = 100,
};

/********************************************************************
        Copyright (C), 2006-2007, by Enoch.
        FileName:       RssiMsg.h
        Description:    RSSI tracking system.
*********************************************************************/

enum
{
    TOTAL_NODE = 16
};

typedef struct RssiMsg
{
    uint8_t addr;
    uint16_t seq;
}RssiMsg;

typedef struct NodeUARTMsg
{   
    uint8_t fromaddr;
    uint8_t rssi;
    uint16_t seq;
}NodeUARTMsg;

typedef struct UARTMsg
{   
    uint8_t rssi[TOTAL_NODE];
    uint16_t seq;
}UARTMsg;

enum
{
    RSSI = 44,
};

/********************************************************************
        Copyright (C), 2006-2007, by Enoch.
        FileName:       RssiM.nc
        Description:    RSSI tracking system.
*********************************************************************/

includes RssiMsg;
includes Rssi;

module RssiM
{
     provides interface StdControl;
     uses
     {
         interface Timer as TimerSend;
         interface SendMsg as Sendtest;
         interface ReceiveMsg as Receivetest;
         interface SendMsg as UARTSend;
         interface Leds;
     }
}

implementation
{
    TOS_Msg MoveData, UARTSendData, MoteSendData;
    uint8_t rssi_value[TOTAL_NODE];
    uint16_t seq = 0;
    uint32_t i = 0;
    task void SendData()
    {
        call UARTSend.send(TOS_UART_ADDR, sizeof(UARTMsg), &UARTSendData);
    }
    task void SendNodeData()
    {
        call Sendtest.send(TOS_BCAST_ADDR, sizeof(RssiMsg), &MoveData);
    }
     command result_t StdControl.init()
     {
         call Leds.init();
         call Leds.greenOn();
         for (i = 0; i < TOTAL_NODE; i++)
        {
            rssi_value[i] = 255;
        }
         seq = 0;
         return SUCCESS;
     }

     command result_t StdControl.start()
     {   
         /* Moving node start the timer */
         if (TOS_LOCAL_ADDRESS == MOVE_NODE)
         {
             call TimerSend.start(TIMER_REPEAT, INITIAL_TIMER_RATE);
             call Leds.greenToggle();
             call Leds.redToggle();
         }
         else if (TOS_LOCAL_ADDRESS == BASE_NODE)
         {
             seq = 1;
         }
         return SUCCESS;
     }

     command result_t StdControl.stop()
     {
         if (TOS_LOCAL_ADDRESS == MOVE_NODE)
         {
             call TimerSend.stop();
         }
         return SUCCESS;
     }
     event result_t TimerSend.fired()
     {
         /* Moving node send message */
         if (TOS_LOCAL_ADDRESS == MOVE_NODE)
         {
             RssiMsg* snd_msg = (RssiMsg*)MoveData.data;
            // Data
             snd_msg->addr = TOS_LOCAL_ADDRESS;
             snd_msg->seq = ++seq;
             call Sendtest.send(TOS_BCAST_ADDR, sizeof(RssiMsg), &MoveData);
             call Leds.yellowToggle();
         }
         return SUCCESS;
     }

     event result_t Sendtest.sendDone(TOS_MsgPtr msg, result_t success)
     {
          call Leds.yellowToggle();
          return SUCCESS;
     }
    /* Motes Reciece Message */
     event TOS_MsgPtr Receivetest.receive(TOS_MsgPtr msgptr)
     {
         /* BASE mote recieve message to UART */
         if (TOS_LOCAL_ADDRESS == BASE_NODE)
         {
             NodeUARTMsg* node_uart_msg = (NodeUARTMsg*)msgptr->data;
             UARTMsg* uart_msg = (UARTMsg*)UARTSendData.data;
             RssiMsg* snd_msg = (RssiMsg*)MoveData.data;
             uint8_t node_addr = node_uart_msg->fromaddr;
             uint16_t node_seq = node_uart_msg->seq;
             uint8_t max_rssi = 255;
             uint16_t max_node = 0;
             if (((RssiMsg*)msgptr->data)->addr == MOVE_NODE)
             {
                 if (((RssiMsg*)msgptr->data)->seq > 0)
                 {
                     /* Select the max rssi value node */
                     for (i = 0; i < TOTAL_NODE; i++)
                     {
                         uart_msg->rssi[i] = rssi_value[i];
                     }
                    // Data
                     uart_msg->seq = node_seq;
                     /* Upstream the data */    
                     //call UARTSend.send(TOS_UART_ADDR, sizeof(RssiMsg), &MoveData);
                     //call UARTSend.send(TOS_UART_ADDR, sizeof(UARTMsg), &UARTSendData);
                     post SendData();
                     //post SendNodeData();
                     //call Sendtest.send(TOS_BCAST_ADDR, sizeof(RssiMsg), &MoveData);
                     for (i = 0; i < TOTAL_NODE; i++)
                     {
                         rssi_value[i] = 255;
                     }
                     rssi_value[node_addr-1] = node_uart_msg->rssi;
                     //call Leds.redToggle();
                 }
                 return msgptr;
             }
             else
             {
                 /* data is recieved for saving */
                 rssi_value[node_addr-1] = node_uart_msg->rssi;
                 //call Leds.greenToggle();
             }   
         }
         /* Node proccess */
         else if (TOS_LOCAL_ADDRESS > BASE_NODE && TOS_LOCAL_ADDRESS != MOVE_NODE)
         {
             RssiMsg* recv_rssi_msg = (RssiMsg*)msgptr->data;
             NodeUARTMsg* send_mote_msg = (NodeUARTMsg*)MoteSendData.data;
             if (recv_rssi_msg->addr == MOVE_NODE)
             {
                 send_mote_msg->fromaddr = TOS_LOCAL_ADDRESS;
                  send_mote_msg->rssi = (int8_t)msgptr->strength;
                  send_mote_msg->seq = recv_rssi_msg->seq;
                  /* Delay send to base mote */
                  for (i = 0; i < TOS_LOCAL_ADDRESS * INITIAL_TIMER_DELAY; i++)
                 call Sendtest.send(BASE_NODE, sizeof(NodeUARTMsg), &MoteSendData);
              }
              else if (recv_rssi_msg->addr == BASE_NODE)
              {
                  if (recv_rssi_msg->seq == TOS_LOCAL_ADDRESS)
                  {
                      call Leds.redOn();
                  }
                  else
                  {
                      call Leds.redOff();
                  }
              }   
         }
         return msgptr;
     }
    // UART Send Message
       event result_t UARTSend.sendDone(TOS_MsgPtr msg, result_t success)
     {
         //call Leds.yellowToggle();
          return SUCCESS;
     }
}
/********************************************************************
        Copyright (C), 2006-2007, by Enoch.
        FileName:       Makefile
        Description:   RSSI tracking system.
*********************************************************************/

COMPONENT = Rssi

XBOWROOT=%T/../contrib/xbow/tos

PFLAGS= -I$(XBOWROOT)/platform/micaz

# For MICA2 and MICA2DOT
#PFLAGS+= -I../../tos/platform/mica2 -I../../tos/CC1000RadioAck -I../../tos/lib/ReliableRoute -I%T/lib/Queue -I%T/lib/Broadcast -I%T/lib/Attributes

# For MICAZ
PFLAGS+= -I../../beta/tos/lib/CC2420Radio -I%T/lib/Broadcast -I%T/lib/Attributes

include ../MakeXbowlocal
include ${TOSROOT}/tools/make/Makerules html

相關文章
相關標籤/搜索