一、 概述
U-boot中的TFTP用于發(fā)送較小的文件。下層使用UDP協(xié)議,發(fā)送使用UDP 69端口,每次發(fā)送的最大分組為512 Bytes。發(fā)送雙方采用超時(shí)重傳機(jī)制。數(shù)據(jù)傳輸模式為octet模式( 二進(jìn)制模式?。?。
在U-boot中使用tftp功能可以使用如下命令:
tftp MemoryAddress FileName
其中MemoryAddress為放入文件的內(nèi)存首地址,F(xiàn)ileName為傳送文件的文件名(文件需放在tftp默認(rèn)目錄下)。
二、 使用TFTP
使用TFTP傳送文件的步驟:
1 使用時(shí)已經(jīng)初始化以下變量:
NetOurIP (本機(jī)IP地址,定義在Net.c文件)
NetServerIP(TFTP服務(wù)器的IP地址,定義在Net.c文件)
BootFile (需要傳送文件的文件名,定于在Tftp.c)
NetOurGatewayIP (本機(jī)的網(wǎng)關(guān)地址)
NetOurSubnetMask (本機(jī)子網(wǎng)掩碼)
2 調(diào)用TftpStart 函數(shù)開始文件傳送。
三、 TFTP實(shí)現(xiàn)
(1)客戶端狀態(tài)
TFTP使用一個(gè)變量TftpState來描述TFTP客戶端可能的5種狀態(tài):
狀態(tài)
說明
STATE_RRQ
發(fā)出讀取請(qǐng)求,正等待批準(zhǔn)
STATE_DATA
正在接收數(shù)據(jù)
STATE_TOO_LARGE
文件太大
STATE_BAD_MAGIC
Bad magic number
STATE_OACK
收到OACK幀
(2)包類型
使用TFTP傳送的包分為6種類型:
類型
說明
TFTP_RRQ
請(qǐng)求讀取文件
TFTP_WRQ
請(qǐng)求寫文件
TFTP_DATA
數(shù)據(jù)包
TFTP_ACK
確認(rèn)包
TFTP_ERROR
包含出錯(cuò)信息的包
TFTP_OACK
option acknowledge,當(dāng)服務(wù)器超時(shí)未收到客戶端的ACK幀時(shí),主動(dòng)發(fā)出一個(gè)OACK幀
(3)各種包結(jié)構(gòu)
TFTP協(xié)議中各種包的結(jié)構(gòu):
圖1.TFTP協(xié)議中包結(jié)構(gòu)
具體到U-boot中客戶端發(fā)送的各種包的結(jié)構(gòu):
RRQ(請(qǐng)求讀的包的結(jié)構(gòu)):
TFTP_RRQ(包的類型)
請(qǐng)求文件名
0
“octet”(傳輸模式)
0
“timeout”(超時(shí)重傳機(jī)制)
0
TIMEOUT(超時(shí)重傳等待時(shí)間)
ACK(確認(rèn)幀)結(jié)構(gòu):
TFTP_ACK
確認(rèn)的包的編號(hào)
(4)主要函數(shù)及作用
U-boot中與tftp協(xié)議有關(guān)的文件有tftp.c與tftp.h文件,主要函數(shù)包括:
static __inline__ void
store_block (unsigned block, uchar * src, unsigned len);
/* 根據(jù)預(yù)先設(shè)定的地址load_addr決定將首地址為src,長度為len的block個(gè)數(shù)據(jù)塊寫入flash 或?qū)懭雰?nèi)存*/
static void
TftpSend (void) ;
/* 根據(jù)TftpState變量的不同值發(fā)送不同的 Tftp包 (使用UDP協(xié)議發(fā)送) */
static void
TftpHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len) ;
/* 處理收到的Tftp包 */
static void
TftpTimeout (void);
/* 超時(shí)處理函數(shù) */
void
TftpStart (void);
/* 初始化各個(gè)需要的數(shù)據(jù) 然后開始發(fā)送TFTP讀請(qǐng)求 */
(5) 流程
TFTP總體流程:
首先客戶端發(fā)出讀寫請(qǐng)求。如果服務(wù)器批準(zhǔn)此請(qǐng)求,則打開連接,并第一個(gè)數(shù)據(jù)包??蛻舳耸盏綌?shù)據(jù)包后發(fā)回確認(rèn),而服務(wù)器發(fā)出下一個(gè)數(shù)據(jù)包以前必須得到客戶對(duì)上一個(gè)數(shù)據(jù)包的確認(rèn)。如果數(shù)據(jù)包在傳輸過程中丟失,服務(wù)器方會(huì)在超時(shí)后重新傳輸最后一個(gè)未被確認(rèn)的數(shù)據(jù)包。
發(fā)送的數(shù)據(jù)包一般為512字節(jié),如果一個(gè)數(shù)據(jù)包小于 512 字節(jié),則表示這個(gè)包是最后一個(gè)包,如果發(fā)送的數(shù)據(jù)正好是 512 的整數(shù)倍,發(fā)送完后再發(fā)一個(gè)空包。
客戶端程序流程:
<1>客戶端設(shè)定NetOurIP 、NetServerIP、BootFile 變量的值。
<2>調(diào)用TftpStart函數(shù),TftpStart函數(shù)完成如下的6步工作:
1若BootFile為空,則使用默認(rèn)文件名;否則使用BootFile為傳送的文件名。
2比較客戶端和服務(wù)器的子網(wǎng)地址,判斷兩者是否在同一個(gè)子網(wǎng)內(nèi)。
3設(shè)定超時(shí)處理函數(shù)為TftpTimeout 。
4設(shè)置處理接收到的TFTP包的函數(shù)為TftpHandler。
5初始化服務(wù)器端口、本機(jī)端口、超時(shí)次數(shù)為0、初始狀態(tài)為RRQ
6調(diào)用TftpSend函數(shù)發(fā)送TFTP讀取請(qǐng)求。
<3> TftpSend函數(shù)根據(jù)TftpState 發(fā)送不同的包,同時(shí)TftpHandler函數(shù)根據(jù)包的類型和當(dāng)前客戶端的狀態(tài)(TftpState) 處理接收到的包。
圖2.TFTP流程