uip 客戶端工作流程

1      概述:

網絡上關於uIP協議棧的文章不少,大多是講解自帶的http服務器爲例子,沒有過多的說明作爲CS客戶端在實際中的應用。

 

本文主要講述ENC28J60和uIP協議棧作爲CS模式在客戶端的應用,即採用主動連接與服務器進行用戶數據交互,保持長連接,支持自動重連。

        

編譯器:Keil3 C51 8.18

uIP版本:0.9

ENC28J60:ENC28J60-I/SO  28-Lead SOIC

單片機:SST89E516RD(1K RAM,64K program ROM 支持在線仿真,兼容51單片機)

                   STC89C58RD+ (512 RAM  32K program ROM)燒錄測試

 

特點:查詢方式收包,定時更新ARP緩存表,協議棧、收、發共用緩存(內存開銷少)

事件回調函數uip_appcall()

支持ICMP/TCP/UDP,端口監聽,主/被動連接

2      代碼文件結構圖:

 

 

 

 

2.1    文件列表:

 

 

 

 

2.2    代碼流程圖:

 

3      系統開銷:

對於一個完成的TCP /IP協議棧來說,uIP算佔用資源比較少的,根據實際應用,本例將去除了demo程序中自帶的http服務器,fs部分,將連接數、監聽端口表、ARP緩存表大小都設置爲1,關掉日誌,統計信息,重組包,把系統開銷降到更低。

 

下表描述uIP系統主要開銷情況(估算):

RAM(內存空間):334字節左右

 

其它全局變量60(左右)

連接狀態 28*1,ARP緩存表11*1,

協議棧收,發共用緩存233+2(可設置,由單片機內存而定

 

對應代碼位置:

 

注:實際用戶數據空間需要減去40(等其它擴展)字節的TCP/IP頭,剩下安全字節179左右,而TCP包用戶數據可以達到1460字節,uIP設置了分割包大小爲安全字節(見iris抓包),服務端(如:windows)會自動將大包拆分成小包發送<=179每包,所以服務端發送大於179字節的用戶數據時,客戶端需要重新組包。

 

uIP用戶數據單包大小:

 

IRIS抓包(設置用戶數據分割片大小):


 

 

 

SP(棧空間):40字節左右(最大時)

 

uIP充分考慮到節約內存,大部分接口函數用宏實現,即加大程序的存儲空間換取更小的棧空間,協議棧核心函數基本由uip_process()一個函數完成,幾乎只有幾個局部變量,函數調用參數也很少,除uip_appcall外(由用戶決定),其它幾個子函數無嵌套調用。

 

 

ROM(程序空間):12K左右

 

uIP自帶http演示程序編譯後bin文件大小在20K左右,本例去掉了http部分,已經壓縮到12K左右,所以選型單片機時ROM至少在16K以上

 

網卡IO腳:最少佔用才4個,最多7個(包括RST)

 

 

如果自己新建工程使用本例代碼,請將工程屬性“Target->Memocy Mode”設置成:Large: variables in XDATA,即使用最大外部內存,否則將產生編譯錯誤,提示內存不足,因爲uIP的RAM開銷超過了單片機內部內存128字節(超出mov尋址範圍),所以需要movx來完成更多內存訪問,有些單片機都內置了外存,打開此選項,Keil C51  C編譯器會自動完成外部內存訪問。


 

4      網卡硬件原理圖:

下圖爲ENC28J60網卡的參考設計圖,SCK,CS,SO,SI直接PIN TO PIN接到單片機(SI和SO不需要反接,不同於串口的是SPI的SO,SI都是相對於slave而言的),有些單片自帶SPI接口,例如本例中使用的SST89E516RD,但我們程序中仍然採用IO口模擬SPI方式,通用性更好。


5      SPI接口驅動:

本例SPI接口採用單片機IO口模擬,只需根據實際的硬件電路設計(IO口需要上/下拉電阻),在spi.h文件中修改IO腳定義即可,需要注意的是ENC28J60採用SPI0模式,即時鐘信號上升沿接收數據,下降沿發送數據,本例中SPI通訊時序已經調通,可以直接使用,至少要接SCK,CS,SI,SO即可,INT沒有使用,可以不接,如果接上,ENC28J60驅動代碼已經開啓了接收中斷,程序中可以接收到,但在使用中斷模式時,請考慮收,發包的同步情況,比如:網卡支持全雙工模式,正在發送包時,又收到一個包產生中斷,而uIP協議棧是共用緩存的(爲節約內存),如果再次去調用協議棧,會將協議棧緩存出錯。

spi.h


SPI相關訊息請參考其它資料,本例略。

 

6      ENC28J60驅動:

ENC28J60除初始化enc28j60_init()外,還需要提供兩個主要原生數據收發接口函數給uIP協議棧:enc28j60PacketReceive()網卡收數據,enc28j60PacketSend()網卡發數據。

 

本例中ENC28J60驅動已經調試成功,可以直接使用,在此只做簡單說明,更詳細請參考相關手冊。


 

注:ENC28J60初始化會等待網卡應答,錯誤無法進入系統。

7      uIP協議棧TCP應用demo:

7.1    uIP代碼結構:



7.2    main.c代碼說明:



8      應用程序接口uip_appcall():

對於處理應用數據的用戶,對uIP整個流程做一個瞭解即可,uIP將處理後的結果全部都回調到uip_appcall()函數統一處理,所以重點需要完成的工作全部在uip_appcall()函數中,以下介紹一個demo代碼:

 

已開啓主動連接功能uip.h 行300  #define UIP_ACTIVE_OPEN 1

 


8.1    uip_send 使用舉例:

uip_send(uip_appdata,sprintf((char*)uip_appdata,"%s","Hello,Iconnected to you! thanks"));

 

uip_send("idle",4);

 

注:uip_send並沒有真正將數據發送到物理網卡,也不保證數據正確到達,僅將數據存儲到uIP協議棧中,由uIP來決定發送到物理網卡(空閒時),結果將產生回調,根據事件代碼進行相應處理,如:收到ACK,可繼續下一包,超時重連,重發等。

9      配置參數:

實際應用中MAC地址,IP地址,網關地址,服務器地址,端口號,應該是可以動態設置的,而MAC,IP地址(除VLAN外)在同一網絡中必須是唯一的,否則導致網絡不可用。

 

MAC地址可以在燒錄程序時讓燒錄程序(或燒錄器)自動加一,寫到ROM固定位置,出廠時就設定好,但是MAC地址是有標準的,去IEEE申請還沒有這個必要,可以借用其它廠家的,或是用01:02:34:56:78:90:AB這樣累加的地址,但MAC地址衝突或不可用這種情況是會有的,比如有些交換機是會拒接一些MAC地址的,還有就是與部分網卡MAC衝突等。

 

本機IP,服務器IP,網關,端口號這些地址必須是可供用戶修改的,出廠時無法確定用戶的網絡環境,需要提供UI供用戶修改並保存到E2PROM或其它Flash中。

 

以下爲各自參數配置代碼位置:

9.1    用戶設定:

初始化時將從E2PROM或flash中讀取的設置參數替換以下處即可:

 

9.2    固定(僅供測試):

以下是固定地址,由編譯時決定,出廠後無法修改,不建議使用:


10            uIP協議棧事件列表:

見uip.h 行:493-600,大部分事件已在demo代碼中描述。

uipotp.h uIP協議棧的配置參數

11            常見問題:

測試中發現windows操作系統,會出現TCP checksum錯誤,導致丟包現象,是由於網卡硬件校驗原因:

 

解決辦法:

網卡配置->高級->Rx Checksum Offload/Tx Checksum Offload,很可能你的這兩處
設置是Enable,將之調整成Disable即可,代價是網絡性能降低。

一般由操作系統的TCP/IP協議棧完成TCP/UDP/IP校驗和的計算工作,這兩處設置成
Enable之後,協議棧不再進行校驗和的計算,而是由網卡自己完成。如果在前述位置
沒有發現Rx Checksum Offload/Tx Checksum Offload項,有兩種可能,一種是網卡
本身不支持這種功能,另一種是網卡驅動未提供配置項,後一種情形居多。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章