劉 凱 呂海燕 張立民
(海軍航空大學(xué)航空基礎(chǔ)學(xué)院 煙臺(tái) 264001)
隨著嵌入式系統(tǒng)和網(wǎng)絡(luò)接入方法的日益發(fā)展,越來(lái)越多的嵌入式系統(tǒng)連接至網(wǎng)絡(luò),作為網(wǎng)絡(luò)終端參與數(shù)據(jù)交互、信息處理[1~2]。基于 TCP/IP 的以太網(wǎng)是一種標(biāo)準(zhǔn)開(kāi)放式的網(wǎng)絡(luò),由于其通用性強(qiáng),組網(wǎng)容易,能夠?qū)崿F(xiàn)遠(yuǎn)距離數(shù)據(jù)傳輸,容易實(shí)現(xiàn)資源共享,受到了廣泛的應(yīng)用和支持[3~4]。因此,基于以太網(wǎng)的嵌入式系統(tǒng)逐漸成為了當(dāng)前片上系統(tǒng)(Sys?tem on Chip,SoC)[5]的發(fā)展熱點(diǎn)。但是,由于嵌入式系統(tǒng)中硬件資源有限,如果移植完整的TCP/IP協(xié)議棧,會(huì)大大增加系統(tǒng)運(yùn)行載荷,導(dǎo)致系統(tǒng)運(yùn)行緩慢且數(shù)據(jù)通信不暢。因此,需要依據(jù)嵌入式系統(tǒng)特點(diǎn),有針對(duì)性地選擇TCP/IP協(xié)議棧精簡(jiǎn)方案,從而實(shí)現(xiàn)網(wǎng)絡(luò)穩(wěn)定通信與系統(tǒng)高效運(yùn)行的平衡。
LM3S8962[6~7]微控制器是德州儀器(TI)公司提供的一款具有32位高性能運(yùn)算能力的基于ARM?CortexTM-M3的控制器,其優(yōu)勢(shì)還在于能夠方便地運(yùn)用多種ARM的開(kāi)發(fā)工具和片上系統(tǒng)(SoC)的底層IP應(yīng)用方案。另外,該微控制器使用了兼容ARM Thumb?的Thumb2指令集來(lái)減少存儲(chǔ)容量的需求,并以此達(dá)到降低成本的目的。最后,LM3S8962微控制器與Stellaris?系列的所有成員是代碼兼容的,這為用戶提供了靈活性,能夠適應(yīng)各種精確的需求。
LM3S8962微控制器的主要特性之一是具有10/100以太網(wǎng)控制器,它遵循IEEE 802.3-2002規(guī)范,遵循IEEE 1588-2002精確時(shí)間協(xié)議(PTP)。在100Mbps和10Mbps速率運(yùn)作下支持全雙工和半雙工的操作方式,集成10/100Mbps收發(fā)器(PHY),自動(dòng)的MDI/MDI-X交叉校驗(yàn),可編程MAC地址[8~9]。
針對(duì)LM3S8962已經(jīng)具備10/100以太網(wǎng)控制器特點(diǎn),需要在其硬件以太網(wǎng)控制器的基礎(chǔ)上構(gòu)建協(xié)議包系統(tǒng),從而完成TCP或UDP數(shù)據(jù)包的處理,實(shí)現(xiàn)TCP/IP協(xié)議棧的通信。
1)以太網(wǎng)協(xié)議
以太網(wǎng)數(shù)據(jù)由以太網(wǎng)幀來(lái)傳送[10]。以太網(wǎng)的沖突退避算法是由硬件自動(dòng)執(zhí)行的,在軟件設(shè)計(jì)中可不用考慮。類型表示上層協(xié)議類型,本協(xié)議棧只處理這兩種類型的以太網(wǎng)幀:IP包、ARP包。
2)地址解析協(xié)議(ARP)和反地址解析協(xié)議(RARP)
為了簡(jiǎn)化TCP/IP協(xié)議棧內(nèi)容,本協(xié)議棧僅僅涉及了使用固定IP地址的方式實(shí)現(xiàn)以太網(wǎng)通信。因此,在本協(xié)議棧中無(wú)需實(shí)現(xiàn)RARP,僅僅需要對(duì)ARP包進(jìn)行處理。ARP請(qǐng)求格式如圖1所示。
圖1 ARP請(qǐng)求應(yīng)答格式
以太網(wǎng)報(bào)頭中的前兩個(gè)字段是以太網(wǎng)的源地址和目的地址。目的地址為全1的特殊地址是廣播地址。兩個(gè)字節(jié)長(zhǎng)的以太網(wǎng)幀類型表示后面數(shù)據(jù)的類型。如果以太網(wǎng)報(bào)文內(nèi)容為ARP請(qǐng)求或應(yīng)答,該字段的值為0×0806。對(duì)于一個(gè)ARP請(qǐng)求,除目的端硬件地址以外的所有其他字段都有填充值。當(dāng)系統(tǒng)收到一份目的端為本機(jī)的ARP請(qǐng)求報(bào)文后,它就把硬件地址填進(jìn)去,然后用兩個(gè)目的端地址分別替換兩個(gè)發(fā)送端地址,并把操作字段置為2,最后把它發(fā)送回去。
3)控制報(bào)文協(xié)議(ICMP)
針對(duì)嵌入式應(yīng)用系統(tǒng)的特點(diǎn),雖然ICMP可以提供很好的網(wǎng)絡(luò)狀態(tài)報(bào)告,但對(duì)于本系統(tǒng)中嵌入式軟件而言,只需要實(shí)現(xiàn)一個(gè)“回顯應(yīng)答”(即Ping應(yīng)答)的功能即可。
Ping是Internet上最常用的調(diào)試工具,它的目的是為了測(cè)試另一臺(tái)主機(jī)是否可達(dá)[11~12]。該程序發(fā)送一份ICMP回顯請(qǐng)求報(bào)文給目的IP設(shè)備,并等待返回ICMP回顯應(yīng)答。用該命令,可以方便地測(cè)試儀表與網(wǎng)絡(luò)是否連通。為實(shí)現(xiàn)響應(yīng)ping命令,本協(xié)議支持的ICMP類型如下:
type=8:ICMP Echor(回送)回答報(bào)文;
type=0:ICMP Echor請(qǐng)求。
4)網(wǎng)際協(xié)議(IP)
IP數(shù)據(jù)包的格式如圖2所示??紤]到本系統(tǒng)網(wǎng)絡(luò)數(shù)據(jù)較小,故在IP協(xié)議實(shí)現(xiàn)時(shí)沒(méi)有支持有選項(xiàng)字段的IP包和分片操作。
圖2 IP數(shù)據(jù)包格式
8位協(xié)議字段表示上層協(xié)議類型,在本項(xiàng)目中只要處理兩種類型的IP包:ICMP包、UDP包。
5)用戶數(shù)據(jù)報(bào)協(xié)議(UDP)
UDP分段的頭部格式如圖3所示。
圖3 UDP分段的頭部格式
在本協(xié)議棧中,設(shè)計(jì)了完整的UDP協(xié)議,并實(shí)現(xiàn)了與計(jì)算機(jī)的Socket通信。
從上面可以得出,經(jīng)過(guò)了剪裁之后在本系統(tǒng)中應(yīng)用的TCP/IP協(xié)議棧層次如圖4所示。
圖4 TCP/IP協(xié)議棧層次設(shè)計(jì)
該層主要為L(zhǎng)M3S8962以太網(wǎng)底層硬件驅(qū)動(dòng),包含以太網(wǎng)中斷響應(yīng)函數(shù)EthernetIntHandler()、硬件初始化函數(shù)InitNic()、處理接收數(shù)據(jù)函數(shù)Rec?Packet()、以太網(wǎng)底層發(fā)送數(shù)據(jù)函數(shù)Send_Packet()。
LM3S8962自帶的函數(shù)庫(kù)包含了基本的以太網(wǎng)通信控制函數(shù),故該協(xié)議是在其函數(shù)庫(kù)基礎(chǔ)上實(shí)現(xiàn)的。
1)InitNic()
要實(shí)現(xiàn)網(wǎng)絡(luò)的驅(qū)動(dòng),必須對(duì)LM3S8962的各個(gè)寄存器進(jìn)行初始化和配置。在對(duì)LM3S8962進(jìn)行初始化之前需要進(jìn)行硬件復(fù)位和軟件復(fù)位;然后進(jìn)行寄存器設(shè)置。LM3S8962網(wǎng)絡(luò)初始化的順序如圖5所示。
圖5 LM3S8962網(wǎng)絡(luò)初始化流程
2)EthernetIntHandler()函數(shù)
該函數(shù)參數(shù)為void,主要是作為接收中斷響應(yīng)函數(shù)調(diào)用RecPacket()函數(shù)。由于該協(xié)議是在μC/OS-Ⅱ基礎(chǔ)上設(shè)計(jì)的,在該函數(shù)最后進(jìn)行了任務(wù)的調(diào)度。
3)RecPacket()函數(shù)
該函數(shù)的參數(shù)為void,該函數(shù)需調(diào)用LM3S8962的庫(kù)函數(shù)EthernetPacketGetNonBlocking Get(),其具體功能是從以太網(wǎng)控制器獲取數(shù)據(jù)包,返回接收數(shù)據(jù)包的長(zhǎng)度。
4)Send_Packet()函數(shù)
在協(xié)議棧中設(shè)計(jì)了鏈表_pkst,其結(jié)構(gòu)如圖6所示。協(xié)議棧利用它作為數(shù)據(jù)讀取和發(fā)送的數(shù)據(jù)結(jié)構(gòu)。
圖6 _pkst結(jié)構(gòu)
Send_Packet()函數(shù)的輸入?yún)?shù)為數(shù)據(jù)鏈初始指針,返回值為void。
數(shù)據(jù)鏈路層中包含地址解析函數(shù)PRO?CESS_ARP_REC(),網(wǎng)絡(luò)的收發(fā)操作函數(shù)Send_IP_LLC()和 Rec_Ethernet_Packet(),還有一些輔助函數(shù),如設(shè)置網(wǎng)絡(luò)地址函數(shù)SetNetPort()等。
1)PROCESS_ARP_REC()函數(shù)
2)Send_IP_LLC()函數(shù)
該函數(shù)能夠?yàn)镮P數(shù)據(jù)包的目標(biāo)IP查找MAC地址并將其發(fā)送出去。輸入?yún)?shù)為發(fā)送結(jié)構(gòu)指針和目標(biāo)IP地址指針。
3)Rec_Ethernet_Packet()函數(shù)
該函數(shù)被RecPacket()函數(shù)調(diào)用,其功能是處理接收到的數(shù)據(jù)包,并將其數(shù)據(jù)指針傳遞到IP層。其輸入?yún)?shù)為接收數(shù)據(jù)指針;輸出參數(shù)為0表示發(fā)送失敗,1表示發(fā)送成功。
網(wǎng)絡(luò)層包括IP包的接收和發(fā)送控制,ICMP請(qǐng)求報(bào)文的接收和 ICMP應(yīng)答報(bào)文的發(fā)送控制[13~14]。考慮到實(shí)際數(shù)據(jù)量較少,在IP數(shù)據(jù)包的處理上沒(méi)有實(shí)現(xiàn)分片處理。
在IP協(xié)議中,創(chuàng)建了消息隊(duì)列RecUdpQFlag和信號(hào)量SendFlag。消息隊(duì)列的用處:如果有UDP數(shù)據(jù)包傳遞到IP協(xié)議層,則釋放該消息隊(duì)列,同時(shí)該消息隊(duì)列保存了UDP數(shù)據(jù)包的存儲(chǔ)地址;信號(hào)量則在Send_Ip_Frame()函數(shù)中使用。具體使用過(guò)程:首先判斷該信號(hào)量是否當(dāng)前可用,以判斷該函數(shù)能否獲得網(wǎng)絡(luò)發(fā)送的權(quán)利,如果該時(shí)間可以進(jìn)行網(wǎng)絡(luò)數(shù)據(jù)發(fā)送,則在IP數(shù)據(jù)包發(fā)送完畢以后釋放信號(hào)量。
1)IP_PROCESS()函數(shù)
該函數(shù)的輸入?yún)?shù)為接收數(shù)據(jù)結(jié)構(gòu)的指針;返回值表明處理結(jié)果,如果為1,則數(shù)據(jù)處理正確,如果為0表明處理失敗。
2)Send_Ip_Frame()函數(shù)
該函數(shù)實(shí)現(xiàn)的是IP數(shù)據(jù)包的發(fā)送。輸入?yún)?shù)由發(fā)送地址指針和目標(biāo)IP地址組成,輸出參數(shù)表明發(fā)送結(jié)果是否成功。
在ICMP協(xié)議中,系統(tǒng)實(shí)現(xiàn)了Ping命令的響應(yīng),即客戶端能夠判斷接收服務(wù)端的ICMP Echo報(bào)文,同時(shí)向服務(wù)端回送一個(gè)ICMP Echo Reply報(bào)文完成Ping。
3)ICMP_PROCESS()函數(shù)
該函數(shù)的功能是對(duì)ICMP數(shù)據(jù)報(bào)進(jìn)行處理。輸入?yún)?shù)為ICMP數(shù)據(jù)報(bào)指針,輸出參數(shù)表示處理結(jié)果。
鑒于LM3S8962內(nèi)部以太網(wǎng)控制器穩(wěn)定性高、通信鏈路延時(shí)低的優(yōu)勢(shì),同時(shí)為了降低通信負(fù)載,在本TCP/IP協(xié)議棧中運(yùn)輸層僅僅使用UDP協(xié)議。為滿足通信要求,在該層設(shè)計(jì)了兩個(gè)結(jié)構(gòu)udp_sub_socket和 udp_socket,其結(jié)構(gòu)如圖 7、8 所示,并且定義了全局Socket變量。
udp_socket UdpStatus;
圖7 udp_sub_socket結(jié)構(gòu)
圖8 udp_socket結(jié)構(gòu)
1)UDP_Process()函數(shù)
該函數(shù)的輸入?yún)?shù)為接收UDP數(shù)據(jù)包指針,輸出參數(shù)表明處理結(jié)果。
2)UDP_Send()函數(shù)
該函數(shù)實(shí)現(xiàn)了UDP數(shù)據(jù)包的發(fā)送,輸入?yún)?shù)由數(shù)據(jù)指針、目的IP和網(wǎng)絡(luò)端口組成。
對(duì)于網(wǎng)絡(luò)數(shù)據(jù)的接收,該協(xié)議棧在系統(tǒng)中的具體使用步驟如下:
1)等待消息隊(duì)列RecUdpQFlag。如果消息隊(duì)列被釋放了,根據(jù)函數(shù)IP_PROCESS()處理流程,表明存在UDP數(shù)據(jù)包。調(diào)用UDP_Process(),相應(yīng)的代碼如下所示:
UdpTemp = OSQPend (RecUdpQFlag, 0,&eer);
if(eer==OS_NO_ERR)
{
Udp_Process((Rec_Ptr*)UdpTemp);
}
2)等待UdpStatus中的信號(hào)量UdpSemRec,通過(guò)UDP_Process()保存后的數(shù)據(jù)指針得到UDP數(shù)據(jù)包中的數(shù)據(jù)。
3)如果要求發(fā)送網(wǎng)絡(luò)數(shù)據(jù),調(diào)用UDP_Send()函數(shù)即可。
為了驗(yàn)證嵌入式TCP/IP協(xié)議棧工作性能,采用兩種方式進(jìn)行測(cè)試,1是Ping測(cè)試,2是將其應(yīng)用于數(shù)據(jù)采集節(jié)點(diǎn)測(cè)試通信效果。
Pin命令主要是對(duì)網(wǎng)絡(luò)層進(jìn)行測(cè)試[15~16]。在測(cè)試中,客戶端設(shè)定的IP地址是192.168.0.18,當(dāng)服務(wù)器發(fā)出Ping命令時(shí),客戶端給出回應(yīng)。從圖9中可以看出,傳遞的數(shù)據(jù)并沒(méi)有丟失,并且傳輸?shù)臅r(shí)延較小,證明通信性能較好??梢宰C明IP層、物理層、數(shù)據(jù)鏈路層是連通的,能夠保證客戶端與服務(wù)器進(jìn)行正常通信。
圖9 ICMP的測(cè)試結(jié)果
在本系統(tǒng)中,數(shù)據(jù)采集節(jié)點(diǎn)通過(guò)以太網(wǎng)完成與上位機(jī)的信息交互。上位機(jī)進(jìn)行UDP測(cè)試工具如圖10所示。
圖10 上位機(jī)測(cè)試UDP包結(jié)果
經(jīng)過(guò)實(shí)驗(yàn)驗(yàn)證,數(shù)據(jù)采集節(jié)點(diǎn)能夠及時(shí)將所采集的數(shù)據(jù)通過(guò)網(wǎng)絡(luò)以UDP包的形式傳遞給上位機(jī),上位機(jī)根據(jù)節(jié)點(diǎn)傳遞的數(shù)據(jù)及時(shí)作出反映。
針對(duì)LM3S8962芯片特點(diǎn),采用了模塊化設(shè)計(jì)方法設(shè)計(jì)了TCP/IP協(xié)議棧。根據(jù)實(shí)際系統(tǒng)通信需要,對(duì)各個(gè)棧功能進(jìn)行精簡(jiǎn),去掉了反地址解析協(xié)議,簡(jiǎn)化了控制報(bào)文協(xié)議和TCP包處理。既保證了以太網(wǎng)通信需求,又節(jié)約了嵌入式系統(tǒng)資源。通過(guò)相關(guān)實(shí)驗(yàn)驗(yàn)證,該協(xié)議棧的設(shè)計(jì)達(dá)到了嵌入式系統(tǒng)預(yù)期要求。本文提出的這種基于嵌入式系統(tǒng)的精簡(jiǎn)TCP/IP協(xié)議棧,對(duì)LM3S8962等同類型芯片的以太網(wǎng)通信等工程實(shí)踐提供了參考借鑒,并且對(duì)該領(lǐng)域中的相關(guān)技術(shù)研究也具有一定的指導(dǎo)意義。