2026-01-19 7:17 AM - last edited on 2026-01-19 7:20 AM by mƎALLEm
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?
Solved! Go to Solution.
2026-01-20 11:35 PM
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 */
2026-01-20 5:10 AM
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.
2026-01-20 9:47 AM
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)..
2026-01-20 11:35 PM
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 */