一、 概述
U-boot中的TFTP用于發送較小的檔案。下層使用UDP協定,發送使用UDP 69端口,每次發送的最大分組為512 Bytes。發送雙方采用逾時重傳機制。資料傳輸模式為octet模式( 二進制模式 )。
在U-boot中使用tftp功能可以使用如下指令:
tftp MemoryAddress FileName
其中MemoryAddress為放入檔案的記憶體首位址,FileName為傳送檔案的檔案名。
二、 使用TFTP
使用TFTP傳送檔案的步驟:
1 使用時已經初始化以下變量:
NetOurIP (本機IP位址,定義在Net.c檔案)
NetServerIP(TFTP伺服器的IP位址,定義在Net.c檔案)
BootFile (需要傳送檔案的檔案名,定于在Tftp.c)
NetOurGatewayIP (本機的網關位址)
NetOurSubnetMask (本機子網路遮罩)
2 調用TftpStart 函數開始檔案傳送。
三、 TFTP實作
(1)用戶端狀态
TFTP使用一個變量TftpState來描述TFTP用戶端可能的5種狀态:
狀态
說明
STATE_RRQ
發出讀取請求,正等待準許
STATE_DATA
正在接收資料
STATE_TOO_LARGE
檔案太大
STATE_BAD_MAGIC
Bad magic number
STATE_OACK
收到OACK幀
(2)包類型
使用TFTP傳送的包分為6種類型:
類型
TFTP_RRQ
請求讀取檔案
TFTP_WRQ
請求寫檔案
TFTP_DATA
資料包
TFTP_ACK
确認包
TFTP_ERROR
包含出錯資訊的包
TFTP_OACK
option acknowledge,當伺服器逾時未收到用戶端的ACK幀時,主動發出一個OACK幀
(3)各種包結構
TFTP協定中各種包的結構:

圖1.TFTP協定中包結構
具體到U-boot中用戶端發送的各種包的結構:
RRQ(請求讀的包的結構):
TFTP_RRQ(包的類型)
請求檔案名
“octet”(傳輸模式)
“timeout”(逾時重傳機制)
TIMEOUT(逾時重傳等待時間)
ACK(确認幀)結構:
确認的包的編号
(4)主要函數及作用
U-boot中與tftp協定有關的檔案有tftp.c與tftp.h檔案,主要函數包括:
static __inline__ void store_block (unsigned block, uchar * src, unsigned len);
/* 根據預先設定的位址load_addr決定将首位址為src,長度為len的block個資料塊寫入flash 或寫入記憶體*/
static void TftpSend (void) ;
/* 根據TftpState變量的不同值發送不同的 Tftp包 (使用UDP協定發送) */
static void TftpHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len) ;
/* 處理收到的Tftp包 */
static void TftpTimeout (void);
/* 逾時處理函數 */
void TftpStart (void);
/* 初始化各個需要的資料 然後開始發送TFTP讀請求 */
(5) 流程
TFTP總體流程:
首先用戶端發出讀寫請求。如果伺服器準許此請求,則打開連接配接,并第一個資料包。用戶端收到資料包後發回确認,而伺服器發出下一個資料包以前必須得到客戶對上一個資料包的确認。如果資料包在傳輸過程中丢失,伺服器方會在逾時後重新傳輸最後一個未被确認的資料包。
發送的資料包一般為512位元組,如果一個資料包小于 512 位元組,則表示這個包是最後一個包,如果發送的資料正好是 512 的整數倍,發送完後再發一個空包。
用戶端程式流程:
用戶端設定NetOurIP 、NetServerIP、BootFile 變量的值。
調用TftpStart函數,TftpStart函數完成如下的6步工作:
1若BootFile為空,則使用預設檔案名;否則使用BootFile為傳送的檔案名。
2比較用戶端和伺服器的子網位址,判斷兩者是否在同一個子網内。
3設定逾時處理函數為TftpTimeout 。
4設定處理接收到的TFTP包的函數為TftpHandler。
5初始化伺服器端口、本機端口、逾時次數為0、初始狀态為RRQ
6調用TftpSend函數發送TFTP讀取請求。
TftpSend函數根據TftpState 發送不同的包,同時TftpHandler函數根據包的類型和目前用戶端的狀态(TftpState) 處理接收到的包。
圖2.TFTP流程