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;
}
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!
-----------------------------------------------------------------------------------------------------------------------