---
title: "W7500P PHY Unable to Link"
url: "https://maker.wiznet.io/forum/16121"
markdown_url: "https://maker.wiznet.io/forum/16121/md"
type: "Forum topic"
category: "MCU & Boards"
author: "kelanucr"
created: "2026-07-17T10:24:05+09:00"
last_activity: "2026-08-20T05:32:31+09:00"
language: "en"
tags: ["W7500P"]
views: 6
replies: 7
source: "WIZnet Makers forum (https://maker.wiznet.io/forum/)"
---

# W7500P PHY Unable to Link

## Question

Asked by kelanucr on 2026-07-17 in MCU & Boards.

Hello,

I am working on a board based around the Wiznet W7500P, I'm using the standard peripheral library from the Wiznet GitHub. With a design functionally identical to the reference schematic.

Recently one of my units fails to establish a link with a connected ethernet cable, the same firmware and hardware succeed on an identical unit. This behavior persists between soft resets of the PHY, toggling RSTn on the W7500P and full power cycling of the board, leaving the board in an unusable state.

I was able to dump the PHY registers on my working unit

===== IP101G PHY register dump (PHY addr 1) =====
-- Page-independent registers (Reg) --
Reg 0 = 3100 Control Register
Reg 1 = 786D Status Register
Reg 2 = 0243 PHY Identifier 1 Register
Reg 3 = 0C54 PHY Identifier 2 Register
Reg 4 = 01E1 Auto-Negotiation Advertisement Register
Reg 5 = 45E1 Auto-Negotiation Link Partner Ability Register
Reg 6 = 0005 Auto-Negotiation Expansion Register
Reg 7 = 2801 Auto-Negotiation Next Page Transmit Register
Reg 8 = 0000 Auto-Negotiation Link Partner Next Page Register
Reg 13 = 4007 MMD Access Control Register
Reg 14 = 0000 MMD Access Address Data Register
Reg 20 = 0010 Page Control Register
-- Paged registers (page.reg) --
1.17 = 0000 PHY Specific Control Register
1.18 = 0000 RX CRC Error Counter Register
1.22 = 2020 Linear Regulator Output Control Register
1.23 = 8000 UTP PHY Specific Control Register
2.18 = 0000 RX Packet Counter Register
3.16 = 0000 LED Control Register
4.16 = 5F40 WOL+ Control Register
4.22 = 4000 Digital IO Pin Driving Control Register
5.16 = 0000 PHY WOL+ MAC Address Register
8.17 = 7000 RX Counter Control Register
11.18 = 0000 UTP PHY Interrupt Control/Status Register
16.16 = 0002 PHY Specific Control Register
16.17 = 0F00 PHY Interrupt Ctrl/Status Register
16.18 = 6D0A PHY Status Monitoring Register
16.26 = 1249 Digital IO Pin Driving Control Register
16.27 = 0012 Digital IO Pin Driving Control Register
16.29 = 0182 Digital I/O Specific Control Register
16.30 = 0106 PHY MDI/MDIX Control and Specific Status Register
17.17 = 0000 PHY WOL+ Status Register
18.17 = 0000 RX Counter Interrupt Control/Status Register
-- MMD registers (devad.addr) --
3.0 = 0000 PCS Control 1 Register
3.1 = 0000 PCS Status 1 Register
3.20 = 0002 EEE Capability Register
3.22 = 0000 EEE Wake Error Count Register
7.60 = 0002 EEE Advertisement Register
7.61 = 0000 EEE Link Partner Ability Register
===== end of dump =====

As well as on a malfunctioning unit

===== IP101G PHY register dump (PHY addr 3) =====
-- Page-independent registers (Reg) --
Reg 0 = 2100 Control Register
Reg 1 = 7849 Status Register
Reg 2 = 0243 PHY Identifier 1 Register
Reg 3 = 0C54 PHY Identifier 2 Register
Reg 4 = 01E1 Auto-Negotiation Advertisement Register
Reg 5 = 0000 Auto-Negotiation Link Partner Ability Register
Reg 6 = 0004 Auto-Negotiation Expansion Register
Reg 7 = 2001 Auto-Negotiation Next Page Transmit Register
Reg 8 = 0000 Auto-Negotiation Link Partner Next Page Register
Reg 13 = 4007 MMD Access Control Register
Reg 14 = 0000 MMD Access Address Data Register
Reg 20 = 0010 Page Control Register
-- Paged registers (page.reg) --
1.17 = 0000 PHY Specific Control Register
1.18 = 0000 RX CRC Error Counter Register
1.22 = 2020 Linear Regulator Output Control Register
1.23 = 8000 UTP PHY Specific Control Register
2.18 = 0000 RX Packet Counter Register
3.16 = 0000 LED Control Register
4.16 = 0000 WOL+ Control Register
4.22 = 4000 Digital IO Pin Driving Control Register
5.16 = 0000 PHY WOL+ MAC Address Register
8.17 = 7000 RX Counter Control Register
11.18 = 0000 UTP PHY Interrupt Control/Status Register
16.16 = 0002 PHY Specific Control Register
16.17 = 0F00 PHY Interrupt Ctrl/Status Register
16.18 = 6808 PHY Status Monitoring Register
16.26 = 1249 Digital IO Pin Driving Control Register
16.27 = 0012 Digital IO Pin Driving Control Register
16.29 = 0382 Digital I/O Specific Control Register
16.30 = 0000 PHY MDI/MDIX Control and Specific Status Register
17.17 = 0000 PHY WOL+ Status Register
18.17 = 0000 RX Counter Interrupt Control/Status Register
-- MMD registers (devad.addr) --
3.0 = 0000 PCS Control 1 Register
3.1 = 0000 PCS Status 1 Register
3.20 = 0002 EEE Capability Register
3.22 = 0000 EEE Wake Error Count Register
7.60 = 0000 EEE Advertisement Register
7.61 = 0000 EEE Link Partner Ability Register
===== end of dump =====

The difference is in registers 0, 1, 5, 6, and 7 as well as page 16 register 18, 29, and 30 and the MMD EEE Advertisement register.

Register 0 differs by bit 12, which corresponds to Auto-Negotiation Enable. In my failure mode this bit is flipped from the default 1 -> 0. In TP mode this bit should be writable, so I modified PHY_Init to set Auto-Negotiation and Loopback (to verify my register writes were holding) then read back the registers.

Here is my modified PHY_Init() function (placed after bitstatus = PHY_GetId())

{
uint32_t bmcr_before = MDIO_GetData(PHY_ADDR, PHYREG_CONTROL);
MDIO_SetData(PHYREG_CONTROL,
bmcr_before | PHYREG_CONTROL_AUTONEGO | PHYREG_CONTROL_LOOPBACK);
uint32_t bmcr_after = MDIO_GetData(PHY_ADDR, PHYREG_CONTROL);
printf("BMCR bit12/14 write: 0x%04X -> 0x%04X (bit12=%u bit14=%u)\r\n",
(unsigned)(bmcr_before & 0xFFFF), (unsigned)(bmcr_after & 0xFFFF),
(unsigned)((bmcr_after >> 12) & 1u), (unsigned)((bmcr_after >> 14) & 1u));
}

Where I defined elsewhere the value of PHYREG_CONTROL_LOOPBACK.

The result is a read back of 0x6100, meaning the loopback write was successful but setting auto-negotiation was not (both should result in 0x7100). Reading the IP101G notes shows that this bit is RO in FX mode and RW in TP mode. Which leads me to believe that this board is getting stuck in FX mode.

Section 5.10 of the IP101G datasheet explains that RXDV is sampled on the rising edge of a reset signal. 0 places the device in TP mode and 1 places the device in FX mode. However, the standard library code sets the pin with a pull up and does nothing else, leaving it either floating at best or high.

Here is the default IP101G configuration code from PHY_Init(), with some extra comments on what each line does based on what I figured out from the eratta.

#elif defined (W7500P)

// IP101G RXDV/CRS_DV/FX_HEN
GPIO_PinPadConfig(GPIOB, GPIO_PinSource12, GPIO_PuPd_UP|GPIO_InputBufferEnable|GPIO_CMOS);

// COL/RMII
GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, PAD_AF1);
GPIO_PinPadConfig(GPIOB, GPIO_PinSource5, GPIO_PuPd_UP|GPIO_InputBufferEnable|GPIO_CMOS);

// DUP (Duplex mode)
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, PAD_AF1);
GPIO_PinPadConfig(GPIOB, GPIO_PinSource6, GPIO_PuPd_UP|GPIO_InputBufferEnable|GPIO_CMOS);

// IP101G RESET_N (active low)

GPIO_PinAFConfig(GPIOD, GPIO_PinSource6, PAD_AF1);
GPIO_PinPadConfig(GPIOD, GPIO_PinSource6, GPIO_PuPd_UP);
// for this GPIOD pin 6, keep the following sequence, set the value & set the output enable
GPIO_ResetBits(GPIOD, GPIO_Pin_6);
GPIO_SetBits(GPIOD, GPIO_Pin_6); // PHY reset pin
GPIOD->OUTENSET = GPIO_Pin_6; // PHY reset pin
#endif

The standard library code here seems to also have no delay on the reset pulse (which is recommended to be 10ms or longer in the IP101G datasheet).

I have tried various modifications on this by adjusting the reset timing and RXDV pin state, but have not been able to make any progress.

(UPDATE)

After more testing I have found that doing a soft reset brings the IP101G into TP mode and it will link in loopback mode. With an external link partner connected and TP mode set the link still remains down.

Stepping through AN_ARBT_STATE I see that it stalls immediately on TRANSMIT_DISABLE.

Here is a dump from a board that fails to link once it is in TP mode

===== IP101G PHY register dump (PHY addr 7) =====
-- Page-independent registers (Reg) --
Reg 0 = 3100 Control Register
Reg 1 = 7849 Status Register
Reg 2 = 0243 PHY Identifier 1 Register
Reg 3 = 0C54 PHY Identifier 2 Register
Reg 4 = 01E1 Auto-Negotiation Advertisement Register
Reg 5 = 0000 Auto-Negotiation Link Partner Ability Register
Reg 6 = 0004 Auto-Negotiation Expansion Register
Reg 7 = 2001 Auto-Negotiation Next Page Transmit Register
Reg 8 = 0000 Auto-Negotiation Link Partner Next Page Register
Reg 13 = 0000 MMD Access Control Register
Reg 14 = 0000 MMD Access Address Data Register
Reg 20 = 0010 Page Control Register
-- Paged registers (page.reg) --
1.17 = 0000 PHY Specific Control Register
1.18 = 0000 RX CRC Error Counter Register
1.22 = 2020 Linear Regulator Output Control Register
1.23 = 8000 UTP PHY Specific Control Register
2.18 = 0000 RX Packet Counter Register
3.16 = 0000 LED Control Register
4.16 = 5F40 WOL+ Control Register
4.22 = 4000 Digital IO Pin Driving Control Register
5.16 = 0000 PHY WOL+ MAC Address Register
8.17 = 7000 RX Counter Control Register
11.18 = 0000 UTP PHY Interrupt Control/Status Register
16.16 = 0002 PHY Specific Control Register
16.17 = 0F00 PHY Interrupt Ctrl/Status Register
16.18 = 4000 PHY Status Monitoring Register
16.26 = 1249 Digital IO Pin Driving Control Register
16.27 = 0012 Digital IO Pin Driving Control Register
16.29 = 0782 Digital I/O Specific Control Register
16.30 = 0000 PHY MDI/MDIX Control and Specific Status Register
17.17 = 0000 PHY WOL+ Status Register
18.17 = 0000 RX Counter Interrupt Control/Status Register
-- MMD registers (devad.addr) --
3.0 = 0000 PCS Control 1 Register
3.1 = 0000 PCS Status 1 Register
3.20 = 0002 EEE Capability Register
3.22 = 0000 EEE Wake Error Count Register
7.60 = 0002 EEE Advertisement Register
7.61 = 0000 EEE Link Partner Ability Register
===== end of dump =====

Most of the differences correspond either to reserved registers or status registers which are only populated after link. The only register which would be set before negotiation is MDI/MDIX in UTP PHY Interrup Control/Status Register which is 1 by default and 1 in a working unit and 0 in a failing unit.

On the hardware side I have double checked the REGOUT/REGIN voltage, ISET resistor, and my external clock all of which are within the datasheet spec. I ruled out a bad RJ45 connector by soldering enamel wires to the TX/RX pair and put them on a 2GHz scope.

With the scope connected I do not see any NLP bursts which should be the default state of the IP101G for link partner discovery since APS is set by default (I did not see any FLP bursts either). Additionally, I tried setting Restart Auto-Negotiation in the Control Register to 1, since I realized this could just be a timing issue, nothing on the scope. I tried increasing the timing delay between to 2s so that the IP101G would have time to restart auto-negotiation (by default after 1-1.5s of a link being down it should attempt to auto-negotiate) and did not see anything.

Any help would be appreciated.

Thanks,

Kelanu R.

## Replies

### Reply 1 by kelanucr, 2026-07-18

It does seem like Auto-MDIX is still functioning as I can see the TX/RX pair occasionally flip on my scope. The fault seems to occur at auto-negotiation, the default state of AN_ARBIT_STATE is 0x8 (AUTO NEGOTIATION ENABLE) and is moving to 0x0 (TRANSMIT DISABLE) then timing out after 5s which means that it is not advancing to ABILITY DETECT. and the break_link_timer is not expiring.

break_link_timer not expiring would either point to a clock issue where the timer itself is just not advancing or an external event resetting the clock, or some unrecoverable fault in the AN state machine. The clock itself is outputting at 25MHz and I assume that the Auto-MDIX timing is managed by the clock so the clock seems to be fine. I am unsure what type of external reset would be causing break_link_timer to reset.

To rule out a faulty AN state machine on the IP101G I set Auto-Negotiation Enable to 0, Speed Selection to 1, and Duplex Mode to 1. The description of Auto-Negotiation Enable says these are the only bits that need to be set for forced mode but I still did not see anything on my scope. I then tried setting FORCE_LINK_100 to 1 and still did not see anything (I also tried disabling low power mode by setting LDPS_ENABLE to 0 and NWAY_PSAVE_DIS to 1).

As a tangent, suddenly the soft reset to bring the board back to TP mode was not working, so I revisited PHY_Init() and found a working combination to bring up in TP mode.

GPIO_PinPadConfig(GPIOB, GPIO_PinSource12, GPIO_PuPd_DOWN|GPIO_InputBufferEnable|GPIO_CMOS);
GPIOB->OUTENSET = GPIO_Pin_12;
GPIO_ResetBits(GPIOB, GPIO_Pin_12);

// COL (collision detect in normal mode)/RMII (MAC interface mode on reset high for RMII 0 for MII)
// RMII is Reduced MII (uses 7 lanes instead of 16)
// This shouldn't work? It doesn't seem to matter
GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, PAD_AF1);
GPIO_PinPadConfig(GPIOB, GPIO_PinSource5, GPIO_PuPd_UP|GPIO_InputBufferEnable|GPIO_CMOS);

// DUP (duplex mode)
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, PAD_AF1);
GPIO_PinPadConfig(GPIOB, GPIO_PinSource6, GPIO_PuPd_UP|GPIO_InputBufferEnable|GPIO_CMOS);

// IP101G RESET_N (active low)
GPIO_PinAFConfig(GPIOD, GPIO_PinSource6, PAD_AF1);
GPIO_PinPadConfig(GPIOD, GPIO_PinSource6, GPIO_PuPd_UP);
// for this GPIOD pin 6, keep the following sequence, set the value & set the output enable
GPIOD->OUTENSET = GPIO_Pin_6;
GPIO_ResetBits(GPIOD, GPIO_Pin_6);
ms_delay(15);
GPIO_SetBits(GPIOD, GPIO_Pin_6);

### Reply 2 by kelanucr, 2026-07-20

I have noticed I can replicate this failure mode on a working unit by modifying my link poll loop, which just calls PHY_GetLinkStatus when no link is detected, to instead first call PHY_Init(). Then after reconnecting a link partner the link fails to come up. This leads me to believe that the startup state of the IP101G is, in addition to causing it to sometimes boot in FX mode, causing the link to fail to come up.

### Reply 3 by Grace_Koo, 2026-07-20 (in reply to reply 2)

Hi Kelanu,

Thanks for the detailed writeup and register dumps. Based on what you've shared, this looks less like an AN state-machine issue or a single bad part, and more like the IP101G strap pins not latching reliably at the rising edge of RESET_N.

The main indicator is that your three units report different PHY addresses (1, 3, 7). The address is strap-latched at reset, so identical firmware/hardware producing different addresses suggests the straps aren't settling to defined levels. The intermittent FX/TP mode and the stalled auto-negotiation likely stem from the same cause. Your poll-loop experiment fits this too — calling `PHY_Init()` re-pulses RESET_N while the RMII lines are toggling, which can re-latch the straps and take down a previously-good unit.

On the W7500P the PHY is in-package, so there are no external strap resistors and the strap levels depend entirely on GPIO state and reset timing. The stock library only sets pull-ups (RXDV/FX_HEN floats high → FX mode) and pulses RESET_N with no delay, which seems relevant here.

Suggestions:

1. Drive the strap pins as GPIO outputs to defined levels rather than relying on pull-ups (FX_HEN/GPIOB12 low for TP). Your `PuPd_DOWN + OUTENSET + ResetBits` change is along these lines.

2. Order the reset sequence as: drive straps → RESET_N low ≥10 ms → release → wait the settling time → access MDIO. Your `ms_delay(15)` has the same intent.

3. In the poll loop, recover via MDIO soft reset (Reg0 bit15) or restart auto-neg (Reg0 bit9) instead of re-running `PHY_Init()`.

4. After the change, power-cycle the previously-failing unit several times and check that the PHY address and TP mode come up consistently. If that unit alone still varies, it's worth checking it at the component level too.

Hope this helps — let us know what you find.

Best regards,

### Reply 4 by kelanucr, 2026-07-22

Hi,

I have tried adjusting the strap logic, here is what I have at the moment

// initialize PHY strap pins
phy_strap.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_5 | GPIO_Pin_6;
phy_strap.GPIO_Direction = GPIO_Direction_OUT;
phy_strap.GPIO_Pad = GPIO_InputBufferEnable | GPIO_CMOS | GPIO_PuPd_DOWN;
phy_strap.GPIO_AF = PAD_AF1;
GPIO_Init(GPIOB, &phy_strap);

// initialize reset pin
phy_reset.GPIO_Pin = GPIO_Pin_6;
phy_reset.GPIO_Direction = GPIO_Direction_OUT;
phy_reset.GPIO_Pad = GPIO_PuPd_UP;
phy_reset.GPIO_AF = PAD_AF1;
GPIO_Init(GPIOD, &phy_reset);

// configure strap
GPIO_ResetBits(GPIOB, GPIO_Pin_12); // FX/TP mode
GPIO_SetBits(GPIOB, GPIO_Pin_5); // RMII mode (I also tried MII mode)
GPIO_SetBits(GPIOB, GPIO_Pin_6); // duplex

// reset sequence
GPIO_ResetBits(GPIOD, GPIO_Pin_6);
ms_delay(15);
GPIO_SetBits(GPIOD, GPIO_Pin_6);
ms_delay(15);

You mentioned RMII, but the W7500P ref manual says it uses MII; so I tried setting both. I have tried setting the restart auto negotiation bit.

### Reply 5 by kelanucr, 2026-07-23

Warming the board by about 10F from the ambient room temperature of about 70F causes all pins on the package to become shorted. I'm going to conclude that this particular unit was damaged from improper ESD protection on the board. I noticed that on the development board schematic an additional ESD protector was installed, which my board does not have.

Additionally, I believe the intermittent link state of the working boards is caused by EMI and improper decoupling after looking at the other posts on this form ie, link issues when near a servo or relay.

### Reply 6 by Alan, 2026-07-23 (in reply to reply 5)

A higher temperature itself does not cause ESD-related issues.
If you send us the design data, we can review it.

### Reply 7 by kelanucr, 2026-08-20

I'm not able to share the full schematic files, but it is functionally identical to the reference schematic from the WizNet Github. The only difference is that the GPIO pins are fanned out to headers but these headers are currently unpopulated. I've since swapped the uC and haven't had this problem yet again.

I did notice though that on another board the PHY link would fail intermittently when attaching external devices to the headers. When attaching an external device with decoupling capacitors the inrush current caused oscillations on the primary and analog 3v3 voltage rail causing swings above 4v and below 3v. That is my new theory on what may have killed the PHY.

---

Source: https://maker.wiznet.io/forum/16121
