调试以太网时卡死在while(ETH_GetSoftwareResetStatus()==SET)

问题描述

最近在调试一个项目的板子,用的STM32F407IGT6+DP83848,以太网例程用的安富莱的,在调试以太网功能时,初始化时老是卡死在while(ETH_GetSoftwareResetStatus()==SET) ,将这行换成if语句后还是执行不下去,仍然无法ping通。

解决过程

请教了了安富莱开发人员(不得不提安富莱的开发人员还是很耐心,8年前买过他家的开发板现在仍然有问必答),又在网上搜了很多大家遇到的结果,大部分人都说应该是时钟问题,在和硬件设计师确认后,确实是时钟原因,虽然板子用的是外部晶振做时钟,但是PHY的时钟还是需要连到STM的PA1脚。

/**
  * @brief  Configures the Ethernet Interface
  * @param  None
  * @retval None
  */
static void ETH_MACDMA_Config(void)
{
  /* 打印调试信息 */
  lwip_printf("LwIP Enter ETH_MACDMA_Config()\r\n");
	
  /* Enable ETHERNET clock  */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_ETH_MAC | RCC_AHB1Periph_ETH_MAC_Tx |
                        RCC_AHB1Periph_ETH_MAC_Rx, ENABLE);

  /* Reset ETHERNET on AHB Bus */
  ETH_DeInit();

  /* Software reset */
  ETH_SoftwareReset();

  /* Wait for software reset */
  while (ETH_GetSoftwareResetStatus() == SET);

  /* ETHERNET Configuration --------------------------------------------------*/
  /* Call ETH_StructInit if you don't like to configure all ETH_InitStructure parameter */
  ETH_StructInit(&ETH_InitStructure);

  /* Fill ETH_InitStructure parametrs */
  /*------------------------   MAC   -----------------------------------*/
  ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Enable;
//  ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Disable;
//  ETH_InitStructure.ETH_Speed = ETH_Speed_10M;
//  ETH_InitStructure.ETH_Mode = ETH_Mode_FullDuplex;

  ETH_InitStructure.ETH_LoopbackMode = ETH_LoopbackMode_Disable;
  ETH_InitStructure.ETH_RetryTransmission = ETH_RetryTransmission_Disable;
  ETH_InitStructure.ETH_AutomaticPadCRCStrip = ETH_AutomaticPadCRCStrip_Disable;
  ETH_InitStructure.ETH_ReceiveAll = ETH_ReceiveAll_Disable;
  ETH_InitStructure.ETH_BroadcastFramesReception = ETH_BroadcastFramesReception_Enable;
  ETH_InitStructure.ETH_PromiscuousMode = ETH_PromiscuousMode_Disable;
  ETH_InitStructure.ETH_MulticastFramesFilter = ETH_MulticastFramesFilter_Perfect;
  ETH_InitStructure.ETH_UnicastFramesFilter = ETH_UnicastFramesFilter_Perfect;
#ifdef CHECKSUM_BY_HARDWARE
  ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Enable;
#endif

  /*------------------------   DMA   -----------------------------------------*/
  /* When we use the Checksum offload feature, we need to enable the Store and Forward mode:
  the store and forward guarantee that a whole frame is stored in the FIFO, so the MAC can insert/verify the checksum,
  if the checksum is OK the DMA can handle the frame otherwise the frame is dropped */
  ETH_InitStructure.ETH_DropTCPIPChecksumErrorFrame = ETH_DropTCPIPChecksumErrorFrame_Enable;
  ETH_InitStructure.ETH_ReceiveStoreForward = ETH_ReceiveStoreForward_Enable;
  ETH_InitStructure.ETH_TransmitStoreForward = ETH_TransmitStoreForward_Enable;

  ETH_InitStructure.ETH_ForwardErrorFrames = ETH_ForwardErrorFrames_Disable;
  ETH_InitStructure.ETH_ForwardUndersizedGoodFrames = ETH_ForwardUndersizedGoodFrames_Disable;
  ETH_InitStructure.ETH_SecondFrameOperate = ETH_SecondFrameOperate_Enable;
  ETH_InitStructure.ETH_AddressAlignedBeats = ETH_AddressAlignedBeats_Enable;
  ETH_InitStructure.ETH_FixedBurst = ETH_FixedBurst_Enable;
  ETH_InitStructure.ETH_RxDMABurstLength = ETH_RxDMABurstLength_32Beat;
  ETH_InitStructure.ETH_TxDMABurstLength = ETH_TxDMABurstLength_32Beat;
  ETH_InitStructure.ETH_DMAArbitration = ETH_DMAArbitration_RoundRobin_RxTx_2_1;
  
  /* 打印调试信息 */
  lwip_printf("LwIP Enter ETH_Init()\r\n");  
  
  /* Configure Ethernet */  
  EthStatus = ETH_Init(&ETH_InitStructure, DP83848_PHY_ADDRESS);
}

结论

将PHY的时钟连到STM的PA1脚。在解决此问题前,我搜了网上大量的回答,以下是一些结果分享,希望可以给后续遇到此问题的同学一点帮助。

分享

下面是分享一些关于网上大家对于“卡死在while(ETH_GetSoftwareResetStatus()==SET)”问题的一些回答或解决建议:

1.检查PHY芯片是否虚焊;
2.用示波器打一下晶振,确认晶振是否起振;
3.用示波器测试时钟和信号,确认是否正常;
4.用示波器检查STM32芯片的ETH时钟引脚,确认程序是否正常运行;
5.确认STM32芯片ETH的时钟引脚是否虚焊;
6.确认IO引脚初始化是否正确;
7.DP83848的34脚和PA1相连,使能PA1就好了;
8.我使用官方st的例程,结果原因是硬件和程序的网络模式不对,用的是MII,而我的硬件模式是RMII,把main.h内的#define RMII注释取消,#define MII注释就好了;
9.定义RMII_MODE,注释掉MII_MODE;
9.MII模式:“adding this line after the PA8 configuration ''GPIO_PinAFConfig(GPIOA,GPIO_PinSource8,GPIO_AF_MCO) ;''
10.MII模式:找到原因了,他需要时钟同步才行,所以之前说的那两条时钟先都应该有25M才对;
11.我用的是STM32F107VCT6+DP83848,停在while (ETH_GetSoftwareResetStatus() == SET);的原因是由于PA8(MCO时钟输出脚),未进行复用推挽输出到PA1(RMII_REF_CLK脚)上。后来只要把PA8的时钟输出到PA1上就可以正常运行了;
12./* Enable the Ethernet Rx Interrupt */ETH_DMAITConfig(ETH_DMA_IT_NIS | ETH_DMA_IT_R, ENABLE);
13.参考Nationstech.N32G45x_SNMP_V1.0 demo移植lwip,发现卡死在以下代码 while (ETH_GetSoftwareResetStatus() == SET),跳过这个while,往下配置phy可以正常配置,但是ping不通,怀疑还是这个SWR的问题,看手册发现SWR是自动清0的,请教各位大佬,啥情况下SWR位会一直为1。answer:时钟没有正确配置
14.正是由于时钟问题,不过我的是由于我MCO和外部50MHZ同时用造成外部有源,波形也不大好,所以我去掉有源了,初始化正常了;
15.今天,我也遇到这个问题,看了些网友说的,MCO有没有输出。我用的芯片DM9161,而芯片是DP83848,就没有问题。我重新修改驱动文件,发现
    GPIO_ETH_MediaInterfaceConfig(GPIO_ETH_MediaInterface_RMII);
    在RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_ETH_MAC | RCC_AHB1Periph_ETH_MAC_Tx |RCC_AHB1Periph_ETH_MAC_Rx, ENABLE); 
    之前进行初始化,导致没有配置成功。还有DM9161,MAC,需要
    ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Disable;
    ETH_InitStructure.ETH_Speed = ETH_Speed_100M;
    ETH_InitStructure.ETH_Mode = ETH_Mode_FullDuplex;
    这样设置,不能自适应方式。才能成功。希望后面的同学,看了此贴绕过这个坑。    
16.#define PHY_SR                           17     /*!< Tranceiver Status Register */    
   #define PHY_Speed_Status            ((u16)0x3000)    /*!< Configured information of Speed: 10Mbps */
   #define PHY_Duplex_Status           ((u16)0xA000)    /*!< Configured information of Duplex: Full-duplex */
17.PA1应该连接到时钟源上面;

RTL8211是一款千兆以太网PHY芯片,它需要在MCU上使用MAC控制器来驱动以太网通信。以下是一个示例代码,用于在STM32 MCU上驱动RTL8211: ```c #include "stm32f4xx.h" #include "stm32f4xx_eth.h" #define PHY_ADDRESS 0x01 #define PHY_BCR 0x00 #define PHY_BSR 0x01 #define PHY_RESET_DELAY ((uint32_t)0x000FFFFF) #define ETH_MAC_ADDRESS_0 0x00 #define ETH_MAC_ADDRESS_1 0x80 #define ETH_MAC_ADDRESS_2 0xE1 #define ETH_MAC_ADDRESS_3 0x00 #define ETH_MAC_ADDRESS_4 0x00 #define ETH_MAC_ADDRESS_5 0x00 void ETH_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; /* Enable GPIOs clocks */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_GPIOG | RCC_AHB1Periph_GPIOH | RCC_AHB1Periph_GPIOI, ENABLE); /* Enable SYSCFG clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); /* MII/RMII Media interface selection --------------------------------------*/ #ifdef MII_MODE /* Mode MII with STM324xG-EVAL */ SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_MII); #elif defined RMII_MODE /* Mode RMII with STM324xG-EVAL */ SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_RMII); #endif /* Ethernet pins configuration ************************************************/ /* ETH_MDIO -------------------------> PA2 ETH_MDC --------------------------> PC1 ETH_RMII_REF_CLK------------------> PA1 ETH_RMII_CRS_DV ------------------> PA7 ETH_RMII_RXD0 --------------------> PC4 ETH_RMII_RXD1 --------------------> PC5 ETH_RMII_TX_EN -------------------> PB11 ETH_RMII_TXD0 --------------------> PB12 ETH_RMII_TXD1 --------------------> PB13 */ /* Configure PA1, PA2 and PA7 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure PB11, PB12 and PB13 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOB, &GPIO_InitStructure); /* Configure PC1, PC4 and PC5 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOC, &GPIO_InitStructure); /* Configure PH2 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOH, &GPIO_InitStructure); /* Configure PH6 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOH, &GPIO_InitStructure); /* Connect PA1, PA2 and PA7 */ GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_ETH); GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_ETH); GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_ETH); /* Connect PB11, PB12 and PB13 */ GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_ETH); GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_ETH); GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_ETH); /* Connect PC1, PC4 and PC5 */ GPIO_PinAFConfig(GPIOC, GPIO_PinSource1, GPIO_AF_ETH); GPIO_PinAFConfig(GPIOC, GPIO_PinSource4, GPIO_AF_ETH); GPIO_PinAFConfig(GPIOC, GPIO_PinSource5, GPIO_AF_ETH); } void ETH_MACDMA_Config(void) { ETH_InitTypeDef ETH_InitStructure; /* Enable ETHERNET clock */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_ETH_MAC | RCC_AHB1Periph_ETH_MAC_Tx | RCC_AHB1Periph_ETH_MAC_Rx, ENABLE); /* Enable SYSCFG clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); /* Reset ETHERNET on AHB Bus */ ETH_DeInit(); /* Software reset */ ETH_SoftwareReset(); /* Wait for software reset */ while (ETH_GetSoftwareResetStatus() == SET); /* MAC Config */ ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Enable; ETH_InitStructure.ETH_Speed = ETH_Speed_100M; ETH_InitStructure.ETH_Mode = ETH_Mode_FullDuplex; ETH_InitStructure.ETH_AutomaticPadCRCStrip = ETH_AutomaticPadCRCStrip_Enable; ETH_InitStructure.ETH_ReceiveAll = ETH_ReceiveAll_Enable; ETH_InitStructure.ETH_BroadcastFramesReception = ETH_BroadcastFramesReception_Enable; ETH_InitStructure.ETH_PromiscuousMode = ETH_PromiscuousMode_Disable; ETH_InitStructure.ETH_MulticastFramesFilter = ETH_MulticastFramesFilter_Perfect; ETH_InitStructure.ETH_UnicastFramesFilter = ETH_UnicastFramesFilter_Perfect; ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Enable; ETH_InitStructure.ETH_VLANTagComparison = ETH_VLANTagComparison_Disable; ETH_InitStructure.ETH_VLANTagIdentifier = 0; ETH_InitStructure.ETH_DropTCPIPChecksumErrorFrame = ETH_DropTCPIPChecksumErrorFrame_Enable; ETH_InitStructure.ETH_ReceiveStoreForward = ETH_ReceiveStoreForward_Enable; ETH_InitStructure.ETH_TransmitStoreForward = ETH_TransmitStoreForward_Enable; ETH_InitStructure.ETH_ForwardErrorFrames = ETH_ForwardErrorFrames_Disable; ETH_InitStructure.ETH_ForwardUndersizedGoodFrames = ETH_ForwardUndersizedGoodFrames_Disable; ETH_InitStructure.ETH_SecondFrameOperate = ETH_SecondFrameOperate_Enable; ETH_InitStructure.ETH_AddressAlignedBeats = ETH_AddressAlignedBeats_Enable; ETH_InitStructure.ETH_FixedBurst = ETH_FixedBurst_Enable; ETH_InitStructure.ETH_RXDMA_BurstLength = ETH_RXDMA_BurstLength_32Beat; ETH_InitStructure.ETH_TXDMA_BurstLength = ETH_TXDMA_BurstLength_32Beat; ETH_InitStructure.ETH_ROKInterrupt = ETH_ROKInterrupt_Enable; ETH_InitStructure.ETH_TOKInterrupt = ETH_TOKInterrupt_Enable; ETH_InitStructure.ETH_DMAInterrupt = ETH_DMAInterrupt_Enable; /* Configure Ethernet */ ETH_Init(&ETH_InitStructure, PHY_ADDRESS); /* Enable the Ethernet Rx Interrupt */ ETH_DMAITConfig(ETH_DMA_IT_NIS | ETH_DMA_IT_R, ENABLE); /* Enable MAC and DMA transmission and reception */ ETH_Start(); } void ETH_PHY_Config(void) { uint16_t reg_value = 0; uint32_t timeout = 0; /* Reset PHY */ ETH_WritePHYRegister(PHY_ADDRESS, PHY_BCR, PHY_Reset); timeout = PHY_RESET_DELAY; while ((ETH_ReadPHYRegister(PHY_ADDRESS, PHY_BCR) & PHY_Reset) && timeout) { timeout--; } /* Configure PHY */ ETH_WritePHYRegister(PHY_ADDRESS, PHY_BCR, PHY_AutoNegotiation); timeout = PHY_RESET_DELAY; while (!(ETH_ReadPHYRegister(PHY_ADDRESS, PHY_BSR) & PHY_AutoNegoComplete) && timeout) { timeout--; } /* Configure MAC */ ETH_MACAddressConfig(ETH_MAC_Address_0, ETH_MAC_Address_1, ETH_MAC_Address_2, ETH_MAC_Address_3, ETH_MAC_Address_4, ETH_MAC_Address_5); ETH_MACAddressPerfectFilterCmd(ENABLE); /* Enable the MAC transmission and reception */ ETH_DMACmd(ETH_DMA_Transmit | ETH_DMA_Receive, ENABLE); /* Enable the Ethernet Rx Interrupt */ NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = ETH_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x7; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } int main(void) { /* Configure GPIOs for Ethernet */ ETH_GPIO_Config(); /* Configure Ethernet MAC/DMA */ ETH_MACDMA_Config(); /* Configure Ethernet PHY */ ETH_PHY_Config(); while(1) { /* Your application code here */ } } ``` 这个示例代码假设你已经正确配置了STM32 MCU的系统钟,并且已经在代码中定义了以下常量: - `MII_MODE`或`RMII_MODE`,指示使用哪种以太网接口模式 - `PHY_ADDRESS`,RTL8211在以太网总线上的地址 - `ETH_MAC_ADDRESS_0`到`ETH_MAC_ADDRESS_5`,你的设备的MAC地址 请注意,这只是一个示例代码,需要根据你的具体应用进行修改。例如,你可能需要在代码中定义和设置更多的寄存器值,以满足你的特定需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值