工作笔记-----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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈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…