在i.MX RT微控制器上初始化LWIP協議棧是一個復雜但有趣的過程,它涉及多個步驟和關鍵組件的配置。以下是該初始化流程的介紹:
LWIP協議棧與開發平臺簡介
LWIP(Light Weight IP),是一種輕量化且開源的TCP/IP協議棧。LwIP在有限的RAM和ROM條件下,實現了一個完整的TCP/IP 協議棧,并且LwIP在MCU平臺上得到了非常廣泛的應用。此外,它既可以基于操作系統運行,也可以在裸機情況下運行。
TCP/IP協議棧的模型結構如下圖所示:
本篇文章基于i.MX RT四位數跨界MCU平臺,RT四位數跨界MCU最高主頻可達1Ghz,并且搭載了很多性能強勁的外設,廣泛的應用于工業,自動化,IoT,消費電子等領域,并且NXP官方提供免費的IDE,開發工具以及SDK軟件包等,為開發者提供了全面的支持。
Ethernet MAC與PHY之間通過以太網接口連接,常見的接口有RMII,MII等。與此同時,RT四位數上的EthernetMAC外設也配備了PHY管理接口,可通過MDC MDIO來實現PHY相關寄存器的讀寫。
此處以RT1060舉例,在RT1060 EVK上默認使用的是RMII以太網接口,對照原理圖完成RMII相關管腳的初始化。
MDC,MDIO初始化:
PHYINIT以及RESET管腳初始化,配成GPIO輸出即可:
RMII的TX_CLK由MCU提供,因此要將TX_CLK的方向配置為輸出:
至此,以太網接口,PHY管理接口等硬件配置基本初始化完成。
LWIP時基初始化與超時事件注冊
在LWIP中,經常會進行一些超時判定,例如ARP緩存表的時間管理,IP分片數據報的重裝等待超時等等,并且LwIP也提供了超時事件注冊函數sys_timeout,在RT1060官方SDK的ping bm demo中就是通過超時事件來發送ping請求。
而超時的判定需要一個時基,MCU中一般會用系統滴答定時器來作為時基,且時間間隔設置為1ms并開啟中斷。每一次進中斷都會將當前時間加1。設置滴答定時器的代碼如下圖所示。
在LWIP協議棧初始化時,也需要注冊一些超時事件,通過調用sys_timeout函數,該函數中又會調用sys_timeout_abs函數。
在sys_timeout_abs函數中會計算出超時事件即將超時的時間,并且根據超時時間將這些超時事件連接成一個鏈表,如下圖所示。當超時發生時就會調用對應的處理函數。
SDK中會把需要注冊的超時事件都放在一個數組中,在初始化時調用注冊函數去一個個注冊這些超時事件。超時事件數組如下圖所示。
LWIP內存堆內存池初始化
在LwIP中,內存分配策略一般有兩種,一種是分配固定大小的內存塊。如TCP 首部、UDP 首部,IP 首部,以太網首部等都是固定的數據結構,其大小就是一個固定的值,那么我們就能采用這種方式分配這些固定大小的內存空間,這樣子的效率就會大大提高。另一種是利用內存堆進行動態分配,屬于可變長度的內存塊。
在LWIP協議棧初始化時一定要對這兩種內存分配方式進行初始化,方便后續協議棧進行相關內存分配。內存堆初始化代碼如下所示,其中LWIP_RAM_HEAP_POINTER實際上就是分配的內存堆數組首地址。
內存堆數組大小為想要分配的內存堆大小對齊后再加上兩倍的mem結構體對齊后的大小,mem結構體中會存放一些內存堆相關管理信息,宏定義如下圖所示。
不難看出在內存堆初始化代碼中實際上就是初始化了兩個mem結構體。第一個mem結構體在內存堆起始地址處,next成員為MEM_SIZE_ALIGNED, prev和used成員皆初始化為0。
第二個mem結構體ram_end設置為內存堆首地址偏移MEM_SIZE_ALIGNED處,used變量設置為1,next和prev皆指向偏移MEM_SIZE_ALIGNED的位置。
內存池初始化函數為memp_init,如下圖所示。它使用輪詢的方式調用memp_init_pool去初始化每一類內存池,memp_pools數組中存放了初始化過的memp結構體。
在memp_init_pool中會根據初始化過的memp結構體中的一些參數,比如下圖中所示的num,num代表有多少個內存塊,memp_init_pool中會根據num將內存塊連接成單鏈表。
網卡掛載及初始化
調用netif_add來掛載網卡,netif結構體是抽象出來的網卡結構體,IP地址,網關,子網掩碼等都會保存在該結構體中。網卡初始化函數也會作為參數之一傳入netif_add函數,并在netif_add函數中被調用。在該初始化函數中最終會完成以下幾部分初始化:
1.以太網相關數據結構的初始化,包括rx_buffer,tx_buffer, buffer descriptor,buffer descriptor ring。初始化這些數據結構,以便在接收發送以太網數據時使用。
2.phy的初始化,初始化以太網外設中的MDC MDIO,如下圖所示。
通過MDC MDIO去操作PHY相關的寄存器,例如去配置PHY的百兆千兆模式,軟復位PHY,檢查自動協商,連接狀態以及配置LED等等。確保PHY工作在想要的狀態下,部分初始化PHY的代碼如下所示。
3.設置netif相關參數,例如MAC地址長度,MTU,flags,以及網絡接口層輸入,網絡接口層輸出函數等。
4.初始化Ethernet MAC外設,去配置以太網外設中的接口類型,速度,工作模式,中斷等等。部分配置代碼如下所示。
LWIP不同API初始化
在完成上述初始化流程之后,還需要調用一些LwIP提供的API,LwIP常用的API有RAW API, Socket API, NETCONN API三種,前者是不需要基于操作系統的,后兩者需要基于操作系統運行。這三種API在初始化時也是不同的,Socket API和NETCONN API類似,此處以RT1060 SDK中的ping demo來舉例說明。
首先是RAW API,在raw.c中定義了一個raw_pcb結構體,初始化時會定義一個新的raw_pcb結構體并插入raw_pcbs鏈表。并且給新定義的raw_pcb賦初值,如下圖所示,通過raw_recv綁定ping_recv函數。通過raw_bind綁定IP地址,并且注冊一個超時事件,超時時就調用ping_timeout函數,參數為ping_pcb。在ping_timeout函數中會發送ping請求。
當LWIP跑在操作系統上時,LWIP協議棧是作為一個獨立線程存在的。因此,在初始化時要創建tcpip_thread線程。用戶代碼與tcpip_thread線程之間是通過郵箱進行數據的交互的。因此,在初始化時也需要創建一個郵箱。
在使用Socket API時,首先要調用lwip_socket函數向內核申請一個套接字,然后調用setsockopt設置套接字的一些選項。接著就可以調用lwip_sendto函數去發送數據包。調用recvfrom函數接收數據包。
至此,在i.MX RT使用LwIP協議棧初始化流程介紹完畢,通過理解和實踐這些步驟,開發者可以在i.MX RT微控制器上成功初始化LWIP協議棧,并實現網絡通信功能。
總體看來,整個初始化流程還是相對復雜的,這個過程不僅涉及硬件驅動編程和TCP/IP協議棧的配置,還需要對內存管理、中斷處理、超時檢查等關鍵知識點有深入的理解。感興趣的讀者可以下載RT四位數的SDK深入了解。
-
微控制器
+關注
關注
48文章
7649瀏覽量
152107 -
TCP
+關注
關注
8文章
1378瀏覽量
79301 -
LwIP
+關注
關注
2文章
88瀏覽量
27361 -
協議棧
+關注
關注
2文章
144瀏覽量
33702
原文標題:在i.MX RT使用LWIP協議棧的初始化流程
文章出處:【微信號:NXP_SMART_HARDWARE,微信公眾號:恩智浦MCU加油站】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論