基于ARM9的UDP協(xié)議棧的設(shè)計(jì)與實(shí)現(xiàn)
隨著嵌入式技術(shù)和網(wǎng)絡(luò)技術(shù)的迅速發(fā)展,以太網(wǎng)接口在嵌入式系統(tǒng)中的應(yīng)用越來(lái)越廣泛.以太網(wǎng)通信速度快.通用,可直接與Internet 相連接,提供更大范圍的遠(yuǎn)程訪問(wèn).目前在工控嵌入式領(lǐng)域,網(wǎng)絡(luò)通信通常采用UDP 和TCP 協(xié)議.UDP 與TCP 相比,UDP 使用非連接的.不可靠的通信方式,因此網(wǎng)絡(luò)傳輸速度快,實(shí)時(shí)性相對(duì)較好.文中設(shè)計(jì)實(shí)用S3C2440.以太網(wǎng)控制器DM9000
1 系統(tǒng)的硬件介紹該系統(tǒng)采用優(yōu)龍科技公司YLP2440 作為開(kāi)發(fā)的硬件系統(tǒng),YLP2440 采用三星S3C2440A
硬件框圖如圖1 所示.
2 以太網(wǎng)軟件的設(shè)計(jì)
2. 1 以太網(wǎng)卡控制器的初始化
首先DM9000A 自檢,讀取DM9000 的生產(chǎn)廠家ID和設(shè)備ID 與已經(jīng)設(shè)定好的ID 進(jìn)行比對(duì),判斷DM9000網(wǎng)卡是否存在,初始化DM9000A,它的過(guò)程就是適當(dāng)配置DM9000A 寄存器的過(guò)程,具體過(guò)程分為以下幾個(gè)步驟:
?。?)啟動(dòng)DM9000A,設(shè)置CPCR[REG_1E] = 0×1,使DM9000 的GPIO3 為輸出,GPR[REG_1F] =0×0,使DM9000 的GPIO3 輸出為低以激活內(nèi)部PHY.延時(shí)2ms 以上以等待PHY 上電.
?。?)進(jìn)行兩次軟復(fù)位,設(shè)置DM9000 為正常工作模式,根據(jù)芯片設(shè)計(jì)要求,要想使芯片在上電之后工作正常就要進(jìn)行兩次軟復(fù)位,設(shè)置為NCR[REG_00] =0×01,NCR[REG_00] =0×00,這兩步操作進(jìn)行兩次.
(3) 清除各種狀態(tài)標(biāo)志位和中斷標(biāo)志位,NSR[REG_01] =0x2c,ISR[REG_FE] =0x3f.
?。?)設(shè)置接收和發(fā)送控制寄存器,并且設(shè)置FIFO的大小,RCR[REG_05] =0×39.TCR[REG_02] =0×00.FCTR[REG_09] =0×38.
(5)設(shè)置板子自身的MAC 地址.
?。?)再一次清除各種狀態(tài)標(biāo)志位和中斷標(biāo)志位,NSR[REG_01] =0x2c,ISR[REG_FE] =0x3f.
?。?)設(shè)置中斷屏蔽寄存器,打開(kāi)接收中斷,IMR[REG_FF] =0×81.
當(dāng)進(jìn)行了以上步驟的設(shè)置之后,DM9000A 芯片就處于正常工作狀態(tài)了.在以后進(jìn)行通信的過(guò)程中,如果發(fā)生異常引起芯片重啟,則再一次進(jìn)行同樣的設(shè)置.
2. 2 以太網(wǎng)卡數(shù)據(jù)的發(fā)送和接收
DM9000A 發(fā)送數(shù)據(jù)采用的是循環(huán)查詢模式,接收數(shù)據(jù)采用的是中斷模式,DM9000 內(nèi)部有0x3FF 大小的SRAM 用于接收和發(fā)送數(shù)據(jù)緩存.在發(fā)送或接收數(shù)據(jù)包之前,數(shù)據(jù)是暫存在這個(gè)SRAM 中的.當(dāng)需要連續(xù)發(fā)送或接收數(shù)據(jù)時(shí),需要分別把DM9000 寄存器MWCMD 或MRCMD 賦予數(shù)據(jù)端口,這樣就指定了SRAM 中的某個(gè)地址,并且在傳輸完一個(gè)數(shù)據(jù)后,指針會(huì)指向SRAM 中的下一個(gè)地址,從而完成了連續(xù)訪問(wèn)數(shù)據(jù)的目的.但當(dāng)發(fā)送或接收一個(gè)數(shù)據(jù)后, 指向SRAM 的數(shù)據(jù)指針不需要變化時(shí),則要把MWCMDX 或MRCMDX 賦予數(shù)據(jù)端口 .
發(fā)送數(shù)據(jù)比較簡(jiǎn)單,接收數(shù)據(jù)就略顯復(fù)雜,因?yàn)樗怯幸欢ǜ袷揭蟮?在接收到的一包數(shù)據(jù)中的首字節(jié)如果為0×01,則表示這是一個(gè)可以接收的數(shù)據(jù)包;如果為0×0,則表示沒(méi)有可接收的數(shù)據(jù)包.因此在讀取其他字節(jié)時(shí),一定要先判斷首字節(jié)是否為0×01.數(shù)據(jù)包的第二個(gè)字節(jié)為數(shù)據(jù)包的一些信息,它的高字節(jié)的格式與DM9000 的寄存器RSR 完全一致.第三個(gè)和第四個(gè)字節(jié)為數(shù)據(jù)包的長(zhǎng)度.后面的數(shù)據(jù)就是真正要接收的數(shù)據(jù)了.
2. 2. 1 UDP 協(xié)議棧的裁剪實(shí)現(xiàn)
在系統(tǒng)中主要使用UDP 通信,只需要實(shí)現(xiàn)ARP協(xié)議.IP 協(xié)議,對(duì)TCP/ IP 協(xié)議進(jìn)行部分的實(shí)現(xiàn).UDP協(xié)議通信(即用戶數(shù)據(jù)報(bào)協(xié)議)與TCP 一樣都是屬于傳輸層協(xié)議,位于IP(網(wǎng)際協(xié)議)協(xié)議的頂層.UDP 相對(duì)于TCP 是一種簡(jiǎn)單協(xié)議,提供的是最少的服務(wù),編寫的代碼量也小,所需的程序和內(nèi)存空間少,運(yùn)行速度快.ARP 為IP 地址對(duì)應(yīng)的硬件地址之間提供動(dòng)態(tài)映射,發(fā)送終端把以太網(wǎng)數(shù)據(jù)幀發(fā)送到位于同一局域網(wǎng)上的另一臺(tái)主機(jī)時(shí),是根據(jù)48bit 的以太網(wǎng)地址來(lái)確定目的接口的.設(shè)備驅(qū)動(dòng)程序從不檢查IP 數(shù)據(jù)報(bào)中的目的IP 地址.IP 協(xié)議是TCP/ IP 協(xié)議中最為核心的協(xié)議,它提供不可靠.無(wú)連接的數(shù)據(jù)報(bào)傳送服務(wù) .
2. 2. 2 數(shù)據(jù)的發(fā)送過(guò)程
數(shù)據(jù)發(fā)送過(guò)程如圖2 所示.發(fā)送終端在第一次發(fā)送數(shù)據(jù)的時(shí)候,要知道接收端的IP 地址和端口號(hào),還要得到對(duì)方的物理MAC 地址,因?yàn)閮蓚€(gè)終端最后通信是通過(guò)尋找對(duì)方的MAC 地址來(lái)進(jìn)行的,因此首先得通過(guò)ARP 協(xié)議,把對(duì)方的IP 地址轉(zhuǎn)換為MAC 地址,得到了物理地址之后才能通信.如果長(zhǎng)時(shí)間不能得到這個(gè)物理地址,則只能說(shuō)明請(qǐng)求失敗,需要重新發(fā)送ARP 請(qǐng)求,ARP 的封裝過(guò)程如圖3(b)所示.
2. 2. 3 數(shù)據(jù)包的封裝過(guò)程
UDP 協(xié)議數(shù)據(jù)包的封裝在運(yùn)輸層進(jìn)行,打好包的UDP 數(shù)據(jù)將送往網(wǎng)絡(luò)層進(jìn)行IP 協(xié)議的打包,UDP 要完成進(jìn)程到進(jìn)程的通信,把報(bào)文交付給正確的進(jìn)程.當(dāng)進(jìn)程有報(bào)文要通過(guò)UDP 發(fā)送時(shí),它就把這個(gè)報(bào)文連同一對(duì)套接字地址以及數(shù)據(jù)長(zhǎng)度傳遞給UDP.UDP 收到數(shù)據(jù)后就加上UDP 首部,也就是UDP 數(shù)據(jù)包的封裝如圖3(c)所示.然后UDP 就把該用戶數(shù)據(jù)包連同IP 加上自己首部,在協(xié)議字段使用值17,指出該數(shù)據(jù)是從UDP 協(xié)議來(lái)的,這個(gè)過(guò)程就是IP 數(shù)據(jù)包的封裝過(guò)程如圖3(a)所示.這個(gè)IP 數(shù)據(jù)包再傳遞給數(shù)據(jù)鏈路層.數(shù)據(jù)鏈路層收到IP 數(shù)據(jù)包之后,加上自己的首部(可能還有尾部),再傳遞給物理層.物理層把這些位編碼為電信號(hào)或者光信號(hào),然后把它發(fā)送到遠(yuǎn)程的機(jī)器.
評(píng)論