Преглед на файлове

[bsp] update emac driver

- fix 10 or hard duplex not work
- rewrite tx/rx function
- update emac init function
tanek liang преди 7 години
родител
ревизия
e2b5f7a722
променени са 1 файла, в които са добавени 524 реда и са изтрити 390 реда
  1. 524 390
      bsp/lpc54608-LPCXpresso/drivers/drv_emac.c

+ 524 - 390
bsp/lpc54608-LPCXpresso/drivers/drv_emac.c

@@ -22,6 +22,7 @@
  */
  */
 
 
 #include <rtthread.h>
 #include <rtthread.h>
+
 #include "lwipopts.h"
 #include "lwipopts.h"
 #include <netif/ethernetif.h>
 #include <netif/ethernetif.h>
 #include <board.h>
 #include <board.h>
@@ -32,6 +33,16 @@
 #include "fsl_sctimer.h"
 #include "fsl_sctimer.h"
 #include "fsl_phy.h"
 #include "fsl_phy.h"
 
 
+#define DEBUG
+//#define ETH_RX_DUMP
+//#define ETH_TX_DUMP
+#define ETH_STATISTICS
+
+#ifdef DEBUG
+#define ETH_PRINTF          rt_kprintf
+#else
+#define ETH_PRINTF(...)
+#endif
 
 
 #define IOCON_PIO_DIGITAL_EN        0x0100u   /*!< Enables digital function */
 #define IOCON_PIO_DIGITAL_EN        0x0100u   /*!< Enables digital function */
 #define IOCON_PIO_FUNC0               0x00u   /*!< Selects pin function 0 */
 #define IOCON_PIO_FUNC0               0x00u   /*!< Selects pin function 0 */
@@ -60,388 +71,313 @@
 #define PORT2_IDX                        2u   /*!< Port index */
 #define PORT2_IDX                        2u   /*!< Port index */
 #define PORT4_IDX                        4u   /*!< Port index */
 #define PORT4_IDX                        4u   /*!< Port index */
 
 
+#define MAX_ADDR_LEN                     6u
+#define ENET_RXBD_NUM                    4u
+#define ENET_TXBD_NUM                    4u
 
 
-#define EMAC_PHY_AUTO       0
-#define EMAC_PHY_10MBIT     1
-#define EMAC_PHY_100MBIT    2
-
-#define MAX_ADDR_LEN 6
+#define ENET_ALIGN(x) \
+    ((unsigned int)((x) + ((ENET_BUFF_ALIGNMENT)-1)) & (unsigned int)(~(unsigned int)((ENET_BUFF_ALIGNMENT)-1)))
 
 
-/* EMAC_RAM_BASE is defined in board.h and the size is 16KB */
-#define RX_DESC_BASE        ETH_RAM_BASE
-#define RX_STAT_BASE        (RX_DESC_BASE + NUM_RX_FRAG*8)
-#define TX_DESC_BASE        (RX_STAT_BASE + NUM_RX_FRAG*8)
-#define TX_STAT_BASE        (TX_DESC_BASE + NUM_TX_FRAG*8)
-#define RX_BUF_BASE         (TX_STAT_BASE + NUM_TX_FRAG*4)
-#define TX_BUF_BASE         (RX_BUF_BASE  + NUM_RX_FRAG*ETH_FRAG_SIZE)
-
-/* RX and TX descriptor and status definitions. */
-#define RX_DESC_PACKET(i)   (*(unsigned int *)(RX_DESC_BASE   + 8*i))
-#define RX_DESC_CTRL(i)     (*(unsigned int *)(RX_DESC_BASE+4 + 8*i))
-#define RX_STAT_INFO(i)     (*(unsigned int *)(RX_STAT_BASE   + 8*i))
-#define RX_STAT_HASHCRC(i)  (*(unsigned int *)(RX_STAT_BASE+4 + 8*i))
-#define TX_DESC_PACKET(i)   (*(unsigned int *)(TX_DESC_BASE   + 8*i))
-#define TX_DESC_CTRL(i)     (*(unsigned int *)(TX_DESC_BASE+4 + 8*i))
-#define TX_STAT_INFO(i)     (*(unsigned int *)(TX_STAT_BASE   + 4*i))
-#define RX_BUF(i)           (RX_BUF_BASE + ETH_FRAG_SIZE*i)
-#define TX_BUF(i)           (TX_BUF_BASE + ETH_FRAG_SIZE*i)
+#define ENET_RXBUFF_SIZE                (ENET_FRAME_MAX_FRAMELEN)
+#define ENET_TXBUFF_SIZE                (ENET_FRAME_MAX_FRAMELEN)
 
 
 struct lpc_emac
 struct lpc_emac
 {
 {
     /* inherit from ethernet device */
     /* inherit from ethernet device */
     struct eth_device parent;
     struct eth_device parent;
-
-    rt_uint8_t phy_mode;
-
+    struct rt_semaphore tx_wait;
+    
+    ENET_Type *base;
+    enet_handle_t handle;
+    
     /* interface address info. */
     /* interface address info. */
     rt_uint8_t  dev_addr[MAX_ADDR_LEN];     /* hw address   */
     rt_uint8_t  dev_addr[MAX_ADDR_LEN];     /* hw address   */
+    uint32_t phyAddr;
+    
+    uint8_t RxBuffDescrip[ENET_RXBD_NUM * sizeof(enet_rx_bd_struct_t) + ENET_BUFF_ALIGNMENT];
+    uint8_t TxBuffDescrip[ENET_TXBD_NUM * sizeof(enet_tx_bd_struct_t) + ENET_BUFF_ALIGNMENT];
+    uint8_t RxDataBuff[ENET_RXBD_NUM * ENET_ALIGN(ENET_RXBUFF_SIZE) + ENET_BUFF_ALIGNMENT];
+    uint8_t TxDataBuff[ENET_TXBD_NUM * ENET_ALIGN(ENET_TXBUFF_SIZE) + ENET_BUFF_ALIGNMENT];
+    uint8_t txIdx;
 };
 };
+
 static struct lpc_emac lpc_emac_device;
 static struct lpc_emac lpc_emac_device;
-static struct rt_semaphore sem_lock;
-static struct rt_event tx_event;
 
 
-#if defined(__GNUC__)
-#ifndef __ALIGN_END
-#define __ALIGN_END __attribute__((aligned(ENET_BUFF_ALIGNMENT)))
-#endif
-#ifndef __ALIGN_BEGIN
-#define __ALIGN_BEGIN
-#endif
-#else
-#ifndef __ALIGN_END
-#define __ALIGN_END
-#endif
-#ifndef __ALIGN_BEGIN
-#if defined(__CC_ARM)
-#define __ALIGN_BEGIN __align(ENET_BUFF_ALIGNMENT)
-#elif defined(__ICCARM__)
-#define __ALIGN_BEGIN
-#endif
-#endif
+#ifdef ETH_STATISTICS
+static uint32_t isr_rx_counter = 0;
+static uint32_t isr_tx_counter = 0;
 #endif
 #endif
 
 
-#define ENET_RXBD_NUM (4)
-#define ENET_TXBD_NUM (4)
-#define PHY_ADDR (0x00U)
-#define ENET_LOOP_COUNT (20U)
-#define ENET_ALIGN(x, align) ((unsigned int)((x) + ((align)-1)) & (unsigned int)(~(unsigned int)((align)-1)))
-#define ENET_BuffSizeAlign(n) ENET_ALIGN(n, ENET_BUFF_ALIGNMENT)
-
-__ALIGN_BEGIN enet_rx_bd_struct_t g_rxBuffDescrip[ENET_RXBD_NUM] __ALIGN_END;
-__ALIGN_BEGIN enet_tx_bd_struct_t g_txBuffDescrip[ENET_TXBD_NUM] __ALIGN_END;
-
-
-uint8_t multicastAddr[6] = {0x01, 0x00, 0x5e, 0x00, 0x01, 0x81};
-uint8_t *g_txbuff[ENET_TXBD_NUM];
-uint32_t g_txIdx = 0;
-uint8_t g_txbuffIdx = 0;
-uint8_t g_txGenIdx = 0;
-uint8_t g_txCosumIdx = 0;
-uint8_t g_txUsed = 0;
-uint8_t g_rxGenIdx = 0;
-uint32_t g_rxCosumIdx = 0;
-uint32_t g_rxbuffer[ENET_RXBD_NUM];
+static inline enet_rx_bd_struct_t *get_rx_desc(uint32_t index)
+{
+    return (enet_rx_bd_struct_t *)ENET_ALIGN(&lpc_emac_device.RxBuffDescrip[index * sizeof(enet_rx_bd_struct_t)]);
+}
 
 
+static inline enet_tx_bd_struct_t *get_tx_desc(uint32_t index)
+{
+    return (enet_tx_bd_struct_t *)ENET_ALIGN(&lpc_emac_device.TxBuffDescrip[index * sizeof(enet_tx_bd_struct_t)]);
+}
 
 
-static uint8_t *ENET_RXRead(int32_t *length)
+#if defined(ETH_RX_DUMP) ||  defined(ETH_TX_DUMP)
+static void packet_dump(const char * msg, const struct pbuf* p)
 {
 {
-    uint32_t control;
-    uint8_t *data;
-    *length = 0;
+    const struct pbuf* q;
+    rt_uint32_t i,j;
+    rt_uint8_t *ptr;
+
+    rt_kprintf("%s %d byte\n", msg, p->tot_len);
 
 
-    /* Get the Frame size */
-    control = ENET_GetRxDescriptor(&g_rxBuffDescrip[g_rxGenIdx]);
-    if (!(control & ENET_RXDESCRIP_RD_OWN_MASK))
+    i=0;
+    for(q=p; q != RT_NULL; q= q->next)
     {
     {
-        if (control & ENET_RXDESCRIP_WR_LD_MASK)
+        ptr = q->payload;
+
+        for(j=0; j<q->len; j++)
         {
         {
-            /* if no error */
-            if (control & ENET_RXDESCRIP_WR_ERRSUM_MASK)
+            if( (i%8) == 0 )
             {
             {
-                *length = -1;
+                rt_kprintf("  ");
             }
             }
-            else
+            if( (i%16) == 0 )
             {
             {
-                *length = control & ENET_RXDESCRIP_WR_PACKETLEN_MASK;
-                data = (uint8_t *)g_rxbuffer[g_rxGenIdx];
+                rt_kprintf("\r\n");
             }
             }
-            g_rxGenIdx = (g_rxGenIdx + 1) % ENET_RXBD_NUM;
-        }
-    }
-    return data;
-}
+            rt_kprintf("%02x ",*ptr);
 
 
-static void ENET_RXClaim(uint8_t* buffer)
-{
-    if (ENET_GetDmaInterruptStatus(ENET, 0) & kENET_DmaRxBuffUnavail)
-    {
-        ENET_UpdateRxDescriptor(&g_rxBuffDescrip[g_rxCosumIdx], buffer, NULL, true, false);
-        /* Command for rx poll when the dma suspend. */
-        ENET_UpdateRxDescriptorTail(ENET, 0, (uint32_t)&g_rxBuffDescrip[ENET_RXBD_NUM]);
-    }
-    else
-    {
-        ENET_UpdateRxDescriptor(&g_rxBuffDescrip[g_rxCosumIdx], buffer, NULL, true, false);
-    }
-
-    if (buffer)
-    {
-        g_rxbuffer[g_rxCosumIdx] = (uint32_t)buffer;
+            i++;
+            ptr++;
+        }
     }
     }
 
 
-    g_rxCosumIdx = (g_rxCosumIdx + 1) % ENET_RXBD_NUM;
+    rt_kprintf("\n\n");
 }
 }
+#else
+#define packet_dump(...)
+#endif /* dump */
 
 
-
-static status_t ENET_TXQueue(uint8_t *data, uint16_t length)
+static void ethernet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, uint8_t channel, void *param)
 {
 {
-    uint32_t txdescTailAddr;
-
-    /* Fill the descriptor. */
-    if (ENET_IsTxDescriptorDmaOwn(&g_txBuffDescrip[g_txGenIdx]))
-    {
-        return kStatus_Fail;
-    }
-    ENET_SetupTxDescriptor(&g_txBuffDescrip[g_txGenIdx], data, length, NULL, 0, length, true, false, kENET_FirstLastFlag, 0);
-
-    /* Increase the index. */
-    g_txGenIdx = (g_txGenIdx + 1) % ENET_TXBD_NUM;
-    g_txUsed++;
-
-    /* Update the transmit tail address. */
-    txdescTailAddr = (uint32_t)&g_txBuffDescrip[g_txGenIdx];
-    if (!g_txGenIdx)
+    switch (event)
     {
     {
-        txdescTailAddr = (uint32_t)&g_txBuffDescrip[ENET_TXBD_NUM];
+        case kENET_RxIntEvent:
+#ifdef ETH_STATISTICS
+            isr_rx_counter++;
+#endif
+            /* a frame has been received */
+            eth_device_ready(&(lpc_emac_device.parent));
+            break;
+        case kENET_TxIntEvent:
+#ifdef ETH_STATISTICS
+            isr_tx_counter++;
+#endif
+            /* set event */
+            rt_sem_release(&lpc_emac_device.tx_wait);
+            break;
+        default:
+            break;
     }
     }
-    ENET_UpdateTxDescriptorTail(ENET, 0, txdescTailAddr);
-    return kStatus_Success;
 }
 }
 
 
-static void ENET_TXReclaim()
+static void lcp_emac_io_init(void)
 {
 {
-    if (!ENET_IsTxDescriptorDmaOwn(&g_txBuffDescrip[g_txCosumIdx]) && (g_txUsed > 0))
-    {
-        /* Free tx buffers. */
-        free(g_txbuff[g_txCosumIdx]);
-        g_txUsed--;
-        g_txCosumIdx = (g_txCosumIdx + 1) % ENET_TXBD_NUM;
-    }
+    const uint32_t port0_pin17_config = (
+                                            IOCON_PIO_FUNC7 |                                        /* Pin is configured as ENET_TXD1 */
+                                            IOCON_PIO_MODE_INACT |                                   /* No addition pin function */
+                                            IOCON_PIO_INV_DI |                                       /* Input function is not inverted */
+                                            IOCON_PIO_DIGITAL_EN |                                   /* Enables digital function */
+                                            IOCON_PIO_INPFILT_OFF |                                  /* Input filter disabled */
+                                            IOCON_PIO_SLEW_STANDARD |                                /* Standard mode, output slew rate control is enabled */
+                                            IOCON_PIO_OPENDRAIN_DI                                   /* Open drain is disabled */
+                                        );
+    IOCON_PinMuxSet(IOCON, PORT0_IDX, PIN17_IDX, port0_pin17_config); /* PORT0 PIN17 (coords: E14) is configured as ENET_TXD1 */
+    const uint32_t port2_pin26_config = (
+                                            IOCON_PIO_FUNC0 |                                        /* Pin is configured as PIO2_26 */
+                                            IOCON_PIO_MODE_PULLUP |                                  /* Selects pull-up function */
+                                            IOCON_PIO_INV_DI |                                       /* Input function is not inverted */
+                                            IOCON_PIO_DIGITAL_EN |                                   /* Enables digital function */
+                                            IOCON_PIO_INPFILT_OFF |                                  /* Input filter disabled */
+                                            IOCON_PIO_SLEW_STANDARD |                                /* Standard mode, output slew rate control is enabled */
+                                            IOCON_PIO_OPENDRAIN_DI                                   /* Open drain is disabled */
+                                        );
+    IOCON_PinMuxSet(IOCON, PORT2_IDX, PIN26_IDX, port2_pin26_config); /* PORT2 PIN26 (coords: H11) is configured as PIO2_26 */
+    const uint32_t port4_pin10_config = (
+                                            IOCON_PIO_FUNC1 |                                        /* Pin is configured as ENET_RX_DV */
+                                            IOCON_PIO_MODE_INACT |                                   /* No addition pin function */
+                                            IOCON_PIO_INV_DI |                                       /* Input function is not inverted */
+                                            IOCON_PIO_DIGITAL_EN |                                   /* Enables digital function */
+                                            IOCON_PIO_INPFILT_OFF |                                  /* Input filter disabled */
+                                            IOCON_PIO_SLEW_STANDARD |                                /* Standard mode, output slew rate control is enabled */
+                                            IOCON_PIO_OPENDRAIN_DI                                   /* Open drain is disabled */
+                                        );
+    IOCON_PinMuxSet(IOCON, PORT4_IDX, PIN10_IDX, port4_pin10_config); /* PORT4 PIN10 (coords: B9) is configured as ENET_RX_DV */
+    const uint32_t port4_pin11_config = (
+                                            IOCON_PIO_FUNC1 |                                        /* Pin is configured as ENET_RXD0 */
+                                            IOCON_PIO_MODE_INACT |                                   /* No addition pin function */
+                                            IOCON_PIO_INV_DI |                                       /* Input function is not inverted */
+                                            IOCON_PIO_DIGITAL_EN |                                   /* Enables digital function */
+                                            IOCON_PIO_INPFILT_OFF |                                  /* Input filter disabled */
+                                            IOCON_PIO_SLEW_STANDARD |                                /* Standard mode, output slew rate control is enabled */
+                                            IOCON_PIO_OPENDRAIN_DI                                   /* Open drain is disabled */
+                                        );
+    IOCON_PinMuxSet(IOCON, PORT4_IDX, PIN11_IDX, port4_pin11_config); /* PORT4 PIN11 (coords: A9) is configured as ENET_RXD0 */
+    const uint32_t port4_pin12_config = (
+                                            IOCON_PIO_FUNC1 |                                        /* Pin is configured as ENET_RXD1 */
+                                            IOCON_PIO_MODE_INACT |                                   /* No addition pin function */
+                                            IOCON_PIO_INV_DI |                                       /* Input function is not inverted */
+                                            IOCON_PIO_DIGITAL_EN |                                   /* Enables digital function */
+                                            IOCON_PIO_INPFILT_OFF |                                  /* Input filter disabled */
+                                            IOCON_PIO_SLEW_STANDARD |                                /* Standard mode, output slew rate control is enabled */
+                                            IOCON_PIO_OPENDRAIN_DI                                   /* Open drain is disabled */
+                                        );
+    IOCON_PinMuxSet(IOCON, PORT4_IDX, PIN12_IDX, port4_pin12_config); /* PORT4 PIN12 (coords: A6) is configured as ENET_RXD1 */
+    const uint32_t port4_pin13_config = (
+                                            IOCON_PIO_FUNC1 |                                        /* Pin is configured as ENET_TX_EN */
+                                            IOCON_PIO_MODE_INACT |                                   /* No addition pin function */
+                                            IOCON_PIO_INV_DI |                                       /* Input function is not inverted */
+                                            IOCON_PIO_DIGITAL_EN |                                   /* Enables digital function */
+                                            IOCON_PIO_INPFILT_OFF |                                  /* Input filter disabled */
+                                            IOCON_PIO_SLEW_STANDARD |                                /* Standard mode, output slew rate control is enabled */
+                                            IOCON_PIO_OPENDRAIN_DI                                   /* Open drain is disabled */
+                                        );
+    IOCON_PinMuxSet(IOCON, PORT4_IDX, PIN13_IDX, port4_pin13_config); /* PORT4 PIN13 (coords: B6) is configured as ENET_TX_EN */
+    const uint32_t port4_pin14_config = (
+                                            IOCON_PIO_FUNC1 |                                        /* Pin is configured as ENET_RX_CLK */
+                                            IOCON_PIO_MODE_INACT |                                   /* No addition pin function */
+                                            IOCON_PIO_INV_DI |                                       /* Input function is not inverted */
+                                            IOCON_PIO_DIGITAL_EN |                                   /* Enables digital function */
+                                            IOCON_PIO_INPFILT_OFF |                                  /* Input filter disabled */
+                                            IOCON_PIO_SLEW_STANDARD |                                /* Standard mode, output slew rate control is enabled */
+                                            IOCON_PIO_OPENDRAIN_DI                                   /* Open drain is disabled */
+                                        );
+    IOCON_PinMuxSet(IOCON, PORT4_IDX, PIN14_IDX, port4_pin14_config); /* PORT4 PIN14 (coords: B5) is configured as ENET_RX_CLK */
+    const uint32_t port4_pin15_config = (
+                                            IOCON_PIO_FUNC1 |                                        /* Pin is configured as ENET_MDC */
+                                            IOCON_PIO_MODE_INACT |                                   /* No addition pin function */
+                                            IOCON_PIO_INV_DI |                                       /* Input function is not inverted */
+                                            IOCON_PIO_DIGITAL_EN |                                   /* Enables digital function */
+                                            IOCON_PIO_INPFILT_OFF |                                  /* Input filter disabled */
+                                            IOCON_PIO_SLEW_STANDARD |                                /* Standard mode, output slew rate control is enabled */
+                                            IOCON_PIO_OPENDRAIN_DI                                   /* Open drain is disabled */
+                                        );
+    IOCON_PinMuxSet(IOCON, PORT4_IDX, PIN15_IDX, port4_pin15_config); /* PORT4 PIN15 (coords: A4) is configured as ENET_MDC */
+    const uint32_t port4_pin16_config = (
+                                            IOCON_PIO_FUNC1 |                                        /* Pin is configured as ENET_MDIO */
+                                            IOCON_PIO_MODE_INACT |                                   /* No addition pin function */
+                                            IOCON_PIO_INV_DI |                                       /* Input function is not inverted */
+                                            IOCON_PIO_DIGITAL_EN |                                   /* Enables digital function */
+                                            IOCON_PIO_INPFILT_OFF |                                  /* Input filter disabled */
+                                            IOCON_PIO_SLEW_STANDARD |                                /* Standard mode, output slew rate control is enabled */
+                                            IOCON_PIO_OPENDRAIN_DI                                   /* Open drain is disabled */
+                                        );
+    IOCON_PinMuxSet(IOCON, PORT4_IDX, PIN16_IDX, port4_pin16_config); /* PORT4 PIN16 (coords: C4) is configured as ENET_MDIO */
+    const uint32_t port4_pin8_config = (
+                                           IOCON_PIO_FUNC1 |                                        /* Pin is configured as ENET_TXD0 */
+                                           IOCON_PIO_MODE_INACT |                                   /* No addition pin function */
+                                           IOCON_PIO_INV_DI |                                       /* Input function is not inverted */
+                                           IOCON_PIO_DIGITAL_EN |                                   /* Enables digital function */
+                                           IOCON_PIO_INPFILT_OFF |                                  /* Input filter disabled */
+                                           IOCON_PIO_SLEW_STANDARD |                                /* Standard mode, output slew rate control is enabled */
+                                           IOCON_PIO_OPENDRAIN_DI                                   /* Open drain is disabled */
+                                       );
+    IOCON_PinMuxSet(IOCON, PORT4_IDX, PIN8_IDX, port4_pin8_config); /* PORT4 PIN8 (coords: B14) is configured as ENET_TXD0 */
 }
 }
 
 
-void ETHERNET_IRQHandler(void)
+static rt_err_t lpc_emac_phy_init(phy_speed_t * speed, phy_duplex_t * duplex)
 {
 {
-    /* Check for the interrupt source type. */
-    /* DMA CHANNEL 0. */
-    uint32_t status;
+    bool link = false;
+    int32_t status;
 
 
-    /* enter interrupt */
-    rt_interrupt_enter();
+    status = PHY_Init(lpc_emac_device.base, lpc_emac_device.phyAddr, 0);
+    if (status != kStatus_Success)
+    {
+        ETH_PRINTF("PHY_Init failed!\n");
+        return RT_ERROR;
+    }
 
 
-    status = ENET_GetDmaInterruptStatus(ENET, 0);
-    if (status)
+    /* Wait for link up and get the actual PHY link speed. */
+    PHY_GetLinkStatus(lpc_emac_device.base, lpc_emac_device.phyAddr, &link);
+    while (!link)
     {
     {
-        if (status & kENET_DmaRx)
-        {
-            /* a frame has been received */
-            eth_device_ready(&(lpc_emac_device.parent));
-        }
-        if (status & kENET_DmaTx)
+        uint32_t timedelay;
+        ETH_PRINTF("PHY Wait for link up!\n");
+        for (timedelay = 0; timedelay < 0xFFFFFU; timedelay++)
         {
         {
-            /* set event */
-            rt_event_send(&tx_event, 0x01);
+            __ASM("nop");
         }
         }
-
-        /* Clear the interrupt. */
-        ENET_ClearDmaInterruptStatus(ENET, 0, status);
+        PHY_GetLinkStatus(lpc_emac_device.base, lpc_emac_device.phyAddr, &link);
     }
     }
-
-    /* leave interrupt */
-    rt_interrupt_leave();
+    
+    RT_ASSERT(speed != NULL);
+    RT_ASSERT(duplex != NULL);
+    
+    PHY_GetLinkSpeedDuplex(lpc_emac_device.base, lpc_emac_device.phyAddr, speed, duplex);
+    
+    return RT_EOK;
 }
 }
 
 
 static rt_err_t lpc_emac_init(rt_device_t dev)
 static rt_err_t lpc_emac_init(rt_device_t dev)
 {
 {
-    int32_t status, index;
-    void *buff;
+    int i;
     phy_speed_t speed;
     phy_speed_t speed;
     phy_duplex_t duplex;
     phy_duplex_t duplex;
     enet_config_t config;
     enet_config_t config;
-    bool link = false;
-    uint32_t timedelay;
-    uint32_t refClock = 50000000; /* 50MHZ for rmii reference clock. */
-
-    for (index = 0; index < ENET_RXBD_NUM; index++)
-    {
-        /* This is for rx buffers, static alloc and dynamic alloc both ok. use as your wish. */
-        buff = rt_malloc(ENET_FRAME_MAX_FRAMELEN);
-        if (buff)
-        {
-            g_rxbuffer[index] = (uint32_t)buff;
-        }
-        else
-        {
-            rt_kprintf("Mem Alloc fail\r\n");
-        }
-    }
-
-    /* prepare the buffer configuration. */
-    enet_buffer_config_t buffConfig =
+    enet_buffer_config_t buffCfg;
+    uint32_t rxBufferStartAddr[ENET_RXBD_NUM];
+        
+    lcp_emac_io_init();
+    
+    if (lpc_emac_phy_init(&speed, &duplex) != RT_EOK)
     {
     {
-        ENET_RXBD_NUM,
-        ENET_TXBD_NUM,
-        &g_txBuffDescrip[0],
-        &g_txBuffDescrip[0],
-        &g_rxBuffDescrip[0],
-        &g_rxBuffDescrip[4],
-        &g_rxbuffer[0],
-        ENET_BuffSizeAlign(ENET_FRAME_MAX_FRAMELEN),
-    };
-
-    {
-        const uint32_t port0_pin17_config = (
-                                                IOCON_PIO_FUNC7 |                                        /* Pin is configured as ENET_TXD1 */
-                                                IOCON_PIO_MODE_INACT |                                   /* No addition pin function */
-                                                IOCON_PIO_INV_DI |                                       /* Input function is not inverted */
-                                                IOCON_PIO_DIGITAL_EN |                                   /* Enables digital function */
-                                                IOCON_PIO_INPFILT_OFF |                                  /* Input filter disabled */
-                                                IOCON_PIO_SLEW_STANDARD |                                /* Standard mode, output slew rate control is enabled */
-                                                IOCON_PIO_OPENDRAIN_DI                                   /* Open drain is disabled */
-                                            );
-        IOCON_PinMuxSet(IOCON, PORT0_IDX, PIN17_IDX, port0_pin17_config); /* PORT0 PIN17 (coords: E14) is configured as ENET_TXD1 */
-        const uint32_t port2_pin26_config = (
-                                                IOCON_PIO_FUNC0 |                                        /* Pin is configured as PIO2_26 */
-                                                IOCON_PIO_MODE_PULLUP |                                  /* Selects pull-up function */
-                                                IOCON_PIO_INV_DI |                                       /* Input function is not inverted */
-                                                IOCON_PIO_DIGITAL_EN |                                   /* Enables digital function */
-                                                IOCON_PIO_INPFILT_OFF |                                  /* Input filter disabled */
-                                                IOCON_PIO_SLEW_STANDARD |                                /* Standard mode, output slew rate control is enabled */
-                                                IOCON_PIO_OPENDRAIN_DI                                   /* Open drain is disabled */
-                                            );
-        IOCON_PinMuxSet(IOCON, PORT2_IDX, PIN26_IDX, port2_pin26_config); /* PORT2 PIN26 (coords: H11) is configured as PIO2_26 */
-        const uint32_t port4_pin10_config = (
-                                                IOCON_PIO_FUNC1 |                                        /* Pin is configured as ENET_RX_DV */
-                                                IOCON_PIO_MODE_INACT |                                   /* No addition pin function */
-                                                IOCON_PIO_INV_DI |                                       /* Input function is not inverted */
-                                                IOCON_PIO_DIGITAL_EN |                                   /* Enables digital function */
-                                                IOCON_PIO_INPFILT_OFF |                                  /* Input filter disabled */
-                                                IOCON_PIO_SLEW_STANDARD |                                /* Standard mode, output slew rate control is enabled */
-                                                IOCON_PIO_OPENDRAIN_DI                                   /* Open drain is disabled */
-                                            );
-        IOCON_PinMuxSet(IOCON, PORT4_IDX, PIN10_IDX, port4_pin10_config); /* PORT4 PIN10 (coords: B9) is configured as ENET_RX_DV */
-        const uint32_t port4_pin11_config = (
-                                                IOCON_PIO_FUNC1 |                                        /* Pin is configured as ENET_RXD0 */
-                                                IOCON_PIO_MODE_INACT |                                   /* No addition pin function */
-                                                IOCON_PIO_INV_DI |                                       /* Input function is not inverted */
-                                                IOCON_PIO_DIGITAL_EN |                                   /* Enables digital function */
-                                                IOCON_PIO_INPFILT_OFF |                                  /* Input filter disabled */
-                                                IOCON_PIO_SLEW_STANDARD |                                /* Standard mode, output slew rate control is enabled */
-                                                IOCON_PIO_OPENDRAIN_DI                                   /* Open drain is disabled */
-                                            );
-        IOCON_PinMuxSet(IOCON, PORT4_IDX, PIN11_IDX, port4_pin11_config); /* PORT4 PIN11 (coords: A9) is configured as ENET_RXD0 */
-        const uint32_t port4_pin12_config = (
-                                                IOCON_PIO_FUNC1 |                                        /* Pin is configured as ENET_RXD1 */
-                                                IOCON_PIO_MODE_INACT |                                   /* No addition pin function */
-                                                IOCON_PIO_INV_DI |                                       /* Input function is not inverted */
-                                                IOCON_PIO_DIGITAL_EN |                                   /* Enables digital function */
-                                                IOCON_PIO_INPFILT_OFF |                                  /* Input filter disabled */
-                                                IOCON_PIO_SLEW_STANDARD |                                /* Standard mode, output slew rate control is enabled */
-                                                IOCON_PIO_OPENDRAIN_DI                                   /* Open drain is disabled */
-                                            );
-        IOCON_PinMuxSet(IOCON, PORT4_IDX, PIN12_IDX, port4_pin12_config); /* PORT4 PIN12 (coords: A6) is configured as ENET_RXD1 */
-        const uint32_t port4_pin13_config = (
-                                                IOCON_PIO_FUNC1 |                                        /* Pin is configured as ENET_TX_EN */
-                                                IOCON_PIO_MODE_INACT |                                   /* No addition pin function */
-                                                IOCON_PIO_INV_DI |                                       /* Input function is not inverted */
-                                                IOCON_PIO_DIGITAL_EN |                                   /* Enables digital function */
-                                                IOCON_PIO_INPFILT_OFF |                                  /* Input filter disabled */
-                                                IOCON_PIO_SLEW_STANDARD |                                /* Standard mode, output slew rate control is enabled */
-                                                IOCON_PIO_OPENDRAIN_DI                                   /* Open drain is disabled */
-                                            );
-        IOCON_PinMuxSet(IOCON, PORT4_IDX, PIN13_IDX, port4_pin13_config); /* PORT4 PIN13 (coords: B6) is configured as ENET_TX_EN */
-        const uint32_t port4_pin14_config = (
-                                                IOCON_PIO_FUNC1 |                                        /* Pin is configured as ENET_RX_CLK */
-                                                IOCON_PIO_MODE_INACT |                                   /* No addition pin function */
-                                                IOCON_PIO_INV_DI |                                       /* Input function is not inverted */
-                                                IOCON_PIO_DIGITAL_EN |                                   /* Enables digital function */
-                                                IOCON_PIO_INPFILT_OFF |                                  /* Input filter disabled */
-                                                IOCON_PIO_SLEW_STANDARD |                                /* Standard mode, output slew rate control is enabled */
-                                                IOCON_PIO_OPENDRAIN_DI                                   /* Open drain is disabled */
-                                            );
-        IOCON_PinMuxSet(IOCON, PORT4_IDX, PIN14_IDX, port4_pin14_config); /* PORT4 PIN14 (coords: B5) is configured as ENET_RX_CLK */
-        const uint32_t port4_pin15_config = (
-                                                IOCON_PIO_FUNC1 |                                        /* Pin is configured as ENET_MDC */
-                                                IOCON_PIO_MODE_INACT |                                   /* No addition pin function */
-                                                IOCON_PIO_INV_DI |                                       /* Input function is not inverted */
-                                                IOCON_PIO_DIGITAL_EN |                                   /* Enables digital function */
-                                                IOCON_PIO_INPFILT_OFF |                                  /* Input filter disabled */
-                                                IOCON_PIO_SLEW_STANDARD |                                /* Standard mode, output slew rate control is enabled */
-                                                IOCON_PIO_OPENDRAIN_DI                                   /* Open drain is disabled */
-                                            );
-        IOCON_PinMuxSet(IOCON, PORT4_IDX, PIN15_IDX, port4_pin15_config); /* PORT4 PIN15 (coords: A4) is configured as ENET_MDC */
-        const uint32_t port4_pin16_config = (
-                                                IOCON_PIO_FUNC1 |                                        /* Pin is configured as ENET_MDIO */
-                                                IOCON_PIO_MODE_INACT |                                   /* No addition pin function */
-                                                IOCON_PIO_INV_DI |                                       /* Input function is not inverted */
-                                                IOCON_PIO_DIGITAL_EN |                                   /* Enables digital function */
-                                                IOCON_PIO_INPFILT_OFF |                                  /* Input filter disabled */
-                                                IOCON_PIO_SLEW_STANDARD |                                /* Standard mode, output slew rate control is enabled */
-                                                IOCON_PIO_OPENDRAIN_DI                                   /* Open drain is disabled */
-                                            );
-        IOCON_PinMuxSet(IOCON, PORT4_IDX, PIN16_IDX, port4_pin16_config); /* PORT4 PIN16 (coords: C4) is configured as ENET_MDIO */
-        const uint32_t port4_pin8_config = (
-                                               IOCON_PIO_FUNC1 |                                        /* Pin is configured as ENET_TXD0 */
-                                               IOCON_PIO_MODE_INACT |                                   /* No addition pin function */
-                                               IOCON_PIO_INV_DI |                                       /* Input function is not inverted */
-                                               IOCON_PIO_DIGITAL_EN |                                   /* Enables digital function */
-                                               IOCON_PIO_INPFILT_OFF |                                  /* Input filter disabled */
-                                               IOCON_PIO_SLEW_STANDARD |                                /* Standard mode, output slew rate control is enabled */
-                                               IOCON_PIO_OPENDRAIN_DI                                   /* Open drain is disabled */
-                                           );
-        IOCON_PinMuxSet(IOCON, PORT4_IDX, PIN8_IDX, port4_pin8_config); /* PORT4 PIN8 (coords: B14) is configured as ENET_TXD0 */
-    }
-
-    status = PHY_Init(ENET, PHY_ADDR, 0);
-    if (status == kStatus_Success)
-    {
-        PHY_GetLinkSpeedDuplex(ENET, PHY_ADDR, &speed, &duplex);
-        /* Use the actual speed and duplex when phy success to finish the autonegotiation. */
-        config.miiSpeed = (enet_mii_speed_t)speed;
-        config.miiDuplex = (enet_mii_duplex_t)duplex;
-    }
-    else
-    {
-        rt_kprintf("PHY_Init failed!\n");
         return RT_ERROR;
         return RT_ERROR;
     }
     }
 
 
-    /* Wait for link up and get the actual PHY link speed. */
-    PHY_GetLinkStatus(ENET, PHY_ADDR, &link);
-    while (!link)
+    /* calculate start addresses of all rx buffers */
+    for (i = 0; i < ENET_RXBD_NUM; i++)
     {
     {
-        rt_kprintf("PHY Wait for link up!\n");
-        for (timedelay = 0; timedelay < 0xFFFFFU; timedelay++)
-        {
-            __ASM("nop");
-        }
-        PHY_GetLinkStatus(ENET, PHY_ADDR, &link);
+        rxBufferStartAddr[i] = ENET_ALIGN(&lpc_emac_device.RxDataBuff[i * ENET_ALIGN(ENET_RXBUFF_SIZE)]);
     }
     }
 
 
+    buffCfg.rxRingLen = ENET_RXBD_NUM;
+    buffCfg.txRingLen = ENET_TXBD_NUM;
+    buffCfg.txDescStartAddrAlign = get_tx_desc(0U);
+    buffCfg.txDescTailAddrAlign  = get_tx_desc(0U);
+    buffCfg.rxDescStartAddrAlign = get_rx_desc(0U);
+    buffCfg.rxDescTailAddrAlign  = get_rx_desc(ENET_RXBD_NUM);
+    buffCfg.rxBufferStartAddr    = rxBufferStartAddr;
+    buffCfg.rxBuffSizeAlign      = ENET_ALIGN(ENET_RXBUFF_SIZE);
+    
     /* Get default configuration 100M RMII. */
     /* Get default configuration 100M RMII. */
     ENET_GetDefaultConfig(&config);
     ENET_GetDefaultConfig(&config);
+    /* Use the actual speed and duplex when phy success to finish the autonegotiation. */
+    config.miiSpeed = (enet_mii_speed_t)speed;
+    config.miiDuplex = (enet_mii_duplex_t)duplex;
+    
+    ETH_PRINTF("Auto negotiation, Speed: ");
+    if (config.miiSpeed == kENET_MiiSpeed100M)
+        ETH_PRINTF("100M");
+    else
+        ETH_PRINTF("10M");
+    
+    ETH_PRINTF(", Duplex: ");
+    if (config.miiSpeed == kENET_MiiSpeed100M)
+        ETH_PRINTF("Full\n");
+    else
+        ETH_PRINTF("Half\n");
 
 
-    /* Initialize ENET. */
-    ENET_Init(ENET, &config, &lpc_emac_device.dev_addr[0], refClock);
+    /* Initialize lpc_emac_device.base. */
+    ENET_Init(lpc_emac_device.base, &config, &lpc_emac_device.dev_addr[0], CLOCK_GetFreq(kCLOCK_CoreSysClk));
 
 
     /* Enable the tx/rx interrupt. */
     /* Enable the tx/rx interrupt. */
-    ENET_EnableInterrupts(ENET, (kENET_DmaTx | kENET_DmaRx));
-    EnableIRQ(ETHERNET_IRQn);
-
+    ENET_EnableInterrupts(lpc_emac_device.base, (kENET_DmaTx | kENET_DmaRx));
+    ENET_CreateHandler(lpc_emac_device.base, &lpc_emac_device.handle, &config, &buffCfg, ethernet_callback, NULL);
+    
     /* Initialize Descriptor. */
     /* Initialize Descriptor. */
-    ENET_DescriptorInit(ENET, &config, &buffConfig);
-
+    ENET_DescriptorInit(lpc_emac_device.base, &config, &buffCfg);
+    
     /* Active TX/RX. */
     /* Active TX/RX. */
-    ENET_StartRxTx(ENET, 1, 1);
+    ENET_StartRxTx(lpc_emac_device.base, 1, 1);
+    
+    eth_device_linkchange(&lpc_emac_device.parent, RT_TRUE);
 
 
     return RT_EOK;
     return RT_EOK;
 }
 }
@@ -489,39 +425,47 @@ static rt_err_t lpc_emac_control(rt_device_t dev, int cmd, void *args)
 /* transmit packet. */
 /* transmit packet. */
 rt_err_t lpc_emac_tx(rt_device_t dev, struct pbuf *p)
 rt_err_t lpc_emac_tx(rt_device_t dev, struct pbuf *p)
 {
 {
-    rt_uint8_t *buffer;
-    rt_err_t result;
-    rt_uint32_t recved;
-
-    /* lock EMAC device */
-    rt_sem_take(&sem_lock, RT_WAITING_FOREVER);
+	rt_err_t result = RT_EOK;
+	enet_handle_t * enet_handle = &lpc_emac_device.handle;
+    ENET_Type *enet_base = lpc_emac_device.base;
+    uint8_t * data;
 
 
-    /* there is no block yet, wait a flag */
-    result = rt_event_recv(&tx_event, 0x01, RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR, RT_WAITING_NO, &recved);
-    if (result == RT_EOK)
-        ENET_TXReclaim();
+	RT_ASSERT(p != NULL);
+    RT_ASSERT(enet_handle != RT_NULL);
 
 
-    /* Create the buffer for zero-copy transmit. */
-    buffer = (uint8_t *)malloc(p->tot_len);
-    if (buffer)
+    if (p->tot_len > ENET_TXBUFF_SIZE)
     {
     {
-        /* copy data to tx buffer */
-        pbuf_copy_partial(p, buffer, p->tot_len, 0);
-
-        while ((g_txbuffIdx + 1) % ENET_TXBD_NUM == g_txCosumIdx)
+        return RT_ERROR;
+    }
+    
+    packet_dump("TX dump", p);
+    
+    /* get free tx buffer */
+    {
+        rt_err_t result;
+        result = rt_sem_take(&lpc_emac_device.tx_wait, RT_TICK_PER_SECOND/10);
+        if (result != RT_EOK)
         {
         {
-            rt_thread_delay(RT_TICK_PER_SECOND / 20);	// 50 ms
+            return RT_ERROR;
         }
         }
-
-        /* Store the buffer for mem free. */
-        g_txbuff[g_txbuffIdx] = buffer;
-        g_txbuffIdx = (g_txbuffIdx + 1) % ENET_TXBD_NUM;
-        /* Send the frame out (wait unitl the descriptor ready). */
-        while (ENET_TXQueue(buffer, p->tot_len) != kStatus_Success);
     }
     }
-
-    /* unlock EMAC device */
-    rt_sem_release(&sem_lock);
+    
+    data = (uint8_t *)ENET_ALIGN(&lpc_emac_device.RxDataBuff[lpc_emac_device.txIdx * ENET_ALIGN(ENET_RXBUFF_SIZE)]);
+    pbuf_copy_partial(p, data, p->tot_len, 0);
+    lpc_emac_device.txIdx = (lpc_emac_device.txIdx + 1) / ENET_TXBD_NUM;
+    
+    result = ENET_SendFrame(enet_base, enet_handle, data, p->len);
+    
+    RT_ASSERT(result != kStatus_ENET_TxFrameBusy);
+    
+    if ((result == kStatus_ENET_TxFrameFail) || (result == kStatus_ENET_TxFrameOverLen))
+    {
+        return RT_ERROR; 
+    }
+    else if (result == kStatus_ENET_TxFrameBusy)
+    {
+        RT_ASSERT(NULL);
+    }
 
 
     return RT_EOK;
     return RT_EOK;
 }
 }
@@ -529,61 +473,59 @@ rt_err_t lpc_emac_tx(rt_device_t dev, struct pbuf *p)
 /* reception packet. */
 /* reception packet. */
 struct pbuf *lpc_emac_rx(rt_device_t dev)
 struct pbuf *lpc_emac_rx(rt_device_t dev)
 {
 {
-    struct pbuf *p;
-    uint8_t *data;
-    int length;
-
-    /* init p pointer */
-    p = RT_NULL;
-
-    /* lock EMAC device */
-    rt_sem_take(&sem_lock, RT_WAITING_FOREVER);
-
-    length = 0;
-    data = ENET_RXRead(&length);
-    if (length > 0)
-    {
-        void *buffer;
-        /* Update the buffers and then we can delivery the previous buffer diectly to
-         the application without memcpy. */
-        buffer = rt_malloc(ENET_FRAME_MAX_FRAMELEN);
-        if (buffer)
+  	uint32_t length = 0;
+	status_t status;
+    
+	struct pbuf* p = RT_NULL;
+	enet_handle_t * enet_handle = &lpc_emac_device.handle;
+    ENET_Type *enet_base = lpc_emac_device.base;
+    
+	/* Get the Frame size */
+	status = ENET_GetRxFrameSize(enet_base, enet_handle, &length, 0);
+
+	/* Call ENET_ReadFrame when there is a received frame. */
+	if (length != 0)
+	{
+		/* Received valid frame. Deliver the rx buffer with the size equal to length. */
+		p = pbuf_alloc(PBUF_RAW, length, PBUF_POOL);
+        
+        if (p != NULL)
         {
         {
-            ENET_RXClaim(buffer);
+            status = ENET_ReadFrame(enet_base, enet_handle, p->payload, length, 0);
+            if (status == kStatus_Success)
+            {
+                packet_dump("RX dump", p);
+                return p;
+            }
+            else
+            {
+                ETH_PRINTF(" A frame read failed\n");
+                pbuf_free(p);
+            }
         }
         }
         else
         else
         {
         {
-            ENET_RXClaim(NULL);
+            ETH_PRINTF(" pbuf_alloc faild\n");
         }
         }
-
-        /* Do what you want to do with the data and then free the used one. */
-        p = pbuf_alloc(PBUF_LINK, length, PBUF_RAM);
-        if (p != RT_NULL)
-        {
-            rt_memcpy(p->payload, data, length);
-            p->tot_len = length;
-        }
-        rt_free(data);
-    }
-    else if (length < 0)
-    {
-        ENET_RXClaim(NULL);
-    }
-
-    /* unlock EMAC device */
-    rt_sem_release(&sem_lock);
-
-    return p;
+	}
+	else if (status == kStatus_ENET_RxFrameError)
+	{
+		ETH_PRINTF("ENET_GetRxFrameSize: kStatus_ENET_RxFrameError\n");
+		ENET_ReadFrame(enet_base, enet_handle, NULL, 0, 0);
+	}
+
+    return NULL;
 }
 }
 
 
 int lpc_emac_hw_init(void)
 int lpc_emac_hw_init(void)
 {
 {
-    rt_event_init(&tx_event, "tx_event", RT_IPC_FLAG_FIFO);
-    rt_sem_init(&sem_lock, "eth_lock", 1, RT_IPC_FLAG_FIFO);
-
-    /* set autonegotiation mode */
-    lpc_emac_device.phy_mode = EMAC_PHY_AUTO;
-
+    /* init tx semaphore */
+    rt_sem_init(&lpc_emac_device.tx_wait, "tx_wait", ENET_TXBD_NUM, RT_IPC_FLAG_FIFO);
+    
+    lpc_emac_device.phyAddr = 0;
+    lpc_emac_device.txIdx = 0;
+    lpc_emac_device.base = ENET;
+    
     // OUI 00-60-37 NXP Semiconductors
     // OUI 00-60-37 NXP Semiconductors
     lpc_emac_device.dev_addr[0] = 0x00;
     lpc_emac_device.dev_addr[0] = 0x00;
     lpc_emac_device.dev_addr[1] = 0x60;
     lpc_emac_device.dev_addr[1] = 0x60;
@@ -605,6 +547,198 @@ int lpc_emac_hw_init(void)
     lpc_emac_device.parent.eth_tx           = lpc_emac_tx;
     lpc_emac_device.parent.eth_tx           = lpc_emac_tx;
 
 
     eth_device_init(&(lpc_emac_device.parent), "e0");
     eth_device_init(&(lpc_emac_device.parent), "e0");
+    
     return 0;
     return 0;
 }
 }
 INIT_DEVICE_EXPORT(lpc_emac_hw_init);
 INIT_DEVICE_EXPORT(lpc_emac_hw_init);
+
+#ifdef ETH_STATISTICS
+int emac_stat(void)
+{
+    rt_kprintf("enter rx isr coutner : %d\n", isr_rx_counter);
+    rt_kprintf("enter tx isr coutner : %d\n", isr_tx_counter);
+    
+    return 0;
+}
+#endif
+
+void phy_dump(void)
+{
+    status_t PHY_Read(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, uint32_t *dataPtr);
+
+    int i;
+    
+    for (i = 0; i < 31; i++)
+    {
+        status_t result = kStatus_Success;
+        uint32_t reg;
+        
+        result = PHY_Read(lpc_emac_device.base, lpc_emac_device.phyAddr, i, &reg);
+        
+        if (result == kStatus_Success)
+        {
+            rt_kprintf("%02d: %08d\n", i, reg);
+        }
+        else
+        {
+            rt_kprintf("read register %d faild\n", i);
+        }
+    }
+}
+
+void emac_dump(void)
+{
+    #define DUMP_REG(__NAME)    \
+        rt_kprintf("%-40s, %08x: %08x\n", #__NAME, (uint32_t)&(lpc_emac_device.base->__NAME), lpc_emac_device.base->__NAME)
+
+    DUMP_REG(MAC_CONFIG);
+    DUMP_REG(MAC_EXT_CONFIG);
+    DUMP_REG(MAC_FRAME_FILTER);
+    DUMP_REG(MAC_WD_TIMEROUT);
+    DUMP_REG(MAC_VLAN_TAG);
+    DUMP_REG(MAC_TX_FLOW_CTRL_Q[0]);
+    DUMP_REG(MAC_TX_FLOW_CTRL_Q[1]);
+    DUMP_REG(MAC_RX_FLOW_CTRL);
+    DUMP_REG(MAC_TXQ_PRIO_MAP);
+    DUMP_REG(MAC_RXQ_CTRL[0]);
+    DUMP_REG(MAC_RXQ_CTRL[1]);
+    DUMP_REG(MAC_RXQ_CTRL[2]);
+    DUMP_REG(MAC_INTR_STAT);
+    DUMP_REG(MAC_INTR_EN);
+    DUMP_REG(MAC_RXTX_STAT);
+    DUMP_REG(MAC_PMT_CRTL_STAT);
+    DUMP_REG(MAC_RWAKE_FRFLT);
+    DUMP_REG(MAC_LPI_CTRL_STAT);
+    DUMP_REG(MAC_LPI_TIMER_CTRL);
+    DUMP_REG(MAC_LPI_ENTR_TIMR);
+    DUMP_REG(MAC_1US_TIC_COUNTR);
+    DUMP_REG(MAC_VERSION);
+    DUMP_REG(MAC_DBG);
+    DUMP_REG(MAC_HW_FEAT[0]);
+    DUMP_REG(MAC_HW_FEAT[1]);
+    DUMP_REG(MAC_HW_FEAT[2]);
+    DUMP_REG(MAC_MDIO_ADDR);
+    DUMP_REG(MAC_MDIO_DATA);
+    DUMP_REG(MAC_ADDR_HIGH);
+    DUMP_REG(MAC_ADDR_LOW);
+    DUMP_REG(MAC_TIMESTAMP_CTRL);
+    DUMP_REG(MAC_SUB_SCND_INCR);
+    DUMP_REG(MAC_SYS_TIME_SCND);
+    DUMP_REG(MAC_SYS_TIME_NSCND);
+    DUMP_REG(MAC_SYS_TIME_SCND_UPD);
+    DUMP_REG(MAC_SYS_TIME_NSCND_UPD);
+    DUMP_REG(MAC_SYS_TIMESTMP_ADDEND);
+    DUMP_REG(MAC_SYS_TIME_HWORD_SCND);
+    DUMP_REG(MAC_SYS_TIMESTMP_STAT);
+    DUMP_REG(MAC_TX_TIMESTAMP_STATUS_NANOSECONDS);
+    DUMP_REG(MAC_TX_TIMESTAMP_STATUS_SECONDS);
+    DUMP_REG(MAC_TIMESTAMP_INGRESS_CORR_NANOSECOND);
+    DUMP_REG(MAC_TIMESTAMP_EGRESS_CORR_NANOSECOND);
+    DUMP_REG(MTL_OP_MODE);
+    DUMP_REG(MTL_INTR_STAT);
+    DUMP_REG(MTL_RXQ_DMA_MAP);
+    DUMP_REG(DMA_MODE);
+    DUMP_REG(DMA_SYSBUS_MODE);
+    DUMP_REG(DMA_INTR_STAT);
+    DUMP_REG(DMA_DBG_STAT);
+    
+    DUMP_REG(MTL_QUEUE[0].MTL_TXQX_OP_MODE);
+    DUMP_REG(MTL_QUEUE[0].MTL_TXQX_UNDRFLW);
+    DUMP_REG(MTL_QUEUE[0].MTL_TXQX_DBG);
+    DUMP_REG(MTL_QUEUE[0].MTL_TXQX_ETS_CTRL);
+    DUMP_REG(MTL_QUEUE[0].MTL_TXQX_ETS_STAT);
+    DUMP_REG(MTL_QUEUE[0].MTL_TXQX_QNTM_WGHT);
+    DUMP_REG(MTL_QUEUE[0].MTL_TXQX_SNDSLP_CRDT);
+    DUMP_REG(MTL_QUEUE[0].MTL_TXQX_HI_CRDT);
+    DUMP_REG(MTL_QUEUE[0].MTL_TXQX_LO_CRDT);
+    DUMP_REG(MTL_QUEUE[0].MTL_TXQX_INTCTRL_STAT);
+    DUMP_REG(MTL_QUEUE[0].MTL_RXQX_OP_MODE);
+    DUMP_REG(MTL_QUEUE[0].MTL_RXQX_MISSPKT_OVRFLW_CNT);
+    DUMP_REG(MTL_QUEUE[0].MTL_RXQX_DBG);
+    DUMP_REG(MTL_QUEUE[0].MTL_RXQX_CTRL);
+
+    DUMP_REG(MTL_QUEUE[1].MTL_TXQX_OP_MODE);
+    DUMP_REG(MTL_QUEUE[1].MTL_TXQX_UNDRFLW);
+    DUMP_REG(MTL_QUEUE[1].MTL_TXQX_DBG);
+    DUMP_REG(MTL_QUEUE[1].MTL_TXQX_ETS_CTRL);
+    DUMP_REG(MTL_QUEUE[1].MTL_TXQX_ETS_STAT);
+    DUMP_REG(MTL_QUEUE[1].MTL_TXQX_QNTM_WGHT);
+    DUMP_REG(MTL_QUEUE[1].MTL_TXQX_SNDSLP_CRDT);
+    DUMP_REG(MTL_QUEUE[1].MTL_TXQX_HI_CRDT);
+    DUMP_REG(MTL_QUEUE[1].MTL_TXQX_LO_CRDT);
+    DUMP_REG(MTL_QUEUE[1].MTL_TXQX_INTCTRL_STAT);
+    DUMP_REG(MTL_QUEUE[1].MTL_RXQX_OP_MODE);
+    DUMP_REG(MTL_QUEUE[1].MTL_RXQX_MISSPKT_OVRFLW_CNT);
+    DUMP_REG(MTL_QUEUE[1].MTL_RXQX_DBG);
+    DUMP_REG(MTL_QUEUE[1].MTL_RXQX_CTRL);
+                                      
+    DUMP_REG(DMA_CH[0].DMA_CHX_CTRL);
+    DUMP_REG(DMA_CH[0].DMA_CHX_TX_CTRL);
+    DUMP_REG(DMA_CH[0].DMA_CHX_RX_CTRL);
+    DUMP_REG(DMA_CH[0].DMA_CHX_TXDESC_LIST_ADDR);
+    DUMP_REG(DMA_CH[0].DMA_CHX_RXDESC_LIST_ADDR);
+    DUMP_REG(DMA_CH[0].DMA_CHX_TXDESC_TAIL_PTR);
+    DUMP_REG(DMA_CH[0].DMA_CHX_RXDESC_TAIL_PTR);
+    DUMP_REG(DMA_CH[0].DMA_CHX_TXDESC_RING_LENGTH);
+    DUMP_REG(DMA_CH[0].DMA_CHX_RXDESC_RING_LENGTH);
+    DUMP_REG(DMA_CH[0].DMA_CHX_INT_EN);
+    DUMP_REG(DMA_CH[0].DMA_CHX_RX_INT_WDTIMER);
+    DUMP_REG(DMA_CH[0].DMA_CHX_SLOT_FUNC_CTRL_STAT);
+    DUMP_REG(DMA_CH[0].DMA_CHX_CUR_HST_TXDESC);
+    DUMP_REG(DMA_CH[0].DMA_CHX_CUR_HST_RXDESC);
+    DUMP_REG(DMA_CH[0].DMA_CHX_CUR_HST_TXBUF);
+    DUMP_REG(DMA_CH[0].DMA_CHX_CUR_HST_RXBUF);
+    DUMP_REG(DMA_CH[0].DMA_CHX_STAT);
+    
+    DUMP_REG(DMA_CH[1].DMA_CHX_CTRL);
+    DUMP_REG(DMA_CH[1].DMA_CHX_TX_CTRL);
+    DUMP_REG(DMA_CH[1].DMA_CHX_RX_CTRL);
+    DUMP_REG(DMA_CH[1].DMA_CHX_TXDESC_LIST_ADDR);
+    DUMP_REG(DMA_CH[1].DMA_CHX_RXDESC_LIST_ADDR);
+    DUMP_REG(DMA_CH[1].DMA_CHX_TXDESC_TAIL_PTR);
+    DUMP_REG(DMA_CH[1].DMA_CHX_RXDESC_TAIL_PTR);
+    DUMP_REG(DMA_CH[1].DMA_CHX_TXDESC_RING_LENGTH);
+    DUMP_REG(DMA_CH[1].DMA_CHX_RXDESC_RING_LENGTH);
+    DUMP_REG(DMA_CH[1].DMA_CHX_INT_EN);
+    DUMP_REG(DMA_CH[1].DMA_CHX_RX_INT_WDTIMER);
+    DUMP_REG(DMA_CH[1].DMA_CHX_SLOT_FUNC_CTRL_STAT);
+    DUMP_REG(DMA_CH[1].DMA_CHX_CUR_HST_TXDESC);
+    DUMP_REG(DMA_CH[1].DMA_CHX_CUR_HST_RXDESC);
+    DUMP_REG(DMA_CH[1].DMA_CHX_CUR_HST_TXBUF);
+    DUMP_REG(DMA_CH[1].DMA_CHX_CUR_HST_RXBUF);
+    DUMP_REG(DMA_CH[1].DMA_CHX_STAT);
+}
+
+void emac_bd_dump(void)
+{
+    int i;
+    
+    rt_kprintf("rx bd dump: \n");
+    for (i = 0; i < ENET_RXBD_NUM; i++)
+    {
+        enet_rx_bd_struct_t * rx_bd = get_rx_desc(i);
+        rt_kprintf("buf1: %p, buf2: %p, ctrl: %08x\n", 
+                        rx_bd->buff1Addr, 
+                        rx_bd->buff2Addr,
+                        rx_bd->control);
+    }
+    
+    rt_kprintf("tx bd dump: \n");
+    for (i = 0; i < ENET_TXBD_NUM; i++)
+    {
+        enet_tx_bd_struct_t * tx_bd = get_tx_desc(i);
+        rt_kprintf("buf1: %p, buf2: %p, len: %08x, ctrl: %08x\n", 
+                        tx_bd->buff1Addr, 
+                        tx_bd->buff2Addr,
+                        tx_bd->buffLen,
+                        tx_bd->controlStat);
+    }
+}
+
+#ifdef RT_USING_FINSH
+#include <finsh.h>
+FINSH_FUNCTION_EXPORT(emac_stat, dump emac stat data);
+FINSH_FUNCTION_EXPORT(phy_dump, dump phy registers);
+FINSH_FUNCTION_EXPORT(emac_dump, dump emac registers);
+FINSH_FUNCTION_EXPORT(emac_bd_dump, dump emac tx and rx descriptor);
+#endif