单片机
返回首页

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的。


进入单片机查看更多内容>>
相关视频
  • 【TI MSPM0 应用实战】智能小车+工业角度编码器+血氧仪+烟雾探测器!硬核参考设计详解!

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

  • 直播回放: Microchip Timberwolf™ 音频处理器在线研讨会

  • 基于灵动MM32W0系列MCU的指夹血氧仪控制及OTA升级应用方案分享

精选电路图
  • 1瓦四级调频发射机

  • 500W MOS场效应管电源逆变器,12V转110V/220V

  • 12V 转 28V DC-DC 变换器(基于 LM2585)

  • 红外开关

  • 12V转110V/220V 500W逆变器

  • DS1669数字电位器

    相关电子头条文章