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

恩智浦i.MX RT600跨界微控制器在功耗、性能和存儲(chǔ)器方面有顯著特點(diǎn)
恩智浦i.MX RT1170開(kāi)創(chuàng)GHz MCU時(shí)代
恩智浦i.MX RT1170在將該系列帶上了更高的層面
i.MX RT開(kāi)發(fā)筆記-01 | 初識(shí) i.MX RT1062 跨界MCU

【044】SylixOS 正式支持 i.MX RT1050平臺(tái)

i.MX RT開(kāi)發(fā)筆記-08 | i.MX RT1062嵌套中斷向量控制器NVIC(按鍵中斷檢測(cè))

RT-Thread & NXP 發(fā)布 i.MX RT 系列 BSP 新框架

如何在i.MX RT1050使用FlexIO模塊模擬XY2-100振鏡通信協(xié)議接口

在i.MX RT10xx使用FlexIO實(shí)現(xiàn)XY2-100振鏡控制協(xié)議

基于NXP微控制器i.MX RT1170的多人體實(shí)時(shí)檢測(cè)算法和系統(tǒng)

使用LwIP協(xié)議棧淺析實(shí)戰(zhàn)分析(i.MX RT)

評(píng)論