STM32H7+CUBE+ETH+LWIP配置及设置

ETH

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
配置EHT_RST引脚
在这里插入图片描述

LWIP

在这里插入图片描述
在这里插入图片描述
注意一定要把LWIP_NETIF_LINK_CALLBACK选上,不然连接状态改变不能进入拔下或者插入网线回调函数,里面做一点自己的事情
在这里插入图片描述
LAN8742
在这里插入图片描述

MPU

Lwip使用DMA传递信息,对应的DMA内存定义在sram中。H7的sram分为好几段,高速段为cpu独享,通俗点说就是这一段允许用户编写的程序使用,但是不允许DMA使用。所以为DMA定义的内存或者数组要避开这一段。另外Lwip使用DMA时存在交互存取问题,避开这一段后,也不能让cpu像使用普通cache那样乱序使用,否则将可能出现严重问题。很多人用F7、H7和Lwip协议栈都出现ping不通的现象,都是内存管理问题。怎样管理??需要使用内存守护单元MPU。

使用CubeMX配置MPU,最多可以管理16段。为lwip配置,管理两段即可。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

MPU设定总结(非操作步骤)
总结一下这样做的原因与目的:
(1)Lwip不被允许使用cpu专用的高速L1缓存(DTCM),只能用D2 Sram区域;
(2)cpu可以无序访问cache,为防止这种情况,Lwip的DMA段必须是device类型或者Strongly-ordered类型,保证有序;
(3)通过MPU配置这段cache,其中一段允许share、允许buffer,长度为256Byte,放TXRX交互存取头;另外一段不share,不buffer,不cache;长度32k。

这里面有很多名词比如share/buffer/cache,如果需要详细了解,可以参考另外一篇博文:
STM32H7的Cache与Bufferhttps://blog.csdn.net/monei3525/article/details/109166516

以下两篇对于这个问题原理与配置过程有详细描述:
https://community.st.com/s/article/FAQ-Ethernet-not-working-on-STM32H7x3
https://community.st.com/s/article/How-to-create-project-for-STM32H7-with-Ethernet-and-LwIP-stack-working
在这里插入图片描述
MPU选项含义(非操作步骤)
cubeMX里面配置TEX、C、B,三者搭配。

https://www.stmicroelectronics.com.cn/resource/en/application_note/DM00272912-.pdf

在这里插入图片描述

Access permission被定义为3,即Full access。

在这里插入图片描述

经过上面的配置,编译下载,不出意外不用写任何代码就可以ping通了。

好了,可以进行下一步!

Lwip协议栈TCP保活(KeepAlive)设定

万事具备了么?no!

以上只解决了异常自动重连的问题,并不等于协议栈具备检测异常的能力。即H7必须知道网线是在什么时候被拔掉。

有很多博客都提到KeepAlive的开启方法,但都是详细说明怎样打开,打开了该怎么用就没说。。。

由于tcp是可靠连接,有数据往来的时候能够检测异常,需要解决的是无数据检测。这就要用到TCP协议的KeepAlive功能,原理就是在空闲的时候,以一定的频率发空数据包给服务器,服务器收到后答复一个数据包,说白了又把空闲段给变成有数据往复状态了。TCP协议栈包含KeepAlive,lwip协议栈这部分也没少,启用几个宏即可自动进行收发。设定方法为:在lwipopts.h后面加入

#define  LWIP_TCP_KEEPALIVE       1             //激活keepalive
#define  TCP_KEEPIDLE_DEFAULT     2000UL        //2秒内连接双方都无数据,则发起保活探测
#define  TCP_KEEPINTVL_DEFAULT    1000UL        //1秒发送一次保活探测
#define  TCP_KEEPCNT_DEFAULT      3UL           //3次保活探测无数据则进入错误回调函数

tcpecho.c中实例化netconn后,为其tcp成员加入SPF_KEEPALIVE属性。

xNetConn->pcb.tcp->so_options |= SOF_KEEPALIVE; //保活设定,实际上是tcp的一个属性选项

这样就能实时检测连接状态了。使用wireshark抓取数据是下图的样子,里面可以看到空闲时段交互的keepalive数据包。
电脑IP :192.168.0.99
单片机IP :192.168.0.80
在这里插入图片描述
自动化流程为:
拔掉网线------进入回调函数销毁tcp资源------主程序while循环连接出错------主程序销毁netconn资源------主程序实例化新的netconn资源------再次连接
如此往复…

用STM32CubeMX 生成了一个包含 EHT ,Lwip 的项目,调试一直不正常,经仔细检查存在以下问题:
1.硬件采用了LAN8720A ,但是STM32CubeMX 生成的是LAN8742A的代码,必须根据硬件连接更改地址。

解决办法: 在 …Src ethernetif.c 修改如下:

heth.Instance = ETH;

heth.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;

// heth.Init.PhyAddress = LAN8742A_PHY_ADDRESS;

heth.Init.PhyAddress = LAN8720A_PHY_ADDRESS; //modify by kmsmg,LAN8720A_PHY_ADDRESS=0,LAN8742A_PHY_ADDRESS=1
2.初始化时必须对LAN8720A 进行硬件复位。

解决办法:

分配一个 GPIO 连接LAN8720A的复位端,在 …Src ethernetif.c 修改如下:

heth.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;

heth.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;

/* USER CODE BEGIN MACADDRESS */

/* USER CODE END MACADDRESS */

LAN8720_RESET();// modify by kmsmg

hal_eth_init_status = HAL_ETH_Init(&heth);

............

//-----------------------------------------------

void LAN8720_RESET(void)

{
HAL_GPIO_WritePin(GPIOD, GP_EHT_REST_Pin, GPIO_PIN_RESET);

HAL_Delay(55);

HAL_GPIO_WritePin(GPIOD, GP_EHT_REST_Pin, GPIO_PIN_SET);

}

  • 9
    点赞
  • 79
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值