【LWIP】STM32H743/750+CubeMX+AC5/AC6+裸机/FreeRTOS+(ETH)LWIP+DP83848/LAN8720/42——创建可ping模板

        花了快一周,执迷于用AC6和H7,想先顺手配好个可ping的CubeMX模板,然后就正常学习lwip,结果一直ping不通,看了基本全网的资料,很少有看到全面的,最后是参考基于STM32CubeMX创建的STM32H743+DP83848+LWIP网络通信程序调试_20221127算是胎教级教程了_h743 cubemx lwip-CSDN博客

        把DP83848的驱动改好了,然后先把AC5的ping通了,后面重新搞AC6版的,一下子就想通了!!后面会全部补齐,劳烦点赞与关注~


目录

我的原文链接(更新较快)

开发环境:

本文基于CubeMX生成的PHY驱动文件、ETH、LWIP来改。

注意事项:

一、裸机工程开发:AC5+LAN8720/8742

参考资料:

3.1. CubeMX配置:

3.1.1. 常规配置(RCC、时钟树、晶振):

3.1.2. 调试串口:

3.1.3. 配置ETH:以太网 DMA 描述符地址、缓冲区地址/大小

3.1.4. GPIO配置:

3.1.4.1. ETH 的 GPIO:配置高速

3.1.4.2. PHY 芯片的复位 GPIO:(有些 PHY 芯片不一定要)

3.1.5. 配置LwIP:(很重要)

General Settings:常规设置

Key Options:系统项设置

LWIP堆栈和内存池设置:(重要)

网卡设置:

选择PHY芯片:

3.1.6. 配置MPU(Cache):(很重要)

3.2. 工程配置:选择程序主 SRAM

3.3. 工程编写:

3.3.1. 串口调试:

3.3.2. 使能 D2SRAM3 时钟:

3.3.3. 在 low_level_init 函数中添加 PHY 复位代码:

3.3.4. 添加MX_LWIP_Process():此时下载即可 ping

二、裸机工程开发:PHY 芯片改成 DP83848

4.1. DP83848 宏定义

4.2. DP83848 相关函数:

4.3. 修改位置:

4.3.1. DP83848_Init(&LAN8742)替换ethernetif.c文件中的LAN8742_Init(&LAN8742)

4.3.2. DP83848_GetLinkState(&LAN8742)替换ethernetif.c文件中的LAN8742_GetLinkState(&LAN8742)

三、裸机工程开发:转由AC6 编译

5.1. cc.h 中修改:

5.2. lwip.h 中添加:

5.3. ethernetif.c 中修改:这里仅改了 MDK 环境下(H7 必须改)

四、FreeRTOS - 开发部分

调试部分(如果出现问题/不可ping


我的原文链接(更新较快)

《【开发】2.1、H7/H743/H750 - lwIP移植(裸机/操作系统)》

开发环境:

  • CubeMX:6.12.x
  • 芯片:H743/H750
  • H7-HAL库:FW_H7 V1.11.2
  • PHY模块:LAN8720/8742,DP83848

本文基于CubeMX生成的PHY驱动文件、ETH、LWIP来改。

        后面有时间会弄,纯自己移植(非生成)/MDK RTE生成的模板

注意事项:

  • 芯片:大部分H7照着做即可,H723有区别
  • 待补充

一、裸机工程开发:AC5+LAN8742

参考资料:

STM32H723+Lwip+ETH+CUBE 完整配置(排了巨多坑!)_stm32h723 iwip +tcpcilent-CSDN博客

STM32H7+CUBE+ETH+LWIP配置及设置_stm32h7 lwip-CSDN博客

STM32H7+LAN8720A之ETH与LWIP配置问题(End)_stm32h7 lan8720a-CSDN博客

【LWIP】(补充)STM32H743(M7内核)CubeMX配置LWIP并ping通_h743 lwip-CSDN博客

终于搞定STM32H743网络了,分享调试经验及注意事项 - STM32 - 论坛-意法半导体STM32/STM8技术社区

这个可能详细一点

手把手教你用STM32cube调通STM32H743以太网通信并实现TCP客户端_stm32h723 tcp客户端-CSDN博客

以上还没有可以直接用的

STM32H743(M7内核)CubeMX配置LWIP并ping通」2024年9月10日_stm32h743 lwip-CSDN博客

最新的,可用的资料,实测H743没什么用

STM32H743ZIT6+LWIP+MPU+CUBEMX,通过stm32cubemx完成初始化,ping包亲测没问题,带解释!!_stm32h7 lwip-CSDN博客

STM32H723ZGT6+LWIP+CUBEMX完成初始化,ping包亲测没问题_h723 ram加载-CSDN博客

11月22日

stm32cubemx版本升级后导致stm32h743芯片LWIP无法Ping通_stm32h743 eth 8720 cubemx-CSDN博客

STM32H7LWIP,过滤,配置opt,调整rxbuffer大小等_lwip+stm32h7怎么提高发送速度-CSDN博客

STM32H743(同样适用于H745)LWIP配置-裸机+FreeRtos V2--笔记_stm32h743 lwip-CSDN博客

STM32H743使用CubeMX配置LWIP+FreeRTOS记录_stm32h743阿波罗lwip-CSDN博客

STM32H750+LAN8720无操作系统移植lwip_stm32h750 lan8720-CSDN博客

非H7:

基于正点原子探索者使用STM32CubeMX+FreeRTOS+LWIP_探索者开发板使用cobemx跑freertos-CSDN博客

11月25日

CUBE配置STM32H750、Lan8720、FreeRTOS、lwip、掉线重连、KeepAlive移植_stm32h750 lan8720-CSDN博客

STM32H750+LAN8720无操作系统移植lwip_stm32h750 lan8720-CSDN博客

STM32CubeIED+H743+DP83848+RTOS+LWIP通信_stm32h743 lwip-CSDN博客

基于STM32CubeMX创建的STM32H743+DP83848+LWIP网络通信程序调试_20221127算是胎教级教程了_h743 cubemx lwip-CSDN博客

这个里面有DP83848代码

问问为什么ping不通,请求超时 - TCP/IP - 硬汉嵌入式论坛 - Powered by Discuz!

不是

关于Lwip移植-测试ping显示超时_单片机移植lwip ping大包时提示校验和不正确-CSDN博客

不是


搞定了!!基于STM32CubeMX创建的STM32H743+DP83848+LWIP网络通信程序调试_20221127算是胎教级教程了_h743 cubemx lwip-CSDN博客

主要是看这篇,文章最后有附件:可以比对

3.1. CubeMX配置:

3.1.1. 常规配置(RCC、时钟树、晶振):

3.1.2. 调试串口:

3.1.3. 配置ETH:以太网 DMA 描述符地址、缓冲区地址/大小

3.1.4. GPIO配置:

3.1.4.1. ETH 的 GPIO:配置高速

3.1.4.2. PHY 芯片的复位 GPIO:(有些 PHY 芯片不一定要)

如:微雪 LAN8720,他是靠上电复位,如果要改也可以改,需要动手,在调试部分说

随便找一个 IO 接上即可

3.1.5. 配置LwIP:(很重要)

没写的默认即可,有问题评论区说

General Settings:常规设置

接入路由器才能使用DHCP协议(动态IP),一般用静态IP

Key Options:系统项设置
LWIP堆栈和内存池设置:(重要)

H723:

H723系列不同于H7系列,官方库默认配置是0x30044000,H723的内存不同于其他H7系列。

H723的RAM_D2的地址范围是0x30000000~0x30008000,而其他的H7空间比这个大得多。

H743/常规H7系列 的 RAM_D2:0x30000000~0x30048000,注意SRAM3

注意勾选

网卡设置:

注意LWIP_NETIF_LINK_CALLBACK(检测网线插拔的)要使能就行,其他配置默认

选择PHY芯片:

这里只有LAN8742可选,后期可改

3.1.6. 配置MPU(Cache):(很重要)

配置MPU是H7需要注意的

因为以太网DMA的内存需要配置好,否则问题很多

3.2. 工程配置:选择程序主 SRAM

还有微库记得勾选

3.3. 工程编写:

检查一下生成的代码,串口初始化是否在 LWIP 初始化之前(否则 DEBUG 未显示)

3.3.1. 串口调试:

/* 重定义fputc函数 */
int fputc(int ch, FILE *f)
{
	if(USART1 != NULL)
    {
		//循环发送,直到发送完毕   
    	while((USART1->ISR&0X40)==0)
		{			
		}	
		USART1->TDR=(uint8_t)ch;
	}
	return ch;
}

3.3.2. 使能 D2SRAM3 时钟:

/* Enable D2 domain SRAM3 Clock (0x30040000 AXI)*/
__HAL_RCC_D2SRAM3_CLK_ENABLE();

使能时钟,使能的是 TX/RX地址描述符的时钟。

3.3.3. 在 low_level_init 函数中添加 PHY 复位代码:

HAL_GPIO_WritePin(ETH_RST_GPIO_Port,ETH_RST_Pin,GPIO_PIN_SET);
HAL_Delay(50);
HAL_GPIO_WritePin(ETH_RST_GPIO_Port,ETH_RST_Pin,GPIO_PIN_RESET);
HAL_Delay(50);
HAL_GPIO_WritePin(ETH_RST_GPIO_Port,ETH_RST_Pin,GPIO_PIN_SET);
HAL_Delay(50);

3.3.4. 添加MX_LWIP_Process():此时下载即可 ping

该函数的作用是从以太网缓冲区读取接收到的数据包, 将其发送到 lwIP 堆栈进行处理

MX_LWIP_Process();

二、裸机工程开发:PHY 芯片改成 LAN8720

4.1. LAN8720 此时可能还 ping 不通

通过调试检查 LAN8720 的寄存器,看一下是否正常,发现第一个寄存器就不对了

stm32cubemx版本升级后导致stm32h743芯片LWIP无法Ping通_stm32 lwip ping不通-CSDN博客

调试:

4.2. 添加 LAN8720 的 初始化函数、补充宏定义

stm32cubemx版本升级后导致stm32h743芯片LWIP无法Ping通_stm32h743 eth 8720 cubemx-CSDN博客

发现和上面链接中的问题差不多,可能是 lan8742_init 对 8720 不适用

4.2.1. 在 lan8742.c 中,将 LAN8742_Init 函数改为:

/**
  * @brief  Initialize the lan8742 and configure the needed hardware resources
  * @param  pObj: device object LAN8742_Object_t. 
  * @retval LAN8742_STATUS_OK  if OK
  *         LAN8742_STATUS_ADDRESS_ERROR if cannot find device address
  *         LAN8742_STATUS_READ_ERROR if connot read register
  *         LAN8742_STATUS_WRITE_ERROR if connot write to register
  *         LAN8742_STATUS_RESET_TIMEOUT if cannot perform a software reset
  */
 int32_t LAN8742_Init(lan8742_Object_t *pObj)
 {
   uint32_t tickstart = 0, regvalue = 0, addr = 0;
   int32_t status = LAN8742_STATUS_OK;
   
   if(pObj->Is_Initialized == 0)
   {
     if(pObj->IO.Init != 0)
     {
       /* GPIO and Clocks initialization */
       pObj->IO.Init();
     }
   
     /* for later check */
     pObj->DevAddr = LAN8742_MAX_DEV_ADDR + 1;
   
     /* Get the device address from special mode register */  
     for(addr = 0; addr <= LAN8742_MAX_DEV_ADDR; addr ++)
     {
       if(pObj->IO.ReadReg(addr, LAN8742_SMR, &regvalue) < 0)
       { 
         status = LAN8742_STATUS_READ_ERROR;
         /* Can't read from this device address 
            continue with next address */
         continue;
       }
     
       if((regvalue & LAN8742_SMR_PHY_ADDR) == addr)
       {
         pObj->DevAddr = addr;
         status = LAN8742_STATUS_OK;
         break;
       }
     }
   
     if(pObj->DevAddr > LAN8742_MAX_DEV_ADDR)
     {
       status = LAN8742_STATUS_ADDRESS_ERROR;
     }
     
     /* if device address is matched */
     if(status == LAN8742_STATUS_OK)
     {
       /* set a software reset  */
       if(pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, LAN8742_BCR_SOFT_RESET) >= 0)
       { 
         /* get software reset status */
         if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &regvalue) >= 0)
         { 
           tickstart = pObj->IO.GetTick();
           printf("\r\nLAN8742_BCR:0x%2x",regvalue);
           
           /* wait until software reset is done or timeout occured  */
           while(regvalue & LAN8742_BCR_SOFT_RESET)
           {
             if((pObj->IO.GetTick() - tickstart) <= LAN8742_SW_RESET_TO)
             {
               if(pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &regvalue) < 0)
               { 
                 status = LAN8742_STATUS_READ_ERROR;
                 break;
               }
             }
             else
             {
               status = LAN8742_STATUS_RESET_TIMEOUT;
               break;
             }
           } 
         }
         else
         {
           status = LAN8742_STATUS_READ_ERROR;
         }
       }
       else
       {
         status = LAN8742_STATUS_WRITE_ERROR;
       }
     }
   }
      
   if(status == LAN8742_STATUS_OK)
   {
     tickstart =  pObj->IO.GetTick();
     
     /* Wait for 2s to perform initialization */
     while((pObj->IO.GetTick() - tickstart) <= LAN8742_INIT_TO)
     {
     }
     pObj->Is_Initialized = 1;
   }
   
   return status;
 }

4.2.2. 在 lan8742.c 中,补充宏定义:

/** @defgroup LAN8742_Private_Defines LAN8742 Private Defines
  * @{
  */
#define LAN8742_SW_RESET_TO    ((uint32_t)500U)
#define LAN8742_INIT_TO        ((uint32_t)2000U)
#define LAN8742_MAX_DEV_ADDR   ((uint32_t)31U)

4.2.3. 这里改完,有些 LAN8720 还是初始化失败,继续查:个别模块存在电路问题:

lan8720A驱动异常 - STM32H7 - 硬汉嵌入式论坛 - Powered by Discuz!

已定位到问题,LED2引脚未接下拉电阻导致(刚好极客是有下拉的)

这里看一下电路图

  • 微雪 LAN8720(我改了电路,NC 为 RST 引脚,但是 LED2 没接地):寄存器有时候读取总失败(显示全 ffff)

  • 极客 LAN8720:寄存器成功,部分有点奇怪

调试:

还有一些寄存器未成功:

这里去查一下手册

LAN8742[5] = 41e1,参考:cde1

41e1 = 0100000111100001

LAN8742[6] = 3,参考:b

0000000000000011

这里补充一下特殊功能寄存器:

可以利用特殊功能寄存器查地址

突然发现,有时候 lan8720 初始化卡住:杜邦线松了…

4.2.4. 单片机无法接收到 ARP 申请(ping 不显示)(LWIP DEBUG):

11月26日没搞出来,应该是杜邦线松了

二、裸机工程开发:PHY 芯片改成 DP83848

4.1. DP83848 宏定义

借鉴的基于STM32CubeMX创建的STM32H743+DP83848+LWIP网络通信程序调试_20221127算是胎教级教程了_h743 cubemx lwip-CSDN博客

#include "lan8742.h"
 
#define DP83848_BMCR_RW      ((uint16_t)0x0000U)  
#define DP83848_BMSR_RO      ((uint16_t)0x0001U) 
 
#define DP83848_PHYSTS_RO    ((uint16_t)0x0010U) 
#define DP83848_PHYCR_RW     ((uint16_t)0x0019U) 
 
#define DP83848_BMSR_LINK_STATUS        ((uint16_t)0x0004U)
 
#define DP83848_BMCR_SOFT_RESET         ((uint16_t)0x8000U)
#define DP83848_BMCR_LOOPBACK           ((uint16_t)0x4000U)
#define DP83848_BMCR_SPEED_SELECT       ((uint16_t)0x2000U)
#define DP83848_BMCR_AUTONEGO_EN        ((uint16_t)0x1000U)
#define DP83848_BMCR_POWER_DOWN         ((uint16_t)0x0800U)
#define DP83848_BMCR_ISOLATE            ((uint16_t)0x0400U)
#define DP83848_BMCR_RESTART_AUTONEGO   ((uint16_t)0x0200U)
#define DP83848_BMCR_DUPLEX_MODE        ((uint16_t)0x0100U) 
 
#define DP83848_STATUS_READ_ERROR            ((int32_t)-5)
#define DP83848_STATUS_WRITE_ERROR           ((int32_t)-4)
#define DP83848_STATUS_ADDRESS_ERROR         ((int32_t)-3)
#define DP83848_STATUS_RESET_TIMEOUT         ((int32_t)-2)
#define DP83848_STATUS_ERROR                 ((int32_t)-1)
#define DP83848_STATUS_OK                    ((int32_t) 0)
#define DP83848_STATUS_LINK_DOWN             ((int32_t) 1)
#define DP83848_STATUS_100MBITS_FULLDUPLEX   ((int32_t) 2)
#define DP83848_STATUS_100MBITS_HALFDUPLEX   ((int32_t) 3)
#define DP83848_STATUS_10MBITS_FULLDUPLEX    ((int32_t) 4)
#define DP83848_STATUS_10MBITS_HALFDUPLEX    ((int32_t) 5)
#define DP83848_STATUS_AUTONEGO_NOTDONE      ((int32_t) 6)
 
#define DP83848_PHYSTS_AUTONEGO_DONE   ((uint16_t)0x0010U)
#define DP83848_PHYSTS_HCDSPEEDMASK    ((uint16_t)0x0006U)
#define DP83848_PHYSTS_10BT_HD         ((uint16_t)0x0002U)
#define DP83848_PHYSTS_10BT_FD         ((uint16_t)0x0006U)
#define DP83848_PHYSTS_100BTX_HD       ((uint16_t)0x0000U)
#define DP83848_PHYSTS_100BTX_FD       ((uint16_t)0x0004U)
 
#define DP83848_INIT_TO        ((uint32_t)2000U)
#define DP83848_MAX_DEV_ADDR   ((uint32_t)31U)
 
#define bit(n) (1 << n) 
#define bit_false(x,mask) (x) &= ~(mask)
 
int32_t DP83848_Init(lan8742_Object_t *pObj);
int32_t DP83848_GetLinkState(lan8742_Object_t *pObj);

4.2. DP83848 相关函数:

借鉴的基于STM32CubeMX创建的STM32H743+DP83848+LWIP网络通信程序调试_20221127算是胎教级教程了_h743 cubemx lwip-CSDN博客

//DP83848的初始化函数
int32_t DP83848_Init(lan8742_Object_t *pObj)
{
 uint32_t tickstart = 0, regvalue = 0, addr = 0;
 int32_t status = DP83848_STATUS_OK;
 
 if(pObj->Is_Initialized == 0)
 {
	 if(pObj->IO.Init != 0)
	 {
		 /* GPIO and Clocks initialization */
		 pObj->IO.Init();
	 }
 
	 /* Get the device address from special mode register */  
	 for(addr = 0; addr <= DP83848_MAX_DEV_ADDR; addr ++)
	 {
 
		 printf("\r\n扫描地址:0x%02x",addr);
	 
		 if(pObj->IO.ReadReg(addr, DP83848_PHYCR_RW, &regvalue) < 0)
		 { 
			 status = DP83848_STATUS_READ_ERROR;
			 /* Can't read from this device address 
					continue with next address */
 
			 printf(",失败");
 
			 continue;
		 }
 
		 printf(",返回值:0x%02x",regvalue);
		
		 if((regvalue & 0x001F) == addr)
		 {
			 //存储地址值
			 pObj->DevAddr = addr;
 
			 status = DP83848_STATUS_OK;
 
			 printf(",获取PHY地址成功");
							 
			 break;
		 }
		 
	 }
 
	 if(pObj->DevAddr > DP83848_MAX_DEV_ADDR)
	 {
		 status = DP83848_STATUS_ADDRESS_ERROR;
	 }
 
		if(pObj->IO.ReadReg(addr, DP83848_BMCR_RW, &regvalue) < 0)
		{ 
				//读取失败
				printf("\r\nDP83848_BMCR_RW read fail");
		}
		else
		{
				//读取成功
				printf("\r\nDP83848_BMCR_RW read ok (0x%X)",regvalue);				
		}
		 
	 //SOFT_RESET
	 regvalue = regvalue|DP83848_BMCR_SOFT_RESET;
 
 
	 if(pObj->IO.WriteReg(addr, DP83848_BMCR_RW, regvalue) < 0)
	 { 
			//写入失败
			printf("\r\nDP83848_BMCR_RW write fail");
	 }
	 else
	 {
			//写入成功
			printf("\r\nDP83848_BMCR_RW write ok (0x%X)",regvalue);			
	 }
	 HAL_Delay(5);
 
	 //先读取该寄存器的数据
	 if(pObj->IO.ReadReg(addr, DP83848_PHYCR_RW, &regvalue) < 0)
	 {
			//读取失败
			printf("\r\nDP83848_PHYCR_RW read  fail");
	 }
	 else
	 {
			//读取成功
			printf("\r\nDP83848_PHYCR_RW read  ok (0x%X)",regvalue);
	 }
 
	 //bit5 是LED寄存器,配置成有数据传输的时候就闪烁 2019/06/03
	 bit_false(regvalue,bit(5));
 
	 if(pObj->IO.WriteReg(addr, DP83848_PHYCR_RW, regvalue) < 0)
	 { 
			//写入失败
			printf("\r\nDP83848_PHYCR_RW write fail");
	 }
	 else
	 {
			//写入成功
			printf("\r\nDP83848_PHYCR_RW write ok (0x%X)",regvalue);			
	 }
	 
	 HAL_Delay(5);
	 
	 //再读取该寄存器的数据,看之前的设置有没有生效
	 if(pObj->IO.ReadReg(addr, DP83848_PHYCR_RW, &regvalue) < 0)
	 {
			//读取失败
			printf("\r\nDP83848_PHYCR_RW read  fail");
	 }
	 else
	 {
			//读取成功
			printf("\r\nDP83848_PHYCR_RW read  ok (0x%X)",regvalue);
	 }
	 
	 DP83848_RESET: 
	 if(pObj->IO.ReadReg(addr, DP83848_PHYSTS_RO, &regvalue) >= 0)
	 {
		printf("PHY状态寄存器:PHYSTS status=0x%x\n", regvalue);
	 
		 if( (regvalue&0x0011) != 0x0011)
		 {
			 printf("\r\nDP83848初始化还未完成,等待中...\r\n");	 
			 
			 HAL_Delay(200);
			 goto DP83848_RESET;		 
		 }
		 else
		 {
			 printf("\r\nDP83848初始化成功!\r\n");
		 }
 
	 }
 }
		
 if(status == DP83848_STATUS_OK)
 {
	 tickstart =  pObj->IO.GetTick();
	 
	 /* Wait for 2s to perform initialization */
	 while((pObj->IO.GetTick() - tickstart) <= DP83848_INIT_TO)
	 {
	 
	 }
	 pObj->Is_Initialized = 1;
 }
 
 return status;
}


//DP83848网络连接状态检测函数
int32_t DP83848_GetLinkState(lan8742_Object_t *pObj)
{
  uint32_t readval = 0;
  
  /* Read Status register  */
  if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_BMSR_RO, &readval) < 0)
  {
    return DP83848_STATUS_READ_ERROR;
  }
  
  /* Read Status register again */
  if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_BMSR_RO, &readval) < 0)
  {
    return DP83848_STATUS_READ_ERROR;
  }
  
  if((readval & DP83848_BMSR_LINK_STATUS) == 0)
  {
    /* Return Link Down status */
    return DP83848_STATUS_LINK_DOWN;    
  }
  
  /* Check Auto negotiaition */
  if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_BMCR_RW, &readval) < 0)
  {
    return DP83848_STATUS_READ_ERROR;
  }
  
  if((readval & DP83848_BMCR_AUTONEGO_EN) != DP83848_BMCR_AUTONEGO_EN)
  {
    if(((readval & DP83848_BMCR_SPEED_SELECT) == DP83848_BMCR_SPEED_SELECT) && ((readval & DP83848_BMCR_DUPLEX_MODE) == DP83848_BMCR_DUPLEX_MODE)) 
    {
      return DP83848_STATUS_100MBITS_FULLDUPLEX;
    }
    else if ((readval & DP83848_BMCR_SPEED_SELECT) == DP83848_BMCR_SPEED_SELECT)
    {
      return DP83848_STATUS_100MBITS_HALFDUPLEX;
    }        
    else if ((readval & DP83848_BMCR_DUPLEX_MODE) == DP83848_BMCR_DUPLEX_MODE)
    {
      return DP83848_STATUS_10MBITS_FULLDUPLEX;
    }
    else
    {
      return DP83848_STATUS_10MBITS_HALFDUPLEX;
    }  		
  }
  else /* Auto Nego enabled */
  {
    if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_PHYSTS_RO, &readval) < 0)
    {
      return DP83848_STATUS_READ_ERROR;
    }
    
    /* Check if auto nego not done */
    if((readval & DP83848_STATUS_AUTONEGO_NOTDONE) == 0)
    {
      return DP83848_STATUS_READ_ERROR;
    }
    
    if((readval & DP83848_PHYSTS_HCDSPEEDMASK) == DP83848_PHYSTS_100BTX_FD)
    {
      return DP83848_STATUS_100MBITS_FULLDUPLEX;
    }
    else if ((readval & DP83848_PHYSTS_HCDSPEEDMASK) == DP83848_PHYSTS_100BTX_HD)
    {
      return DP83848_STATUS_100MBITS_HALFDUPLEX;
    }
    else if ((readval & DP83848_PHYSTS_HCDSPEEDMASK) == DP83848_PHYSTS_10BT_FD)
    {
      return DP83848_STATUS_10MBITS_FULLDUPLEX;
    }
    else if ((readval & DP83848_PHYSTS_HCDSPEEDMASK) == DP83848_PHYSTS_10BT_HD)
    {
      return DP83848_STATUS_10MBITS_HALFDUPLEX;
    }				
  }
}

4.3. 修改位置:

具体可以看原文,这里拷贝过来,特此谢谢稿主

基于STM32CubeMX创建的STM32H743+DP83848+LWIP网络通信程序调试_20221127算是胎教级教程了_h743 cubemx lwip-CSDN博客

将代码放置在合适的位置,我直接放在main函数下面了。

添加两个函数后,

4.3.1. DP83848_Init(&LAN8742)替换ethernetif.c文件中的LAN8742_Init(&LAN8742)

看划线部分

static void low_level_init(struct netif *netif)
{
    省略……
/* USER CODE BEGIN PHY_PRE_CONFIG */
	HAL_GPIO_WritePin(ETH_RST_GPIO_Port,ETH_RST_Pin,GPIO_PIN_SET);
	HAL_Delay(50);
	HAL_GPIO_WritePin(ETH_RST_GPIO_Port,ETH_RST_Pin,GPIO_PIN_RESET);
	HAL_Delay(50);
	HAL_GPIO_WritePin(ETH_RST_GPIO_Port,ETH_RST_Pin,GPIO_PIN_SET);
	HAL_Delay(50);
	
#if 0
/* USER CODE END PHY_PRE_CONFIG */
  /* Set PHY IO functions */
  LAN8742_RegisterBusIO(&LAN8742, &LAN8742_IOCtx);

  /* Initialize the LAN8742 ETH PHY */
  if(LAN8742_Init(&LAN8742) != LAN8742_STATUS_OK)
  {
    netif_set_link_down(netif);
    netif_set_down(netif);
    return;
  }

  if (hal_eth_init_status == HAL_OK)
  {
  /* Get link state */
  ethernet_link_check_state(netif);
  }
  else
  {
    Error_Handler();
  }
#endif /* LWIP_ARP || LWIP_ETHERNET */

/* USER CODE BEGIN LOW_LEVEL_INIT */
#endif
  /* DP83484 INIT */
  /* Set PHY IO functions */
  LAN8742_RegisterBusIO(&LAN8742, &LAN8742_IOCtx);

  /* Initialize the LAN8742 ETH PHY */
  if(DP83848_Init(&LAN8742) != LAN8742_STATUS_OK)
  {
    netif_set_link_down(netif);
    netif_set_down(netif);
    return;
  }

  if (hal_eth_init_status == HAL_OK)
  {
  /* Get link state */
  ethernet_link_check_state(netif);
  }
  else
  {
    Error_Handler();
  }
/* USER CODE END LOW_LEVEL_INIT */
}

4.3.2. DP83848_GetLinkState(&LAN8742)替换ethernetif.c文件中的LAN8742_GetLinkState(&LAN8742)

各一处,替换完成后,记得确认相应头文件是否包含。

第二处比较麻烦,每次生成后都要修改!

void ethernet_link_check_state(struct netif *netif)
{
  ETH_MACConfigTypeDef MACConf = {0};
  int32_t PHYLinkState = 0;
  uint32_t linkchanged = 0U, speed = 0U, duplex = 0U;

  PHYLinkState = DP83848_GetLinkState(&LAN8742);

    省略……
}

三、裸机工程开发:转由AC6 编译

记得在MDK中修改

5.1. cc.h 中修改:

5.2. lwip.h 中添加:

#define __CC_ARM

5.3. ethernetif.c 中修改:这里仅改了 MDK 环境下(H7 必须改)

对于 H7 来说不止要改两个接口文件(之前参考一篇配置 F4 的文章),这里 H7 因为以太网 DMA 描述符的地址问题,涉及到了数组定义指定 SRAM 问题,用到了汇编,但是又因为 AC5/6 的汇编改变问题,所以要多改一个地方!

#if defined ( __ICCARM__ ) /*!< IAR Compiler */

#pragma location=0x30040000
ETH_DMADescTypeDef  DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
#pragma location=0x30040060
ETH_DMADescTypeDef  DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */

#elif defined ( __CC_ARM )  /* MDK ARM Compiler */

__attribute__((at(0x30040000))) ETH_DMADescTypeDef  DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
__attribute__((at(0x30040060))) ETH_DMADescTypeDef  DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */

#elif defined ( __GNUC__ ) /* GNU Compiler */

#if !(__ARMCC_VERSION >= 6010050)   /* 不是AC6编译器,即使用AC5编译器时 */
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] __attribute__((section(".RxDecripSection"))); /* Ethernet Rx DMA Descriptors */
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT] __attribute__((section(".TxDecripSection")));   /* Ethernet Tx DMA Descriptors */
#else      							/* 使用AC6编译器时 */
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] __attribute__((section(".bss.ARM.__at_0x30040000"))); /* Ethernet Rx DMA Descriptors */
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT] __attribute__((section(".bss.ARM.__at_0x30040060")));   /* Ethernet Tx DMA Descriptors */
#endif

#endif

#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma location = 0x30040200
extern u8_t memp_memory_RX_POOL_base[];

#elif defined ( __CC_ARM ) /* MDK ARM Compiler */
__attribute__((section(".Rx_PoolSection"))) extern u8_t memp_memory_RX_POOL_base[];

#elif defined ( __GNUC__ ) /* GNU */

#if !(__ARMCC_VERSION >= 6010050)   /* 不是AC6编译器,即使用AC5编译器时 */
__attribute__((section(".Rx_PoolSection"))) extern u8_t memp_memory_RX_POOL_base[];
#else      							/* 使用AC6编译器时 */
extern u8_t memp_memory_RX_POOL_base[] __attribute__((section(".bss.ARM.__at_0x30040200")));
#endif

#endif

四、FreeRTOS - 开发部分

待更新


调试部分(如果出现问题/不可ping)

【LWIP】STM32H7开发LWIP时遇到的问题(2024-11)-CSDN博客

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值