问题描述
最近在调试一个项目的板子,用的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(Ð_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(Ð_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应该连接到时钟源上面;