STM32CubeIDE STM32F7+FreeRTOS+LWIP ping不通以及丢包问题
2025-10-29 来源:bilibili
和F1、F4系列一样,先使用STM32CubeIDE进行图形配置。
FreeRTOS就不说了,见STM32CubeIDE软件开发文集。

有了操作系统,再配置LWIP。

网卡IC我使用的LAN8742这里就直接选择不用配置了。

这里我PHY Adress根据实际IC硬件地址引脚修改。我也怀疑过是不是我硬件走线的问题导致,我测量了CLK的波形也正常,改低100M为10M也不行,就应该不是走线原因了。

配置LWIP,和F1、F4配置一样,使用静态IP。

配置完成后生成代码,由于我这个网口使用过多次,生成之后我并没有Ping而是直接开始写TCP以及其他代码,写了部分我编译下载(程序已经完成TCP初始化),发现连接不上以及ping不通。
第一个想到的是堆栈不够(很多问题都是堆栈溢出导致的额),加大后没用。然后我开启调试输出,Wireshark抓包查看STM32在PC端ICMP后没有返回,一顿改改改编译下载有时候能ping通几个包,有时候直接ping不通。我怀疑过MAC,怀疑过是不是我TCP程序被我改过来错误了,各种怀疑,能配置的地方都怀疑了一遍。简直了没啥用。
开始出现标题所说问题时在网上搜索,关于F7、H7 LWIP这个问题的文章很少,看了几篇H7ping不通的。F7在此基础上多了CORTEX_M7配置,我怀疑没有配置CPU ICache和CPU DCache导致,参考H7的配置了。

也没用,ping不通。而且问题更严重了,很明显没有配置正确,系列不同MPU Region配置可能不一样。我又去找官方F7的例程果然,参考配置完成。我以为就要成功了,结果还是不行。
后来新建工程重来一遍,写几句编译看能不能行,但使用FreeRTOS+LWIP配置完是能连续Ping的不丢包,当我加入TCP代码并初始化时问题出现了丢包严重且有时候Ping不通,取消写入的TCP初始化也一样。最后逐步定位发现问题所在:
建立了一个结构体:
//用于初始化TCP的参数
typedef struct StructTCP{
uint8_t IP_ADDRESS[4];
uint8_t NETMASK_ADDRESS[4];
uint8_t GATEWAY_ADDRESS[4];
uint16_t TCP_SERVER_PORT;
}StructTCP;
StructTCP myTCP={ //在lwip.c里面覆盖初始化
{192,168,11,112}, //IP
{255,255,255,0}, //子网掩码
{192,168,11,1}, //网关
8000 //端口
};
并在lwip文件中进行IP、子网掩码、网关的覆盖初始化。
void MX_LWIP_Init(void)
{
/* IP addresses initialization */
IP_ADDRESS[0] = 192;
IP_ADDRESS[1] = 168;
IP_ADDRESS[2] = 11;
IP_ADDRESS[3] = 123;
NETMASK_ADDRESS[0] = 255;
NETMASK_ADDRESS[1] = 255;
NETMASK_ADDRESS[2] = 255;
NETMASK_ADDRESS[3] = 0;
GATEWAY_ADDRESS[0] = 192;
GATEWAY_ADDRESS[1] = 168;
GATEWAY_ADDRESS[2] = 11;
GATEWAY_ADDRESS[3] = 1;
/* USER CODE BEGIN IP_ADDRESSES */
IP_ADDRESS[0] = myTCP.IP_ADDRESS[0];
IP_ADDRESS[1] = myTCP.IP_ADDRESS[1];
IP_ADDRESS[2] = myTCP.IP_ADDRESS[2];
IP_ADDRESS[3] = myTCP.IP_ADDRESS[3];
NETMASK_ADDRESS[0] = myTCP.NETMASK_ADDRESS[0];
NETMASK_ADDRESS[1] = myTCP.NETMASK_ADDRESS[1];
NETMASK_ADDRESS[2] = myTCP.NETMASK_ADDRESS[2];
NETMASK_ADDRESS[3] = myTCP.NETMASK_ADDRESS[3];
GATEWAY_ADDRESS[0] = myTCP.GATEWAY_ADDRESS[0];
GATEWAY_ADDRESS[1] = myTCP.GATEWAY_ADDRESS[1];
GATEWAY_ADDRESS[2] = myTCP.GATEWAY_ADDRESS[2];
GATEWAY_ADDRESS[3] = myTCP.GATEWAY_ADDRESS[3];
/* USER CODE END IP_ADDRESSES */
注释掉上面这段这样:
void MX_LWIP_Init(void)
{
/* IP addresses initialization */
IP_ADDRESS[0] = 192;
IP_ADDRESS[1] = 168;
IP_ADDRESS[2] = 11;
IP_ADDRESS[3] = 123;
NETMASK_ADDRESS[0] = 255;
NETMASK_ADDRESS[1] = 255;
NETMASK_ADDRESS[2] = 255;
NETMASK_ADDRESS[3] = 0;
GATEWAY_ADDRESS[0] = 192;
GATEWAY_ADDRESS[1] = 168;
GATEWAY_ADDRESS[2] = 11;
GATEWAY_ADDRESS[3] = 1;
/* USER CODE BEGIN IP_ADDRESSES */
/* USER CODE END IP_ADDRESSES */
没问题,加上有问题。没道理直接修改上面的IP赋值也没问题,我想到了编译器优化问题,调试以及打印覆盖进行赋值数值传递也正确,这还能有啥优化。
之后该优化等级无

再改原代码结构体为数组形式:
uint8_t user_IP_ADDRESS[]={192,168,11,112}; //IP
uint8_t user_NETMASK_ADDRESS[]={255,255,255,0}; //子网掩码
uint8_t user_GATEWAY_ADDRESS[]={192,168,11,1}; //网关
uint16_t user_TCP_SERVER_PORT=8000; //端口
uint8_t user_IP_ADDRESS[]={192,168,11,112}; //IP
uint8_t user_NETMASK_ADDRESS[]={255,255,255,0}; //子网掩码
uint8_t user_GATEWAY_ADDRESS[]={192,168,11,1}; //网关
uint16_t user_TCP_SERVER_PORT=8000; //端口
void MX_LWIP_Init(void)
{
/* IP addresses initialization */
IP_ADDRESS[0] = 192;
IP_ADDRESS[1] = 168;
IP_ADDRESS[2] = 11;
IP_ADDRESS[3] = 123;
NETMASK_ADDRESS[0] = 255;
NETMASK_ADDRESS[1] = 255;
NETMASK_ADDRESS[2] = 255;
NETMASK_ADDRESS[3] = 0;
GATEWAY_ADDRESS[0] = 192;
GATEWAY_ADDRESS[1] = 168;
GATEWAY_ADDRESS[2] = 11;
GATEWAY_ADDRESS[3] = 1;
/* USER CODE BEGIN IP_ADDRESSES */
IP_ADDRESS[0] = user_IP_ADDRESS[0];
IP_ADDRESS[1] = user_IP_ADDRESS[1];
IP_ADDRESS[2] = user_IP_ADDRESS[2];
IP_ADDRESS[3] = user_IP_ADDRESS[3];
NETMASK_ADDRESS[0] = user_NETMASK_ADDRESS[0];
NETMASK_ADDRESS[1] = user_NETMASK_ADDRESS[1];
NETMASK_ADDRESS[2] = user_NETMASK_ADDRESS[2];
NETMASK_ADDRESS[3] = user_NETMASK_ADDRESS[3];
GATEWAY_ADDRESS[0] = user_GATEWAY_ADDRESS[0];
GATEWAY_ADDRESS[1] = user_GATEWAY_ADDRESS[1];
GATEWAY_ADDRESS[2] = user_GATEWAY_ADDRESS[2];
GATEWAY_ADDRESS[3] = user_GATEWAY_ADDRESS[3];
ping正常,TCP功能正常。
优化加一级不行,改回用结构体的方式不行。
问题解决,时间有限暂未深究。
cut-off
提醒,优化等级一大坑遇很多次。若使用软件模拟时许则慎重了。
cut-off
后来在写代码过程中遇见在某些函数中写入if语句就会出现这个问题,以及写while语句等我只好一个个试,非常痛苦,我想到肯定是没有使用CPU Cache的问题,我搜索相关参考配置,有一篇F7的却发现我使用的型号并未有实例当中的提供的配置,尝试了各种各种配置CPU Cache也不行,对手册改了地址,对着官方例程在CubeIDE里面配置也不行。
cut-off
最后在ST官方看见一个17年的终于解决了不使用CPU Cache配置网口这个问题:

在stm32f7x_hal_eth.c文件里搜索以下代码:
if (((heth->Instance)->DMASR & ETH_DMASR_TBUS) != (uint32_t)RESET)
然后在这句代码前加入
__DSB();
这段代码,就OK了,问题解决就几个字。为什么呢?看看这个函数的作用吧,__DSB();
有些CPU的时钟太快,快于中断使用的时钟,就会出现清除中断标志的动作还未完成,CPU就又一次重新进入同一个中断处理函数,导致死循环,__DSB() 指令的作用就是避免上述情况的发生。
理解了为什么F4、F1都可以就到了F7就非要用CPU Cache了。时间有限要用这里就先加这个函数用了,后面再看看怎么使用CPU Cache的。
- STM32CubeIDE使用说明_3 —— 实时调试
- STM32CubeIDE软件下载安装、汉化、主题修改、固件下载地址设置
- STM32CubeIDE优化等级问题
- STM32 stm32cubeide 定时器
- 动量轮平衡自行车(五)——STM32CubeIDE+PID调参
- STM32CubeIDE嵌入式开发入门到入坟-软件篇-2、新建工程与GPIO(IO)口配置
- 动量轮平衡自行车(一)——STM32CubeIDE+MPU6050调试
- STM32集成开发工具 | STM32CubeIDE介绍、下载、安装和使用教程
- STM32CubeIDE实战教程:使用STM32和DRV8825驱动42步步进电机的保姆级指南
- 一段有关MPU配置代码的几个小疑问
- 六大全新产品系列推出,MCX A微控制器家族迎来创新
- 意法半导体全新STM32C5系列,重新定义入门级微控制器性能与价值,赋能万千智能设备
- 从控制到系统:TI利用边缘AI重塑嵌入式MCU的边界
- 模组复用与整机重测在SRRC、CCC、CTA/NAL认证中的实践操作指南
- 有源晶振与无源晶振的六大区别详解
- 英飞凌持续巩固全球微控制器市场领导地位
- 使用 Keil Studio for Visual Studio Code开发 STM32 设备
- 蓝牙信道探测技术原理与开发套件实践
- LoRa、LoRaWAN、NB-IoT与4G DTU技术对比及工业无线方案选型分析
- Microchip 推出生产就绪型全栈边缘 AI 解决方案,赋能MCU和MPU实现 智能实时决策




