嵌入式Intemet技術已逐步趨于實用化,在工控與信息電器等領域得到了可喜的應用。據專家預測,今后在Intemet上傳輸的信息有70%來自小型嵌入式設備,構建基于嵌入式系統的網絡平臺已成為嵌入式領域的一個重要研究方向 。目前Intemet上的通信方式大都是基于TCP/IP協議,嵌入式設備要與Intemet網絡直接交換信息,就必須支持TCP/IP協議。在當前SoPC技術和嵌入式網絡技術飛速發展、日益結合的背景下,將LwIP協議棧引入到SoPC系統中,以支持嵌入式設備接入網絡,是適合應用需求的。
LwIP(lightweightIP)即輕型TCP/IP協議棧,一般只需要幾十K的RAM 和40K左右的ROM 就可以運行,并實現了較為完備的IP、ICMP、UDP、TCP,DHCP協議。以SOC的形式基于uC/OS II實現LwIP,并成功應用到實際當中的,已有很多文獻進行了報道。但是,基于SoPC系統的LwIP的實現比較少見。謝兵森等人主要報道了如何在Altera公司提供的SoPC系統開發環境下設計嵌入式以太網網絡終端,偏重于應用 。本文詳細闡述LwIP協議棧及其在SoPC系統上的移植原理,在此的基礎上基于SoPC系統完成LwIP協議棧的移植。
1 LwIP協議棧實現原理
LwIP是瑞士計算機科學院(SCICS)的Adam Dunkels等開發的一套用于嵌入式系統的開放源碼的輕型TCP/IP協議棧,LwIP實現了較為完備的IP、ICMP、UDP、TCP、DHCP協議,具有超時時間估計、快速恢復和重發、窗口調整等功能。LwIP在保持協議主要功能的基礎上減少對RAM 和ROM 的占用,一般只需要幾十K 的RA M 和40K左右的ROM 就可以運行,很適合同uC/OS II相配合用在嵌入式系統中。在使用和移植的過程中可根據傳輸數據的不同需求進行刪減和增補。移植過程主要是針對系統采用的微處理器、編譯器、操作系統和網絡控制器做相關的移植工作。本次研究采用lwip-0.6.3版本,經移植優化的LwIP作為uC/OS II擴展的網絡模塊運行,為系統提供基本的網絡通信功能。并且在其基礎上構造了一個基于TCP的Telnet echo測試服務器,以特定網絡應用任務形式運行。
LwIP可移植到操作系統上,也可在無操作系統的情況下獨立運行。本次研究LwIP在uC/OS-II下實現的原理如圖1。

圖1 LwIP實現的原理
系統硬件核心為Stratix1s10的FPGA芯片。根據開發板的資源和研究要求將FPGA配置成定制的SoPC系統,具體的硬件系統如圖2所示。網絡控制器是SMSC公司生產的自適應10M/100M第3代快速以太網控制器LAN91c111,集成了SMSC/CD協議的MAC(媒體層)和PHY(物理層)。外圍設備的驅動和控制接口都有相應的IP核來完成。
系統軟件核心為uC/OS-II-2.76,是一個源碼開放的適合于小型、微控制器的占先式多任務管理的實時操作系統。它內核短小精悍、可裁減、執行時間確定。uC/OS II提供的僅僅只是一個實時的調度及任務間通信的內核,沒有集成網絡協議。針對NiosII處理器,首先完成uC/OS-II的移植工作。
2 LwIP實現的硬件平臺
采用Altera公司的Stratix1s10開發板。在Altera公司的FPGA集成開發環境QuartusII 4.0和SoPC Builder下構建基于Avalon總線的SoPC系統。根據研究的需要,在FPGA上定制的SoPC系統硬件映像如圖2所示。
SoPC系統的硬件核心是Nios II處理器,Nios II內核有3種配置——快速(Nios II/f)、標準(Nios II/s)和經濟型(Nios II/e)。Nios II是Nios的第2代,是專門針對Altera的可編程邏輯和可編程單芯片系統(SoPC)而設計的軟CPU。此處配置成標準。jtag-uart是PC機和開發板的連接電纜,功能是下載FPGA配置、軟件程序和調試程序。tri_bridge是Avalon片內總線和片外設備的連接總線。lan91c111是以太網控制器接口,允許中斷。
3 LwIP協議棧的移植
移植LwIP協議棧,主要是針對系統所采用的Nios II處理器、GCC編譯器、uC/OS-II-2.76和LAN91c111以太網控制器做相關的移植。
3.1 處理器和編譯器相關部分的移植
LwIP協議棧把所有和硬件,編譯器相關的部分獨立出來,放在/src/arch下面。/arch目錄下cc.h、cpu.h、perf.h中是與Nios II和GCC相關的定義。如數據長度、字的高低位順序等。這些應與用戶實現uC/OS-II時定義的數據長度等參數是一致的。例如:
#define BYTE_ORDER LITTLE_ENDIAN //Nios II默認為小端存儲系統
一般情況下,C語言的結構體struct是4字節對齊的,但是在處理數據包的時候,LwIP使用的是通過結構體中不同數據的長度來讀取相應的數據的。所以,一定要在定義struct的時候使用_packed關鍵字,讓編譯器放棄struct的字節對齊。在Nios II上對應GCC編譯器的定義為:
#define PACK_STRUCT FIELD(x)x _attribute_ ((packed))
#define PACK_STRUCT_STRUCT _auribute_((packed))
#define PACK_STRUCT_BEGIN
#define PACK_STRUCT_END
3.2 改寫操作系統有關部分的函數
sys_arch.c文件是和操作系統相關的一些結構和函數。和uC/OS-II的接口函數主要分為5個部分 。
(1)信號量:LwIP中需用信號量通信,對信號量的處理函數:
sys_sem_t sys_sem_new(u8_t count) //創建一個信號量
void sys_sem_free(sys_sem_t sem)//釋放并刪除一個信號量
void sys_sem_signal(sys_sem_t sem)//發送一個信號量
u32_t sys_arch_sem_wait(sys_sem_t sem,u32_t timeout))//等待一個信號量
由于uC/OS-II已實現了信號量OS_EVENT的各種操作,且功能和LwIP上面幾個函數的目的功能是完全一樣的,所以只要把uC/OS II的函數重新包裝成上面的函數,就可以直接使用。
(2)消息隊列:LwIP使用消息隊列來緩沖、傳遞數據報文,對消息隊列的處理函數如下:
sys_mbox_t sys_mbox_new(void) //創建一個消息隊列
void sys_mbox_free(sys_mbox_t mbox ) //釋放一個消息隊列
void sys_mbox_post(sys_mbox_t mbox,void *data)//向消息隊列發送消息
u32_t sys_arch_mbox_fetch(sys_mbox_t mbox,void **msg,u32_t timeout) //從消息隊列中獲取消息
uC/OS II同樣實現了消息隊列結構及其操作,但是uC/OS II沒有對消息隊列中的消息進行管理,因此不能直接使用,必須在uC/OS II的基礎上重新實現。
(3)等待超時函數:LwIP中每個與外界網絡連接的線程都有自己的timeout屬性,即等待超時時間。這個屬性表現為每個線程的timeout時間長度, 以及超時后應調用的timeout函數,做相應的處理。用戶要實現的函數如下:
struct sys_timeouts *sys_arch_timeouts(void);//返回正處于運行狀態的線程所對應的timeout隊列指針
(4)創建新線程:LwIP可以是單線程運行,也可以多線程運行。為提高效率并降低編程復雜度,用戶需要實現創建新線程的函數:
sys_thread_t sys_thread_new(void(*function)(void *arg),void *arg,int prio);
在uC/OS II中,沒有線程的概念,只有任務。只要把OSTaskCreate封裝一下,就可以實現sys_thread new。
(5)系統初始化:
void sys_init(void);//系統初始化
3.3 網絡控制器的驅動
TCP/IP協議棧引入到uC/OS II后,為了實現網絡通訊還必須完成相應網絡控制器驅動程序的添加。Stratix1s10開發板所帶的網絡芯片是由SMSC公司生產的以太網控制器芯片LAN91c111。驅動程序工作在IP協議模型的網絡接口層,它提供給上層(IP層)的接口函數如下:
err_t alt_avalon_lan91c111_init(struct netif *netif)//網卡初始化函數
void alt_avalon_lan91c111_rx(alt_lwip_dev *dev)//網卡接收函數, 由網卡ISR調用
err_t alt)avalon)lan91c111_output(struct netif *netif,struct pbuf *p,struct ip_addr *ipaddr)//網卡發送數據函數
void alt_avalon_lan91c111_irq(void* context,alt_u32 interrupt)//網卡中斷處理函數
以上的函數都可以分為協議棧本身的處理和對網絡接口硬件的操作兩部份,但硬件操作是對上層屏蔽的。
4 實驗測試
在Altera公司的Nios II IDE 開發環境下以前文建立的SoPC系統硬件為目標硬件建立名為lwip test的軟件工程。同時,開發環境會自動建立名為lwip_test_syslib的工程。uC/OS II的初始化在lwip_test_syslib中由系統自動完成,在lwip_test中建立主函數程序框架如下:
main(void)
{
……
Lwip_stack_init();
OSStart();
}
Lwip_stack_init(int thread_prio,void(*inti_done_func)(void *),void arg)函數初始化LwIP協議棧。它的形參init_done_func是函數指針,指向tcpip_init_done的函數。tcpip_init_done函數是在LwIP協議棧初始化完畢后被調用,目的是安裝以太網控制器的驅動和建立相應的Telnet echo任務,監聽7號端口,為客戶機提供回顯服務。程序編譯調試通過后,將其燒入Flash中,開發板通過以太網線經Hub與局域網連接,作為局域網的一臺小型嵌入式服務器運行。等待LwIP從網絡服務器動態獲取IP地址后,通過局域網中一臺Pc機,在DOS環境下,鍵入ping 172.18.6.136命令向目標板發送ICMP請求,客戶端可得ICMP回應。鍵入telnet 172.18.6.136 7(7號端口)命令登錄開發板Telnet echo服務,客戶端用戶可在顯示屏幕上看到自己鍵入的字符。實驗說明各網絡協議得到正確配置,同時各任務在內核調度管理下運行正常。
5 結束語
基于實時內核uC/OS II,在SoPC系統中實現了LwIP協議棧的移植與優化。移植優化后的LwIP棧做為一個網絡模塊運行,代碼占用40 K的ROM,實現了以太網/IP/TCP/Telnet網絡功能,并提供了模塊API,與系統實現無縫連接。基于LwIP的網絡應用任務與其它非網絡應用任務,在uC/OS II實時內核管理下協調運行。進一步增強協議棧的網絡安全性與穩定性,并開發相應的的網絡應用程序,“SoPC系統/uCOS II/LwIP協議棧”的架構有望應用在信息家電和網絡化的儀器、儀表方面。