From 5fd89e44618ddc4f6cd495c16df350aee7230d07 Mon Sep 17 00:00:00 2001 From: tanek liang Date: Thu, 7 Dec 2017 13:14:41 +0800 Subject: [PATCH] [bsp] update eth driver: fix phy init never timeout bug --- bsp/imxrt1052-evk/drivers/drv_eth.c | 163 +++++++++++++++------------- bsp/imxrt1052-evk/drivers/fsl_phy.c | 10 +- 2 files changed, 94 insertions(+), 79 deletions(-) diff --git a/bsp/imxrt1052-evk/drivers/drv_eth.c b/bsp/imxrt1052-evk/drivers/drv_eth.c index 8d02e26aea..79139753d9 100644 --- a/bsp/imxrt1052-evk/drivers/drv_eth.c +++ b/bsp/imxrt1052-evk/drivers/drv_eth.c @@ -28,7 +28,7 @@ #include #include "lwipopts.h" - + #define ENET_RXBD_NUM (4) #define ENET_TXBD_NUM (4) #define ENET_RXBUFF_SIZE (ENET_FRAME_MAX_FRAMELEN) @@ -36,16 +36,17 @@ #define PHY_ADDRESS 0x02u + + /* debug option */ -//#define DEBUG //#define ETH_RX_DUMP //#define ETH_TX_DUMP -#ifdef DEBUG -#define ETH_PRINTF rt_kprintf -#else -#define ETH_PRINTF(...) -#endif +#define DBG_ENABLE +#define DBG_SECTION_NAME "[ETH]" +#define DBG_COLOR +#define DBG_LEVEL DBG_INFO +#include #define MAX_ADDR_LEN 6 @@ -54,12 +55,12 @@ struct rt_imxrt_eth { /* inherit from ethernet device */ struct eth_device parent; - + enet_handle_t enet_handle; ENET_Type *enet_base; enet_data_error_stats_t error_statistic; rt_uint8_t dev_addr[MAX_ADDR_LEN]; /* hw address */ - + rt_bool_t tx_is_waiting; struct rt_semaphore tx_wait; }; @@ -75,9 +76,9 @@ static struct rt_imxrt_eth imxrt_eth_device; void _enet_rx_callback(struct rt_imxrt_eth * eth) { rt_err_t result; - + ENET_DisableInterrupts(eth->enet_base, kENET_RxFrameInterrupt); - + result = eth_device_ready(&(eth->parent)); if( result != RT_EOK ) rt_kprintf("RX err =%d\n", result ); @@ -97,30 +98,30 @@ void _enet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, switch(event) { case kENET_RxEvent: - + _enet_rx_callback((struct rt_imxrt_eth *)userData); break; - + case kENET_TxEvent: _enet_tx_callback((struct rt_imxrt_eth *)userData); break; - + case kENET_ErrEvent: //rt_kprintf("kENET_ErrEvent\n"); break; - + case kENET_WakeUpEvent: //rt_kprintf("kENET_WakeUpEvent\n"); break; - + case kENET_TimeStampEvent: //rt_kprintf("kENET_TimeStampEvent\n"); break; - + case kENET_TimeStampAvailEvent: //rt_kprintf("kENET_TimeStampAvailEvent \n"); break; - + default: //rt_kprintf("unknow error\n"); break; @@ -314,21 +315,21 @@ static void _enet_io_init(void) Pull Up / Down Config. Field: 100K Ohm Pull Up Hyst. Enable Field: Hysteresis Disabled */ - + } static void _enet_clk_init(void) { const clock_enet_pll_config_t config = {true, false, false, 1, 1}; CLOCK_InitEnetPll(&config); - + IOMUXC_EnableMode(IOMUXC_GPR, kIOMUXC_GPR_ENET1TxClkOutputDir, true); } static void _delay(void) { volatile int i = 1000000; - + while (i--) i = i; } @@ -336,7 +337,7 @@ static void _delay(void) static void _enet_phy_reset_by_gpio(void) { gpio_pin_config_t gpio_config = {kGPIO_DigitalOutput, 0, kGPIO_NoIntmode}; - + GPIO_PinInit(GPIO1, 9, &gpio_config); GPIO_PinInit(GPIO1, 10, &gpio_config); /* pull up the ENET_INT before RESET. */ @@ -354,7 +355,7 @@ static void _enet_config(void) phy_speed_t speed; phy_duplex_t duplex; bool link = false; - + /* prepare the buffer configuration. */ enet_buffer_config_t buffConfig = { ENET_RXBD_NUM, @@ -366,7 +367,7 @@ static void _enet_config(void) &g_rxDataBuff[0][0], &g_txDataBuff[0][0], }; - + /* Get default configuration. */ /* * config.miiMode = kENET_RmiiMode; @@ -377,26 +378,36 @@ static void _enet_config(void) ENET_GetDefaultConfig(&config); config.interrupt = kENET_TxFrameInterrupt | kENET_RxFrameInterrupt; //config.interrupt = 0xFFFFFFFF; - + /* Set SMI to get PHY link status. */ sysClock = CLOCK_GetFreq(kCLOCK_AhbClk); + status = PHY_Init(imxrt_eth_device.enet_base, PHY_ADDRESS, sysClock); - while (status != kStatus_Success) + + if (status == kStatus_Success) { - ETH_PRINTF("\r\nPHY Auto-negotiation failed. Please check the cable connection and link partner setting.\r\n"); - status = PHY_Init(imxrt_eth_device.enet_base, PHY_ADDRESS, sysClock); + PHY_GetLinkStatus(imxrt_eth_device.enet_base, PHY_ADDRESS, &link); + if (link) + { + /* Get the actual PHY link speed. */ + PHY_GetLinkSpeedDuplex(imxrt_eth_device.enet_base, PHY_ADDRESS, &speed, &duplex); + /* Change the MII speed and duplex for actual link status. */ + config.miiSpeed = (enet_mii_speed_t)speed; + config.miiDuplex = (enet_mii_duplex_t)duplex; + } + + dbg_log(DBG_LOG, "PHY Auto-negotiation success.\n"); + eth_device_linkchange(&imxrt_eth_device.parent, RT_TRUE); } - - PHY_GetLinkStatus(imxrt_eth_device.enet_base, PHY_ADDRESS, &link); - if (link) + else { - /* Get the actual PHY link speed. */ - PHY_GetLinkSpeedDuplex(imxrt_eth_device.enet_base, PHY_ADDRESS, &speed, &duplex); - /* Change the MII speed and duplex for actual link status. */ - config.miiSpeed = (enet_mii_speed_t)speed; - config.miiDuplex = (enet_mii_duplex_t)duplex; - } - + config.miiSpeed = kENET_MiiSpeed10M; + config.miiDuplex = kENET_MiiHalfDuplex; + + dbg_log(DBG_WARNING, "PHY Auto-negotiation failed. Please check the cable connection and link partner setting.\n"); + eth_device_linkchange(&imxrt_eth_device.parent, RT_FALSE); + } + ENET_Init(imxrt_eth_device.enet_base, &imxrt_eth_device.enet_handle, &config, &buffConfig, &imxrt_eth_device.dev_addr[0], sysClock); ENET_SetCallback(&imxrt_eth_device.enet_handle, _enet_callback, &imxrt_eth_device); ENET_ActiveRead(imxrt_eth_device.enet_base); @@ -408,7 +419,7 @@ static rt_err_t rt_imxrt_eth_init(rt_device_t dev) _enet_io_init(); _enet_clk_init(); _enet_phy_reset_by_gpio(); - + _enet_config(); return RT_EOK; @@ -416,33 +427,33 @@ static rt_err_t rt_imxrt_eth_init(rt_device_t dev) static rt_err_t rt_imxrt_eth_open(rt_device_t dev, rt_uint16_t oflag) { - ETH_PRINTF("rt_imxrt_eth_open...\n"); + dbg_log(DBG_LOG, "rt_imxrt_eth_open...\n"); return RT_EOK; } static rt_err_t rt_imxrt_eth_close(rt_device_t dev) { - ETH_PRINTF("rt_imxrt_eth_close...\n"); + dbg_log(DBG_LOG, "rt_imxrt_eth_close...\n"); return RT_EOK; } static rt_size_t rt_imxrt_eth_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) { - ETH_PRINTF("rt_imxrt_eth_read...\n"); + dbg_log(DBG_LOG, "rt_imxrt_eth_read...\n"); rt_set_errno(-RT_ENOSYS); return 0; } static rt_size_t rt_imxrt_eth_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) { - ETH_PRINTF("rt_imxrt_eth_write...\n"); + dbg_log(DBG_LOG, "rt_imxrt_eth_write...\n"); rt_set_errno(-RT_ENOSYS); return 0; } static rt_err_t rt_imxrt_eth_control(rt_device_t dev, int cmd, void *args) { - ETH_PRINTF("rt_imxrt_eth_control...\n"); + dbg_log(DBG_LOG, "rt_imxrt_eth_control...\n"); switch(cmd) { case NIOCTL_GADDR: @@ -468,7 +479,7 @@ rt_err_t rt_imxrt_eth_tx( rt_device_t dev, struct pbuf* p) RT_ASSERT(p != NULL); RT_ASSERT(enet_handle != RT_NULL); - ETH_PRINTF("rt_imxrt_eth_tx: %d\n", p->len); + dbg_log(DBG_LOG, "rt_imxrt_eth_tx: %d\n", p->len); #ifdef ETH_TX_DUMP { @@ -477,11 +488,11 @@ rt_err_t rt_imxrt_eth_tx( rt_device_t dev, struct pbuf* p) buf = (uint8_t *)p->payload; for (i = 0; i < p->len; i++) { - ETH_PRINTF("%02X ", buf[i]); + dbg_log(DBG_LOG, "%02X ", buf[i]); if (i % 16 == 15) - ETH_PRINTF("\n"); + dbg_log(DBG_LOG, "\n"); } - ETH_PRINTF("\n"); + dbg_log(DBG_LOG, "\n"); } #endif @@ -504,12 +515,12 @@ struct pbuf *rt_imxrt_eth_rx(rt_device_t dev) { uint32_t length = 0; status_t status; - + struct pbuf* p = RT_NULL; enet_handle_t * enet_handle = &imxrt_eth_device.enet_handle; ENET_Type *enet_base = imxrt_eth_device.enet_base; enet_data_error_stats_t *error_statistic = &imxrt_eth_device.error_statistic; - + /* Get the Frame size */ status = ENET_GetRxFrameSize(enet_handle, &length); @@ -518,7 +529,7 @@ struct pbuf *rt_imxrt_eth_rx(rt_device_t dev) { /* Received valid frame. Deliver the rx buffer with the size equal to length. */ p = pbuf_alloc(PBUF_RAW, length, PBUF_POOL); - + if (p != NULL) { status = ENET_ReadFrame(enet_base, enet_handle, p->payload, length); @@ -532,28 +543,28 @@ struct pbuf *rt_imxrt_eth_rx(rt_device_t dev) buf = (uint8_t *)p->payload; for (i = 0; i < p->len; i++) { - ETH_PRINTF("%02X ", buf[i]); + dbg_log(DBG_LOG, "%02X ", buf[i]); if (i % 16 == 15) - ETH_PRINTF("\n"); + dbg_log(DBG_LOG, "\n"); } - ETH_PRINTF("\n"); + dbg_log(DBG_LOG, "\n"); #endif return p; } else { - ETH_PRINTF(" A frame read failed\n"); + dbg_log(DBG_LOG, " A frame read failed\n"); pbuf_free(p); } } else { - ETH_PRINTF(" pbuf_alloc faild\n"); + dbg_log(DBG_LOG, " pbuf_alloc faild\n"); } } else if (status == kStatus_ENET_RxFrameError) { - ETH_PRINTF("ENET_GetRxFrameSize: kStatus_ENET_RxFrameError\n"); + dbg_log(DBG_WARNING, "ENET_GetRxFrameSize: kStatus_ENET_RxFrameError\n"); /* Update the received buffer when error happened. */ /* Get the error information of the received g_frame. */ ENET_GetRxErrBeforeReadFrame(enet_handle, error_statistic); @@ -577,7 +588,7 @@ static int rt_hw_imxrt_eth_init(void) imxrt_eth_device.dev_addr[3] = 0x12; imxrt_eth_device.dev_addr[4] = 0x34; imxrt_eth_device.dev_addr[5] = 0x56; - + imxrt_eth_device.enet_base = ENET; imxrt_eth_device.parent.parent.init = rt_imxrt_eth_init; @@ -591,20 +602,20 @@ static int rt_hw_imxrt_eth_init(void) imxrt_eth_device.parent.eth_rx = rt_imxrt_eth_rx; imxrt_eth_device.parent.eth_tx = rt_imxrt_eth_tx; - ETH_PRINTF("sem init: tx_wait\r\n"); + dbg_log(DBG_LOG, "sem init: tx_wait\r\n"); /* init tx semaphore */ rt_sem_init(&imxrt_eth_device.tx_wait, "tx_wait", 0, RT_IPC_FLAG_FIFO); /* register eth device */ - ETH_PRINTF("eth_device_init start\r\n"); + dbg_log(DBG_LOG, "eth_device_init start\r\n"); state = eth_device_init(&(imxrt_eth_device.parent), "e0"); if (RT_EOK == state) { - ETH_PRINTF("eth_device_init success\r\n"); + dbg_log(DBG_LOG, "eth_device_init success\r\n"); } else { - ETH_PRINTF("eth_device_init faild: %d\r\n", state); + dbg_log(DBG_LOG, "eth_device_init faild: %d\r\n", state); } return state; } @@ -618,7 +629,7 @@ void phy_read(uint32_t phyReg) { uint32_t data; status_t status; - + status = PHY_Read(imxrt_eth_device.enet_base, PHY_ADDRESS, phyReg, &data); if (kStatus_Success == status) { @@ -633,7 +644,7 @@ void phy_read(uint32_t phyReg) void phy_write(uint32_t phyReg, uint32_t data) { status_t status; - + status = PHY_Write(imxrt_eth_device.enet_base, PHY_ADDRESS, phyReg, data); if (kStatus_Success == status) { @@ -649,7 +660,7 @@ void phy_dump(void) { uint32_t data; status_t status; - + int i; for (i = 0; i < 32; i++) { @@ -659,7 +670,7 @@ void phy_dump(void) rt_kprintf("phy_dump: %02X --> faild", i); break; } - + if (i % 8 == 7) { rt_kprintf("%02X --> %08X ", i, data); @@ -668,17 +679,17 @@ void phy_dump(void) { rt_kprintf("%02X --> %08X\n", i, data); } - + } } void enet_reg_dump(void) { ENET_Type *enet_base = imxrt_eth_device.enet_base; - + #define DUMP_REG(__REG) \ rt_kprintf("%s(%08X): %08X\n", #__REG, (uint32_t)&enet_base->__REG, enet_base->__REG) - + DUMP_REG(EIR); DUMP_REG(EIMR); DUMP_REG(RDAR); @@ -785,16 +796,16 @@ void enet_nvic_tog(void) void enet_rx_stat(void) { enet_data_error_stats_t *error_statistic = &imxrt_eth_device.error_statistic; - + #define DUMP_STAT(__VAR) \ rt_kprintf("%-25s: %08X\n", #__VAR, error_statistic->__VAR); - + DUMP_STAT(statsRxLenGreaterErr); DUMP_STAT(statsRxAlignErr); DUMP_STAT(statsRxFcsErr); DUMP_STAT(statsRxOverRunErr); DUMP_STAT(statsRxTruncateErr); - + #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE DUMP_STAT(statsRxProtocolChecksumErr); DUMP_STAT(statsRxIpHeadChecksumErr); @@ -808,8 +819,8 @@ void enet_rx_stat(void) DUMP_STAT(statsTxExcessCollisionErr); DUMP_STAT(statsTxUnderFlowErr); DUMP_STAT(statsTxTsErr); -#endif - +#endif + } void enet_buf_info(void) @@ -818,7 +829,7 @@ void enet_buf_info(void) int i = 0; for (i = 0; i < ENET_RXBD_NUM; i++) { - rt_kprintf("%d: length: %-8d, control: %04X, buffer:%p\n", + rt_kprintf("%d: length: %-8d, control: %04X, buffer:%p\n", i, g_rxBuffDescrip[i].length, g_rxBuffDescrip[i].control, @@ -827,7 +838,7 @@ void enet_buf_info(void) for (i = 0; i < ENET_TXBD_NUM; i++) { - rt_kprintf("%d: length: %-8d, control: %04X, buffer:%p\n", + rt_kprintf("%d: length: %-8d, control: %04X, buffer:%p\n", i, g_txBuffDescrip[i].length, g_txBuffDescrip[i].control, diff --git a/bsp/imxrt1052-evk/drivers/fsl_phy.c b/bsp/imxrt1052-evk/drivers/fsl_phy.c index ec8443244b..d835e758e0 100644 --- a/bsp/imxrt1052-evk/drivers/fsl_phy.c +++ b/bsp/imxrt1052-evk/drivers/fsl_phy.c @@ -29,12 +29,13 @@ */ #include "fsl_phy.h" +#include /******************************************************************************* * Definitions ******************************************************************************/ /*! @brief Defines the timeout macro. */ -#define PHY_TIMEOUT_COUNT 0x3FFFFFFU +#define PHY_TIMEOUT_COUNT 0xFFFFU /******************************************************************************* * Prototypes @@ -83,14 +84,14 @@ status_t PHY_Init(ENET_Type *base, uint32_t phyAddr, uint32_t srcClock_Hz) PHY_Read(base, phyAddr, PHY_ID1_REG, &idReg); counter --; } - + if (!counter) { return kStatus_Fail; } /* Reset PHY. */ - counter = PHY_TIMEOUT_COUNT; + counter = 6; result = PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, PHY_BCTL_RESET_MASK); if (result == kStatus_Success) { @@ -136,6 +137,9 @@ status_t PHY_Init(ENET_Type *base, uint32_t phyAddr, uint32_t srcClock_Hz) break; } } + + rt_kprintf("[PHY] wait autonegotiation complete...\n"); + rt_thread_delay(RT_TICK_PER_SECOND); if (!counter) {