]> granicus.if.org Git - esp-idf/commitdiff
feature/ethernet_driver: update ethernet driver
authorshangke <shangke@espressif.com>
Sun, 18 Dec 2016 13:18:37 +0000 (21:18 +0800)
committershangke <shangke@espressif.com>
Mon, 26 Dec 2016 06:50:49 +0000 (14:50 +0800)
1. The transmitting mode of the packets from LWIP to MAC is changed from synchronous to asynchronous.
2. The receive buf mode : support pointer mode and copy mode.
3. Add get phy status func used to config mac register.

12 files changed:
components/ethernet/Kconfig
components/ethernet/emac_common.h
components/ethernet/emac_dev.c
components/ethernet/emac_dev.h
components/ethernet/emac_main.c
components/ethernet/include/esp_eth.h
components/lwip/core/pbuf.c
components/lwip/include/lwip/lwip/pbuf.h
components/lwip/port/netif/ethernetif.c
components/lwip/port/netif/wlanif.c
examples/14_ethernet/main/tlk110_phy.h [new file with mode: 0644]
examples/17_ethernet/main/ethernet_main.c

index cbd3bfbe47d571d30bb8f8dcde3cc9d75326bb97..9eb897cbba1b74fe766a7e8093586966720910a7 100644 (file)
@@ -3,18 +3,32 @@ menuconfig ETHERNET
     default n
     help
         Enable this option to enable ethernet driver and show the menu with ethernet features.
-        
 
 config DMA_RX_BUF_NUM
-    int "Dma Rx Buf Num"
+    int "DMA Rx Buf Num"
     default  10
     depends on ETHERNET
     help
         Dma rx buf num ,can not be 0 .
 
 config DMA_TX_BUF_NUM
-    int "Dma Tx Buf Num"
+    int "DMA Tx Buf Num"
     default 10
     depends on ETHERNET
     help
         Dma tx Buf num ,can not be 0.
+
+config EMAC_L2_TO_L3_RX_BUF_MODE
+    bool "L2 To L3 RX BUF COPY MODE"
+    default n
+    depends on ETHERNET
+    help
+        Receive Buf user copy mode or pointer mode.
+
+config EMAC_TASK_PRIORITY
+    int "EMAC_TASK_PRIORITY"
+    default 20
+    depends on ETHERNET
+    help
+        Emac task priority ,suggest 3 ~ 23.
+
index 48f71fd90fa88cef991e05888438b222225be55d..774c287ad5a093bb540023fe386f4dd4a0dab983 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "esp_err.h"
 #include "emac_dev.h"
+#include "esp_eth.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -32,11 +33,6 @@ typedef struct {
     emac_par_t par;
 } emac_event_t;
 
-enum emac_mode {
-    EMAC_MODE_RMII = 0,
-    EMAC_MDOE_MII,
-};
-
 enum emac_runtime_status {
     EMAC_RUNTIME_NOT_INIT = 0,
     EMAC_RUNTIME_INIT,
@@ -45,36 +41,37 @@ enum emac_runtime_status {
 };
 
 enum {
+    SIG_EMAC_RX_UNAVAIL,
     SIG_EMAC_TX_DONE,
     SIG_EMAC_RX_DONE,
-    SIG_EMAC_TX,
     SIG_EMAC_START,
     SIG_EMAC_STOP,
+    SIG_EMAC_CHECK_LINK,
     SIG_EMAC_MAX
 };
 
-typedef void (*emac_phy_fun)(void);
-typedef esp_err_t (*emac_tcpip_input_fun)(void *buffer, uint16_t len, void *eb);
-typedef void (*emac_gpio_config_func)(void);
-
 struct emac_config_data {
-    unsigned int  phy_addr;
-    enum emac_mode mac_mode;
+    eth_phy_base_t phy_addr;
+    eth_mode_t mac_mode;
     struct dma_extended_desc *dma_etx;
-    unsigned int cur_tx;
-    unsigned int dirty_tx;
-    signed int cnt_tx;
+    uint32_t cur_tx;
+    uint32_t dirty_tx;
+    int32_t cnt_tx;
     struct dma_extended_desc *dma_erx;
-    unsigned int cur_rx;
-    unsigned int dirty_rx;
-    signed int cnt_rx;
-    unsigned int rx_need_poll;
+    uint32_t cur_rx;
+    uint32_t dirty_rx;
+    int32_t cnt_rx;
+    uint32_t rx_need_poll;
     bool phy_link_up;
     enum emac_runtime_status emac_status;
     uint8_t macaddr[6];
-    emac_phy_fun phy_init;
-    emac_tcpip_input_fun emac_tcpip_input;
-    emac_gpio_config_func emac_gpio_config;
+    eth_phy_func phy_init;
+    eth_tcpip_input_func emac_tcpip_input;
+    eth_gpio_config_func emac_gpio_config;
+    eth_phy_check_link_func emac_phy_check_link;
+    eth_phy_check_init_func emac_phy_check_init;
+    eth_phy_get_speed_mode_func emac_phy_get_speed_mode;
+    eth_phy_get_duplex_mode_func emac_phy_get_duplex_mode;
 };
 
 enum emac_post_type {
@@ -103,18 +100,15 @@ struct emac_close_cmd {
 #if CONFIG_ETHERNET
 #define DMA_RX_BUF_NUM CONFIG_DMA_RX_BUF_NUM
 #define DMA_TX_BUF_NUM CONFIG_DMA_TX_BUF_NUM
+#define EMAC_TASK_PRIORITY CONFIG_EMAC_TASK_PRIORITY
 #else
 #define DMA_RX_BUF_NUM 1
 #define DMA_TX_BUF_NUM 1
+#define EMAC_TASK_PRIORITY 10
 #endif
 #define DMA_RX_BUF_SIZE 1600
 #define DMA_TX_BUF_SIZE 1600
 
-//lwip err
-#define ERR_OK   0
-#define ERR_MEM -1
-#define ERR_IF  -16
-
 #define EMAC_CMD_OK 0
 #define EMAC_CMD_FAIL -1
 
index a8095fecba94d7e62aadefef1c22ce74f56289e3..244da084323f5846da65b7dc703b5e6109e37ff1 100644 (file)
 
 static const char *TAG = "emac";
 
-void emac_poll_tx_cmd(void)
-{
-    //write any to wake up dma
-    REG_WRITE(EMAC_DMATXPOLLDEMAND_REG, 1);
-}
-
-void emac_poll_rx_cmd(void)
-{
-    //write any to wake up dma
-    REG_WRITE(EMAC_DMARXPOLLDEMAND_REG, 1);
-}
-
 void emac_enable_dma_tx(void)
 {
     REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_START_STOP_TRANSMISSION_COMMAND);
@@ -66,15 +54,6 @@ void emac_disable_dma_rx(void)
     REG_CLR_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_START_STOP_RECEIVE);
 }
 
-uint32_t emac_read_tx_cur_reg(void)
-{
-    return REG_READ(EMAC_DMATXCURRDESC_REG);
-}
-
-uint32_t emac_read_rx_cur_reg(void)
-{
-    return REG_READ(EMAC_DMARXCURRDESC_REG);
-}
 
 uint32_t emac_read_mac_version(void)
 {
@@ -121,16 +100,18 @@ void emac_dma_init(void)
     REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_FORWARD_UNDERSIZED_GOOD_FRAMES);
     REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_OPERATE_SECOND_FRAME);
     REG_SET_FIELD(EMAC_DMABUSMODE_REG, EMAC_PROG_BURST_LEN, 4);
+    REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG,EMAC_DMAOPERATION_MODE_REG);
 }
 
 void emac_mac_init(void)
 {
-    REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACRX);
-    REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACTX);
     REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACDUPLEX);
     REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACMIIGMII);
     REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACFESPEED);
     REG_SET_BIT(EMAC_GMACFRAMEFILTER_REG, EMAC_PROMISCUOUS_MODE);
+
+    REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACRX);
+    REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACTX);
 }
 
 void emac_set_clk_rmii(void)
index ede15271ebd2e7304b55c6916c5f3d486fce501b..bc04d8d9e2ee9e4b314b77063e6b6d1840062eef 100644 (file)
@@ -49,14 +49,52 @@ uint32_t emac_read_mac_version(void);
 void emac_dma_init(void);
 void emac_mac_init(void);
 void emac_enable_dma_tx(void);
-void emac_poll_tx_cmd(void);
-uint32_t emac_read_tx_cur_reg(void);
 void emac_enable_dma_rx(void);
-uint32_t emac_read_rx_cur_reg(void);
-void emac_poll_rx_cmd(void);
 void emac_disable_dma_tx(void);
 void emac_disable_dma_rx(void);
 
+uint32_t inline emac_read_tx_cur_reg(void)
+{
+    return REG_READ(EMAC_DMATXCURRDESC_REG);
+}
+
+uint32_t inline emac_read_rx_cur_reg(void)
+{
+    return REG_READ(EMAC_DMARXCURRDESC_REG);
+}
+
+void inline emac_poll_tx_cmd(void)
+{
+    //write any to wake up dma
+    REG_WRITE(EMAC_DMATXPOLLDEMAND_REG, 1);
+}
+
+void inline emac_poll_rx_cmd(void)
+{
+    //write any to wake up dma
+    REG_WRITE(EMAC_DMARXPOLLDEMAND_REG, 1);
+}
+
+void inline emac_disable_rx_intr(void)
+{
+    REG_CLR_BIT(EMAC_DMAINTERRUPT_EN_REG,EMAC_RECEIVE_INTERRUPT_ENABLE);
+}
+
+void inline emac_enable_rx_intr(void)
+{
+    REG_SET_BIT(EMAC_DMAINTERRUPT_EN_REG,EMAC_RECEIVE_INTERRUPT_ENABLE);
+}
+
+void inline emac_disable_rx_unavail_intr(void)
+{
+    REG_CLR_BIT(EMAC_DMAINTERRUPT_EN_REG,EMAC_RECEIVE_BUFFER_UNAVAILABLE_ENABLE);
+}
+
+void inline emac_enable_rx_unavail_intr(void)
+{
+    REG_SET_BIT(EMAC_DMAINTERRUPT_EN_REG,EMAC_RECEIVE_BUFFER_UNAVAILABLE_ENABLE);  
+}
+
 #ifdef __cplusplus
 }
 #endif
index 3dc61d809cce328d162e616d154f4199a6dfeb32..ab2ca8964c999adb4de555a77fd717aedaa782a1 100644 (file)
@@ -47,6 +47,8 @@
 #include "freertos/semphr.h"
 #include "freertos/timers.h"
 
+#include "lwip/err.h"
+
 #define EMAC_EVT_QNUM 200
 #define EMAC_SIG_MAX 50
 
@@ -63,7 +65,8 @@ static xTaskHandle emac_task_hdl;
 static xQueueHandle emac_xqueue;
 static uint8_t emac_sig_cnt[EMAC_SIG_MAX] = {0};
 static TimerHandle_t emac_timer = NULL;
-
+static SemaphoreHandle_t emac_rx_xMutex = NULL;
+static SemaphoreHandle_t emac_tx_xMutex = NULL;
 static const char *TAG = "emac";
 
 static esp_err_t emac_ioctl(emac_sig_t sig, emac_par_t par);
@@ -82,20 +85,24 @@ void esp_eth_get_mac(uint8_t mac[6])
 
 static void emac_setup_tx_desc(struct dma_extended_desc *tx_desc , uint32_t size)
 {
-    tx_desc->basic.desc0 = EMAC_DESC_TX_OWN | EMAC_DESC_INT_COMPL | EMAC_DESC_LAST_SEGMENT | EMAC_DESC_FIRST_SEGMENT | EMAC_DESC_SECOND_ADDR_CHAIN;
     tx_desc->basic.desc1 = size & 0xfff;
+    tx_desc->basic.desc0 = EMAC_DESC_INT_COMPL | EMAC_DESC_LAST_SEGMENT | EMAC_DESC_FIRST_SEGMENT | EMAC_DESC_SECOND_ADDR_CHAIN;
+    tx_desc->basic.desc0 = EMAC_DESC_TX_OWN | EMAC_DESC_INT_COMPL | EMAC_DESC_LAST_SEGMENT | EMAC_DESC_FIRST_SEGMENT | EMAC_DESC_SECOND_ADDR_CHAIN;
 }
 
 static void emac_clean_tx_desc(struct dma_extended_desc *tx_desc)
 {
-    tx_desc->basic.desc0 = 0;
     tx_desc->basic.desc1 = 0;
+    tx_desc->basic.desc0 = 0;
 }
 
-static void emac_clean_rx_desc(struct dma_extended_desc *rx_desc)
+static void emac_clean_rx_desc(struct dma_extended_desc *rx_desc ,uint32_t buf_ptr)
 {
-    rx_desc->basic.desc0 = EMAC_DESC_RX_OWN;
+    if(buf_ptr != 0) {
+        rx_desc->basic.desc2 = buf_ptr;
+    }
     rx_desc->basic.desc1 = EMAC_DESC_RX_SECOND_ADDR_CHAIN | DMA_RX_BUF_SIZE;
+    rx_desc->basic.desc0 = EMAC_DESC_RX_OWN;
 }
 
 static void emac_set_tx_base_reg(void)
@@ -156,18 +163,15 @@ static void emac_init_dma_chain(void)
     dma_phy = (uint32_t)(emac_config.dma_erx);
     p = emac_config.dma_erx;
 
-    for (i = 0; i < (DMA_TX_BUF_NUM - 1); i++ ) {
+    for (i = 0; i < (DMA_RX_BUF_NUM - 1); i++ ) {
         dma_phy += sizeof(struct dma_extended_desc);
-        emac_clean_rx_desc(p);
+        emac_clean_rx_desc(p, (uint32_t)(&emac_dma_rx_buf[0]) + (i * DMA_RX_BUF_SIZE));
         p->basic.desc3 = dma_phy;
-        p->basic.desc2 = (uint32_t)(&emac_dma_rx_buf[0]) + (i * DMA_RX_BUF_SIZE);
         p++;
     }
-    p->basic.desc3 = (uint32_t)(emac_config.dma_erx);
-    p->basic.desc2 = (uint32_t)(&emac_dma_rx_buf[0]) + (i * DMA_RX_BUF_SIZE);
 
-    //init desc0 desc1
-    emac_clean_rx_desc(p);
+    emac_clean_rx_desc(p, (uint32_t)(&emac_dma_rx_buf[0]) + (i * DMA_RX_BUF_SIZE));
+    p->basic.desc3 = (uint32_t)(emac_config.dma_erx);
 }
 
 void esp_eth_smi_write(uint32_t reg_num, uint16_t value)
@@ -207,18 +211,32 @@ static void emac_set_user_config_data(eth_config_t *config )
     emac_config.phy_init = config->phy_init;
     emac_config.emac_tcpip_input = config->tcpip_input;
     emac_config.emac_gpio_config = config->gpio_config;
+    emac_config.emac_phy_check_link = config->phy_check_link;
+    emac_config.emac_phy_check_init = config->phy_check_init;
+    emac_config.emac_phy_get_speed_mode = config->phy_get_speed_mode;
+    emac_config.emac_phy_get_duplex_mode = config->phy_get_duplex_mode;
+}
+
+static void emac_enable_intr()
+{
+    REG_WRITE(EMAC_DMAINTERRUPT_EN_REG, EMAC_INTR_ENABLE_BIT);
+}
+
+static void emac_disable_intr()
+{
+    REG_WRITE(EMAC_DMAINTERRUPT_EN_REG, 0);
 }
 
 static esp_err_t emac_verify_args(void)
 {
     esp_err_t ret = ESP_OK;
 
-    if (emac_config.phy_addr > 31) {
+    if (emac_config.phy_addr > PHY31) {
         ESP_LOGE(TAG, "phy addr err");
         ret = ESP_FAIL;
     }
 
-    if (emac_config.mac_mode != EMAC_MODE_RMII) {
+    if (emac_config.mac_mode != ETH_MODE_RMII) {
         ESP_LOGE(TAG, "mac mode err,now only support RMII");
         ret = ESP_FAIL;
     }
@@ -238,6 +256,26 @@ static esp_err_t emac_verify_args(void)
         ret = ESP_FAIL;
     }
 
+    if (emac_config.emac_phy_check_link == NULL) {
+        ESP_LOGE(TAG, "phy check link func is null");
+        ret = ESP_FAIL;
+    }
+
+    if (emac_config.emac_phy_check_init == NULL) {
+        ESP_LOGE(TAG, "phy check init func is null");
+        ret = ESP_FAIL;
+    }
+
+    if (emac_config.emac_phy_get_speed_mode == NULL) {
+        ESP_LOGE(TAG, "phy get speed mode func is null");
+        ret = ESP_FAIL;
+    }
+
+    if (emac_config.emac_phy_get_duplex_mode == NULL) {
+        ESP_LOGE(TAG, "phy get duplex mode func is null");
+        ret = ESP_FAIL;
+    }
+
     return ret;
 }
 
@@ -255,7 +293,13 @@ static void emac_process_tx(void)
 {
     uint32_t cur_tx_desc = emac_read_tx_cur_reg();
 
-    while (((uint32_t) & (emac_config.dma_etx[emac_config.dirty_tx].basic.desc0) != cur_tx_desc)) {
+    if(emac_config.emac_status == EMAC_RUNTIME_STOP) {
+        return;
+    }
+
+    xSemaphoreTakeRecursive( emac_tx_xMutex, ( TickType_t ) portMAX_DELAY );
+
+    while (((uint32_t) &(emac_config.dma_etx[emac_config.dirty_tx].basic.desc0) != cur_tx_desc)) {
         emac_clean_tx_desc(&(emac_config.dma_etx[emac_config.dirty_tx]));
         emac_config.dirty_tx = (emac_config.dirty_tx + 1) % DMA_TX_BUF_NUM;
         emac_config.cnt_tx --;
@@ -263,11 +307,33 @@ static void emac_process_tx(void)
         if (emac_config.cnt_tx < 0) {
             ESP_LOGE(TAG, "emac tx chain err");
         }
+        cur_tx_desc = emac_read_tx_cur_reg();
+    }
+
+    xSemaphoreGiveRecursive( emac_tx_xMutex );
+}
+
+void esp_eth_free_rx_buf(void *buf)
+{
+    xSemaphoreTakeRecursive( emac_rx_xMutex, ( TickType_t ) portMAX_DELAY );
+
+    emac_clean_rx_desc(&(emac_config.dma_erx[emac_config.cur_rx]),(uint32_t) buf);
+    emac_config.cur_rx = (emac_config.cur_rx + 1) % DMA_RX_BUF_NUM;
+    emac_config.cnt_rx--;
+    if(emac_config.cnt_rx < 0) {
+       ESP_LOGE(TAG, "emac rx buf err!!\n");
     }
+    emac_poll_rx_cmd();
+
+    xSemaphoreGiveRecursive( emac_rx_xMutex );
 }
 
+#if CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE
 static void emac_process_rx(void)
 {
+    if(emac_config.emac_status == EMAC_RUNTIME_STOP) {
+        return;
+    }
     uint32_t cur_rx_desc = emac_read_rx_cur_reg();
 
     while (((uint32_t) & (emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) != cur_rx_desc)) {
@@ -275,17 +341,116 @@ static void emac_process_rx(void)
         emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[emac_config.dirty_rx].basic.desc2),
                                      (((emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) & EMAC_DESC_FRAME_LENGTH) , NULL);
 
-        emac_clean_rx_desc(&(emac_config.dma_erx[emac_config.dirty_rx]));
+        emac_clean_rx_desc(&(emac_config.dma_erx[emac_config.dirty_rx]),(emac_config.dma_erx[emac_config.dirty_rx].basic.desc2));
         emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM;
-        if (emac_config.rx_need_poll != 0) {
-            emac_poll_rx_cmd();
-            emac_config.rx_need_poll = 0;
-        }
+
         //if open this ,one intr can do many intrs ?
-        //cur_rx_desc = emac_read_rx_cur_reg();
+        cur_rx_desc = emac_read_rx_cur_reg();
+    }
+
+    emac_enable_rx_intr();
+}
+
+static void emac_process_rx_unavail(void)
+{
+    if(emac_config.emac_status == EMAC_RUNTIME_STOP) {
+        return;
+    }
+
+    uint32_t dirty_cnt = 0;
+    while (dirty_cnt < DMA_RX_BUF_NUM) {
+
+        if(emac_config.dma_erx[emac_config.dirty_rx].basic.desc0 == EMAC_DESC_RX_OWN) {
+            break;
+        }
+
+        dirty_cnt ++;
+        //copy data to lwip
+        emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[emac_config.dirty_rx].basic.desc2),
+                                     (((emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) & EMAC_DESC_FRAME_LENGTH) , NULL);
+
+        emac_clean_rx_desc(&(emac_config.dma_erx[emac_config.dirty_rx]),(emac_config.dma_erx[emac_config.dirty_rx].basic.desc2));
+        emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM;
+    }
+    emac_enable_rx_intr();
+    emac_enable_rx_unavail_intr();
+    emac_poll_rx_cmd();
+}
+
+#else
+static void emac_process_rx_unavail(void)
+{
+    if(emac_config.emac_status == EMAC_RUNTIME_STOP) {
+        return;
+    }
+
+    xSemaphoreTakeRecursive( emac_rx_xMutex, ( TickType_t ) portMAX_DELAY );
+
+    while (emac_config.cnt_rx < DMA_RX_BUF_NUM) {
+
+        //copy data to lwip 
+        emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[emac_config.dirty_rx].basic.desc2),
+                                     (((emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) & EMAC_DESC_FRAME_LENGTH) , NULL);
+        emac_config.cnt_rx++;
+        if(emac_config.cnt_rx > DMA_RX_BUF_NUM) {
+            ESP_LOGE(TAG, "emac rx unavail buf err !!\n");
+        }
+        emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM;
     }
+    emac_enable_rx_intr();
+    emac_enable_rx_unavail_intr();
+    xSemaphoreGiveRecursive( emac_rx_xMutex );
 }
 
+static void emac_process_rx(void)
+{
+    if(emac_config.emac_status == EMAC_RUNTIME_STOP) {
+        return;
+    }
+
+    uint32_t cur_rx_desc = emac_read_rx_cur_reg();
+
+    xSemaphoreTakeRecursive( emac_rx_xMutex, ( TickType_t ) portMAX_DELAY );
+
+    if(((uint32_t) &(emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) != cur_rx_desc)) {
+
+        while (((uint32_t) &(emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) != cur_rx_desc) && emac_config.cnt_rx < DMA_RX_BUF_NUM ) {
+            //copy data to lwip
+            emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[emac_config.dirty_rx].basic.desc2),
+                               (((emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) & EMAC_DESC_FRAME_LENGTH) , NULL);
+
+            emac_config.cnt_rx++;
+
+            if(emac_config.cnt_rx > DMA_RX_BUF_NUM ) {
+                ESP_LOGE(TAG, "emac rx buf err!!\n");
+            }
+            emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM;
+
+            cur_rx_desc = emac_read_rx_cur_reg();
+        }
+    } else {
+        if(emac_config.cnt_rx < DMA_RX_BUF_NUM) {
+            if((emac_config.dma_erx[emac_config.dirty_rx].basic.desc0 & EMAC_DESC_RX_OWN) == 0) {
+                while (emac_config.cnt_rx < DMA_RX_BUF_NUM) {
+
+                    //copy data to lwip
+                    emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[emac_config.dirty_rx].basic.desc2),
+                               (((emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) & EMAC_DESC_FRAME_LENGTH) , NULL);
+                    emac_config.cnt_rx++;
+                    if(emac_config.cnt_rx > DMA_RX_BUF_NUM) {
+                        ESP_LOGE(TAG,"emac rx buf err!!!\n");
+                    }
+
+                    emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM;
+                }
+            }
+        }
+    }
+    emac_enable_rx_intr();
+    xSemaphoreGiveRecursive( emac_rx_xMutex );
+}
+#endif
+
 //TODO other events need to do something
 static void IRAM_ATTR emac_process_intr(void *arg)
 {
@@ -295,35 +460,37 @@ static void IRAM_ATTR emac_process_intr(void *arg)
     //clr intrs
     REG_WRITE(EMAC_DMASTATUS_REG, event);
 
-    if (event & EMAC_RECV_BUF_UNAVAIL) {
-        emac_config.rx_need_poll = 1;
-    } else if (event & EMAC_TRANS_INT) {
-        emac_post(SIG_EMAC_TX_DONE, 0);
-    } else if (event & EMAC_RECV_INT) {
+    if (event & EMAC_RECV_INT) {
+        emac_disable_rx_intr();
         emac_post(SIG_EMAC_RX_DONE, 0);
-    } else {
-        //other events
     }
-}
 
-//ToDo: this should only be called once because this allocates the interrupt as well.
-static void emac_enable_intr()
-{
-    //init emac intr
-    esp_intr_alloc(ETS_ETH_MAC_INTR_SOURCE, 0, emac_process_intr, NULL, NULL);
-    REG_WRITE(EMAC_DMAINTERRUPT_EN_REG, EMAC_INTR_ENABLE_BIT);
-}
+    if (event & EMAC_RECV_BUF_UNAVAIL) {
+        emac_disable_rx_unavail_intr();
+        emac_post(SIG_EMAC_RX_UNAVAIL,0);
+    }
 
-static void emac_disable_intr()
-{
-    REG_WRITE(EMAC_DMAINTERRUPT_EN_REG, 0);
+    if (event & EMAC_TRANS_INT) {
+        emac_post(SIG_EMAC_TX_DONE, 0);
+    }
 }
 
-static bool emac_check_phy_link_status(void)
+static void emac_check_phy_init(void)
 {
-    return ((esp_eth_smi_read(1) & 0x4) == 0x4 );
-}
+    emac_config.emac_phy_check_init();
+    if(emac_config.emac_phy_get_duplex_mode() == ETH_MDOE_FULLDUPLEX) {
+        REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACDUPLEX);
+    } else {
+        REG_CLR_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACDUPLEX);
+    }
+    if(emac_config.emac_phy_get_speed_mode() == ETH_SPEED_MODE_100M) {
+        REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACFESPEED);
+    } else {
+        REG_CLR_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACFESPEED);
+    }
 
+    emac_mac_init();
+}
 static void emac_process_link_updown(bool link_status)
 {
     system_event_t evt;
@@ -331,10 +498,10 @@ static void emac_process_link_updown(bool link_status)
     emac_config.phy_link_up = link_status;
 
     if (link_status == true) {
+        emac_check_phy_init();
         ESP_LOGI(TAG, "eth link_up!!!");
         emac_enable_dma_tx();
         emac_enable_dma_rx();
-        ets_delay_us(200000);
         evt.event_id = SYSTEM_EVENT_ETH_CONNECTED;
     } else {
         ESP_LOGI(TAG, "eth link_down!!!");
@@ -356,26 +523,20 @@ static void emac_hw_init(void)
     //ipc TODO
 }
 
-static esp_err_t emac_xmit(void *param)
+esp_err_t esp_eth_tx(uint8_t *buf, uint16_t size)
 {
-    struct emac_post_cmd  *post_cmd = (struct emac_post_cmd *)param;
-    struct emac_tx_cmd *cmd = (struct emac_tx_cmd *)(post_cmd->cmd);
     esp_err_t ret = ESP_OK;
 
-    void *buf = cmd->buf;
-    uint16_t size = cmd->size;
-
     if (emac_config.emac_status != EMAC_RUNTIME_START || emac_config.emac_status == EMAC_RUNTIME_NOT_INIT) {
         ESP_LOGI(TAG, "tx netif close");
-        cmd->err = ERR_IF;
-        ret = ESP_FAIL;
+        ret = ERR_IF;
         goto _exit;
     }
 
-    if (emac_config.cnt_tx == DMA_TX_BUF_NUM) {
-        ESP_LOGI(TAG, "tx buf full");
-        cmd->err = ERR_MEM;
-        ret = ESP_FAIL;
+    xSemaphoreTakeRecursive( emac_tx_xMutex, ( TickType_t ) portMAX_DELAY );
+    if (emac_config.cnt_tx == DMA_TX_BUF_NUM -1) {
+        ESP_LOGD(TAG, "tx buf full");
+        ret = ERR_MEM;
         goto _exit;
     }
 
@@ -390,26 +551,23 @@ static esp_err_t emac_xmit(void *param)
 
 _exit:
 
-    if (post_cmd->post_type == EMAC_POST_SYNC) {
-        xSemaphoreGive(emac_g_sem);
-    }
-
+    xSemaphoreGiveRecursive( emac_tx_xMutex );
     return ret;
 }
 
 static void emac_init_default_data(void)
 {
-    emac_config.rx_need_poll = 0;
+    memset((uint8_t *)&emac_config, 0,sizeof(struct emac_config_data));
 }
 
-void emac_link_check_func(void *pv_parameters)
+void emac_process_link_check(void) 
 {
     if (emac_config.emac_status != EMAC_RUNTIME_START ||
         emac_config.emac_status == EMAC_RUNTIME_NOT_INIT) {
         return;
     }
 
-    if (emac_check_phy_link_status() == true ) {
+    if (emac_config.emac_phy_check_link() == true ) {
         if (emac_config.phy_link_up == false) {
             emac_process_link_updown(true);
         }
@@ -420,9 +578,14 @@ void emac_link_check_func(void *pv_parameters)
     }
 }
 
+void emac_link_check_func(void *pv_parameters)
+{
+    emac_post(SIG_EMAC_CHECK_LINK,0);
+}
+
 static bool emac_link_check_timer_init(void)
 {
-    emac_timer = xTimerCreate("emac_timer", (1000 / portTICK_RATE_MS),
+    emac_timer = xTimerCreate("emac_timer", (2000 / portTICK_RATE_MS),
                               pdTRUE, (void *)rand(), emac_link_check_func);
     if (emac_timer == NULL) {
         return false;
@@ -473,18 +636,11 @@ static void emac_start(void *param)
 
     emac_set_tx_base_reg();
     emac_set_rx_base_reg();
-    emac_mac_init();
 
     emac_config.phy_init();
 
-    //for test
-    //emac_wait_linkup();
-
-    //mmc  not support
-
     //ptp TODO
 
-    //enable emac intr
     emac_enable_intr();
 
     emac_config.emac_status = EMAC_RUNTIME_START;
@@ -573,7 +729,7 @@ esp_err_t esp_eth_disable(void)
         return close_cmd.err;
     }
 
-    if (emac_config.emac_status != EMAC_RUNTIME_NOT_INIT) {
+    if (emac_config.emac_status == EMAC_RUNTIME_START) {
         if (emac_ioctl(SIG_EMAC_STOP, (emac_par_t)(&post_cmd)) != 0) {
             close_cmd.err = EMAC_CMD_FAIL;
         }
@@ -608,9 +764,6 @@ static esp_err_t emac_ioctl(emac_sig_t sig, emac_par_t par)
         case SIG_EMAC_TX_DONE:
             emac_process_tx();
             break;
-        case SIG_EMAC_TX:
-            emac_xmit((void *)par);
-            break;
         case SIG_EMAC_START:
             emac_start((void *)par);
             break;
@@ -626,29 +779,6 @@ static esp_err_t emac_ioctl(emac_sig_t sig, emac_par_t par)
     return ret;
 }
 
-esp_err_t esp_eth_tx(uint8_t *buf, uint16_t size)
-{
-    struct emac_post_cmd post_cmd;
-    struct emac_tx_cmd tx_cmd;
-
-    post_cmd.cmd = (void *)(&tx_cmd);
-
-    if (emac_check_phy_link_status() == false) {
-        emac_process_link_updown(false);
-        tx_cmd.err = ERR_IF;
-    } else {
-        tx_cmd.buf = buf;
-        tx_cmd.size = size;
-        tx_cmd.err = ERR_OK;
-
-        if (emac_ioctl(SIG_EMAC_TX, (emac_par_t)(&post_cmd)) != 0) {
-            tx_cmd.err = ERR_MEM;
-        }
-    }
-
-    return tx_cmd.err;
-}
-
 void emac_task(void *pv)
 {
     emac_event_t e;
@@ -662,18 +792,21 @@ void emac_task(void *pv)
             case SIG_EMAC_RX_DONE:
                 emac_process_rx();
                 break;
+            case SIG_EMAC_RX_UNAVAIL:
+                emac_process_rx_unavail();
+                break;
             case SIG_EMAC_TX_DONE:
                 emac_process_tx();
                 break;
-            case SIG_EMAC_TX:
-                emac_xmit((void *)e.par);
-                break;
             case SIG_EMAC_START:
                 emac_start((void *)e.par);
                 break;
             case SIG_EMAC_STOP:
                 emac_stop((void *)e.par);
                 break;
+            case SIG_EMAC_CHECK_LINK:
+                emac_process_link_check();
+                break;
             default:
                 ESP_LOGE(TAG, "unexpect sig %d", e.sig);
                 break;
@@ -684,27 +817,35 @@ void emac_task(void *pv)
 
 esp_err_t IRAM_ATTR emac_post(emac_sig_t sig, emac_par_t par)
 {
-    portENTER_CRITICAL(&g_emac_mux);
+    if(sig <= SIG_EMAC_RX_DONE) {
+        if (emac_sig_cnt[sig]) {
+            return ESP_OK;
+        } else {
+            emac_sig_cnt[sig]++;
+            emac_event_t evt;
+            signed portBASE_TYPE ret;
+            evt.sig = sig;
+            evt.par = par;
+            portBASE_TYPE tmp;
+
+            ret = xQueueSendFromISR(emac_xqueue, &evt, &tmp);
 
-    if (emac_sig_cnt[sig] && sig != SIG_EMAC_TX) {
-        portEXIT_CRITICAL(&g_emac_mux);
-        return ESP_OK;
+            if(tmp != pdFALSE) {
+                portYIELD_FROM_ISR();
+            }
+
+            if(ret != pdPASS) {
+                return ESP_FAIL;
+            }
+        }
     } else {
         emac_sig_cnt[sig]++;
-        portEXIT_CRITICAL(&g_emac_mux);
         emac_event_t evt;
         evt.sig = sig;
         evt.par = par;
-        if (sig <= SIG_EMAC_RX_DONE) {
-            portBASE_TYPE tmp;
 
-            if (xQueueSendFromISR(emac_xqueue, &evt, &tmp) != pdPASS) {
-                return ESP_FAIL;
-            }
-        } else {
-            if (xQueueSend(emac_xqueue, &evt, 10 / portTICK_RATE_MS) != pdTRUE) {
-                return ESP_FAIL;
-            }
+        if (xQueueSend(emac_xqueue, &evt, 10 / portTICK_RATE_MS) != pdTRUE) {
+            return ESP_FAIL;
         }
     }
 
@@ -737,7 +878,7 @@ esp_err_t esp_eth_init(eth_config_t *config)
     REG_SET_FIELD(EMAC_EX_PHYINF_CONF_REG, EMAC_EX_PHY_INTF_SEL, EMAC_EX_PHY_INTF_RMII);
 
     emac_dma_init();
-    if (emac_config.mac_mode == EMAC_MODE_RMII) {
+    if (emac_config.mac_mode == ETH_MODE_RMII) {
         emac_set_clk_rmii();
     } else {
         emac_set_clk_mii();
@@ -752,8 +893,12 @@ esp_err_t esp_eth_init(eth_config_t *config)
 
     //init task for emac
     emac_g_sem = xSemaphoreCreateBinary();
+    emac_rx_xMutex = xSemaphoreCreateRecursiveMutex();
+    emac_tx_xMutex = xSemaphoreCreateRecursiveMutex();
     emac_xqueue = xQueueCreate(EMAC_EVT_QNUM, sizeof(emac_event_t));
-    xTaskCreate(emac_task, "emacT", 2048 * 4, NULL, (19), &emac_task_hdl);
+    xTaskCreate(emac_task, "emacT", 2048, NULL, EMAC_TASK_PRIORITY, &emac_task_hdl);
+
+    esp_intr_alloc(ETS_ETH_MAC_INTR_SOURCE, 0, emac_process_intr, NULL, NULL);
 
     emac_reset();
     emac_enable_clk(false);
index b97289dd2bd08c1a528ed6113d6ae559255fbb14..2aae9d202497b62575baf0c71b954762625b0c77 100644 (file)
 extern "C" {
 #endif
 
-typedef void (*eth_phy_fun)(void);
-typedef esp_err_t (*eth_tcpip_input_fun)(void *buffer, uint16_t len, void *eb);
-typedef void (*eth_gpio_config_func)(void);
-
 typedef enum {
     ETH_MODE_RMII = 0,
     ETH_MDOE_MII,
 } eth_mode_t;
 
+typedef enum {
+    ETH_SPEED_MODE_10M = 0,
+    ETH_SPEED_MODE_100M,
+} eth_speed_mode_t;
+
+typedef enum {
+    ETH_MODE_HALFDUPLEX = 0,
+    ETH_MDOE_FULLDUPLEX,
+} eth_duplex_mode_t;
+
 typedef enum {
     PHY0 = 0,
     PHY1,
@@ -66,6 +72,15 @@ typedef enum {
     PHY31,
 } eth_phy_base_t;
 
+typedef bool (*eth_phy_check_link_func)(void);
+typedef void (*eth_phy_check_init_func)(void);
+typedef eth_speed_mode_t (*eth_phy_get_speed_mode_func)(void);
+typedef eth_duplex_mode_t (*eth_phy_get_duplex_mode_func)(void);
+typedef void (*eth_phy_func)(void);
+typedef esp_err_t (*eth_tcpip_input_func)(void *buffer, uint16_t len, void *eb);
+typedef void (*eth_gpio_config_func)(void);
+
+
 /**
  * @brief ethernet configuration
  *
@@ -73,8 +88,12 @@ typedef enum {
 typedef struct {
     eth_phy_base_t  phy_addr;                   /*!< phy base addr (0~31) */
     eth_mode_t mac_mode;                        /*!< mac mode only support RMII now */
-    eth_tcpip_input_fun tcpip_input;            /*!< tcpip input func  */
-    eth_phy_fun phy_init;                       /*!< phy init func  */
+    eth_tcpip_input_func tcpip_input;            /*!< tcpip input func  */
+    eth_phy_func phy_init;                       /*!< phy init func  */
+    eth_phy_check_link_func phy_check_link;     /*!< phy check link func  */
+    eth_phy_check_init_func phy_check_init;     /*!< phy check init func  */
+    eth_phy_get_speed_mode_func phy_get_speed_mode;     /*!< phy check init func  */
+    eth_phy_get_duplex_mode_func phy_get_duplex_mode;     /*!< phy check init func  */
     eth_gpio_config_func gpio_config;           /*!< gpio config func  */
 } eth_config_t;
 
@@ -159,6 +178,16 @@ void esp_eth_smi_write(uint32_t reg_num, uint16_t value);
  */
 uint16_t esp_eth_smi_read(uint32_t reg_num);
 
+/**
+ * @brief  Free emac rx buf.
+ *
+ * @note  buf can not be null,and it is tcpip input buf.
+ *
+ * @param[in] buf: start address of recevie packet data.
+ *
+ */
+void esp_eth_free_rx_buf(void *buf);
+
 #ifdef __cplusplus
 }
 #endif
index 29e24ef2b414d5251a3fbec545fcf23caae9e3d3..b954817492b1f13db60414e19e9784fb653e452f 100755 (executable)
@@ -80,6 +80,7 @@
 
 #if ESP_LWIP
 #include "esp_wifi_internal.h"
+#include "esp_eth.h"
 #endif
 
 #define SIZEOF_STRUCT_PBUF        LWIP_MEM_ALIGN_SIZE(sizeof(struct pbuf))
@@ -351,7 +352,8 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
   p->flags = 0;
   
 #if ESP_LWIP
-  p->eb = NULL; 
+  p->user_buf = NULL;
+  p->user_flag = PBUF_USER_FLAG_OWNER_NULL; 
 #endif
 
   LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p));
@@ -720,9 +722,13 @@ pbuf_free(struct pbuf *p)
         } else if (type == PBUF_ROM || type == PBUF_REF) {
         
 #if ESP_LWIP
-          if (type == PBUF_REF && p->eb != NULL ) esp_wifi_internal_free_rx_buffer(p->eb);
+          if (type == PBUF_REF && p->user_flag == PBUF_USER_FLAG_OWNER_WIFI ) {
+               esp_wifi_internal_free_rx_buffer(p->user_buf);
+          }
+          if (type == PBUF_REF && p->user_flag == PBUF_USER_FLAG_OWNER_ETH ) {  
+               esp_eth_free_rx_buf(p->user_buf);
+          }
 #endif
-
             memp_free(MEMP_PBUF, p);
             /* type == PBUF_RAM */
         } else {
index 1834c4e04cf21319dce3928fbfc00130261fcc1a..d84aabaf81430cf27f88576ff522ef93c6db100f 100755 (executable)
@@ -105,6 +105,12 @@ typedef enum {
 /** indicates this pbuf includes a TCP FIN flag */
 #define PBUF_FLAG_TCP_FIN   0x20U
 
+#if ESP_LWIP
+#define PBUF_USER_FLAG_OWNER_NULL   0
+#define PBUF_USER_FLAG_OWNER_WIFI   1
+#define PBUF_USER_FLAG_OWNER_ETH    2
+#endif
+
 struct pbuf {
   /** next pbuf in singly linked pbuf chain */
   struct pbuf *next;
@@ -138,7 +144,8 @@ struct pbuf {
   u16_t ref;
   
 #if ESP_LWIP
-  void  *eb;
+  void  *user_buf;
+  u8_t user_flag;
 #endif
 };
 
index c6f08ec832f6e138912066bc810f3a06fcf0f162..79f21f6b3f71574c210d568aa8eebe1658693593 100755 (executable)
@@ -113,7 +113,8 @@ ethernet_low_level_output(struct netif *netif, struct pbuf *p)
   esp_interface_t eth_if = tcpip_adapter_get_esp_if(netif);
 
   if (eth_if != ESP_IF_ETH) {
-    printf("eth_if=%d netif=%p pbuf=%p len=%d\n", eth_if, netif, p, p->len); 
+    LWIP_DEBUGF(NETIF_DEBUG,("eth_if=%d netif=%p pbuf=%p len=%d\n", eth_if, netif, p, p->len)); 
+
     return ERR_IF;
   } 
   
@@ -134,7 +135,6 @@ ethernet_low_level_output(struct netif *netif, struct pbuf *p)
         }
     }
    
-    //printf("netif=%p pbuf=%p len=%d\n", netif, p, p->len); 
     return esp_eth_tx(q->payload, pbuf_x_len);
 #else
     for(q = p; q != NULL; q = q->next) {
@@ -160,7 +160,7 @@ ethernetif_input(struct netif *netif, void *buffer, uint16_t len)
   
   if(buffer== NULL || netif == NULL)
        goto _exit;
-
+#if CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE
   p = pbuf_alloc(PBUF_RAW, len, PBUF_RAM);
   if (p == NULL) {
     //g_rx_alloc_pbuf_fail_cnt++;
@@ -168,12 +168,28 @@ ethernetif_input(struct netif *netif, void *buffer, uint16_t len)
   }
   memcpy(p->payload, buffer, len);
 
-  /* full packet send to tcpip_thread to process */
-  if (netif->input(p, netif) != ERR_OK) {
-    LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
-    pbuf_free(p);
+/* full packet send to tcpip_thread to process */
+if (netif->input(p, netif) != ERR_OK) {
+  LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
+  pbuf_free(p);
+}
+
+#else
+  p = pbuf_alloc(PBUF_RAW, len, PBUF_REF);
+  if (p == NULL){
+    return;
   }
-  
+  p->payload = buffer;
+  p->user_flag = PBUF_USER_FLAG_OWNER_ETH;
+  p->user_buf = buffer;
+  /* full packet send to tcpip_thread to process */
+if (netif->input(p, netif) != ERR_OK) {
+  LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
+  p->user_flag = PBUF_USER_FLAG_OWNER_NULL;
+  pbuf_free(p);
+}
+#endif
 _exit:
 ;        
 }
index efaa76a73f92c2e38f931969f3b594adc041bf78..fea163f8cc36ac43fdd5e76213878cb69234d470 100755 (executable)
@@ -176,7 +176,8 @@ wlanif_input(struct netif *netif, void *buffer, u16_t len, void* eb)
     return;
   }
   p->payload = buffer;
-  p->eb = eb;
+  p->user_buf = eb;
+  p->user_flag = PBUF_USER_FLAG_OWNER_WIFI;
 #endif
 
   /* full packet send to tcpip_thread to process */
diff --git a/examples/14_ethernet/main/tlk110_phy.h b/examples/14_ethernet/main/tlk110_phy.h
new file mode 100644 (file)
index 0000000..5f2ca64
--- /dev/null
@@ -0,0 +1,28 @@
+#define BASIC_MODE_STATUS_REG           (0x1)
+#define AUTO_NEGOTIATION_COMPLETE          BIT(5)
+#define LINK_STATUS                        BIT(2)
+
+#define PHY_IDENTIFIER_REG              (0x2)
+#define OUI_MSB_21TO6_DEF                      0x2000
+
+#define SOFTWARE_STAP_CONTROL_REG       (0x9)
+#define SW_STRAP_CONFIG_DONE               BIT(15)
+#define AUTO_MDIX_ENABLE                   BIT(14)
+#define AUTO_NEGOTIATION_ENABLE            BIT(13)
+#define AN_1                               BIT(12)
+#define AN_0                               BIT(11)
+#define LED_CFG                            BIT(10)
+#define RMII_ENHANCED_MODE                 BIT(9) 
+
+#define PHY_STATUS_REG                  (0x10)
+#define AUTO_NEGTIATION_STATUS             BIT(4)
+#define DUPLEX_STATUS                      BIT(2)
+#define SPEED_STATUS                       BIT(1)       
+
+#define CABLE_DIAGNOSTIC_CONTROL_REG    (0x1e)
+#define DIAGNOSTIC_DONE                    BIT(1)
+
+#define PHY_RESET_CONTROL_REG           (0x1f)
+#define SOFTWARE_RESET                     BIT(15)
+
+
index 836e977f481a231b31068c764d3bfb47112ee906..7e84a9badd12e307caeab3fae574f2e544064092 100644 (file)
 #include "tcpip_adapter.h"
 #include "nvs_flash.h"
 #include "driver/gpio.h"
+#include "tlk110_phy.h"
 
 static const char *TAG = "eth_demo";
 
+#define DEFAULT_PHY_CONFIG (AUTO_MDIX_ENABLE|AUTO_NEGOTIATION_ENABLE|AN_1|AN_0|LED_CFG)
+
+void phy_tlk110_check_phy_init(void)
+{
+    while((esp_eth_smi_read(BASIC_MODE_STATUS_REG) & AUTO_NEGOTIATION_COMPLETE ) != AUTO_NEGOTIATION_COMPLETE)
+    {};
+    while((esp_eth_smi_read(PHY_STATUS_REG) & AUTO_NEGTIATION_STATUS ) != AUTO_NEGTIATION_STATUS)
+    {};
+    while((esp_eth_smi_read(CABLE_DIAGNOSTIC_CONTROL_REG) & DIAGNOSTIC_DONE ) != DIAGNOSTIC_DONE)
+    {};
+}
+
+eth_speed_mode_t phy_tlk110_get_speed_mode(void)
+{
+    if((esp_eth_smi_read(PHY_STATUS_REG) & SPEED_STATUS ) != SPEED_STATUS) {
+        return ETH_SPEED_MODE_100M;
+    } else {
+        return ETH_SPEED_MODE_10M;
+    }   
+}
+
+eth_duplex_mode_t phy_tlk110_get_duplex_mode(void)
+{
+    if((esp_eth_smi_read(PHY_STATUS_REG) & DUPLEX_STATUS ) == DUPLEX_STATUS) {
+        return ETH_MDOE_FULLDUPLEX;
+    } else {
+        return ETH_MODE_HALFDUPLEX;
+    }   
+}
+
+bool phy_tlk110_check_phy_link_status(void)
+{
+    return ((esp_eth_smi_read(BASIC_MODE_STATUS_REG) & LINK_STATUS) == LINK_STATUS );
+}
+
 void phy_tlk110_init(void)
 {
-    esp_eth_smi_write(0x1f, 0x8000);
-    ets_delay_us(20000);
+    esp_eth_smi_write(PHY_RESET_CONTROL_REG, SOFTWARE_RESET);
 
-    while (esp_eth_smi_read(0x2) != 0x2000) {
+    while (esp_eth_smi_read(PHY_IDENTIFIER_REG) != OUI_MSB_21TO6_DEF) {
     }
 
-    esp_eth_smi_write(0x9, 0x7400);
-    esp_eth_smi_write(0x9, 0xf400);
-    ets_delay_us(20000);
+    esp_eth_smi_write(SOFTWARE_STAP_CONTROL_REG, DEFAULT_PHY_CONFIG |SW_STRAP_CONFIG_DONE);
+    ets_delay_us(300);
 }
 
 void eth_gpio_config_rmii(void)
 {
     //txd0 to gpio19 ,can not change
-    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO19_U, 5);
-    //rx_en to gpio21 ,can not change
-    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO21_U, 5);
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO19_U, FUNC_GPIO19_EMAC_TXD0);
+    //tx_en to gpio21 ,can not change
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO21_U, FUNC_GPIO21_EMAC_TX_EN);
     //txd1 to gpio22 , can not change
-    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO22_U, 5);
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO22_U, FUNC_GPIO22_EMAC_TXD1);
     //rxd0 to gpio25 , can not change
     gpio_set_direction(25, GPIO_MODE_INPUT);
     //rxd1 to gpio26 ,can not change
@@ -102,8 +136,13 @@ void app_main()
     config.phy_init = phy_tlk110_init;
     config.gpio_config = eth_gpio_config_rmii;
     config.tcpip_input = tcpip_adapter_eth_input;
+    config.phy_check_init = phy_tlk110_check_phy_init;
+    config.phy_check_link = phy_tlk110_check_phy_link_status;
+    config.phy_get_speed_mode = phy_tlk110_get_speed_mode;
+    config.phy_get_duplex_mode = phy_tlk110_get_duplex_mode;
 
     ret = esp_eth_init(&config);
+
     if(ret == ESP_OK) {
         esp_eth_enable();
         xTaskCreate(eth_task, "eth_task", 2048, NULL, (tskIDLE_PRIORITY + 2), NULL);