單芯片解決方案,開啟全新體驗——W55MH32 高性能以太網單片機
W55MH32是WIZnet重磅推出的高性能以太網單片機,它為用戶帶來前所未有的集成化體驗。這顆芯片將強大的組件集于一身,具體來說,一顆W55MH32內置高性能Arm? Cortex-M3核心,其主頻最高可達216MHz;配備1024KB FLASH與96KB SRAM,滿足存儲與數據處理需求;集成TOE引擎,包含WIZnet全硬件TCP/IP協議棧、內置MAC以及PHY,擁有獨立的32KB以太網收發緩存,可供8個獨立硬件socket使用。如此配置,真正實現了All-in-One解決方案,為開發者提供極大便利。
在封裝規格上,W55MH32提供了兩種選擇:QFN100和QFN68。
W55MH32L采用QFN100封裝版本,尺寸為12x12mm,其資源豐富,專為各種復雜工控場景設計。它擁有66個GPIO、3個ADC、12通道DMA、17個定時器、2個I2C、5個串口、2個SPI接口(其中1個帶I2S接口復用)、1個CAN、1個USB2.0以及1個SDIO接口。如此豐富的外設資源,能夠輕松應對工業控制中多樣化的連接需求,無論是與各類傳感器、執行器的通信,還是對復雜工業協議的支持,都能游刃有余,成為復雜工控領域的理想選擇。同系列還有QFN68封裝的W55MH32Q版本,該版本體積更小,僅為8x8mm,成本低,適合集成度高的網關模組等場景,軟件使用方法一致。更多信息和資料請進入http://www.w5500.com/網站或者私信獲取。
此外,本W55MH32支持硬件加密算法單元,WIZnet還推出TOE+SSL應用,涵蓋TCP SSL、HTTP SSL以及 MQTT SSL等,為網絡通信安全再添保障。
為助力開發者快速上手與深入開發,基于W55MH32L這顆芯片,WIZnet精心打造了配套開發板。開發板集成WIZ-Link芯片,借助一根USB C口數據線,就能輕松實現調試、下載以及串口打印日志等功能。開發板將所有外設全部引出,拓展功能也大幅提升,便于開發者全面評估芯片性能。
若您想獲取芯片和開發板的更多詳細信息,包括產品特性、技術參數以及價格等,歡迎訪問官方網頁:http://www.w5500.com/,我們期待與您共同探索W55MH32的無限可能。
第十四章 W55MH32 TFTP示例
本篇文章,我們將詳細介紹如何在W55MH32芯片上面實現TFTP協議。并通過實戰例程,為大家講解如何使用TFTP客戶端模式向服務器獲取文本文件。
該例程用到的其他網絡協議,例如DHCP請參考相關章節。有關W55MH32的初始化過程,也請參考Network Install章節,這里將不再贅述。
1 TFTP協議簡介
TFTP(TrivialFileTransferProtocol)協議是一種輕量級的文件傳輸協議,它通常用于需要快速、簡單的文件交換場景,尤其是在網絡設備啟動和配置過程中。與FTP(文件傳輸協議)不同,TFTP設計得非常簡單,僅提供基本的文件讀寫功能,并且使用UDP作為傳輸層協議,因而不具備TCP的復雜性和重傳機制。
2 TFTP協議特點
簡單性:TFTP協議設計簡單,它的報頭格式簡潔,操作命令種類少,這使得實現起來相對容易,對資源的需求也較低。
輕量級:TFTP協議不需要復雜的連接建立和管理過程,開銷小,因此適合在一些對性能要求不高、資源有限的環境中使用。
基于UDP:TFTP使用UDP作為傳輸層協議,利用了UDP的快速傳輸和無連接特性,從而能夠快速地傳輸數據。不過,這也意味著TFTP本身不提供可靠的傳輸保證,需要在應用層實現可靠性機制。
端口固定:TFTP使用固定的端口69來監聽客戶端的請求。數據傳輸使用的端口是動態分配的,每次傳輸會在此基礎上選擇一個臨時端口。
數據塊大小限制:每個數據報文最多只能傳輸512字節的數據,如果文件較大,會分多次傳輸,每次發送一個512字節的數據塊。最后一個數據塊可能小于512字節,表示文件的結束。
3 TFTP協議應用場景
接下來,我們了解下在W55MH32上,可以使用TFTP協議完成哪些操作及應用呢?
固件升級:對于路由器、交換機等網絡設備,TFTP協議常用于將固件傳輸到這些設備以進行固件更新。TFTP協議能夠確保固件文件快速、準確地傳輸到目標設備。
配置文件傳輸:TFTP協議也常用于管理網絡設備的配置文件。將配置文件傳輸到網絡設備以進行配置更新,或者從網絡設備下載配置文件進行備份或分析。
IOT設備固件升級:TFTP協議因其簡單性和高效性,成為IOT設備固件升級的一種常用協議。
4 TFTP協議基本工作流程
請求發送:客戶端向服務器發送讀請求(RRQ,Read Request)或寫請求(WRQ,Write Request)。這些請求包含了要讀取或寫入的文件名以及傳輸模式(如二進制或ASCII碼)。
建立連接:服務器接收到客戶端的請求后,根據請求中的文件名和傳輸模式,打開相應的文件(對于寫請求)或準備發送文件數據(對于讀請求),并向客戶端發送確認信息,從而建立連接。
數據傳輸:在寫請求的情況下,客戶端開始發送文件數據到服務器,服務器接收并寫入文件。數據以數據塊的形式發送,每個數據塊的大小通常為512字節(但可以根據網絡狀況調整)。
在讀請求的情況下,服務器開始發送文件數據到客戶端,客戶端接收并保存文件。同樣,數據也是以數據塊的形式發送的。
回應與確認:每當客戶端或服務器發送一個數據塊后,接收方會發送一個回應包(ACK,Acknowledgment)來確認接收到了該數據塊。這個回應包包含了接收到的數據塊的編號,以確保數據的順序和完整性。
繼續傳輸或結束:根據回應包,發送方會繼續發送下一個數據塊,直到整個文件傳輸完成。如果傳輸過程中出現錯誤,服務器會向客戶端發送錯誤信息包(ERROR),中斷傳輸過程。
關閉連接:文件傳輸完成后,客戶端和服務器會關閉連接。
5 TFTP協議報文解析
常見的操作碼:
1:讀請求(RRQ),用于請求讀取服務器上的文件。
2:寫請求(WRQ),用于請求向服務器上寫入文件。
3:數據(DATA),用于傳輸文件數據。
4:回應(ACK),用于確認接收到的數據塊。
5:錯誤信息(ERROR),用于報告傳輸過程中發生的錯誤。
常見操作碼的報文格式如下:
報文類型 | 報文格式 | 操作碼 | 其他關鍵字段及說明 |
讀請求(RRQ) | 總長可變,由2字節操作碼、可變長文件名(以1字節0結尾)、可變長傳輸模式(以1字節 0結尾)組成 | 1 |
文件名:明確要讀取的文件名稱 傳輸模式:“netascii”表示ASCI碼模式,“octet”表示二進制模式 |
寫請求(WRQ) | 總長可變,由2字節操作碼、可變長文件名(以1字節0結尾)、可變長傳輸模式(以1字節 0結尾)組成 | 2 |
文件名:明確要讀取的文件名稱 傳輸模式:“netascii”表示ASCII碼模式,“octet”表示二進制模式 |
數據(DATA) | 由2字節操作碼、2字節數據塊編號、最多512字節數據組成 | 3 |
數據塊編號:從1開始,用于標識數據塊順序 數據:實際傳輸的文件內容 |
確認(ACK) | 由2字節操作碼和2字節確認的數據塊編號組成 | 4 | 數據塊編號:與接收到的數據塊編號一致,用于確認接收 |
錯誤(ERROR) | 由2字節操作碼、2字節錯誤碼、可變長錯誤信息(以 1字節0結尾)組成 | 5 |
錯誤碼:明確錯誤類型 錯誤信息:具體描述錯誤情況 |
報文示例:
客戶端讀請求報文:
|報文解析| Trivial File Transfer Protocol Opcode: Read Request (1) (操作碼為01,讀請求報文) Source File: tftp_test_file.txt (明確要讀取的文件名為tftp_test_file.txt) Type: octet (傳輸模式為octet) Option: timeout = 5 |報文原文| 00 01 74 66 74 70 5f 74 65 73 74 5f 66 69 6c 65 2e 74 78 74 00 6f 63 74 65 74 00 74 69 6d 65 6f 75 74 00 35 00
服務器響應報文:
|報文解析| Trivial File Transfer Protocol Opcode: Option Acknowledgement (6) (操作碼為06,擴展操作碼) [Destination File: tftp_test_file.txt] [Read Request in frame 125] Option: timeout = 5 |報文原文| 00 06 74 69 6d 65 6f 75 74 00 35 00
客戶端響應報文:
|報文解析| Trivial File Transfer Protocol Opcode: Acknowledgement (4) (操作碼為04,回應報文) [Destination File: tftp_test_file.txt] [Read Request in frame 125] Block: 0 (數據塊標號為00 00) [Full Block Number: 0] |報文原文| 00 04 00 00
服務器響應報文:
|報文解析| Trivial File Transfer Protocol Opcode: Data Packet (3) (操作碼為03,數據報文) [Destination File: tftp_test_file.txt] [Read Request in frame 125] Block: 1 (數據塊標號為00 01) [Full Block Number: 1] Data (36 bytes) Data: 736461666173646661736466617364666666666666666641617364666173666166736466 (數據) [Length: 36] |報文原文| 00 03 00 01 73 64 61 66 61 73 64 66 61 73 64 66 61 73 64 66 66 66 66 66 66 66 66 41 61 73 64 66 61 73 66 61 66 73 64 66
客戶端響應報文:
|報文解析| Trivial File Transfer Protocol Opcode: Acknowledgement (4) (操作碼為04,回應報文) [Destination File: tftp_test_file.txt] [Read Request in frame 125] Block: 1 (數據塊標號為00 01) [Full Block Number: 1] |報文原文| 00 04 00 01
6實現過程
接下來,我們在W55MH32上實現TFTP協議讀取文件。
注意:測試實例需要PC端和W55MH32處于同一網段。
在主函數中調用do_tftp_client()函數不斷檢查和處理 TFTP客戶端的狀態,并根據讀取的結果(成功或失敗)進入相應的處理狀態。
1. do_tftp_client(SOCKET_ID, ethernet_buf);
do_tftp_client()函數如下:
void do_tftp_client(uint8_t sn, uint8_t *buff) { uint32_t tftp_server_ip = inet_addr(TFTP_SERVER_IP); uint8_t tftp_read_file_name[] = TFTP_SERVER_FILE_NAME; TFTP_init(sn, buff); while (1) { if (tftp_read_flag == 0) { printf("tftp server ip: %s, file name: %srn", TFTP_SERVER_IP, TFTP_SERVER_FILE_NAME); printf("send requestrn"); TFTP_read_request(tftp_server_ip, TFTP_SERVER_FILE_NAME); tftp_read_flag = 1; } else { tftp_state = TFTP_run(); if (tftp_state == TFTP_SUCCESS) { printf("tftp read success, file name: %srn", tftp_read_file_name); while (1) { // 成功后進入死循環 } } else if (tftp_state == TFTP_FAIL) { printf("tftp read fail, file name: %srn", tftp_read_file_name); while (1) { // 失敗后進入死循環 } } } } }
進入do_tftp_client()函數后開始進行TFTP客戶端處理,步驟如下:
步驟一:TFTP初始化
調用TFTP_init()函數對TFTP客戶端進行初始化,參數sn和buff分別是socket號,socket緩存。
void TFTP_init(uint8_t socket, uint8_t *buf) { init_tftp(); g_tftp_socket = open_tftp_socket(socket); g_tftp_rcv_buf = buf; } static void init_tftp(void) { g_filename[0] = 0; set_server_ip(0); set_server_port(0); set_local_port(0); set_tftp_state(STATE_NONE); set_block_number(0); // timeout flag g_resend_flag = 0; tftp_retry_cnt = tftp_time_cnt = 0; g_progress_state = TFTP_PROGRESS; }
步驟二:發送 TFTP讀請求
當tftp_read_flag為 0時,表示尚未發送讀取請求。此時,打印 TFTP服務器的 IP地址和要讀取的文件名,然后調用TFTP_read_request()函數向服務器發送讀取請求。發送請求后,將tftp_read_flag設置為 1,表示已發送請求。
void TFTP_read_request(uint32_t server_ip, uint8_t *filename) { set_server_ip(server_ip); #ifdef __TFTP_DEBUG__ DBG_PRINT(INFO_DBG, "[%s] Set Tftp Server : %xrn", __func__, server_ip); #endif g_progress_state = TFTP_PROGRESS; send_tftp_rrq(filename, (uint8_t *)TRANS_BINARY, &default_tftp_opt, 1); }
步驟三:運行 TFTP協議并處理結果
當 tftp_read_flag為 1時調用 TFTP_run()函數處理 TFTP協議操作,依據其返回的 tftp_state判斷結果:若為 TFTP_SUCCESS則打印成功信息并進入無限循環,若為 TFTP_FAIL則打印失敗信息并進入無限循環。
TFTP_run()函數如下:
int TFTP_run(void) { int len; uint16_t from_port; uint32_t from_ip; /* Timeout Process */ if (g_resend_flag) { if (tftp_time_cnt >= g_timeout) { switch (get_tftp_state()) { case STATE_WRQ: break; case STATE_RRQ: send_tftp_rrq(g_filename, (uint8_t *)TRANS_BINARY, &default_tftp_opt, 1); break; case STATE_OACK: case STATE_DATA: send_tftp_ack(get_block_number()); break; case STATE_ACK: break; default: break; } tftp_time_cnt = 0; tftp_retry_cnt++; if (tftp_retry_cnt >= 5) { init_tftp(); g_progress_state = TFTP_FAIL; } } } /* Receive Packet Process */ len = recv_udp_packet(g_tftp_socket, g_tftp_rcv_buf, MAX_MTU_SIZE, &from_ip, &from_port); if (len < 0) { #ifdef __TFTP_DEBUG__ DBG_PRINT(ERROR_DBG, "[%s] recv_udp_packet errorrn", __func__); #endif return g_progress_state; } recv_tftp_packet(g_tftp_rcv_buf, len, from_ip, from_port); return g_progress_state; }
在處理接收到的TFTP數據包時,首先調用recv_tftp_packet()函數。
recv_tftp_packet()函數如下:
static void recv_tftp_packet(uint8_t *packet, uint32_t packet_len, uint32_t from_ip, uint16_t from_port) { uint16_t opcode; /* Verify Server IP */ if (from_ip != get_server_ip()) { #ifdef __TFTP_DEBUG__ DBG_PRINT(ERROR_DBG, "[%s] Server IP faultsrn", __func__); DBG_PRINT(ERROR_DBG, "from IP : %08x, Server IP : %08xrn", from_ip, get_server_ip()); #endif return; } opcode = ntohs(*((uint16_t *)packet)); /* Set Server Port */ if ((get_tftp_state() == STATE_WRQ) || (get_tftp_state() == STATE_RRQ)) { set_server_port(from_port); #ifdef __TFTP_DEBUG__ DBG_PRINT(INFO_DBG, "[%s] Set Server Port : %drn", __func__, from_port); #endif } switch (opcode) { case TFTP_RRQ: /* When Server */ recv_tftp_rrq(packet, packet_len); break; case TFTP_WRQ: /* When Server */ recv_tftp_wrq(packet, packet_len); break; case TFTP_DATA: recv_tftp_data(packet, packet_len); break; case TFTP_ACK: recv_tftp_ack(packet, packet_len); break; case TFTP_OACK: recv_tftp_oack(packet, packet_len); break; case TFTP_ERROR: recv_tftp_error(packet, packet_len); break; default: // Unknown Message break; } }
進入該函數后,第一步驗證接收到的數據包的源IP地址,只有當它與服務器IP地址一致時才繼續處理,若不一致則直接返回。接著,從數據包中獲取操作碼(opcode)。根據獲取到的操作碼,調用相應的處理函數:如果是TFTP讀請求(RRQ),則調用 recv_tftp_rrq()函數;若是寫請求(WRQ),則調用recv_tftp_wrq()函數;對于接收到的數據數據包,調用 recv_tftp_data()函數;確認數據包則由recv_tftp_ack()函數處理;OACK數據包由recv_tftp_oack()函數處理;若遇到錯誤數據包,調用recv_tftp_error()函數來解析錯誤代碼和錯誤信息。最后,返回g_progress_state,以此表示當前TFTP操作的狀態。
7運行結果
燒錄例程運行后,首先進行了PHY鏈路檢測,然后是DHCP獲取網絡地址結果,最后打印服務器IP和文本名稱,讀取文本內容,如下圖所示:
8總結
本文講解了如何在 W55MH32芯片上實現 TFTP協議,通過實戰例程詳細展示了使用 TFTP客戶端模式從服務器獲取文本文件的過程,涵蓋 TFTP初始化、發送讀請求、運行協議并處理結果等核心步驟。文章還對 TFTP協議的簡介、特點、應用場景、基本工作流程和報文解析進行了分析,幫助讀者理解其在文件傳輸中的實際應用價值。
下一篇文章將聚焦 SNMP協議,解析其核心原理及在網絡管理中的應用,同時講解如何在相關設備上實現 SNMP功能,敬請期待!
WIZnet是一家無晶圓廠半導體公司,成立于 1998年。產品包括互聯網處理器 iMCU?,它采用 TOE(TCP/IP卸載引擎)技術,基于獨特的專利全硬連線 TCP/IP。iMCU?面向各種應用中的嵌入式互聯網設備。
WIZnet在全球擁有 70多家分銷商,在香港、韓國、美國設有辦事處,提供技術支持和產品營銷。
香港辦事處管理的區域包括:澳大利亞、印度、土耳其、亞洲(韓國和日本除外)。
審核編輯 黃宇
-
以太網
+關注
關注
41文章
5682瀏覽量
176226 -
TFTP
+關注
關注
0文章
23瀏覽量
14548
發布評論請先 登錄
W55MH32高性能以太網單片機開發課件 第十四章 ADC(上篇)

第十四章 ADC(下篇)

第二章 W55MH32 DHCP示例

第五章 W55MH32 UDP示例

第九章 W55MH32 HTTP Server示例

第十章 W55MH32 SNTP示例

第十一章 W55MH32 SMTP示例

第十二章 W55MH32 NetBIOS示例

第十三章 W55MH32 UPnP端口轉發示例

第十五章 W55MH32 SNMP示例

第十六章 W55MH32 PING示例

第十七章 W55MH32 ARP示例

第十八章 W55MH32 FTP_Server示例

第二十六章 W55MH32?上位機搜索和配置示例

評論