Skip to main content
paulrbryson
Associate III
January 19, 2026
Solved

nucleo-429zi ethernet Phy Sometimes fails auto-negotiation

  • January 19, 2026
  • 2 replies
  • 288 views

I am using a Nucelo-429zi board for development and my custom PCB schematic is based on this board.  I am experiencing a problem where about 10% - 20% of the time after a hardware reset the PHY will fail auto-negotiation.  The green led does not come on and the amber led blinks.  This happens even when on the debugger and the MCU is not allowed to run.  I only have one Nucleo board so I cannot try another to see if the problem is unique to this board.

Is this a known problem? seen before?

What could it be?  Possibly the clock circuit?

Best answer by paulrbryson

I am not sure of the cause for the original problem - i.e. a hardware reset leaves the PHY in "bad" state.  I suspect it may have something to do with the internal 25MHz oscillator not stabilizing before auto-negotiation starts?  
In any event I found what looks to be a reliable solution - retstart the auto-negotiation in firmware after the PHY chip has stabilized.  I Inserted the following code in the stm32cubemx generated source, in "ethernet.c".

 

 
/* USER CODE BEGIN PHY_PRE_CONFIG */
 /* Force a PHY Auto-Negotiation -- Hardware Reset Can leave Phy in Bad state*/
 {
 /* PHY Register Definitions */
 const uint32_t NEG_LAN8742A_ADDRESS = 0x00U;
 const uint32_t NEG_PHY_BCR = 0x00U; /* Basic Control Register */
 const uint32_t NEG_PHY_BCR_SOFT_RESET = (1 << 15);
 const uint32_t NEG_PHY_BCR_AUTONEGO_EN = (1 << 12);
 const uint32_t NEG_PHY_BCR_RESTART_AN = (1 << 9);
 
 /* Implementation of the missing function */
 uint32_t phy_reg = 0;
 
 // 1. Send Soft Reset command
 HAL_ETH_WritePHYRegister(&heth, NEG_LAN8742A_ADDRESS, NEG_PHY_BCR, NEG_PHY_BCR_SOFT_RESET);
 
 // 2. Wait for Reset bit to self-clear (indicates PHY is ready)
 uint32_t timeout = HAL_GetTick() + 500;
 do {
 HAL_ETH_ReadPHYRegister(&heth, NEG_LAN8742A_ADDRESS, NEG_PHY_BCR, &phy_reg);
 } while ((phy_reg & NEG_PHY_BCR_SOFT_RESET) && (HAL_GetTick() < timeout));
 
 // 3. Force Auto-Negotiation Enable and Restart
 HAL_ETH_WritePHYRegister(&heth, NEG_LAN8742A_ADDRESS, NEG_PHY_BCR,
 NEG_PHY_BCR_AUTONEGO_EN | NEG_PHY_BCR_RESTART_AN);
 
 }
 
/* USER CODE END PHY_PRE_CONFIG */

2 replies

sergey23
Associate
January 20, 2026

If you can post the ethernet part of the schematic, and your ethernet firmware code snippet, that would help.

You could try to load Mongoose-based test firmware and see if the same happens. Visit https://mongoose.ws/wizard/#/output?board=f429&ide=CubeIDE&rtos=baremetal&file=README.md , select destination directory in the settings tab, click "generate" button on top right, load the project in Cube IDE, start serial console, and build & flash the firmware. Board's IP address should appear in the log, as well as the other debug info like PHY parameters, link speed, etc.

paulrbryson
Associate III
January 20, 2026

I am using the nucleo-429zi development board.  I don't think firmware is involved.  This happens before the firmware even runs.  The phy chip either fails or succeeds at auto-negotiation even if the MCU is completely erased or is prevented from running by the debugger.  Once the phy chip has failed to auto-negotiate it does not recover.  I can repeatedly perform a hardware reset on the phy chip until the auto-negotiation succeeds.  But this seems like a hack rather than a solution and how do I know that board to board variations will not produce some units which never work?

This is the schematic for the nucleo board (also see attached)..

 

paulrbryson_1-1768931106066.png

 

paulrbryson
paulrbrysonAuthorBest answer
Associate III
January 21, 2026

I am not sure of the cause for the original problem - i.e. a hardware reset leaves the PHY in "bad" state.  I suspect it may have something to do with the internal 25MHz oscillator not stabilizing before auto-negotiation starts?  
In any event I found what looks to be a reliable solution - retstart the auto-negotiation in firmware after the PHY chip has stabilized.  I Inserted the following code in the stm32cubemx generated source, in "ethernet.c".

 

 
/* USER CODE BEGIN PHY_PRE_CONFIG */
 /* Force a PHY Auto-Negotiation -- Hardware Reset Can leave Phy in Bad state*/
 {
 /* PHY Register Definitions */
 const uint32_t NEG_LAN8742A_ADDRESS = 0x00U;
 const uint32_t NEG_PHY_BCR = 0x00U; /* Basic Control Register */
 const uint32_t NEG_PHY_BCR_SOFT_RESET = (1 << 15);
 const uint32_t NEG_PHY_BCR_AUTONEGO_EN = (1 << 12);
 const uint32_t NEG_PHY_BCR_RESTART_AN = (1 << 9);
 
 /* Implementation of the missing function */
 uint32_t phy_reg = 0;
 
 // 1. Send Soft Reset command
 HAL_ETH_WritePHYRegister(&heth, NEG_LAN8742A_ADDRESS, NEG_PHY_BCR, NEG_PHY_BCR_SOFT_RESET);
 
 // 2. Wait for Reset bit to self-clear (indicates PHY is ready)
 uint32_t timeout = HAL_GetTick() + 500;
 do {
 HAL_ETH_ReadPHYRegister(&heth, NEG_LAN8742A_ADDRESS, NEG_PHY_BCR, &phy_reg);
 } while ((phy_reg & NEG_PHY_BCR_SOFT_RESET) && (HAL_GetTick() < timeout));
 
 // 3. Force Auto-Negotiation Enable and Restart
 HAL_ETH_WritePHYRegister(&heth, NEG_LAN8742A_ADDRESS, NEG_PHY_BCR,
 NEG_PHY_BCR_AUTONEGO_EN | NEG_PHY_BCR_RESTART_AN);
 
 }
 
/* USER CODE END PHY_PRE_CONFIG */