單片機(jī)的TCP/IP的實(shí)現(xiàn)與UNIX的不同
由于指令的原因,以及資源上的原因,在UNIX上實(shí)現(xiàn)的TCP/IP協(xié)議的原代碼并不能夠直接移植到8位的單片機(jī)上。最早期的LINUX1.0版的內(nèi)核是最小的實(shí)現(xiàn)TCP/IP的操作系統(tǒng),它的程序的大小大概在1兆字節(jié)。而現(xiàn)在的紅旗LINUX,紅帽子LINUX,內(nèi)核多達(dá)幾十兆,整個(gè)系統(tǒng)要幾張光盤來裝。早期的LINIX因?yàn)樾?,而被移植到掌上電腦,PDA等產(chǎn)品中。 單片機(jī)的程序空間是極為有限的,直接尋址的空間僅64K字節(jié),這跟電腦的存儲(chǔ)空間相比要差幾個(gè)數(shù)量級(jí)。除了程序空間小之外,可用的內(nèi)存RAM也是非常小的,最多只能擴(kuò)64K的RAM,而電腦的RAM至少在1兆以上。單片機(jī)的運(yùn)算速度也極為有限,一般只有2MIPS,而電腦上的處理能力在100MIPS以上。
有些人提到有沒有必要在單片機(jī)上實(shí)現(xiàn)TCP/IP的問題。因?yàn)門CP/IP是一種標(biāo)準(zhǔn),以太網(wǎng)也成為局域網(wǎng)的標(biāo)準(zhǔn)。在很多情況下運(yùn)用以太網(wǎng)和TCP/IP,能夠簡(jiǎn)化結(jié)構(gòu)。比如目前較熱的智能小區(qū),因?yàn)椴季€的原因,不能為每個(gè)家庭布很多線,而以太網(wǎng)的8芯雙絞是一定有的。例如寬帶上網(wǎng),是直接通過以太網(wǎng)的,如果你制造的設(shè)備,比如安全產(chǎn)品,遠(yuǎn)程抄表產(chǎn)品,家居智能產(chǎn)品能夠走以太網(wǎng)的話,可以利用現(xiàn)成的以太網(wǎng)絡(luò)。但如果走其它網(wǎng)絡(luò),比如RS485、CAN單線、LONWORKS等,那么需要另外布線。布線是復(fù)雜的,還涉及到消防安全等。從成本看,用以太網(wǎng)實(shí)現(xiàn)聯(lián)網(wǎng)要比CAN、LONWORKS等更為便宜,集線器、交換機(jī)現(xiàn)在都非常便宜,而且將來有三網(wǎng)合一的趨勢(shì),電話、電視、計(jì)算機(jī)三網(wǎng)合一。將來的趨勢(shì)可能是高速的以太網(wǎng)的天下,電話信號(hào)、電視信號(hào)、聯(lián)網(wǎng)都在以太網(wǎng)上跑。盡管目前還未能實(shí)現(xiàn),但是這種趨勢(shì)是不可避免的。
有網(wǎng)友提到就算要利用以太網(wǎng),也沒有必要跑TCP/IP。那么為什么要跑TCP/IP呢? TCP/IP是一標(biāo)準(zhǔn),這個(gè)標(biāo)準(zhǔn)使得數(shù)據(jù)傳輸不一定是要局域網(wǎng),而可以在互聯(lián)網(wǎng)、跨地區(qū)跨國(guó)界。例如你在某一區(qū)域安裝了很多監(jiān)控產(chǎn)品,但數(shù)據(jù)中心可能不設(shè)在那個(gè)區(qū)域,而設(shè)在其他地區(qū)。TCP/IP有兩種協(xié)議TCP和UDP;TCP保證了數(shù)據(jù)傳輸?shù)恼_性,(如果你的數(shù)據(jù)只跑以及網(wǎng)層,那么你的數(shù)據(jù)完整性是要你的編程來保證的,校驗(yàn)的計(jì)算。數(shù)據(jù)包的丟失需要你手工處理,而TCP把這些所有你要處理細(xì)節(jié)都幫你處理了。UDP可以面向廣播的、視頻的、音頻的等方面的應(yīng)用。實(shí)現(xiàn)TCP/IP的協(xié)議的好處是可以統(tǒng)一平臺(tái),比如智能小區(qū)的產(chǎn)品,如果大家都遵守TCP/IP的協(xié)議,那么大家的產(chǎn)品才能兼容,假設(shè)一個(gè)大型的智能社區(qū),這個(gè)社區(qū)可能由多家設(shè)備供應(yīng)商進(jìn)行建設(shè),可能有某些廠商做平臺(tái)、做軟件,一些廠商做硬件。如果大家遵守TCP/IP協(xié)議,各自的遠(yuǎn)程抄表產(chǎn)品,智能防盜產(chǎn)品就有可能兼容,對(duì)地產(chǎn)開發(fā)商來說,可以選擇多個(gè)供應(yīng)商,有利于競(jìng)爭(zhēng),也避免某個(gè)廠家倒閉造成重大影響。
題外話說的多了,還是回到本章要談的內(nèi)容吧。由于單片機(jī)與電腦的差別很大,兩者的實(shí)現(xiàn)有很大的不同。在電腦里編寫TCP/IP程序,你可以不考慮代碼大小、代碼速度,但在單片機(jī)上這些都是你要考慮的問題。 綜合來說,單片機(jī)實(shí)現(xiàn)與UNIX實(shí)現(xiàn)TCP/IP有如下區(qū)別: (1)、操作系統(tǒng)。不論是WINDOWS、UNIX、LINUX,它們都有一個(gè)多任務(wù)操作系統(tǒng),這使得代碼編寫簡(jiǎn)單化,而在單片機(jī)上,因?yàn)橘Y源的原因而無法使用多任務(wù)操作系統(tǒng),這使得代碼結(jié)構(gòu)變?yōu)轫樞驁?zhí)行+硬件中斷的方式,而在電腦里卻可以并發(fā)地執(zhí)行。對(duì)程序執(zhí)行結(jié)構(gòu),單片機(jī)要考慮更多。
(2)、內(nèi)存分配。WINDOWS或UNIX的內(nèi)存分配是動(dòng)態(tài)的,根據(jù)需要隨時(shí)分配,隨時(shí)撤消 。我們閱讀一些關(guān)于LINUX、UNIX的書,它們都是mbuf的存儲(chǔ)結(jié)構(gòu)。mbuf是一個(gè)存儲(chǔ)鏈,這個(gè)鏈可以動(dòng)態(tài)地增加和減小。比如在數(shù)據(jù)包很少的情況下,UNIX分配一個(gè)2K字節(jié)的緩沖區(qū)可能就夠用了,但如果數(shù)據(jù)包很多,就有可能要分配64K甚至更多的緩沖區(qū),可分配的內(nèi)存要根據(jù)CPU的可用內(nèi)存來調(diào)整。 但是在單片機(jī)卻不能夠這樣做。一個(gè)最大的以太網(wǎng)數(shù)據(jù)包有1500多個(gè)字節(jié),分配一包的緩沖區(qū)就要1.5K字節(jié),而一般實(shí)現(xiàn)TCP/IP的單片機(jī)只外接一塊32K字節(jié)的RAM。而這32K字節(jié)的RAM要被各個(gè)協(xié)議所用,而不僅僅是存放收到的數(shù)據(jù)包。一般的做法是分配一個(gè)256×6=1536個(gè)字節(jié)的RAM來存放收到的以太網(wǎng)數(shù)據(jù)包。收到一包就處理一包。而UNIX卻可以收很多包才處理。在單片機(jī)里,存放收到的以太網(wǎng)數(shù)據(jù)包的RAM是固定的,而不是動(dòng)態(tài)分配的。所有UNIX關(guān)于內(nèi)存管理、內(nèi)存分配、mbuf的結(jié)構(gòu)在單片機(jī)里并不適用。這些代碼對(duì)單片機(jī)是無用的。
(3)、指針。在電腦里,指針只有一種,就是指向某一地址的RAM,而在單片機(jī)里指針有幾種:
1、 指向外部RAM的指針 例uchar xdata *p 使用指令 movx @dptr 占二個(gè)字節(jié)
2、 指向程序ROM的指針 例uchar code *p 使用指令 movc 占二個(gè)字節(jié)
3、 指向內(nèi)部的RAM的指針 例uchar data *p 使用指令 mov @ri 占一個(gè)字節(jié)
4、 指向外部RAM的分頁指針 例uchar pdata *p 使用指令 movx @ri 占一個(gè)字節(jié)
5、 一般指針,可以指向以上的任何一種 占三個(gè)字節(jié)
6. 還有其它用于分組切換的指針。
在電腦里,所有程序都必須先放在RAM里才能運(yùn)行,所以它的指針只有一種情況,就是指向RAM。而單片機(jī)的結(jié)構(gòu)和電腦的結(jié)構(gòu)有很大差別,指針類型很多,對(duì)指針運(yùn)算的速度也不一樣,由于第5種指針"一般指針"運(yùn)算很慢,同時(shí)又需要占用很多程序空間,這使得指針運(yùn)算不能從UNIX源代碼直接移植到單片機(jī)上,而UNIX實(shí)現(xiàn)TCP/IP的源代碼中,用的最多的就是指針,而在單片機(jī)里一般要求少用指針,或使用特定類型的指針。這使用UNIX的源代碼需要作很多的改動(dòng)。
(4)、參數(shù)傳遞。在UNIX實(shí)現(xiàn)的TCP/IP源代碼中,一般有很多的參數(shù)傳遞,而在單片機(jī)里允許傳遞的參數(shù)是有限的(因?yàn)槭艿絻?nèi)部RAM的限制),同時(shí)參數(shù)傳遞的過程要浪費(fèi)程序代碼空間,也降低單片機(jī)執(zhí)行速度。所以在單片機(jī)的實(shí)現(xiàn)里,一般不要做太多的參數(shù)傳遞,而多使用公共的全局變量來實(shí)現(xiàn)調(diào)用的過程。這種情況下,UNIX的一般源程序是相對(duì)獨(dú)立的,受其它函數(shù)或變量的影響很小,而單片機(jī)里各程序的相互依賴程度要大。因?yàn)樵趩纹瑱C(jī)里往往共享某一數(shù)據(jù)、某一變量。
(5)變量定義。UNIX和KEIL C51雖然都是C語言,但兩者又有所不同,對(duì)于一些變量的定義,兩者卻不能通用。例如,單片機(jī)的特殊寄存器定義,sfr sfr16 sbit等,在標(biāo)準(zhǔn)C里是沒有的。在標(biāo)準(zhǔn)C里支持的結(jié)構(gòu),在KEIL C里也有可能不支持,比如一些C++的語法。在處理上的特殊性,也可能不一樣,比如IP地址類型,在UNIX里一般將IP地址定義為數(shù)組:
uchar ip[4]; 而在單片機(jī)里,我的定義是
union IP_address_type{uchar bytes[4];
uint words[2];
ulong dwords;}
IP 被定義為共用體,而不是簡(jiǎn)單的一個(gè)數(shù)組。為什么要這樣做,是因?yàn)閱纹瑱C(jī)處理的特殊性,例如比較兩個(gè)IP地址IP1,IP2是否相等,如果使用數(shù)組,比較是麻煩的: 要寫成 if(IP1[0]==IP2[1])**IP1[1]=IP2[1]**…… 用共用體可以簡(jiǎn)化為
if(IP1.dwords==IP2.dwords)…… 有時(shí)候,我們又要把IP地址按16位來計(jì)算,比如較驗(yàn)和計(jì)算,那么IP地址按16位加可以寫成: IP.dwords[0]+ IP.dwords[1], 有時(shí),我們又要對(duì)IP地址按字節(jié)賦值,比如IP地址從24C02里讀出來,需要按字節(jié)賦值:可以為 IP.bytes[0]=×× IP.bytes[1]=×× IP.bytes[2]=×× IP.bytes[3]=××
如果不作這樣的定義,運(yùn)算將復(fù)雜很多。而且一些編譯會(huì)認(rèn)為類型混亂而無法編譯。 在單片機(jī)里使用共用體會(huì)簡(jiǎn)化很多。而在UNIX里要對(duì)這些值作改變,一般是利用指針進(jìn)行的。在電腦里,用指針運(yùn)算是方便的,而且速度也快,但在單片機(jī)里,卻不能夠方便地使用指針。 在UNIX里的一些結(jié)構(gòu)類型的定義都要被改寫。這樣也使得UNIX的源代碼不能直接用在單片機(jī)上。
(6)、協(xié)議支持。在UNIX里可支持比較完整的TCP/IP協(xié)議,但在單片機(jī)里無法做到,這是因?yàn)閱纹瑱C(jī)根本沒有足夠的代碼空間來支持這些協(xié)議。一般在單片機(jī)里實(shí)現(xiàn)與需要有關(guān)的部分,而不使用的協(xié)議則一概不支持。例如文件共享SMB協(xié)議,在UNIX、WINDOWS都支持,但單片機(jī)上卻沒有必要。一般只能在單片機(jī)中實(shí)現(xiàn):ARP、IP,ICMP、TCP、UDP這些協(xié)議,而更高層的協(xié)議,http、smtp、ftp一般是不需要支持的。雖然有些單片機(jī)例如AVR上網(wǎng)方案實(shí)現(xiàn)了http、smtp、ftp協(xié)議,但我們認(rèn)為實(shí)用性不太,因?yàn)锳VR上網(wǎng)方案用的是MEGA103,而該芯片要150元左右,高昂的造價(jià)使得AVR上網(wǎng)方案沒有得到廣泛的應(yīng)用。單片機(jī)應(yīng)用的TCP/IP協(xié)議大多是為了完成數(shù)據(jù)采集和數(shù)據(jù)傳輸,而不是網(wǎng)頁瀏覽、文件傳輸這些功能。就對(duì)某一協(xié)議而言,例如ARP協(xié)議,UNIX系統(tǒng)支持以太網(wǎng)、令牌環(huán)等網(wǎng)絡(luò)的ARP,但單片機(jī)里只支持以太網(wǎng),也就是說,對(duì)于某一協(xié)議,也有可能要作簡(jiǎn)化。IP包最大可以為65K,可以分段傳輸,而在單片機(jī)里根本無法容納如此大的數(shù)據(jù)包,因此一般是不支持分段的。單片機(jī)一般采用發(fā)送小數(shù)據(jù)包的方式,以避免分段。
(7)、硬件接口。在UNIX或WINDOWS里,對(duì)網(wǎng)卡驅(qū)動(dòng)無一例外都是采用中斷方式。而在單片機(jī)的應(yīng)用中,大部份的方案都是查詢式的。因?yàn)殡娔X的處理速度快,一次中斷的處理時(shí)間也很短,不會(huì)影響系統(tǒng)內(nèi)的其它中斷。但在單片機(jī)里就不行了,處理一次中斷,收取一個(gè)數(shù)據(jù)包一般要幾毫秒的時(shí)間,這將封鎖其它中斷的產(chǎn)生(只有高優(yōu)先級(jí)的中斷可以執(zhí)行),而單片機(jī)往往還存在其它一些中斷,比如串口按收中斷,A/D條件中斷、鍵盤中斷等需要被執(zhí)行,這就使得消耗時(shí)間長(zhǎng)的網(wǎng)卡中斷改為查詢式執(zhí)行。在電腦里,對(duì)網(wǎng)卡的驅(qū)動(dòng)相對(duì)簡(jiǎn)單,而在單片機(jī)里需要處理的事情更多。比如緩沖區(qū)溢出,閱讀一些驅(qū)動(dòng)程序源代碼,你可能發(fā)現(xiàn)在電腦里的一些程序根本沒有處理溢出的代碼。因?yàn)殡娔X執(zhí)行快,網(wǎng)卡緩沖區(qū)的溢出幾乎是不會(huì)發(fā)生的,不要說10M網(wǎng)卡,就是100M網(wǎng)卡,電腦也能夠很快處理。電腦往往采用即插即用方式來驅(qū)動(dòng)網(wǎng)卡,而單片機(jī)卻不能這樣做,因?yàn)榧床寮从靡芏啻a來實(shí)現(xiàn),而使用跳線方式,電腦里驅(qū)動(dòng)NE2000的網(wǎng)卡,一般都是用16位DMA的方式,而在單片機(jī)里卻只能用8位DMA方式。這也使用UNIX對(duì)網(wǎng)卡驅(qū)動(dòng)的代碼不能直接移植。
評(píng)論