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