平台下的LwIP移植Word文件下载.docx
《平台下的LwIP移植Word文件下载.docx》由会员分享,可在线阅读,更多相关《平台下的LwIP移植Word文件下载.docx(98页珍藏版)》请在冰豆网上搜索。
5.4.4EMACInit()――網卡初始化工作的實際完成者.......................................................................40
5.4.5ethernetif_input()――實現接收線程...................................................................................47
5.4.6low_level_input()――得到一整幀資料.................................................................................49
5.4.7GetInputPacketLen()――獲得幀長.........................................................................................50
5.4.8EMACReadPacket()――複製,從接收緩衝區到pbuf...............................................................53
5.4.9EMACSendPacket()――發送一幀資料.......................................................................................55
5.4.10編譯――ethernetif.c及lib_emac.c......................................................................................56
6ping――結束LwIP的移植...................................................................................................................................57
6.1編譯、鏈結整個工程...............................................................................................................................57
6.2ping測試...................................................................................................................................................59
後記...............................................................................................................................................................................62
本文將指導讀者一步步完成LwIP在ADS1.2開發環境下的移植工作,包括底層驅動的編寫。
本文使用的硬體平臺是AT91SAM7X256+RTL8201BL(PHY),至於軟體平臺,讀者從本文標題即可看出。
我們使用uC/OS-II作為底層作業系統,而LwIP的移植亦將主要圍繞uC/OS-II展開。
好了,不再多說,開始吧……
1下載LwIP
很簡單,到LwIP的官方網站即可:
http:
//savannah.nongnu.org/projects/lwip/。
如果你不想看看
其他內容(可能對你會很重要),就只是想得到源碼,好的,直接到這個地址下載:
//download.savannah.nongnu.org/releases/lwip/。
目前官方發佈的最新版本是1.1.1,找到lwip-1.1.1.zip,然後下載、解壓縮,第一項工作完成。
2建立一個最基本的工程
要想完成移植工作,我們必須要有一個包含uC/OS-II的工程才行,這一步我們就是要建立這個工程。
工程建立完畢後,編譯鏈結沒有問題,那麼,第二項工作也完成了。
關於如何建立一個包含uC/OS-II的
ADS工程的問題,不在本文描述範圍之內,這裏不做講述。
隨本筆記一同發佈的源碼文檔中LwIPPortingTest_2檔夾下包含了這個最基本工程的源碼,讀者可以直接使用。
我的基本工程建立的路徑是D:
\work\LwIPPortingTest,下文將以相對路徑進行講述,不再提供絕對路徑。
3把LwIP加入工程
首先,在\src\文件夾下,建立LwIP文件夾,即:
\src\LwIP;
然後將下載的LwIP源碼文件中api、
core、include、netif文件複製到\src\LwIP\文件夾下,如下圖所示:
圖3.1
然後,用ADS打開工程檔,按照LwIP源碼檔的實際存放路徑建立LwIP的工程結構,如下圖所示:
圖3.2
這裏需要特別說明的是,源碼中的IPV6、SLIP及PPP部分我們沒有添加進來,主要是考慮我及大多數讀者的網路還是V4,而SLIP、PPP暫時不在我的考慮範圍之內。
另外,在移植層面V6也和V4相差不多,這裏就不再講解這部分內容了。
現在基礎工程結構建立完畢,可以把LwIP源碼添加進來了。
這一步很容易,按照檔存放路徑,將源碼檔添加到相應的工程結構下即可。
源碼添加完成後的工程參見所附源碼檔的LwIPPortingTest_3文件夾。
4編寫作業系統類比層相關代碼
LwIP的作者為作業系統類比層提供了較為詳細的說明,檔案名為sys_arch.txt,在LwIP的doc文件夾下。
我們的編寫工作根據這個說明進行。
4.1作業系統類比層移植說明――中文翻譯
事先聲明,之所以筆者要翻譯該文檔,主要是筆者在撰寫這篇筆記時亦沒有通讀該文檔。
筆者先前使用的模擬層源碼是楊曄大俠的。
為了真正弄懂LwIP,筆者決定自己重新實現LwIP的移植,本筆記是跟隨移植同步進行的,因此,翻譯的文檔也放在了這篇筆記中,使讀者能夠真正瞭解筆者的移植歷程。
另外再說一句,這個文檔是為LwIP0.6++版編寫,筆者搜遍了整個LwIP官方網站,沒有發現比這更新的,筆者只好認為作業系統類比層在0.6++之後沒有任何改動,如果有誰發現了更新的,一定通知筆者,先謝謝了。
好的,言歸正傳,下面就是譯文:
LwIP0.6++sys_arch介面
作者:
AdamDunkels
作業系統類比層(sys_arch)存在的目的主要是為了方便LwIP的移植,它在底層作業系統和
LwIP之間提供了一個介面。
這樣,我們在移植LwIP到一個新的目標系統時,只需修改這個介面即
可。
不過,不依賴底層作業系統的支援也可以實現這個介面。
sys_arch需要為LwIP提供信號量(semaphores)和郵箱(mailboxes)兩種進程間通訊方式(IPC)。
如果想獲得LwIP的完整功能,sys_arch還必須支持多線程。
當然,對於僅需要基本功能的用戶來
說,可以不去實現多線程。
LwIP以前的版本還要求sys_arch實現計時器調度,不過,從LwIP0.5
開始,這一需求在更高一層實現。
除了上文所述的sys_arch原始檔案需要實現的功能外,LwIP還要
求用戶提供幾個頭檔,這幾個頭檔包含LwIP使用的巨集定義。
下文將詳細講述sys_arch及頭文
件的實現。
信號量即可以是計數信號量,也可以是二值信號量――LwIP都可以正常工作。
郵箱用於消息傳
遞,用戶即可以將其實現為一個佇列,允許多條消息投遞到這個郵箱,也可以每次只允許投遞一個
消息。
這兩種方式LwIP都可以正常運作。
不過,前者更加有效。
需要用戶特別注意的是――投遞到
郵箱中的消息只能是一個指標。
在sys_arch.h檔中,我們指定資料類型“sys_sem_t”表示信號量,“sys_mbox_t”表示郵箱。
至於sys_sem_t和sys_mbox_t如何表示這兩種不同類型,LwIP沒有任何限制。
以下函數必須在sys_arch中實現:
-voidsys_init(void)
初始化sys_arch層。
-sys_sem_tsys_sem_new(u8_tcount)
建立並返回一個新的信號量。
參數count指定信號量的初始狀態。
-voidsys_sem_free(sys_sem_tsem)
釋放信號量。
-voidsys_sem_signal(sys_sem_tsem)
發送一個信號。
-u32_tsys_arch_sem_wait(sys_sem_tsem,u32_ttimeout)
等待指定的信號並阻塞線程。
timeout參數為0,線程會一直被阻塞至收到指定的信號;
非0,
則線程僅被阻塞至指定的timeout時間(單位為毫秒)。
在timeout參數值非0的情況下,返回值為
等待指定的信號所消耗的毫秒數。
如果在指定的時間內並沒有收到信號,返回值為
SYS_ARCH_TIMEOUT。
如果線程不必再等待這個信號(也就是說,已經收到信號),返回值也可以為0。
注意,LwIP實現了一個名稱與之相似的函數來調用這個函數,sys_sem_wait(),注意區別。
-sys_mbox_tsys_mbox_new(void)
建立一個空的郵箱。
-voidsys_mbox_free(sys_mbox_tmbox)
釋放一個郵箱。
如果釋放時郵箱中還有消息,它表明LwIP中存在一個編程錯誤,應該通知開發
者(原文如此,這句話很費解。
個人理解的意思是:
當執行sys_mbox_free()這個函數時,按道理郵箱中不應該再
存在任何消息,如果用戶使用LwIP時發現郵箱中還存在消息,說明LwIP的開發者存在一個編程錯誤,不能把郵箱
中的消息全部取出並處理掉。
遇到這種情況,用戶應該告訴LwIP的作者,糾正這個bug,譯注)。
-voidsys_mbox_post(sys_mbox_tmbox,void*msg)
投遞消息“msg”到指定的郵箱“mbox”。
-u32_tsys_arch_mbox_fetch(sys_mbox_tmbox,void**msg,u32_ttimeout)
阻塞線程直至郵箱收到至少一條消息。
最長阻塞時間由timeout參數指定(與
sys_arch_sem_wait()函數類似)。
msg是一個結果參數,用來保存郵箱中的消息指標(即*msg=ptr),
它的值由這個函數設置。
“msg”參數有可能為空,這表明當前這條消息應該被丟棄。
返回值與sys_arch_sem_wait()函數相同:
等待的毫秒數或者SYS_ARCH_TIMEOUT――如果時間溢出
的話。
LwIP實現的函數中,有一個名稱與之相似的――sys_mbox_fetch(),注意區分。
-structsys_timeouts*sys_arch_timeouts(void)
返回一個指向當前線程使用的sys_timeouts結構的指標。
LwIP中,每一個線程都有一個
timeouts鏈表,這個鏈表由sys_timeout結構組成,sys_timeouts結構則保存了指向這個鏈表的指
針。
這個函數由LwIP的超時調度程式調用,並且不能返回一個空(NULL)值。
單線程sys_arch實現中,這個函數只需簡單返回一個指標即可。
這個指標指向保存在sys_arch模
塊中的sys_timeouts總體變數。
如果底層作業系統支援多線程並且LwIP中需要這樣的功能,那麼,下面的函數必須實現:
-sys_thread_tsys_thread_new(void(*thread)(void*arg),void*arg,intprio)
啟動一個由函數指標thread指定的新線程,arg將作為參數傳遞給thread()函數,prio指定
這個新線程的優先順序。
返回值為這個新線程的ID,ID和優先順序由底層作業系統決定。
-sys_prot_tsys_arch_protect(void)
這是一個可選函數,它負責完成臨界區域保護並返回先前的保護狀態。
該函數只有在小的臨界
區域需要保護時才會被調用。
基於ISR驅動的嵌入式系統可以通過禁止中斷來實現這個函數。
基於
任務的系統可以通過互斥量或禁止任務來實現這個函數。
該函數應該支援來自於同一個任務或中斷
的遞迴調用。
換句話說,當該區域已經被保護,sys_arch_protect()函數依然能被調用。
這時,函
數的返回值會通知調用者該區域已經被保護。
如果你的移植正在支援一個作業系統,sys_arch_protect()函數僅僅是一個需要。
-voidsys_arch_unprotect(sys_prot_tpval)
該函數同樣是一個可選函數。
它的功能就是恢復受保護區域的先前保護狀態,先前是受到保護
還是沒有受到保護由參數pval指定。
它與sys_arch_protect()函數配套使用,詳細資訊參看
sys_arch_protect()函數。
該函數的說明是按照譯者個人理解的意思翻譯,原文講述不是很清楚,如有錯誤,歡迎批評指正,譯注。
--------------------------------------------------------------------------------------
OS支援的類比層需要添加的頭檔說明
-------------------------------------------------------------------------------------
-cc.h與硬體平臺及編譯器相關的環境變數及資料類型聲明檔(一些或許應該移到sys_arch.h
文件)。
LwIP使用的資料類型定義――u8_t,s8_t,u16_t,s16_t,u32_t,s32_t,mem_ptr_t。
與編譯器相關的LwIP結構體封裝巨集:
PACK_STRUCT_FIELD(x)
PACK_STRUCT_STRUCT
PACK_STRUCT_BEGIN
PACK_STRUCT_END
與平臺相關的調試輸出:
LWIP_PLATFORM_DIAG(X)-非故障,輸出一條提示資訊。
LWIP_PLATFORM_ASSERT(x)-故障,輸出一條故障資訊並放棄執行。
“輕便的(lightweight)”同步機制:
SYS_ARCH_DECL_PROTECT(x)-聲明一個保護狀態變數。
SYS_ARCH_PROTECT(x)-進入保護模式。
SYS_ARCH_UNPROTECT(x)-脫離保護模式。
如果編譯器不提供memset()函數,這個檔必須包含它的定義,或者包含(include)一個定
義它的文件。
這個檔要麼包含一個本地系統(system-local)提供的頭檔<
errno.h>
――這個檔定義了
標準的*nix錯誤編碼,要麼增加一條巨集定義語句:
#defineLWIP_PROVIDE_ERRNO,這將使得
lwip/arch.h頭檔來定義這些編碼。
這些編碼被用於LwIP的各個部分。
-perf.h定義了性能測量使用的巨集,由LwIP調用,可以將其定義為一個空的宏。
PERF_START-開始測量。
PERF_STOP(x)-結束測量並記錄結果。
-sys_arch.hsys_arch.c的頭文件。
定義Arch(即整個移植所依賴的作業系統平臺,譯注)需要的資料類型:
sys_sem_t,sys_mbox_t,
sys_thread_t,以及可選類型:
sys_prot_t。
sys_mbox_t和sys_sem_t變數的NULL值定義:
SYS_MBOX_NULLNULL
SYS_SEM_NULLNULL
4.2編寫作業系統類比層
4.1節已經明白的講述了如何實現sys_arch介面,我們按照這個說明完成即