工作筆記-----lwip網絡任務初始化問題排查

工作筆記-----基于FreeRTOS的lwIP網絡任務初始化問題排查

@@ Author:明月清了個風

@@ Date: 2025/8/10

@@ PS:新項目中在STMF7開發板上基于freeRTOS和lwIP開發網口相關任務,開發過程中遇到了網口無法連接的問題,進行了一系列的排查,找到了問題所在,基本將整個lwIP的啟動流程詳細的看了一遍,現將整個排查過程記錄一下,以供參考.

內容結構如下:

  1. 問題現象及最終解決方法
  2. lwIP啟動流程的簡單介紹(細節的后面單獨寫一篇吧,涉及的內容太多了,這里只把主要的調用過程寫一下)
  3. 排查問題過程中嘗試的方法
    4.題外----一個仍然沒有想通的問題

一.問題現象及最終解決方法

首先給出問題的現象以及最后找到的問題根源:

現象:初始化lwip后,創建了基于lwIP接口的網絡任務,任務正常運行,但無法連通,阻塞在accept_err = netconn_accept(conn, &newconn);接收消息這一步。主機ping MCU,網口黃色指示燈對應閃爍,表明物理傳輸層已連通。

解決方法:phy地址設置錯誤,CubeMX生成的代碼默認設置為1,需根據網口芯片的實際電路連接進行設置,我這里是LAN8742A,phy地址引腳接地,在low_level_init()函數中修改對應賦值語句或者修改宏定義LAN8742A_PHY_ADDRESS,在文件stm32f7xx_hal_conf.h中。注意并不一定完全和你的位置一樣,需要自己找到這個設置在哪里,下面有啟動流程講解,幫助你找到它。

二.lwIP啟動流程

在排查問題的過程中,基本將lwIP啟動涉及到的源碼看了一遍,整理后以供參考。(使用的版本應該比較新,且已經進行過修改,可能會有一些不一樣)

由CubeMX導出的代碼中會有一個MX_LWIP_Init()函數,這個函數完成了lwIP的初始化,函數的主要調用棧如下:(調試基本就在這些函數里去調就行,基本覆蓋了)

MX_LWIP_Init()|---> tcpip_init()|---> lwip_init()|---> sys_thread_new(tcpip_thread)|---> netif_add()|---> ethernetif_init()|---> low_level_init()|---> HAL_EHT_Init()|---> HAL_ETH_MspInit()|---> HAL_ETH_DMATxDescListInit()|---> HAL_ETH_DMARxDescListInit()|---> osThreadCreate()----ethernetif_input|---> netif_set_default()|---> netif_set_up() / netif_set_down()|---> netif_set_link_callback()
  1. tcpip_init()函數

    該函數中主要進行了兩個步驟:

    • 首先調用了lwip_init(),這個函數完成了lwIP各功能組件的內核初始化,比如lwIP的內存管理,和外部環境基本無關。

    • 然后創建了tcpip_thread任務,該任務會一直嘗試在tcpic_mbox中獲取消息(可以不用知道這個是什么,只要知道他在等待消息就行)

  2. netif_add()函數

    這一句的源碼為netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &tcpip_input);

    這個函數非常長,用于完成虛擬網卡的初始化,傳入的參數如下:

netif_add(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input)
```

也就是虛擬網卡`netif`,IP地址,子網掩碼,網關,虛擬網卡初始化函數,網卡輸入函數。這個函數中會對`netif`結構體成員進行初始化,并執行傳入的`init`函數,也就是`ethernetif_init`函數,接著他會調用`low_level_init()`函數,這個函數完成了lwIP所需的硬件初始化過程,也就是硬件網口的初始化,我的是LAN8742A,根據函數的調用棧可以找到`HAL_ETH_MspInit()`函數,這個函數中可以看到網口相關的GPIO被初始化,然后又開啟了DMA收發以及網絡中斷。在`low_level_init()`函數中還創建了一個任務`ethernetif_input`,這個任務非常短,源碼如下:```c
void ethernetif_input( void const * argument )
{struct pbuf *p;struct netif *netif = (struct netif *) argument;for( ;; ){if (osSemaphoreWait( s_xSemaphore, TIME_WAITING_FOR_INPUT)==osOK){do{p = low_level_input( netif );if (p != NULL){if (netif->input( p, netif) != ERR_OK ){pbuf_free(p);}}}while(p!=NULL);}}
}
```他會阻塞等待`s_xSemaphore`信號量,該信號量在`HAL_ETH_IRQHandler()`中斷服務函數中釋放,接受到消息后,通過`low_level_input()`函數處理并返回。
  1. netif_set_default()函數

    這個函數很短,將netif設置為默認網口

  2. 然后會根據netif_is_link_up(&gnetif)的值來選擇執行那個函數,這個函數判斷是phy芯片的bit2是否為1,如果為1,表示硬件上已經初始化成功,那么調用netif_set_up(),否則調用netif_set_down()

  3. netif_set_link_callback()函數設置了一個回調函數,當網絡連接狀態發生改變時會被執行,主要做硬件上的檢查和處理

  4. 如果你使用的是官方的例程,會發現后面還創建了一個ethernetif_set_link(),任務,該任務是用來檢測連接狀態的,也是通過HAL_ETH_ReadPHYRegister(&EthHandle, PHY_MISR, &regvalue);讀取PHY芯片寄存器的相關位來判斷是否連接。

三.排查問題過程中嘗試的方法(以下方法先后順序不一定啊,試的太多了,我也有點忘了😢)

  1. 首先嘗試ping MCU地址,看是否ping通,如果無法ping通,查看電腦IP是否與MCU IP在同一網段,并且對應IP沒有被占用,并查看子網掩碼,網關的設置是否正確。

  2. 硬件檢查,觀察網口連接處指示燈,綠燈表示物理層連接正常,黃燈表示有數據收發,并判斷PHY芯片是否初始化正確,也就是上面的函數中的HAL_ETH_Init()中的初始化,這里面需要注意的有:引腳是否對應,PHY芯片地址和原理圖對應(這里就是我出的問題)。

  3. 嘗試調整lwIP協議棧的初始化時序,從上面的啟動流程可以看出,lwIP的啟動中會創建多個處理任務,需要保證你的任務和這些任務之間沒有沖突

  4. 電腦cmd中執行arp -a看有沒有板子的IP和MAC地址,如果沒有就是物理層和驅動的問題,我也是在這定位到了是驅動有問題,重新回去看硬件配置代碼的。

  5. arp -a中看不到板子的IP后,確定是網絡鏈路層的問題,在low_level_output()函數中添加測試代碼,初始化串口后在不同位置輸出點東西就行;

  6. ethernetif_update_config()函數中添加以下代碼看phy芯片啟動狀態

    // 在 ethernetif.c 中添加
    void ethernetif_update_config(struct netif *netif) {uint32_t phyreg;HAL_ETH_ReadPHYRegister(&heth, PHY_BSR, &phyreg);if(phyreg & PHY_LINKED_STATUS) {netif_set_link_up(netif);printf("PHY Link UP\n");} else {netif_set_link_down(netif);printf("PHY Link DOWN\n");}
    }// 在初始化中注冊定時器,就是需要你定期查詢,可以通過自己的方式實現,不一定要和這里一樣
    void ethernet_link_thread(void *arg) {for(;;) {ethernetif_update_config(&gnetif);osDelay(500);}
    }
    
  7. 在lwIP啟動流程后,也就是進入開啟任務調度前,強制軟復位PHY芯片,參考代碼如下,

    
    HAL_ETH_Start(&heth);
    osDelay(100);// 軟復位PHY
    HAL_ETH_WritePHYRegister(&heth, PHY_BCR, PHY_RESET);
    osDelay(100);// 重新配置PHY
    uint32_t phyreg;
    HAL_ETH_ReadPHYRegister(&heth, PHY_BCR, &phyreg);
    phyreg |= PHY_AUTONEGOTIATION;
    HAL_ETH_WritePHYRegister(&heth, PHY_BCR, phyreg);
    printf("PHY reinitialized!\n");
    
  8. 如果電腦端ping的時候黃燈會對應閃,那么說明物理層正常,那么在low_level_input()函數中添加調試代碼,也是隨便輸出點什么,看看有沒有進這個函數,然后看調用路徑一點點加調試代碼

  9. 看以太網中斷void ETH_IRQHandler(void)有沒有進去,加調試信息或者keil直接調試也行

嘗試上面的方法應該從硬件到軟件都涉及到了,希望對你有幫助,當然還可以使用物理方法,示波器去抓網口的波形,不過這個不一定都有,這里就說軟件上我試了哪些。

題外

這個還有一個坑我沒有解決,在一開始沒有配置對PHY芯片地址的時候,竟然有一段時間成功連上了TCP,并且能夠正確收發數據,這也導致我以為硬件配置沒有問題,后續排查了很久,發現還是硬件配置的問題,但是還是不知道為什么會出現這個情況,也沒有復現出來過,很不理解.

猜測可能是和上電時序或者電平干擾有關,希望下次能夠復現以下.

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/918349.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/918349.shtml
英文地址,請注明出處:http://en.pswp.cn/news/918349.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Kotlin動態代理池+無頭瀏覽器協程化實戰

我看到了很多作者展示了Kotlin在爬蟲領域的各種高級用法。我需要從中提取出最"牛叉"的操作,也就是那些充分利用Kotlin語言特性,使爬蟲開發更高效、更強大的技巧。 我準備用幾個主要部分來組織內容,每個部分會突出Kotlin特有的"…

PDF編輯工具,免費OCR識別表單

軟件介紹 今天推薦一款功能全面的PDF編輯工具——PDF XChange Editor,支持文本、圖片編輯及OCR識別,還能一鍵提取表單信息,滿足多樣化PDF處理需求。 軟件優勢 該軟件完全免費,下載后雙擊圖標即可直接運行,無需安裝&…

OpenEnler等Linux系統中安裝git工具的方法

在歐拉系統中安裝 Git使用 yum 包管理器安裝(推薦,適用于歐拉等基于 RPM 的系統):# 切換到 root 用戶(若當前不是) su - root# 安裝 Git yum install -y git驗證安裝是否成功:git --version若輸…

UE5 第三人稱視角如何設置camera移動旋轉

“奇怪,這blog不支持md格式嗎”## 第1步:設置玩家Pawn 創建一個藍圖類,繼承自 Pawn,在游戲模式(Game Mode)中,將這個Pawn設置為默認 在組件面板中,添加一個 Spring Arm 組件 在組件面…

OpenCV 入門教程:開啟計算機視覺之旅

目錄 一、引言? 二、OpenCV 簡介 ?(一)什么是 OpenCV (二)OpenCV 的特點與優勢 (三)OpenCV 的應用領域 三、環境搭建 (一)安裝 OpenCV 庫? 四、OpenCV 基礎操作 &#xf…

C++高頻知識點(十九)

文章目錄91. TCP斷開連接的時候為什么必須4次而不是3次?92. 為什么要區分用戶態和內核態?93. 說說編寫socket套接字的步驟1. 服務器端編寫步驟1.1 創建套接字1.2 綁定套接字1.3 監聽連接1.4 接受連接1.5 數據傳輸1.6 關閉套接字2. 客戶端編寫步驟2.1 創建…

一個基于 epoll 實現的多路復用 TCP 服務器程序,相比 select 和 poll 具有更高的效率

/*5 - 使用epoll實現多路復用 */ #include <stdio.h> // 標準輸入輸出函數庫 #include <stdlib.h> // 標準庫函數&#xff0c;包含exit等 #include <string.h> // 字符串處理函數 #include <unistd.h> // Unix標準函…

元數據管理與數據治理平臺:Apache Atlas 通知和業務元數據 Notifications And Business Metadata

文中內容僅限技術學習與代碼實踐參考&#xff0c;市場存在不確定性&#xff0c;技術分析需謹慎驗證&#xff0c;不構成任何投資建議。Apache Atlas 框架是一套可擴展的核心基礎治理服務&#xff0c;使企業能夠有效、高效地滿足 Hadoop 中的合規性要求&#xff0c;并支持與整個企…

rem:CSS中的相對長度單位

&#x1f90d; 前端開發工程師、技術日更博主、已過CET6 &#x1f368; 阿珊和她的貓_CSDN博客專家、23年度博客之星前端領域TOP1 &#x1f560; 牛客高級專題作者、打造專欄《前端面試必備》 、《2024面試高頻手撕題》、《前端求職突破計劃》 &#x1f35a; 藍橋云課簽約作者、…

【10】C#實戰篇——C# 調用 C++ dll(C++ 導出函數、C++導出類)

文章目錄1 導出C 類函數 、導出 C函數1.1 .h文件1.2 .cpp 文件1.3 C# 調用2 C與C#數據類型對應3 保姆級教程&#xff08;項目搭建、代碼、調用&#xff0c;圖文并茂&#xff09;1 導出C 類函數 、導出 C函數 C 生成動態庫.dll 詳細教程&#xff1a; C 生成動態庫.dll 及 C調用…

Flutter 與 Android NDK 集成實戰:實現高性能原生功能

Flutter 與 NDK 集成實現 Flutter 可以通過 Platform Channels 與原生代碼&#xff08;包括使用 NDK 編寫的 C/C 代碼&#xff09;進行交互。以下是實現 Flutter 與 NDK 集成的步驟&#xff1a; 基本步驟 1. 創建 Flutter 項目 flutter create flutter_ndk_example cd flutter_…

elementui cascader 遠程加載請求使用 選擇單項等

背景&#xff1a;小程序與后端使用自定義表單渲染視圖。發現若沒有全選&#xff08;如&#xff1a;省市縣全部選擇&#xff0c;指定的市3級&#xff09;在pc端就會無法渲染出已經選擇的區縣名稱。 解決方案&#xff1a;參考官方文檔&#xff0c;設置屬性可獨立勾選element ui c…

Unity WebGL打包后啟動方法,本地方法

引言&#xff1a;常見WebGL開啟方法常需要重新打包點擊Build and Run或者將游戲放到Unity的云服務器上&#xff0c;作為開發者而言這兩個方案一個為了開啟再次打包&#xff0c;另一個直接放到了公開環境都不太合適。所以我們需要一個能在本地開啟測試的WebGL的方法。 解決方案 …

安全引導功能及ATF的啟動過程(五)

安全引導功能及ATF的啟動過程&#xff08;五&#xff09; ATF中bl32的啟動 bl31中的runtime_svc_init函數會初始化OP-TEE對應的服務&#xff0c;通過調用該服務項的初始化函數來完成OP-TEE的啟動。對于OP-TEE的服務項會通過DECLARE_RT_SVC宏在編譯時被存放到rt_svc_des段中。該…

Numpy科學計算與數據分析:Numpy入門之多平臺安裝與基礎環境配置

Numpy環境搭建與基礎操作 學習目標 本課程將指導學員在Windows、macOS和Linux三種操作系統上安裝Numpy&#xff0c;并配置開發環境&#xff0c;包括使用Jupyter Notebook和Spyder等IDE的基本操作。通過本課程的學習&#xff0c;學員將能夠獨立搭建Numpy開發環境&#xff0c;并…

內存溢出的原因有哪些,如何排查線上問題?

1. java.lang.OutOfMemoryError: ......java heap space..... 堆棧溢出&#xff0c;代碼問題的可能性極大 2. java.lang.OutOfMemoryError: GC over head limit exceeded 系統處于高頻的GC狀態&#xff0c;而且回收的效果依然 不佳的情況&#xff0c;就會開始報這個錯誤&…

Cesium 無人機視角飛行漫游,截屏

1.實現Cesium模擬無人機離屏渲染&#xff0c;無人機視角飛行漫游。視錐體顯示 具體效果如下地址&#xff1a; 【CESIUM無人機視角飛行截屏】 https://www.bilibili.com/video/BV1zQ89zGE14/?share_sourcecopy_web&vd_source8239ec37df07d6a5d56c9ece00146783

vscode 打開設置

目錄 方法 1&#xff08;快捷鍵&#xff09;&#xff1a; 方法2&#xff0c;界面操作&#xff0c;有時沒有 方法 1&#xff08;快捷鍵&#xff09;&#xff1a; 按下&#xff1a;Cmd Shift P 輸入并選擇&#xff1a;Preferences: Open Settings (JSON) 方法2&#xff0c;…

繁花深處:花店建設的時代意義與多元應用—仙盟創夢IDE

花店當第一縷晨光透過花店的玻璃窗&#xff0c;落在帶著露水的玫瑰花瓣上時&#xff0c;這個空間便不再只是商品交易的場所。花店作為城市肌理中充滿生命力的細胞&#xff0c;承載著遠比銷售鮮花更豐富的社會意義。在快節奏的現代生活中&#xff0c;一束鮮花的綻放不僅是自然之…

AtomicStampedReference解決方案

1、通過引入版本戳(stamp)機制解決ABA問題&#xff1a; 每次修改時遞增版本號執行CAS時同時檢查值和版本號即使值相同但版本不同&#xff0c;操作也會失敗2、具體代碼實現 import java.util.concurrent.atomic.AtomicStampedReference;public class AtomicStampedReferenceDemo…