PHY device not responding to MDIO

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

PHY device not responding to MDIO

2,277 Views
chaitannyamahat
Contributor II

Hello Everyone,

I am using the K60DN512 device with 8720A PHY IC. I have written a simple program to communicate with the PHY IC. I have checked it on logic analyser and I am not getting any response from the PHY device. What can be possible causes.

Configuration of PHY device straps.

PHYAD[0]: Pulled low.

MODE[2:0] : 011 100Base-TX Full Duplex. Auto-negotiation disabled. CRS is active during Receive.

MDIO : Pulled high.

MDC: 1 Mhz.

I am using the processor expert generated code. So in that case there shouldn't be any error. What can be the possible reason for communication failure. The value is either 0 or 0xFFFF.

main(){

    MAChandler = mac_Init(NULL);

    Bit1_Init(NULL);

   

    uint16_t id = 0;

    uint16_t value = 0;

    uint16_t timeout = 0;

    uint16_t count = 0;

    uint8_t sfr = 0;

    const uint8_t netifLINK_DELAY = 3;

    do {

        mii_read(id, PHY_PHYIDR1, &value);

        count++;

    } while (value == 0xffff);

    do {

        value = 0xffff;

        mii_read(id, sfr, &value);

        if (value != 0xffff)

            sfr++;

        count++;

    } while (sfr <= 0x1F);

    uint16 config;

    do {

        config = 0x2200;

        mii_write(id, PHY_BMCR, config);

        uint16_t i, j;

        for (i = 0; i < 0xFF; i++)

            for (j = 0; j < 0xFFFF; j++)

                ;

        mii_read(id, PHY_BMCR, &value);

        count++;

    } while (value != config);

}

int mii_write(int phy_addr, int reg_addr, uint16_t data) {

    int timeout;

    /* Clear the MII interrupt bit */ENET_EIR /*(ch)*/= ENET_EIR_MII_MASK;

    /* Initiatate the MII Management write */ENET_MMFR /*(ch)*/=

            0 | ENET_MMFR_ST(0x01) | ENET_MMFR_OP(0x01) | ENET_MMFR_PA(phy_addr)

                    | ENET_MMFR_RA(reg_addr) | ENET_MMFR_TA(0x02)

                    | ENET_MMFR_DATA(data);

    /* Poll for the MII interrupt (interrupt should be masked) */

    for (timeout = 0; timeout < MII_TIMEOUT; timeout++) {

        if (ENET_EIR /*(ch)*/& ENET_EIR_MII_MASK)

            break;

    }

    if (timeout == MII_TIMEOUT)

        return 1;

    /* Clear the MII interrupt bit */ENET_EIR /*(ch)*/= ENET_EIR_MII_MASK;

    return 0;

}

/********************************************************************/

/*!

* \brief   Read a value from a PHY's MII register.

* \param   phy_addr    Address of the PHY

* \param   reg_addr    Address of the register in the PHY

* \param   data        Pointer to location were read data will be stored

* \return  0 if write is successful; 1 if write times out

*

* mii_read() polls for the FEC's MII interrupt event (which should

* be masked from the interrupt handler) and clears it. If after a

* suitable amount of time the event isn't triggered, a non-zero value

* is returned.

*/

int mii_read(int phy_addr, int reg_addr, uint16_t *data) {

    int timeout;

    /* Clear the MII interrupt bit */ENET_EIR /*(ch)*/= ENET_EIR_MII_MASK;

    Bit1_SetVal(NULL); // Indication that the MDIO transfer is about to begin.

    /* Initiatate the MII Management read */ENET_MMFR /*(ch)*/= 0

            | ENET_MMFR_ST(0x01) | ENET_MMFR_OP(0x2) | ENET_MMFR_PA(phy_addr)

            | ENET_MMFR_RA(reg_addr) | ENET_MMFR_TA(0x02);

    /* Poll for the MII interrupt (interrupt should be masked) */

    for (timeout = 0; timeout < MII_TIMEOUT; timeout++) {

        if (ENET_EIR /*(ch)*/& ENET_EIR_MII_MASK){

            Bit1_ClrVal(NULL); // Indication that the MDIO transfer is complete.

            break;

        }

    }

    if (timeout == MII_TIMEOUT)

        return 1;

   

    /* Clear the MII interrupt bit */ENET_EIR /*(ch)*/= ENET_EIR_MII_MASK;

    uint16_t test = ENET_MMFR /*(ch)*/& 0x0000FFFF;

    *data = ENET_MMFR /*(ch)*/& 0x0000FFFF;

    return 0;

}

Labels (1)
0 Kudos
1 Reply

1,057 Views
Kan_Li
NXP TechSupport
NXP TechSupport

Hi,

Are you sure you are using the PE generated code? after I checked the Ethernet demo from CW 10.6, the generated driver is different from what you show, for example, the mii_read() should be the following:

/*

** ===================================================================

**    Method      :  ETH_ReadMII (component Ethernet_LDD)

*/

/*!

**    @brief

**        Initiates a MII register read operation. The end of the

**        operation is signalized by the OnMIIFinished event in the

**        interrupt mode or by the GetMIIResult method in the polled

**        mode. The value of the register is returned by the

**        GetMIIResult method. This method is available only if

**        management bus is enabled.

**    @param

**        DeviceDataPtr  - Pointer to device data

**                          structure.

**    @param

**        PhyAddr        - PHY device address.

**    @param

**        RegAddr        - MII register address.

**    @return

**                        -

**                          Error code, possible values:

**                          ERR_OK - OK

**                          ERR_SPEED - The component does not work in

**                          the active clock configuration

**                          ERR_DISABLED - The component is disabled

*/

/* ===================================================================*/

LDD_TError ETH_ReadMII(LDD_TDeviceData *DeviceDataPtr, uint8_t PhyAddr, uint8_t RegAddr)

{

  ETH_TDeviceData *DeviceDataPrv = (ETH_TDeviceData*)DeviceDataPtr;

  (void)DeviceDataPrv;                /* Supress unused variable warning if needed */

  ENET_PDD_SendMIIFrame(ENET_BASE_PTR, ENET_PDD_MII_READ, PhyAddr, RegAddr, 0U);

  return ERR_OK;

}

#define ENET_PDD_SendMIIFrame(PeripheralBase, OpCode, PhyAddr, RegAddr, Data) ( \

    ENET_MMFR_REG(PeripheralBase) = \

    (uint32_t)(( \

      (uint32_t)((uint32_t)0x1U << ENET_MMFR_ST_SHIFT)) | (( \

      (uint32_t)(OpCode)) | (( \

      (uint32_t)((uint32_t)(PhyAddr) << ENET_MMFR_PA_SHIFT)) | (( \

      (uint32_t)((uint32_t)(RegAddr) << ENET_MMFR_RA_SHIFT)) | (( \

      (uint32_t)((uint32_t)0x2U << ENET_MMFR_TA_SHIFT)) | ( \

      (uint32_t)(Data))))))) \

  )

and have you configured the pins for MDIO and MDC, for the device of K60N512, they are PTB0 and PTB1.

Please kindly refer to "C:\Freescale\CW MCU v10.6\MCU\CodeWarrior_Examples\Processor_Expert\Kinetis\TWR-K60N512\Ethernet" for more details.

Hope that helps,


Have a great day,
Kan

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos