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