引言 隨著嵌入式系統應用的快速發展,為實現對其他設備的控制、監視或管理等功能,需要將嵌入式設備連入互聯網,以便于遠程控制和監測。為將嵌入式設備連入互聯網,需要有通信模塊實現通信協議。目前嵌入式設備能夠通過主流的TCP/IP 協議可直接與外網連接。然而隨著網絡規模的日益擴大、上網設備和人數的激增,目前采用的IPv4逐漸接近其自身發展的極限,其中比較顯著的問題是IP 地址資源的不足。IPv6[1] 采用長度為128 位的地址,地址空間幾乎可以視為無限,IPv6不僅完全地解決了地址短缺問題,還對在IPv4 中解決不好的其他問題(如,端到端IP連接、服務質量、安全性、移動性等方面)進行了改進。IPv6成為嵌入式設備進行網絡互連的首選。 1 嵌入式系統中TCP/IPv6 協議棧的特點與設計 1.1 嵌入式系統中TCP/IPv6 協議棧的特點 嵌入式系統不同于普通系統,它在硬件資源的占有量以及處理器的處理能力等方面受到限制,因此TCP/IP 協議棧在嵌入式系統與其在通用操作系統中的實現有很大不同。對于嵌入式系統而言,考慮到TCP/IP協議的復雜性以及嵌入式系統自身資源的有限,對TCP /IP 的實現并不是一件容易的事情[2]。因此就需要對原本復雜的TCP/IPv6 協議棧的實現進行精簡。嵌入式IPv6 協議棧獨立于嵌入式設備的操作,代碼空間小、移植性好,可以在無法承載操作系統的小存儲空間的嵌入式設備上實施,以實現這些設備間的基本網絡功能。 1.2 嵌入式系統中TCP/IPv6 協議棧的設計 芯片采用挪威Chipcon 公司推出的符合2.4GHz IEEE802.15.4 標準的射頻收發器CC2420[3] 。該協議棧要實現TCP/IPv6 協議棧的基本功能,運行于無線網環境下。底層協議采用IEEE 802.15 工作組制定的802.15.4 協議,802.15.4 協議是一個短距離的無線通信標準。網絡層支持TCP、ICMPv6 協議,不實現UDP 協議。 1.2.1 網絡接口層 網絡接口層是TCP/IPv6 協議棧與以太網設備的驅動程序之間的接口。一方面,它將從網卡接收到的數據提交給上層網絡層協議軟件處理;另一方面,它將從網絡層接收來的數據傳送給網卡驅動。接口函數介紹如下: (1)初始化函數 初始化函數InitNi()負責實現網絡接口層以及下層的物理設備驅動程序的初始化。主要包括以太網控制器的上電復位、MAC 地址的配置、收發緩沖環首尾地址的配置以及DMA 的初始化和收發數據格式的定義等。 (2)發送函數 在發送數據時,網絡接口層發送函數Send_Ethernet_Frame()負責接收IP協議產生的數據,將其封裝成以太網數據幀后,調用下層的 Send_ Packet()函數實現發送。Send_Packet()函數實現的是把以太網數據幀通過遠程DMA 通道送到RTL8019AS 中的發送緩存區,然后再啟動本地DMA,將數據發送網上。 (3)接收函數 在接收數據時,網絡接口層接收函數Rec_Ethernet_Packed( )被下層以太網驅動程序的數據接收函數Rec_Packet()調用。Rec_Ethernet_Packed()的作用根據以太類型值,調用不同的函數,同時去除以太幀的頭部,將正確的IPv6 數據從NIC 的數據緩沖區內發送到ARM 的接收緩沖區內。Rec_Packet()函數通過讀取RTL8019AS的當前寄存器CURR(寫寄存器)和邊界寄存器BNRY(讀寄存器)的值來確定是否有新數據的到來,若有新數據到來,則設置數據地址和數據長度,然后啟動遠程DMA 將接收緩沖環中的以太網幀送交給上層。 2 嵌入式TCP/IPv6 協議棧的實現 2.1 嵌入式TCP/IPv6 協議棧處理流程 如圖1 所示,嵌入式TCP/IPv6 協議接收數據包的過程就是解析數據包的過程。首先由底層處理函數解析數據包,根據類型,將去掉幀首部的數據包分配到緩沖區BUF 中,接著由IP 協議處理程序繼續解析。IP 協議處理程序對數據包解析后,將數據交給TCP 或ICMPv6 協議處理程序。嵌入式TCP/IPv6 協議棧發送數據包的過程是封裝數據包的過程,數據經過某層協議的處理,就會在數據包首部增加某種格式的首部。 ![]() 圖1 嵌入式TCP/IPv6協議解析數據包的過程 2.2 軟件實現 首先做如下類型定義: #define PROTO_ICMP 58 #define PROTO_TCP 6 #define ICMP_ECHO_REPLY 129 #define ICMP_ECHO 128 芯片接收到數據包后,放入緩沖區BUF 中交由上層協議處理。然后對數據包進行判斷。過程下: for(c=0;c<8;c++) if(BUF->destipaddr[c] != hostaddr[c]) { STAT(++stat.ip.drop); goto drop; } 接收數據包后,檢查下一個報頭中的協議類型,如果是TCP 或ICMP 協議,則分別轉向其處理程序,否則丟棄。 if(BUF->proto == PROTO_TCP) /* Check for TCP packet.If so,jump to the tcp_input label.*/ goto tcp_input; if(BUF->proto = PROTO_ICMP) /*Check for ICMP packet.If so,jump to the icmp_input label.*/ goto icmp_input; goto drop; 3 IPv6 在ARM 中的移植 IPv6協議棧在設計時就考慮到了移植問題,已把所有與硬件、OS、編譯器相關的部分獨立出來[4]。因此,IPv6 在本文研究的系統中的移植就是針對LPC2210 硬件平臺、uC/OS-II 操作系統和ADS1.2 的編譯器對其進行相應的修改。 1 數據類型定義 IPv6 的數據定義應該與uC/OS-II 定義的數據長度類型是一致的。 typedef unsigned char uint8;/* 無符號8 位整型變量*/ typedef signed char int8;/* 有符號8 位整型變量*/ typedef unsigned short uintl6;/* 無符號16 位整型變量*/ typedef signed short int16;/* 有符號16 位整型變量*/ typedef unsigned int uint32;/* 無符號32 位整型變量*/ typedef signed int int32;/*有符號32位整型變量*/ typedef float fp32;/* 單精度浮點數(32 位長度)*/ typedef double fp64;/* 雙精度浮點數(64 位長度)*/ 2 操作系統相關部分 (1)信號量 IPv6 中需要使用信號量進行同步。信號量實際上是一種約定機制,在多任務內核中普遍使用。信號像是一把鑰匙,任務要運行下去,得先拿到這把鑰匙。如果信號已被別的任務占用,該任務被掛起,直到信號被當前使用者釋放。一般地說,對信號量只能實施三種操作:初始化(也可稱作建立)、等信號(也可稱作掛起)、給信號或發信號。信號量初始化時要給信號量賦初值,等待信號量的任務表應清為空。想要得到信號量的任務執行等待操作。如果該信號量有效(即信號量值大于0),則信號量值減1,任務得以繼續運行。如果信號量的值為0,等待信號量的任務就被列入等待信號量任務表。多數內核允許用戶定義等待超時,如果等待時間超過了某一設定值時,該信號量還是無效,則等待信號量的任務進入就緒態準備運行,并返回出錯代碼(指出發生了等待超時錯誤)。任務以發信號操作釋放信號量。如果沒有任務在等待信號量,信號量的值僅僅是簡單地加1。如果有任務在等待該信號量,那么就會有一個任務進入就緒態,信號量的值也就不加1。于是,鑰匙給了等待信號量的諸任務中的等待信號量任務中優先級最高的任務、信號量處理函數: OSSemCreate / * 創建一個信號量* / OSSemDel()/* 刪除信號量*/ OSSemPend()/* 等待信號量*/ OSSemPost()/* 發送信號量*/ (2) 消息隊列 消息隊列用于給任務發消息。通過內核提供的服務、任務或中斷服務子程序可以將一條消息(該消息的指針)放入消息隊列。同樣,一個或多個任務可以通過內核服務從消息隊列中得到消息。發送和接收消息的任務約定,傳遞的消息實際上是傳遞的指針指向的內容。通常,先進入消息隊列的消息先傳給任務[5],也就是說,任務先得到的是最先進入消息隊列的消息,即先進先出原則(FIFO)。然而,uC/OS-II也允許使用后進先出方式(LIFO)。當一個以上的任務要從消息隊列接收消息時,每個消息隊列有一張等待消息任務的等待列表。如果消息隊列中沒有消息,即消息隊列是空,等待消息的任務就被掛起并放入等待消息任務列表中,直到有消息到來。通常,內核允許等待消息的任務定義等待超時的時間。如果限定時間內,任務沒有收到消息,該任務就進入就緒態并開始運行,同時返回出錯代碼,指出出現等待超時錯誤。一旦一則消息放入消息隊列,該消息將傳給等待消息的任務中優先級最高的那個任務,或是最先進入等待消息任務列表的任務。 2.3 庫函數的實現 IPv6 協議棧中用到了6 個外部函數,這些函數通常與用戶使用的系統或編譯器有關。返回字符串長度、字符串比較、內存數據塊之間的互相拷貝和內存中指定長度的數據塊清零,4 個函數已由ADS1.2 中的運行時庫提供,不需要再編寫。因為網絡數據采用的是大端數據存儲[6] , 而LPC2210 是工作在小端,所以,在存取網絡數據時要進行字節的交換。 下面兩個簡單的函數需要實現: uintl6 swapw( uintl6 n); //16位數據高低字節交換 { return(((n<<8)&0xff00)}((n>>8)&0x00ff)); } uint32 swapl(uint32 n);//32 位數據大小頭對調 { return(((n << 24 & 0xff000000L) ) ((n +8) & 0x00ff0000L) ( ( n >> 8 ) & 0x0000ff00L) ( ( n >> 2 4 )&0x000000ffL)); } 3 結束語 該文詳細描述了在嵌入式系統中如何實現IPv6 協議棧,使得在資源有限的嵌入式系統中實現IPv6 協議棧具有可能, 隨著IPv6 技術及嵌入式技術的不斷發展,可以用微型網關、微型路由器實現嵌入式網與互聯網的通信,并最終使IPv6 技術應用于工業控制、家庭網絡等各個領域. 本文作者創新點: 通過分析IEEE 802.15.4 和IPv6 協議,在保證實現網絡基本功能的前提下,著重研究了如何對復雜的TCP/IPv6 協議棧進行精簡,并提出了一套可行的方案,此方案能夠適應嵌入式系統的需要,然后用軟件實現嵌入式系統中的精簡的TCP/IPv6 協議棧,模塊之間能夠互相通信。 作者:應明峰,蔡瑞英 來源:《微計算機信息》(嵌入式與soc)2009年第25卷5-2期 |