]> granicus.if.org Git - esp-idf/commitdiff
Ethernet: optimize and bugfix
authorsuda-morris <362953310@qq.com>
Thu, 19 Sep 2019 03:27:42 +0000 (11:27 +0800)
committersuda-morris <362953310@qq.com>
Fri, 11 Oct 2019 04:15:17 +0000 (12:15 +0800)
1. simplify deallocate in esp_eth_mac_new_esp32, esp_eth_mac_new_dm9051
2. remove blocking operation in os timer callback
3. check buffer size in ethernet receive function

12 files changed:
components/esp_eth/include/esp_eth.h
components/esp_eth/include/esp_eth_mac.h
components/esp_eth/src/esp_eth_mac_dm9051.c
components/esp_eth/src/esp_eth_mac_esp32.c
components/esp_eth/src/esp_eth_phy_dm9051.c
components/esp_eth/src/esp_eth_phy_dp83848.c
components/esp_eth/src/esp_eth_phy_ip101.c
components/esp_eth/src/esp_eth_phy_lan8720.c
components/esp_eth/src/esp_eth_phy_rtl8201.c
components/esp_eth/test/test_emac.c
components/soc/esp32/emac_hal.c
components/soc/esp32/include/hal/emac.h

index cf4b570502b5261534b82c97f2e6352fe086b314..0d40d0956279bf1601fbe6734895ef00192e8044 100644 (file)
@@ -148,9 +148,14 @@ esp_err_t esp_eth_transmit(esp_eth_handle_t hdl, uint8_t *buf, uint32_t length);
 * @param[out] buf: buffer to preserve the received packet
 * @param[out] length: length of the received packet
 *
+* @note Before this function got invoked, the value of "length" should set by user, equals the size of buffer.
+*       After the function returned, the value of "length" means the real length of received data.
+*
 * @return
 *       - ESP_OK: receive frame buffer successfully
 *       - ESP_ERR_INVALID_ARG: receive frame buffer failed because of some invalid argument
+*       - ESP_ERR_INVALID_SIZE: input buffer size is not enough to hold the incoming data.
+*                               in this case, value of returned "length" indicates the real size of incoming data.
 *       - ESP_FAIL: receive frame buffer failed because some other error occurred
 */
 esp_err_t esp_eth_receive(esp_eth_handle_t hdl, uint8_t *buf, uint32_t *length);
index c189acb2898378b255d893d7315bb9bdc008a9cf..efcbe98d00c08bd8f04ae2da294ca526a840ae36 100644 (file)
@@ -99,10 +99,14 @@ struct esp_eth_mac_s {
     * @param[out] length: length of the received packet
     *
     * @note Memory of buf is allocated in the Layer2, make sure it get free after process.
+    * @note Before this function got invoked, the value of "length" should set by user, equals the size of buffer.
+    *       After the function returned, the value of "length" means the real length of received data.
     *
     * @return
     *      - ESP_OK: receive packet successfully
     *      - ESP_ERR_INVALID_ARG: receive packet failed because of invalid argument
+    *      - ESP_ERR_INVALID_SIZE: input buffer size is not enough to hold the incoming data.
+    *                              in this case, value of returned "length" indicates the real size of incoming data.
     *      - ESP_FAIL: receive packet failed because some other error occurred
     *
     */
index 5fb9456ccc642ed9abc36f901bd6d2123a71491b..17bad75e5447cd1c30b26a0d6149dcbc9bb2a710 100644 (file)
@@ -38,7 +38,6 @@ static const char *TAG = "emac_dm9051";
         }                                                                         \
     } while (0)
 
-#define RX_QUEUE_WAIT_MS (100)
 #define DM9051_SPI_LOCK_TIMEOUT_MS (50)
 #define DM9051_PHY_OPERATION_TIMEOUT_US (1000)
 
@@ -308,6 +307,30 @@ static esp_err_t dm9051_memory_read(emac_dm9051_t *emac, uint8_t *buffer, uint32
     return ret;
 }
 
+/**
+ * @brief peek buffer from dm9051 internal memory (without internal cursor moved)
+ */
+static esp_err_t dm9051_memory_peek(emac_dm9051_t *emac, uint8_t *buffer, uint32_t len)
+{
+    esp_err_t ret = ESP_OK;
+    spi_transaction_t trans = {
+        .cmd = DM9051_SPI_RD,
+        .addr = DM9051_MRCMDX1,
+        .length = len * 8,
+        .rx_buffer = buffer
+    };
+    if (dm9051_lock(emac)) {
+        if (spi_device_polling_transmit(emac->spi_hdl, &trans) != ESP_OK) {
+            ESP_LOGE(TAG, "%s(%d): spi transmit failed", __FUNCTION__, __LINE__);
+            ret = ESP_FAIL;
+        }
+        dm9051_unlock(emac);
+    } else {
+        ret = ESP_ERR_TIMEOUT;
+    }
+    return ret;
+}
+
 /**
  * @brief read mac address from internal registers
  */
@@ -501,26 +524,27 @@ static void emac_dm9051_task(void *arg)
     uint8_t *buffer = NULL;
     uint32_t length = 0;
     while (1) {
-        if (ulTaskNotifyTake(pdFALSE, pdMS_TO_TICKS(RX_QUEUE_WAIT_MS))) {
-            /* clear interrupt status */
-            dm9051_register_read(emac, DM9051_ISR, &status);
-            dm9051_register_write(emac, DM9051_ISR, status);
-            /* packet received */
-            if (status & ISR_PR) {
-                do {
-                    buffer = (uint8_t *)heap_caps_malloc(ETH_MAX_PACKET_SIZE, MALLOC_CAP_DMA);
-                    if (emac->parent.receive(&emac->parent, buffer, &length) == ESP_OK) {
-                        /* pass the buffer to stack (e.g. TCP/IP layer) */
-                        if (length) {
-                            emac->eth->stack_input(emac->eth, buffer, length);
-                        } else {
-                            free(buffer);
-                        }
+        // block indefinitely until some task notifies me
+        ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
+        /* clear interrupt status */
+        dm9051_register_read(emac, DM9051_ISR, &status);
+        dm9051_register_write(emac, DM9051_ISR, status);
+        /* packet received */
+        if (status & ISR_PR) {
+            do {
+                length = ETH_MAX_PACKET_SIZE;
+                buffer = (uint8_t *)heap_caps_malloc(length, MALLOC_CAP_DMA);
+                if (emac->parent.receive(&emac->parent, buffer, &length) == ESP_OK) {
+                    /* pass the buffer to stack (e.g. TCP/IP layer) */
+                    if (length) {
+                        emac->eth->stack_input(emac->eth, buffer, length);
                     } else {
                         free(buffer);
                     }
-                } while (emac->packets_remain);
-            }
+                } else {
+                    free(buffer);
+                }
+            } while (emac->packets_remain);
         }
     }
     vTaskDelete(NULL);
@@ -744,13 +768,26 @@ static esp_err_t emac_dm9051_receive(esp_eth_mac_t *mac, uint8_t *buf, uint32_t
     if (rxbyte > 1) {
         MAC_CHECK(dm9051_stop(emac) == ESP_OK, "stop dm9051 failed", err, ESP_FAIL);
         /* reset rx fifo pointer */
-        MAC_CHECK(dm9051_register_write(emac, DM9051_MPTRCR, MPTRCR_RST_RX) == ESP_OK, "write MPTRCR failed", err, ESP_FAIL);
+        MAC_CHECK(dm9051_register_write(emac, DM9051_MPTRCR, MPTRCR_RST_RX) == ESP_OK,
+                  "write MPTRCR failed", err, ESP_FAIL);
         ets_delay_us(10);
         MAC_CHECK(dm9051_start(emac) == ESP_OK, "start dm9051 failed", err, ESP_FAIL);
         MAC_CHECK(false, "reset rx fifo pointer", err, ESP_FAIL);
     } else if (rxbyte) {
-        MAC_CHECK(dm9051_memory_read(emac, (uint8_t *)&header, sizeof(header)) == ESP_OK, "read rx header failed", err, ESP_FAIL);
+        MAC_CHECK(dm9051_memory_peek(emac, (uint8_t *)&header, sizeof(header)) == ESP_OK,
+                  "peek rx header failed", err, ESP_FAIL);
         rx_len = header.length_low + (header.length_high << 8);
+        /* check if the buffer can hold all the incoming data */
+        if (*length < rx_len - 4) {
+            ESP_LOGE(TAG, "buffer size too small");
+            /* tell upper layer the size we need */
+            *length = rx_len - 4;
+            ret = ESP_ERR_INVALID_SIZE;
+            goto err;
+        }
+        MAC_CHECK(*length >= rx_len - 4, "buffer size too small", err, ESP_ERR_INVALID_SIZE);
+        MAC_CHECK(dm9051_memory_read(emac, (uint8_t *)&header, sizeof(header)) == ESP_OK,
+                  "read rx header failed", err, ESP_FAIL);
         MAC_CHECK(dm9051_memory_read(emac, buf, rx_len) == ESP_OK, "read rx data failed", err, ESP_FAIL);
         MAC_CHECK(!(header.status & 0xBF), "receive status error: %xH", err, ESP_FAIL, header.status);
         *length = rx_len - 4; // substract the CRC length (4Bytes)
@@ -818,9 +855,10 @@ static esp_err_t emac_dm9051_del(esp_eth_mac_t *mac)
 esp_eth_mac_t *esp_eth_mac_new_dm9051(const eth_dm9051_config_t *dm9051_config, const eth_mac_config_t *mac_config)
 {
     esp_eth_mac_t *ret = NULL;
+    emac_dm9051_t *emac = NULL;
     MAC_CHECK(dm9051_config, "can't set dm9051 specific config to null", err, NULL);
     MAC_CHECK(mac_config, "can't set mac config to null", err, NULL);
-    emac_dm9051_t *emac = calloc(1, sizeof(emac_dm9051_t));
+    emac = calloc(1, sizeof(emac_dm9051_t));
     MAC_CHECK(emac, "calloc emac failed", err, NULL);
     /* bind methods and attributes */
     emac->sw_reset_timeout_ms = mac_config->sw_reset_timeout_ms;
@@ -841,16 +879,22 @@ esp_eth_mac_t *esp_eth_mac_new_dm9051(const eth_dm9051_config_t *dm9051_config,
     emac->parent.receive = emac_dm9051_receive;
     /* create mutex */
     emac->spi_lock = xSemaphoreCreateMutex();
-    MAC_CHECK(emac->spi_lock, "create lock failed", err_lock, NULL);
+    MAC_CHECK(emac->spi_lock, "create lock failed", err, NULL);
     /* create dm9051 task */
     BaseType_t xReturned = xTaskCreate(emac_dm9051_task, "dm9051_tsk", mac_config->rx_task_stack_size, emac,
                                        mac_config->rx_task_prio, &emac->rx_task_hdl);
-    MAC_CHECK(xReturned == pdPASS, "create dm9051 task failed", err_tsk, NULL);
+    MAC_CHECK(xReturned == pdPASS, "create dm9051 task failed", err, NULL);
     return &(emac->parent);
-err_tsk:
-    vSemaphoreDelete(emac->spi_lock);
-err_lock:
-    free(emac);
+
 err:
+    if (emac) {
+        if (emac->rx_task_hdl) {
+            vTaskDelete(emac->rx_task_hdl);
+        }
+        if (emac->spi_lock) {
+            vSemaphoreDelete(emac->spi_lock);
+        }
+        free(emac);
+    }
     return ret;
 }
index bbc3df22da505499da48c39c68f04743a5c36612..dc68238d42c1f22858bd3cc9aad6a0eb51a04998 100644 (file)
@@ -40,7 +40,6 @@ static const char *TAG = "emac_esp32";
         }                                                                         \
     } while (0)
 
-#define RX_QUEUE_WAIT_MS (20)
 #define PHY_OPERATION_TIMEOUT_US (1000)
 
 typedef struct {
@@ -224,7 +223,16 @@ static esp_err_t emac_esp32_receive(esp_eth_mac_t *mac, uint8_t *buf, uint32_t *
     esp_err_t ret = ESP_OK;
     emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
     MAC_CHECK(buf && length, "can't set buf and length to null", err, ESP_ERR_INVALID_ARG);
-    *length = emac_hal_receive_frame(&emac->hal, buf, &emac->frames_remain);
+    uint32_t receive_len = emac_hal_receive_frame(&emac->hal, buf, *length, &emac->frames_remain);
+    /* we need to check the return value in case the buffer size is not enough */
+    if (*length < receive_len) {
+        ESP_LOGE(TAG, "buffer size too small");
+        /* tell upper layer the size we need */
+        *length = receive_len;
+        ret = ESP_ERR_INVALID_SIZE;
+        goto err;
+    }
+    *length = receive_len;
     return ESP_OK;
 err:
     return ret;
@@ -236,21 +244,22 @@ static void emac_esp32_rx_task(void *arg)
     uint8_t *buffer = NULL;
     uint32_t length = 0;
     while (1) {
-        if (ulTaskNotifyTake(pdFALSE, pdMS_TO_TICKS(RX_QUEUE_WAIT_MS))) {
-            do {
-                buffer = (uint8_t *)malloc(ETH_MAX_PACKET_SIZE);
-                if (emac_esp32_receive(&emac->parent, buffer, &length) == ESP_OK) {
-                    /* pass the buffer to stack (e.g. TCP/IP layer) */
-                    if (length) {
-                        emac->eth->stack_input(emac->eth, buffer, length);
-                    } else {
-                        free(buffer);
-                    }
+        // block indefinitely until some task notifies me
+        ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
+        do {
+            length = ETH_MAX_PACKET_SIZE;
+            buffer = (uint8_t *)malloc(length);
+            if (emac_esp32_receive(&emac->parent, buffer, &length) == ESP_OK) {
+                /* pass the buffer to stack (e.g. TCP/IP layer) */
+                if (length) {
+                    emac->eth->stack_input(emac->eth, buffer, length);
                 } else {
                     free(buffer);
                 }
-            } while (emac->frames_remain);
-        }
+            } else {
+                free(buffer);
+            }
+        } while (emac->frames_remain);
     }
     vTaskDelete(NULL);
 }
@@ -358,42 +367,29 @@ void emac_esp32_isr_handler(void *args)
 esp_eth_mac_t *esp_eth_mac_new_esp32(const eth_mac_config_t *config)
 {
     esp_eth_mac_t *ret = NULL;
+    void *descriptors = NULL;
+    emac_esp32_t *emac = NULL;
     MAC_CHECK(config, "can't set mac config to null", err, NULL);
-    emac_esp32_t *emac = calloc(1, sizeof(emac_esp32_t));
+    emac = calloc(1, sizeof(emac_esp32_t));
     MAC_CHECK(emac, "calloc emac failed", err, NULL);
     /* alloc memory for ethernet dma descriptor */
     uint32_t desc_size = CONFIG_ETH_DMA_RX_BUFFER_NUM * sizeof(eth_dma_rx_descriptor_t) +
                          CONFIG_ETH_DMA_TX_BUFFER_NUM * sizeof(eth_dma_tx_descriptor_t);
-    void *descriptors = heap_caps_calloc(1, desc_size, MALLOC_CAP_DMA);
-    MAC_CHECK(descriptors, "calloc descriptors failed", err_desc, NULL);
+    descriptors = heap_caps_calloc(1, desc_size, MALLOC_CAP_DMA);
+    MAC_CHECK(descriptors, "calloc descriptors failed", err, NULL);
     int i = 0;
     /* alloc memory for ethernet dma buffer */
     for (i = 0; i < CONFIG_ETH_DMA_RX_BUFFER_NUM; i++) {
         emac->rx_buf[i] = heap_caps_calloc(1, CONFIG_ETH_DMA_BUFFER_SIZE, MALLOC_CAP_DMA);
         if (!(emac->rx_buf[i])) {
-            break;
-        }
-    }
-    if (i != CONFIG_ETH_DMA_RX_BUFFER_NUM) {
-        for (--i; i >= 0; i--) {
-            free(emac->rx_buf[i]);
+            goto err;
         }
-        goto err_buffer;
     }
     for (i = 0; i < CONFIG_ETH_DMA_TX_BUFFER_NUM; i++) {
         emac->tx_buf[i] = heap_caps_calloc(1, CONFIG_ETH_DMA_BUFFER_SIZE, MALLOC_CAP_DMA);
         if (!(emac->tx_buf[i])) {
-            break;
-        }
-    }
-    if (i != CONFIG_ETH_DMA_TX_BUFFER_NUM) {
-        for (--i; i >= 0; i--) {
-            free(emac->tx_buf[i]);
-        }
-        for (i = 0; i < CONFIG_ETH_DMA_RX_BUFFER_NUM; i++) {
-            free(emac->rx_buf[i]);
+            goto err;
         }
-        goto err_buffer;
     }
     /* initialize hal layer driver */
     emac_hal_init(&emac->hal, descriptors, emac->rx_buf, emac->tx_buf);
@@ -415,26 +411,32 @@ esp_eth_mac_t *esp_eth_mac_new_esp32(const eth_mac_config_t *config)
     /* Interrupt configuration */
     MAC_CHECK(esp_intr_alloc(ETS_ETH_MAC_INTR_SOURCE, ESP_INTR_FLAG_IRAM, emac_esp32_isr_handler,
                              &emac->hal, &(emac->intr_hdl)) == ESP_OK,
-              "alloc emac interrupt failed", err_intr, NULL);
+              "alloc emac interrupt failed", err, NULL);
     /* create rx task */
     BaseType_t xReturned = xTaskCreate(emac_esp32_rx_task, "emac_rx", config->rx_task_stack_size, emac,
                                        config->rx_task_prio, &emac->rx_task_hdl);
-    MAC_CHECK(xReturned == pdPASS, "create emac_rx task failed", err_task, NULL);
+    MAC_CHECK(xReturned == pdPASS, "create emac_rx task failed", err, NULL);
     return &(emac->parent);
-err_task:
-    esp_intr_free(emac->intr_hdl);
-err_intr:
-    for (int i = 0; i < CONFIG_ETH_DMA_TX_BUFFER_NUM; i++) {
-        free(emac->tx_buf[i]);
+
+err:
+    if (emac) {
+        if (emac->rx_task_hdl) {
+            vTaskDelete(emac->rx_task_hdl);
+        }
+        if (emac->intr_hdl) {
+            esp_intr_free(emac->intr_hdl);
+        }
+        for (int i = 0; i < CONFIG_ETH_DMA_TX_BUFFER_NUM; i++) {
+            free(emac->tx_buf[i]);
+        }
+        for (int i = 0; i < CONFIG_ETH_DMA_RX_BUFFER_NUM; i++) {
+            free(emac->rx_buf[i]);
+        }
+        free(emac);
     }
-    for (int i = 0; i < CONFIG_ETH_DMA_RX_BUFFER_NUM; i++) {
-        free(emac->rx_buf[i]);
+    if (descriptors) {
+        free(descriptors);
     }
-err_buffer:
-    free(descriptors);
-err_desc:
-    free(emac);
-err:
     return ret;
 }
 
index cb658c181d9bc6e258b8e4e3c7d00fa827f393f3..070a80050029edad93b2ac2ff5d171b164290cfb 100644 (file)
@@ -79,16 +79,55 @@ typedef union {
 typedef struct {
     esp_eth_phy_t parent;
     esp_eth_mediator_t *eth;
-    const char *name;
     uint32_t addr;
     uint32_t reset_timeout_ms;
     uint32_t autonego_timeout_ms;
     eth_link_t link_status;
 } phy_dm9051_t;
 
+static esp_err_t dm9051_update_link_duplex_speed(phy_dm9051_t *dm9051)
+{
+    esp_eth_mediator_t *eth = dm9051->eth;
+    eth_speed_t speed = ETH_SPEED_10M;
+    eth_duplex_t duplex = ETH_DUPLEX_HALF;
+    bmsr_reg_t bmsr;
+    dscsr_reg_t dscsr;
+    PHY_CHECK(eth->phy_reg_read(eth, dm9051->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK,
+              "read BMSR failed", err);
+    eth_link_t link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
+    /* check if link status changed */
+    if (dm9051->link_status != link) {
+        /* when link up, read negotiation result */
+        if (link == ETH_LINK_UP) {
+            PHY_CHECK(eth->phy_reg_read(eth, dm9051->addr, ETH_PHY_DSCSR_REG_ADDR, &(dscsr.val)) == ESP_OK,
+                      "read DSCSR failed", err);
+            if (dscsr.fdx100 || dscsr.hdx100) {
+                speed = ETH_SPEED_100M;
+            } else {
+                speed = ETH_SPEED_10M;
+            }
+            if (dscsr.fdx100 || dscsr.fdx10) {
+                duplex = ETH_DUPLEX_FULL;
+            } else {
+                duplex = ETH_DUPLEX_HALF;
+            }
+            PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_SPEED, (void *)speed) == ESP_OK,
+                      "change speed failed", err);
+            PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_DUPLEX, (void *)duplex) == ESP_OK,
+                      "change duplex failed", err);
+        }
+        PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)link) == ESP_OK,
+                  "change link failed", err);
+        dm9051->link_status = link;
+    }
+    return ESP_OK;
+err:
+    return ESP_FAIL;
+}
+
 static esp_err_t dm9051_set_mediator(esp_eth_phy_t *phy, esp_eth_mediator_t *eth)
 {
-    PHY_CHECK(eth, "can't set mediator for dm9051 to null", err);
+    PHY_CHECK(eth, "can't set mediator to null", err);
     phy_dm9051_t *dm9051 = __containerof(phy, phy_dm9051_t, parent);
     dm9051->eth = eth;
     return ESP_OK;
@@ -99,19 +138,8 @@ err:
 static esp_err_t dm9051_get_link(esp_eth_phy_t *phy)
 {
     phy_dm9051_t *dm9051 = __containerof(phy, phy_dm9051_t, parent);
-    esp_eth_mediator_t *eth = dm9051->eth;
-    bmsr_reg_t bmsr;
-
-    PHY_CHECK(eth->phy_reg_read(eth, dm9051->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK, "read BMSR failed", err);
-    eth_link_t link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
-    if (dm9051->link_status != link) {
-        if (link == ETH_LINK_UP) {
-            phy->negotiate(phy);
-        } else {
-            PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)link) == ESP_OK, "send link event failed", err);
-            dm9051->link_status = link;
-        }
-    }
+    /* Updata information about link, speed, duplex */
+    PHY_CHECK(dm9051_update_link_duplex_speed(dm9051) == ESP_OK, "update link duplex speed failed", err);
     return ESP_OK;
 err:
     return ESP_FAIL;
@@ -122,17 +150,22 @@ static esp_err_t dm9051_reset(esp_eth_phy_t *phy)
     phy_dm9051_t *dm9051 = __containerof(phy, phy_dm9051_t, parent);
     esp_eth_mediator_t *eth = dm9051->eth;
     dscr_reg_t dscr;
-    PHY_CHECK(eth->phy_reg_read(eth, dm9051->addr, ETH_PHY_DSCR_REG_ADDR, &(dscr.val)) == ESP_OK, "read DSCR failed", err);
+    PHY_CHECK(eth->phy_reg_read(eth, dm9051->addr, ETH_PHY_DSCR_REG_ADDR, &(dscr.val)) == ESP_OK,
+              "read DSCR failed", err);
     dscr.smrst = 1;
-    PHY_CHECK(eth->phy_reg_write(eth, dm9051->addr, ETH_PHY_DSCR_REG_ADDR, dscr.val) == ESP_OK, "write DSCR failed", err);
+    PHY_CHECK(eth->phy_reg_write(eth, dm9051->addr, ETH_PHY_DSCR_REG_ADDR, dscr.val) == ESP_OK,
+              "write DSCR failed", err);
     bmcr_reg_t bmcr = {.reset = 1};
-    PHY_CHECK(eth->phy_reg_write(eth, dm9051->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK, "write BMCR failed", err);
+    PHY_CHECK(eth->phy_reg_write(eth, dm9051->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK,
+              "write BMCR failed", err);
     /* Wait for reset complete */
     uint32_t to = 0;
     for (to = 0; to < dm9051->reset_timeout_ms / 10; to++) {
         vTaskDelay(pdMS_TO_TICKS(10));
-        PHY_CHECK(eth->phy_reg_read(eth, dm9051->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK, "read BMCR failed", err);
-        PHY_CHECK(eth->phy_reg_read(eth, dm9051->addr, ETH_PHY_DSCR_REG_ADDR, &(dscr.val)) == ESP_OK, "read DSCR failed", err);
+        PHY_CHECK(eth->phy_reg_read(eth, dm9051->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK,
+                  "read BMCR failed", err);
+        PHY_CHECK(eth->phy_reg_read(eth, dm9051->addr, ETH_PHY_DSCR_REG_ADDR, &(dscr.val)) == ESP_OK,
+                  "read DSCR failed", err);
         if (!bmcr.reset && !dscr.smrst) {
             break;
         }
@@ -154,15 +187,18 @@ static esp_err_t dm9051_negotiate(esp_eth_phy_t *phy)
         .en_auto_nego = 1,     /* Auto Negotiation */
         .restart_auto_nego = 1 /* Restart Auto Negotiation */
     };
-    PHY_CHECK(eth->phy_reg_write(eth, dm9051->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK, "write BMCR failed", err);
+    PHY_CHECK(eth->phy_reg_write(eth, dm9051->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK,
+              "write BMCR failed", err);
     /* Wait for auto negotiation complete */
     bmsr_reg_t bmsr;
     dscsr_reg_t dscsr;
     uint32_t to = 0;
     for (to = 0; to < dm9051->autonego_timeout_ms / 10; to++) {
         vTaskDelay(pdMS_TO_TICKS(10));
-        PHY_CHECK(eth->phy_reg_read(eth, dm9051->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK, "read BMSR failed", err);
-        PHY_CHECK(eth->phy_reg_read(eth, dm9051->addr, ETH_PHY_DSCSR_REG_ADDR, &(dscsr.val)) == ESP_OK, "read DSCSR failed", err);
+        PHY_CHECK(eth->phy_reg_read(eth, dm9051->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK,
+                  "read BMSR failed", err);
+        PHY_CHECK(eth->phy_reg_read(eth, dm9051->addr, ETH_PHY_DSCSR_REG_ADDR, &(dscsr.val)) == ESP_OK,
+                  "read DSCSR failed", err);
         if (bmsr.auto_nego_complete && dscsr.anmb & 0x08) {
             break;
         }
@@ -171,27 +207,7 @@ static esp_err_t dm9051_negotiate(esp_eth_phy_t *phy)
         ESP_LOGW(TAG, "Ethernet PHY auto negotiation timeout");
     }
     /* Updata information about link, speed, duplex */
-    PHY_CHECK(eth->phy_reg_read(eth, dm9051->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK, "read BMSR failed", err);
-    PHY_CHECK(eth->phy_reg_read(eth, dm9051->addr, ETH_PHY_DSCSR_REG_ADDR, &(dscsr.val)) == ESP_OK, "read DSCSR failed", err);
-    eth_link_t link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
-    eth_speed_t speed = ETH_SPEED_10M;
-    eth_duplex_t duplex = ETH_DUPLEX_HALF;
-    if (dscsr.fdx100 || dscsr.hdx100) {
-        speed = ETH_SPEED_100M;
-    } else {
-        speed = ETH_SPEED_10M;
-    }
-    if (dscsr.fdx100 || dscsr.fdx10) {
-        duplex = ETH_DUPLEX_FULL;
-    } else {
-        duplex = ETH_DUPLEX_HALF;
-    }
-    PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_SPEED, (void *)speed) == ESP_OK, "send speed event failed", err);
-    PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_DUPLEX, (void *)duplex) == ESP_OK, "send duplex event failed", err);
-    if (dm9051->link_status != link) {
-        PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)link) == ESP_OK, "send link event failed", err);
-        dm9051->link_status = link;
-    }
+    PHY_CHECK(dm9051_update_link_duplex_speed(dm9051) == ESP_OK, "update link duplex speed failed", err);
     return ESP_OK;
 err:
     return ESP_FAIL;
@@ -202,7 +218,8 @@ static esp_err_t dm9051_pwrctl(esp_eth_phy_t *phy, bool enable)
     phy_dm9051_t *dm9051 = __containerof(phy, phy_dm9051_t, parent);
     esp_eth_mediator_t *eth = dm9051->eth;
     bmcr_reg_t bmcr;
-    PHY_CHECK(eth->phy_reg_read(eth, dm9051->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK, "read BMCR failed", err);
+    PHY_CHECK(eth->phy_reg_read(eth, dm9051->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK,
+              "read BMCR failed", err);
     if (!enable) {
         /* Enable IEEE Power Down Mode */
         bmcr.power_down = 1;
@@ -210,8 +227,10 @@ static esp_err_t dm9051_pwrctl(esp_eth_phy_t *phy, bool enable)
         /* Disable IEEE Power Down Mode */
         bmcr.power_down = 0;
     }
-    PHY_CHECK(eth->phy_reg_write(eth, dm9051->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK, "write BMCR failed", err);
-    PHY_CHECK(eth->phy_reg_read(eth, dm9051->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK, "read BMCR failed", err);
+    PHY_CHECK(eth->phy_reg_write(eth, dm9051->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK,
+              "write BMCR failed", err);
+    PHY_CHECK(eth->phy_reg_read(eth, dm9051->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK,
+              "read BMCR failed", err);
     if (!enable) {
         PHY_CHECK(bmcr.power_down == 1, "power down failed", err);
     } else {
@@ -231,7 +250,7 @@ static esp_err_t dm9051_set_addr(esp_eth_phy_t *phy, uint32_t addr)
 
 static esp_err_t dm9051_get_addr(esp_eth_phy_t *phy, uint32_t *addr)
 {
-    PHY_CHECK(addr, "get phy address failed", err);
+    PHY_CHECK(addr, "addr can't be null", err);
     phy_dm9051_t *dm9051 = __containerof(phy, phy_dm9051_t, parent);
     *addr = dm9051->addr;
     return ESP_OK;
@@ -251,15 +270,18 @@ static esp_err_t dm9051_init(esp_eth_phy_t *phy)
     phy_dm9051_t *dm9051 = __containerof(phy, phy_dm9051_t, parent);
     esp_eth_mediator_t *eth = dm9051->eth;
     /* Power on Ethernet PHY */
-    PHY_CHECK(dm9051_pwrctl(phy, true) == ESP_OK, "power on Ethernet PHY failed", err);
+    PHY_CHECK(dm9051_pwrctl(phy, true) == ESP_OK, "power control failed", err);
     /* Reset Ethernet PHY */
-    PHY_CHECK(dm9051_reset(phy) == ESP_OK, "reset Ethernet PHY failed", err);
+    PHY_CHECK(dm9051_reset(phy) == ESP_OK, "reset failed", err);
     /* Check PHY ID */
     phyidr1_reg_t id1;
     phyidr2_reg_t id2;
-    PHY_CHECK(eth->phy_reg_read(eth, dm9051->addr, ETH_PHY_IDR1_REG_ADDR, &(id1.val)) == ESP_OK, "read ID1 failed", err);
-    PHY_CHECK(eth->phy_reg_read(eth, dm9051->addr, ETH_PHY_IDR2_REG_ADDR, &(id2.val)) == ESP_OK, "read ID2 failed", err);
-    PHY_CHECK(id1.oui_msb == 0x0181 && id2.oui_lsb == 0x2E && id2.vendor_model == 0x0A, "wrong PHY chip ID", err);
+    PHY_CHECK(eth->phy_reg_read(eth, dm9051->addr, ETH_PHY_IDR1_REG_ADDR, &(id1.val)) == ESP_OK,
+              "read ID1 failed", err);
+    PHY_CHECK(eth->phy_reg_read(eth, dm9051->addr, ETH_PHY_IDR2_REG_ADDR, &(id2.val)) == ESP_OK,
+              "read ID2 failed", err);
+    PHY_CHECK(id1.oui_msb == 0x0181 && id2.oui_lsb == 0x2E && id2.vendor_model == 0x0A,
+              "wrong chip ID", err);
     return ESP_OK;
 err:
     return ESP_FAIL;
@@ -268,7 +290,7 @@ err:
 static esp_err_t dm9051_deinit(esp_eth_phy_t *phy)
 {
     /* Power off Ethernet PHY */
-    PHY_CHECK(dm9051_pwrctl(phy, false) == ESP_OK, "power off Ethernet PHY failed", err);
+    PHY_CHECK(dm9051_pwrctl(phy, false) == ESP_OK, "power control failed", err);
     return ESP_OK;
 err:
     return ESP_FAIL;
@@ -279,8 +301,7 @@ esp_eth_phy_t *esp_eth_phy_new_dm9051(const eth_phy_config_t *config)
     PHY_CHECK(config, "can't set phy config to null", err);
     PHY_CHECK(config->phy_addr == 1, "dm9051's phy address can only set to 1", err);
     phy_dm9051_t *dm9051 = calloc(1, sizeof(phy_dm9051_t));
-    PHY_CHECK(dm9051, "calloc dm9051 object failed", err);
-    dm9051->name = "dm9051";
+    PHY_CHECK(dm9051, "calloc dm9051 failed", err);
     dm9051->addr = config->phy_addr;
     dm9051->reset_timeout_ms = config->reset_timeout_ms;
     dm9051->link_status = ETH_LINK_DOWN;
@@ -295,7 +316,6 @@ esp_eth_phy_t *esp_eth_phy_new_dm9051(const eth_phy_config_t *config)
     dm9051->parent.get_addr = dm9051_get_addr;
     dm9051->parent.set_addr = dm9051_set_addr;
     dm9051->parent.del = dm9051_del;
-
     return &(dm9051->parent);
 err:
     return NULL;
index ac76f7a99c6d1d9c22c86379f4ab59e05d1900e6..f889a47ddf5a543c1d54b335b23f71b23ab742e2 100644 (file)
@@ -85,16 +85,55 @@ typedef union {
 typedef struct {
     esp_eth_phy_t parent;
     esp_eth_mediator_t *eth;
-    const char *name;
     uint32_t addr;
     uint32_t reset_timeout_ms;
     uint32_t autonego_timeout_ms;
     eth_link_t link_status;
 } phy_dp83848_t;
 
+static esp_err_t dp83848_update_link_duplex_speed(phy_dp83848_t *dp83848)
+{
+    esp_eth_mediator_t *eth = dp83848->eth;
+    eth_speed_t speed = ETH_SPEED_10M;
+    eth_duplex_t duplex = ETH_DUPLEX_HALF;
+    bmsr_reg_t bmsr;
+    physts_reg_t physts;
+    PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK,
+              "read BMSR failed", err);
+    eth_link_t link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
+    /* check if link status changed */
+    if (dp83848->link_status != link) {
+        /* when link up, read negotiation result */
+        if (link == ETH_LINK_UP) {
+            PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_STS_REG_ADDR, &(physts.val)) == ESP_OK,
+                      "read PHYSTS failed", err);
+            if (physts.speed_status) {
+                speed = ETH_SPEED_10M;
+            } else {
+                speed = ETH_SPEED_100M;
+            }
+            if (physts.duplex_status) {
+                duplex = ETH_DUPLEX_FULL;
+            } else {
+                duplex = ETH_DUPLEX_HALF;
+            }
+            PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_SPEED, (void *)speed) == ESP_OK,
+                      "change speed failed", err);
+            PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_DUPLEX, (void *)duplex) == ESP_OK,
+                      "change duplex failed", err);
+        }
+        PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)link) == ESP_OK,
+                  "change link failed", err);
+        dp83848->link_status = link;
+    }
+    return ESP_OK;
+err:
+    return ESP_FAIL;
+}
+
 static esp_err_t dp83848_set_mediator(esp_eth_phy_t *phy, esp_eth_mediator_t *eth)
 {
-    PHY_CHECK(eth, "can't set mediator for dp83848 to null", err);
+    PHY_CHECK(eth, "can't set mediator to null", err);
     phy_dp83848_t *dp83848 = __containerof(phy, phy_dp83848_t, parent);
     dp83848->eth = eth;
     return ESP_OK;
@@ -105,19 +144,8 @@ err:
 static esp_err_t dp83848_get_link(esp_eth_phy_t *phy)
 {
     phy_dp83848_t *dp83848 = __containerof(phy, phy_dp83848_t, parent);
-    esp_eth_mediator_t *eth = dp83848->eth;
-    bmsr_reg_t bmsr;
-
-    PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK, "read BMSR failed", err);
-    eth_link_t link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
-    if (dp83848->link_status != link) {
-        if (link == ETH_LINK_UP) {
-            phy->negotiate(phy);
-        } else {
-            PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)link) == ESP_OK, "send link event failed", err);
-            dp83848->link_status = link;
-        }
-    }
+    /* Updata information about link, speed, duplex */
+    PHY_CHECK(dp83848_update_link_duplex_speed(dp83848) == ESP_OK, "update link duplex speed failed", err);
     return ESP_OK;
 err:
     return ESP_FAIL;
@@ -128,17 +156,19 @@ static esp_err_t dp83848_reset(esp_eth_phy_t *phy)
     phy_dp83848_t *dp83848 = __containerof(phy, phy_dp83848_t, parent);
     esp_eth_mediator_t *eth = dp83848->eth;
     bmcr_reg_t bmcr = {.reset = 1};
-    PHY_CHECK(eth->phy_reg_write(eth, dp83848->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK, "write BMCR failed", err);
+    PHY_CHECK(eth->phy_reg_write(eth, dp83848->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK,
+              "write BMCR failed", err);
     /* Wait for reset complete */
     uint32_t to = 0;
     for (to = 0; to < dp83848->reset_timeout_ms / 10; to++) {
         vTaskDelay(pdMS_TO_TICKS(10));
-        PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK, "read BMCR failed", err);
+        PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK,
+                  "read BMCR failed", err);
         if (!bmcr.reset) {
             break;
         }
     }
-    PHY_CHECK(to < dp83848->reset_timeout_ms / 10, "PHY reset timeout", err);
+    PHY_CHECK(to < dp83848->reset_timeout_ms / 10, "reset timeout", err);
     return ESP_OK;
 err:
     return ESP_FAIL;
@@ -155,45 +185,28 @@ static esp_err_t dp83848_negotiate(esp_eth_phy_t *phy)
         .en_auto_nego = 1,     /* Auto Negotiation */
         .restart_auto_nego = 1 /* Restart Auto Negotiation */
     };
-    PHY_CHECK(eth->phy_reg_write(eth, dp83848->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK, "write BMCR failed", err);
+    PHY_CHECK(eth->phy_reg_write(eth, dp83848->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK,
+              "write BMCR failed", err);
     /* Wait for auto negotiation complete */
     bmsr_reg_t bmsr;
     physts_reg_t physts;
     uint32_t to = 0;
     for (to = 0; to < dp83848->autonego_timeout_ms / 10; to++) {
         vTaskDelay(pdMS_TO_TICKS(10));
-        PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK, "read BMSR failed", err);
-        PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_STS_REG_ADDR, &(physts.val)) == ESP_OK, "read PHYSTS failed", err);
+        PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK,
+                  "read BMSR failed", err);
+        PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_STS_REG_ADDR, &(physts.val)) == ESP_OK,
+                  "read PHYSTS failed", err);
         if (bmsr.auto_nego_complete && physts.auto_nego_complete) {
             break;
         }
     }
     /* Auto negotiation failed, maybe no network cable plugged in, so output a warning */
     if (to >= dp83848->autonego_timeout_ms / 10) {
-        ESP_LOGW(TAG, "Ethernet PHY auto negotiation timeout");
+        ESP_LOGW(TAG, "auto negotiation timeout");
     }
     /* Updata information about link, speed, duplex */
-    PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK, "read BMSR failed", err);
-    PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_STS_REG_ADDR, &(physts.val)) == ESP_OK, "read PHYSTS failed", err);
-    eth_link_t link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
-    eth_speed_t speed = ETH_SPEED_10M;
-    eth_duplex_t duplex = ETH_DUPLEX_HALF;
-    if (physts.speed_status) {
-        speed = ETH_SPEED_10M;
-    } else {
-        speed = ETH_SPEED_100M;
-    }
-    if (physts.duplex_status) {
-        duplex = ETH_DUPLEX_FULL;
-    } else {
-        duplex = ETH_DUPLEX_HALF;
-    }
-    PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_SPEED, (void *)speed) == ESP_OK, "send speed event failed", err);
-    PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_DUPLEX, (void *)duplex) == ESP_OK, "send duplex event failed", err);
-    if (dp83848->link_status != link) {
-        PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)link) == ESP_OK, "send link event failed", err);
-        dp83848->link_status = link;
-    }
+    PHY_CHECK(dp83848_update_link_duplex_speed(dp83848) == ESP_OK, "update link duplex speed failed", err);
     return ESP_OK;
 err:
     return ESP_FAIL;
@@ -204,7 +217,8 @@ static esp_err_t dp83848_pwrctl(esp_eth_phy_t *phy, bool enable)
     phy_dp83848_t *dp83848 = __containerof(phy, phy_dp83848_t, parent);
     esp_eth_mediator_t *eth = dp83848->eth;
     bmcr_reg_t bmcr;
-    PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK, "read BMCR failed", err);
+    PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK,
+              "read BMCR failed", err);
     if (!enable) {
         /* Enable IEEE Power Down Mode */
         bmcr.power_down = 1;
@@ -212,8 +226,10 @@ static esp_err_t dp83848_pwrctl(esp_eth_phy_t *phy, bool enable)
         /* Disable IEEE Power Down Mode */
         bmcr.power_down = 0;
     }
-    PHY_CHECK(eth->phy_reg_write(eth, dp83848->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK, "write BMCR failed", err);
-    PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK, "read BMCR failed", err);
+    PHY_CHECK(eth->phy_reg_write(eth, dp83848->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK,
+              "write BMCR failed", err);
+    PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK,
+              "read BMCR failed", err);
     if (!enable) {
         PHY_CHECK(bmcr.power_down == 1, "power down failed", err);
     } else {
@@ -233,7 +249,7 @@ static esp_err_t dp83848_set_addr(esp_eth_phy_t *phy, uint32_t addr)
 
 static esp_err_t dp83848_get_addr(esp_eth_phy_t *phy, uint32_t *addr)
 {
-    PHY_CHECK(addr, "get phy address failed", err);
+    PHY_CHECK(addr, "addr can't be null", err);
     phy_dp83848_t *dp83848 = __containerof(phy, phy_dp83848_t, parent);
     *addr = dp83848->addr;
     return ESP_OK;
@@ -253,15 +269,18 @@ static esp_err_t dp83848_init(esp_eth_phy_t *phy)
     phy_dp83848_t *dp83848 = __containerof(phy, phy_dp83848_t, parent);
     esp_eth_mediator_t *eth = dp83848->eth;
     /* Power on Ethernet PHY */
-    PHY_CHECK(dp83848_pwrctl(phy, true) == ESP_OK, "power on Ethernet PHY failed", err);
+    PHY_CHECK(dp83848_pwrctl(phy, true) == ESP_OK, "power control failed", err);
     /* Reset Ethernet PHY */
-    PHY_CHECK(dp83848_reset(phy) == ESP_OK, "reset Ethernet PHY failed", err);
+    PHY_CHECK(dp83848_reset(phy) == ESP_OK, "reset failed", err);
     /* Check PHY ID */
     phyidr1_reg_t id1;
     phyidr2_reg_t id2;
-    PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_IDR1_REG_ADDR, &(id1.val)) == ESP_OK, "read ID1 failed", err);
-    PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_IDR2_REG_ADDR, &(id2.val)) == ESP_OK, "read ID2 failed", err);
-    PHY_CHECK(id1.oui_msb == 0x2000 && id2.oui_lsb == 0x17 && id2.vendor_model == 0x09, "wrong PHY chip ID", err);
+    PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_IDR1_REG_ADDR, &(id1.val)) == ESP_OK,
+              "read ID1 failed", err);
+    PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_IDR2_REG_ADDR, &(id2.val)) == ESP_OK,
+              "read ID2 failed", err);
+    PHY_CHECK(id1.oui_msb == 0x2000 && id2.oui_lsb == 0x17 && id2.vendor_model == 0x09,
+              "wrong chip ID", err);
     return ESP_OK;
 err:
     return ESP_FAIL;
@@ -270,7 +289,7 @@ err:
 static esp_err_t dp83848_deinit(esp_eth_phy_t *phy)
 {
     /* Power off Ethernet PHY */
-    PHY_CHECK(dp83848_pwrctl(phy, false) == ESP_OK, "power off Ethernet PHY failed", err);
+    PHY_CHECK(dp83848_pwrctl(phy, false) == ESP_OK, "power control failed", err);
     return ESP_OK;
 err:
     return ESP_FAIL;
@@ -280,8 +299,7 @@ esp_eth_phy_t *esp_eth_phy_new_dp83848(const eth_phy_config_t *config)
 {
     PHY_CHECK(config, "can't set phy config to null", err);
     phy_dp83848_t *dp83848 = calloc(1, sizeof(phy_dp83848_t));
-    PHY_CHECK(dp83848, "calloc dp83848 object failed", err);
-    dp83848->name = "dp83848";
+    PHY_CHECK(dp83848, "calloc dp83848 failed", err);
     dp83848->addr = config->phy_addr;
     dp83848->reset_timeout_ms = config->reset_timeout_ms;
     dp83848->link_status = ETH_LINK_DOWN;
index e5dfd5555767b2f2f9b27ef11d930856c8fde024..93312f2ae98cf8b0bbfa9e5831f87abf6d10cb86 100644 (file)
@@ -102,7 +102,6 @@ typedef union {
 typedef struct {
     esp_eth_phy_t parent;
     esp_eth_mediator_t *eth;
-    const char *name;
     uint32_t addr;
     uint32_t reset_timeout_ms;
     uint32_t autonego_timeout_ms;
@@ -121,9 +120,60 @@ err:
     return ESP_FAIL;
 }
 
+static esp_err_t ip101_update_link_duplex_speed(phy_ip101_t *ip101)
+{
+    esp_eth_mediator_t *eth = ip101->eth;
+    eth_speed_t speed = ETH_SPEED_10M;
+    eth_duplex_t duplex = ETH_DUPLEX_HALF;
+    cssr_reg_t cssr;
+    bmsr_reg_t bmsr;
+    PHY_CHECK(ip101_page_select(ip101, 16) == ESP_OK, "select page 16 failed", err);
+    PHY_CHECK(eth->phy_reg_read(eth, ip101->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK,
+              "read BMSR failed", err);
+    eth_link_t link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
+    /* check if link status changed */
+    if (ip101->link_status != link) {
+        /* when link up, read negotiation result */
+        if (link == ETH_LINK_UP) {
+            PHY_CHECK(eth->phy_reg_read(eth, ip101->addr, ETH_PHY_CSSR_REG_ADDR, &(cssr.val)) == ESP_OK,
+                      "read CSSR failed", err);
+            switch (cssr.op_mode) {
+            case 1: //10M Half
+                speed = ETH_SPEED_10M;
+                duplex = ETH_DUPLEX_HALF;
+                break;
+            case 2: //100M Half
+                speed = ETH_SPEED_100M;
+                duplex = ETH_DUPLEX_HALF;
+                break;
+            case 5: //10M Full
+                speed = ETH_SPEED_10M;
+                duplex = ETH_DUPLEX_FULL;
+                break;
+            case 6: //100M Full
+                speed = ETH_SPEED_100M;
+                duplex = ETH_DUPLEX_FULL;
+                break;
+            default:
+                break;
+            }
+            PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_SPEED, (void *)speed) == ESP_OK,
+                      "change speed failed", err);
+            PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_DUPLEX, (void *)duplex) == ESP_OK,
+                      "change duplex failed", err);
+        }
+        PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)link) == ESP_OK,
+                  "chagne link failed", err);
+        ip101->link_status = link;
+    }
+    return ESP_OK;
+err:
+    return ESP_FAIL;
+}
+
 static esp_err_t ip101_set_mediator(esp_eth_phy_t *phy, esp_eth_mediator_t *eth)
 {
-    PHY_CHECK(eth, "can't set mediator for ip101 to null", err);
+    PHY_CHECK(eth, "can't set mediator to null", err);
     phy_ip101_t *ip101 = __containerof(phy, phy_ip101_t, parent);
     ip101->eth = eth;
     return ESP_OK;
@@ -134,19 +184,8 @@ err:
 static esp_err_t ip101_get_link(esp_eth_phy_t *phy)
 {
     phy_ip101_t *ip101 = __containerof(phy, phy_ip101_t, parent);
-    esp_eth_mediator_t *eth = ip101->eth;
-    bmsr_reg_t bmsr;
-
-    PHY_CHECK(eth->phy_reg_read(eth, ip101->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK, "read BMSR failed", err);
-    eth_link_t link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
-    if (ip101->link_status != link) {
-        if (link == ETH_LINK_UP) {
-            phy->negotiate(phy);
-        } else {
-            PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)link) == ESP_OK, "send link event failed", err);
-            ip101->link_status = link;
-        }
-    }
+    /* Updata information about link, speed, duplex */
+    PHY_CHECK(ip101_update_link_duplex_speed(ip101) == ESP_OK, "update link duplex speed failed", err);
     return ESP_OK;
 err:
     return ESP_FAIL;
@@ -157,17 +196,19 @@ static esp_err_t ip101_reset(esp_eth_phy_t *phy)
     phy_ip101_t *ip101 = __containerof(phy, phy_ip101_t, parent);
     esp_eth_mediator_t *eth = ip101->eth;
     bmcr_reg_t bmcr = {.reset = 1};
-    PHY_CHECK(eth->phy_reg_write(eth, ip101->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK, "write BMCR failed", err);
+    PHY_CHECK(eth->phy_reg_write(eth, ip101->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK,
+              "write BMCR failed", err);
     /* wait for reset complete */
-    uint32_t to = 0; 
+    uint32_t to = 0;
     for (to = 0; to < ip101->reset_timeout_ms / 10; to++) {
         vTaskDelay(pdMS_TO_TICKS(10));
-        PHY_CHECK(eth->phy_reg_read(eth, ip101->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK, "read BMCR failed", err);
+        PHY_CHECK(eth->phy_reg_read(eth, ip101->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK,
+                  "read BMCR failed", err);
         if (!bmcr.reset) {
             break;
         }
     }
-    PHY_CHECK(to < ip101->reset_timeout_ms / 10, "PHY reset timeout", err);
+    PHY_CHECK(to < ip101->reset_timeout_ms / 10, "reset timeout", err);
     return ESP_OK;
 err:
     return ESP_FAIL;
@@ -177,65 +218,32 @@ static esp_err_t ip101_negotiate(esp_eth_phy_t *phy)
 {
     phy_ip101_t *ip101 = __containerof(phy, phy_ip101_t, parent);
     esp_eth_mediator_t *eth = ip101->eth;
-    /* Start auto negotiation */
+    /* Restart auto negotiation */
     bmcr_reg_t bmcr = {
         .speed_select = 1,     /* 100Mbps */
         .duplex_mode = 1,      /* Full Duplex */
         .en_auto_nego = 1,     /* Auto Negotiation */
         .restart_auto_nego = 1 /* Restart Auto Negotiation */
     };
-    PHY_CHECK(eth->phy_reg_write(eth, ip101->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK, "write BMCR failed", err);
+    PHY_CHECK(eth->phy_reg_write(eth, ip101->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK,
+              "write BMCR failed", err);
     /* Wait for auto negotiation complete */
     bmsr_reg_t bmsr;
     uint32_t to = 0;
     for (to = 0; to < ip101->autonego_timeout_ms / 10; to++) {
         vTaskDelay(pdMS_TO_TICKS(10));
-        PHY_CHECK(eth->phy_reg_read(eth, ip101->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK, "read BMSR failed", err);
+        PHY_CHECK(eth->phy_reg_read(eth, ip101->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK,
+                  "read BMSR failed", err);
         if (bmsr.auto_nego_complete) {
             break;
         }
     }
     /* Auto negotiation failed, maybe no network cable plugged in, so output a warning */
     if (to >= ip101->autonego_timeout_ms / 10) {
-        ESP_LOGW(TAG, "Ethernet PHY auto negotiation timeout");
+        ESP_LOGW(TAG, "auto negotiation timeout");
     }
-    PHY_CHECK(ip101_page_select(ip101, 16) == ESP_OK, "select page failed", err);
     /* Updata information about link, speed, duplex */
-    cssr_reg_t cssr;
-    PHY_CHECK(eth->phy_reg_read(eth, ip101->addr, ETH_PHY_CSSR_REG_ADDR, &(cssr.val)) == ESP_OK, "read CSSR failed", err);
-    PHY_CHECK(eth->phy_reg_read(eth, ip101->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK, "read BMSR failed", err);
-    eth_link_t link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
-    eth_speed_t speed = ETH_SPEED_10M;
-    eth_duplex_t duplex = ETH_DUPLEX_HALF;
-    switch (cssr.op_mode) {
-    case 0: //Link off
-        link = ETH_LINK_DOWN;
-        break;
-    case 1: //10M Half
-        speed = ETH_SPEED_10M;
-        duplex = ETH_DUPLEX_HALF;
-        break;
-    case 2: //100M Half
-        speed = ETH_SPEED_100M;
-        duplex = ETH_DUPLEX_HALF;
-        break;
-    case 5: //10M Full
-        speed = ETH_SPEED_10M;
-        duplex = ETH_DUPLEX_FULL;
-        break;
-    case 6: //100M Full
-        speed = ETH_SPEED_100M;
-        duplex = ETH_DUPLEX_FULL;
-        break;
-    default:
-        break;
-    }
-    PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_SPEED, (void *)speed) == ESP_OK, "send speed event failed", err);
-    PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_DUPLEX, (void *)duplex) == ESP_OK, "send duplex event failed", err);
-    if (ip101->link_status != link) {
-        PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)link) == ESP_OK, "send link event failed", err);
-        ip101->link_status = link;
-    }
+    PHY_CHECK(ip101_update_link_duplex_speed(ip101) == ESP_OK, "update link duplex speed failed", err);
     return ESP_OK;
 err:
     return ESP_FAIL;
@@ -246,7 +254,8 @@ static esp_err_t ip101_pwrctl(esp_eth_phy_t *phy, bool enable)
     phy_ip101_t *ip101 = __containerof(phy, phy_ip101_t, parent);
     esp_eth_mediator_t *eth = ip101->eth;
     bmcr_reg_t bmcr;
-    PHY_CHECK(eth->phy_reg_read(eth, ip101->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK, "read BMCR failed", err);
+    PHY_CHECK(eth->phy_reg_read(eth, ip101->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK,
+              "read BMCR failed", err);
     if (!enable) {
         /* Enable IEEE Power Down Mode */
         bmcr.power_down = 1;
@@ -254,8 +263,10 @@ static esp_err_t ip101_pwrctl(esp_eth_phy_t *phy, bool enable)
         /* Disable IEEE Power Down Mode */
         bmcr.power_down = 0;
     }
-    PHY_CHECK(eth->phy_reg_write(eth, ip101->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK, "write BMCR failed", err);
-    PHY_CHECK(eth->phy_reg_read(eth, ip101->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK, "read BMCR failed", err);
+    PHY_CHECK(eth->phy_reg_write(eth, ip101->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK,
+              "write BMCR failed", err);
+    PHY_CHECK(eth->phy_reg_read(eth, ip101->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK,
+              "read BMCR failed", err);
     if (!enable) {
         PHY_CHECK(bmcr.power_down == 1, "power down failed", err);
     } else {
@@ -275,7 +286,7 @@ static esp_err_t ip101_set_addr(esp_eth_phy_t *phy, uint32_t addr)
 
 static esp_err_t ip101_get_addr(esp_eth_phy_t *phy, uint32_t *addr)
 {
-    PHY_CHECK(addr, "get phy address failed", err);
+    PHY_CHECK(addr, "addr can't be null", err);
     phy_ip101_t *ip101 = __containerof(phy, phy_ip101_t, parent);
     *addr = ip101->addr;
     return ESP_OK;
@@ -295,15 +306,15 @@ static esp_err_t ip101_init(esp_eth_phy_t *phy)
     phy_ip101_t *ip101 = __containerof(phy, phy_ip101_t, parent);
     esp_eth_mediator_t *eth = ip101->eth;
     /* Power on Ethernet PHY */
-    PHY_CHECK(ip101_pwrctl(phy, true) == ESP_OK, "power on Ethernet PHY failed", err);
+    PHY_CHECK(ip101_pwrctl(phy, true) == ESP_OK, "power control failed", err);
     /* Reset Ethernet PHY */
-    PHY_CHECK(ip101_reset(phy) == ESP_OK, "reset Ethernet PHY failed", err);
+    PHY_CHECK(ip101_reset(phy) == ESP_OK, "reset failed", err);
     /* Check PHY ID */
     phyidr1_reg_t id1;
     phyidr2_reg_t id2;
     PHY_CHECK(eth->phy_reg_read(eth, ip101->addr, ETH_PHY_IDR1_REG_ADDR, &(id1.val)) == ESP_OK, "read ID1 failed", err);
     PHY_CHECK(eth->phy_reg_read(eth, ip101->addr, ETH_PHY_IDR2_REG_ADDR, &(id2.val)) == ESP_OK, "read ID2 failed", err);
-    PHY_CHECK(id1.oui_msb == 0x243 && id2.oui_lsb == 0x3 && id2.vendor_model == 0x5, "wrong PHY chip ID", err);
+    PHY_CHECK(id1.oui_msb == 0x243 && id2.oui_lsb == 0x3 && id2.vendor_model == 0x5, "wrong chip ID", err);
     return ESP_OK;
 err:
     return ESP_FAIL;
@@ -312,7 +323,7 @@ err:
 static esp_err_t ip101_deinit(esp_eth_phy_t *phy)
 {
     /* Power off Ethernet PHY */
-    PHY_CHECK(ip101_pwrctl(phy, false) == ESP_OK, "power off Ethernet PHY failed", err);
+    PHY_CHECK(ip101_pwrctl(phy, false) == ESP_OK, "power control failed", err);
     return ESP_OK;
 err:
     return ESP_FAIL;
@@ -322,8 +333,7 @@ esp_eth_phy_t *esp_eth_phy_new_ip101(const eth_phy_config_t *config)
 {
     PHY_CHECK(config, "can't set phy config to null", err);
     phy_ip101_t *ip101 = calloc(1, sizeof(phy_ip101_t));
-    PHY_CHECK(ip101, "calloc ip101 object failed", err);
-    ip101->name = "ip101";
+    PHY_CHECK(ip101, "calloc ip101 failed", err);
     ip101->addr = config->phy_addr;
     ip101->reset_timeout_ms = config->reset_timeout_ms;
     ip101->link_status = ETH_LINK_DOWN;
index 8cbcd11298711b85b9e1dd73c544e191c85847fb..b685d136becbeea83b6fd88d5960ad64a70a3d5e 100644 (file)
@@ -157,16 +157,65 @@ typedef union {
 typedef struct {
     esp_eth_phy_t parent;
     esp_eth_mediator_t *eth;
-    const char *name;
     uint32_t addr;
     uint32_t reset_timeout_ms;
     uint32_t autonego_timeout_ms;
     eth_link_t link_status;
 } phy_lan8720_t;
 
+static esp_err_t lan8720_update_link_duplex_speed(phy_lan8720_t *lan8720)
+{
+    esp_eth_mediator_t *eth = lan8720->eth;
+    eth_speed_t speed = ETH_SPEED_10M;
+    eth_duplex_t duplex = ETH_DUPLEX_HALF;
+    bmsr_reg_t bmsr;
+    pscsr_reg_t pscsr;
+    PHY_CHECK(eth->phy_reg_read(eth, lan8720->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK,
+              "read BMSR failed", err);
+    eth_link_t link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
+    /* check if link status changed */
+    if (lan8720->link_status != link) {
+        /* when link up, read negotiation result */
+        if (link == ETH_LINK_UP) {
+            PHY_CHECK(eth->phy_reg_read(eth, lan8720->addr, ETH_PHY_PSCSR_REG_ADDR, &(pscsr.val)) == ESP_OK,
+                      "read PSCSR failed", err);
+            switch (pscsr.speed_indication) {
+            case 1: //10Base-T half-duplex
+                speed = ETH_SPEED_10M;
+                duplex = ETH_DUPLEX_HALF;
+                break;
+            case 2: //100Base-TX half-duplex
+                speed = ETH_SPEED_100M;
+                duplex = ETH_DUPLEX_HALF;
+                break;
+            case 5: //10Base-T full-duplex
+                speed = ETH_SPEED_10M;
+                duplex = ETH_DUPLEX_FULL;
+                break;
+            case 6: //100Base-TX full-duplex
+                speed = ETH_SPEED_100M;
+                duplex = ETH_DUPLEX_FULL;
+                break;
+            default:
+                break;
+            }
+            PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_SPEED, (void *)speed) == ESP_OK,
+                      "change speed failed", err);
+            PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_DUPLEX, (void *)duplex) == ESP_OK,
+                      "change duplex failed", err);
+        }
+        PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)link) == ESP_OK,
+                  "change link failed", err);
+        lan8720->link_status = link;
+    }
+    return ESP_OK;
+err:
+    return ESP_FAIL;
+}
+
 static esp_err_t lan8720_set_mediator(esp_eth_phy_t *phy, esp_eth_mediator_t *eth)
 {
-    PHY_CHECK(eth, "can't set mediator for lan8720 to null", err);
+    PHY_CHECK(eth, "can't set mediator to null", err);
     phy_lan8720_t *lan8720 = __containerof(phy, phy_lan8720_t, parent);
     lan8720->eth = eth;
     return ESP_OK;
@@ -177,19 +226,8 @@ err:
 static esp_err_t lan8720_get_link(esp_eth_phy_t *phy)
 {
     phy_lan8720_t *lan8720 = __containerof(phy, phy_lan8720_t, parent);
-    esp_eth_mediator_t *eth = lan8720->eth;
-    bmsr_reg_t bmsr;
-
-    PHY_CHECK(eth->phy_reg_read(eth, lan8720->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK, "read BMSR failed", err);
-    eth_link_t link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
-    if (lan8720->link_status != link) {
-        if (link == ETH_LINK_UP) {
-            phy->negotiate(phy);
-        } else {
-            PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)link) == ESP_OK, "send link event failed", err);
-            lan8720->link_status = link;
-        }
-    }
+    /* Updata information about link, speed, duplex */
+    PHY_CHECK(lan8720_update_link_duplex_speed(lan8720) == ESP_OK, "update link duplex speed failed", err);
     return ESP_OK;
 err:
     return ESP_FAIL;
@@ -200,17 +238,19 @@ static esp_err_t lan8720_reset(esp_eth_phy_t *phy)
     phy_lan8720_t *lan8720 = __containerof(phy, phy_lan8720_t, parent);
     esp_eth_mediator_t *eth = lan8720->eth;
     bmcr_reg_t bmcr = {.reset = 1};
-    PHY_CHECK(eth->phy_reg_write(eth, lan8720->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK, "write BMCR failed", err);
+    PHY_CHECK(eth->phy_reg_write(eth, lan8720->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK,
+              "write BMCR failed", err);
     /* wait for reset complete */
     uint32_t to = 0;
     for (to = 0; to < lan8720->reset_timeout_ms / 10; to++) {
         vTaskDelay(pdMS_TO_TICKS(10));
-        PHY_CHECK(eth->phy_reg_read(eth, lan8720->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK, "read BMCR failed", err);
+        PHY_CHECK(eth->phy_reg_read(eth, lan8720->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK,
+                  "read BMCR failed", err);
         if (!bmcr.reset) {
             break;
         }
     }
-    PHY_CHECK(to < lan8720->reset_timeout_ms / 10, "PHY reset timeout", err);
+    PHY_CHECK(to < lan8720->reset_timeout_ms / 10, "reset timeout", err);
     return ESP_OK;
 err:
     return ESP_FAIL;
@@ -220,7 +260,7 @@ static esp_err_t lan8720_negotiate(esp_eth_phy_t *phy)
 {
     phy_lan8720_t *lan8720 = __containerof(phy, phy_lan8720_t, parent);
     esp_eth_mediator_t *eth = lan8720->eth;
-    /* Start auto negotiation */
+    /* Restart auto negotiation */
     bmcr_reg_t bmcr = {
         .speed_select = 1,     /* 100Mbps */
         .duplex_mode = 1,      /* Full Duplex */
@@ -234,48 +274,20 @@ static esp_err_t lan8720_negotiate(esp_eth_phy_t *phy)
     int32_t to = 0;
     for (to = 0; to < lan8720->autonego_timeout_ms / 10; to++) {
         vTaskDelay(pdMS_TO_TICKS(10));
-        PHY_CHECK(eth->phy_reg_read(eth, lan8720->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK, "read BMSR failed", err);
-        PHY_CHECK(eth->phy_reg_read(eth, lan8720->addr, ETH_PHY_PSCSR_REG_ADDR, &(pscsr.val)) == ESP_OK, "read PSCSR failed", err);
+        PHY_CHECK(eth->phy_reg_read(eth, lan8720->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK,
+                  "read BMSR failed", err);
+        PHY_CHECK(eth->phy_reg_read(eth, lan8720->addr, ETH_PHY_PSCSR_REG_ADDR, &(pscsr.val)) == ESP_OK,
+                  "read PSCSR failed", err);
         if (bmsr.auto_nego_complete && pscsr.auto_nego_done) {
             break;
         }
     }
     /* Auto negotiation failed, maybe no network cable plugged in, so output a warning */
     if (to >= lan8720->autonego_timeout_ms / 10) {
-        ESP_LOGW(TAG, "Ethernet PHY auto negotiation timeout");
+        ESP_LOGW(TAG, "auto negotiation timeout");
     }
     /* Updata information about link, speed, duplex */
-    PHY_CHECK(eth->phy_reg_read(eth, lan8720->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK, "read BMSR failed", err);
-    PHY_CHECK(eth->phy_reg_read(eth, lan8720->addr, ETH_PHY_PSCSR_REG_ADDR, &(pscsr.val)) == ESP_OK, "read PSCSR failed", err);
-    eth_link_t link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
-    eth_speed_t speed = ETH_SPEED_10M;
-    eth_duplex_t duplex = ETH_DUPLEX_HALF;
-    switch (pscsr.speed_indication) {
-    case 1: //10Base-T half-duplex
-        speed = ETH_SPEED_10M;
-        duplex = ETH_DUPLEX_HALF;
-        break;
-    case 2: //100Base-TX half-duplex
-        speed = ETH_SPEED_100M;
-        duplex = ETH_DUPLEX_HALF;
-        break;
-    case 5: //10Base-T full-duplex
-        speed = ETH_SPEED_10M;
-        duplex = ETH_DUPLEX_FULL;
-        break;
-    case 6: //100Base-TX full-duplex
-        speed = ETH_SPEED_100M;
-        duplex = ETH_DUPLEX_FULL;
-        break;
-    default:
-        break;
-    }
-    PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_SPEED, (void *)speed) == ESP_OK, "send speed event failed", err);
-    PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_DUPLEX, (void *)duplex) == ESP_OK, "send duplex event failed", err);
-    if (lan8720->link_status != link) {
-        PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)link) == ESP_OK, "send link event failed", err);
-        lan8720->link_status = link;
-    }
+    PHY_CHECK(lan8720_update_link_duplex_speed(lan8720) == ESP_OK, "update link duplex speed failed", err);
     return ESP_OK;
 err:
     return ESP_FAIL;
@@ -286,7 +298,8 @@ static esp_err_t lan8720_pwrctl(esp_eth_phy_t *phy, bool enable)
     phy_lan8720_t *lan8720 = __containerof(phy, phy_lan8720_t, parent);
     esp_eth_mediator_t *eth = lan8720->eth;
     bmcr_reg_t bmcr;
-    PHY_CHECK(eth->phy_reg_read(eth, lan8720->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK, "read BMCR failed", err);
+    PHY_CHECK(eth->phy_reg_read(eth, lan8720->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK,
+              "read BMCR failed", err);
     if (!enable) {
         /* General Power Down Mode */
         bmcr.power_down = 1;
@@ -294,8 +307,10 @@ static esp_err_t lan8720_pwrctl(esp_eth_phy_t *phy, bool enable)
         /* Normal operation Mode */
         bmcr.power_down = 0;
     }
-    PHY_CHECK(eth->phy_reg_write(eth, lan8720->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK, "write BMCR failed", err);
-    PHY_CHECK(eth->phy_reg_read(eth, lan8720->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK, "read BMCR failed", err);
+    PHY_CHECK(eth->phy_reg_write(eth, lan8720->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK,
+              "write BMCR failed", err);
+    PHY_CHECK(eth->phy_reg_read(eth, lan8720->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK,
+              "read BMCR failed", err);
     if (!enable) {
         PHY_CHECK(bmcr.power_down == 1, "power down failed", err);
     } else {
@@ -315,7 +330,7 @@ static esp_err_t lan8720_set_addr(esp_eth_phy_t *phy, uint32_t addr)
 
 static esp_err_t lan8720_get_addr(esp_eth_phy_t *phy, uint32_t *addr)
 {
-    PHY_CHECK(addr, "get phy address failed", err);
+    PHY_CHECK(addr, "addr can't be null", err);
     phy_lan8720_t *lan8720 = __containerof(phy, phy_lan8720_t, parent);
     *addr = lan8720->addr;
     return ESP_OK;
@@ -335,15 +350,17 @@ static esp_err_t lan8720_init(esp_eth_phy_t *phy)
     phy_lan8720_t *lan8720 = __containerof(phy, phy_lan8720_t, parent);
     esp_eth_mediator_t *eth = lan8720->eth;
     /* Power on Ethernet PHY */
-    PHY_CHECK(lan8720_pwrctl(phy, true) == ESP_OK, "power on Ethernet PHY failed", err);
+    PHY_CHECK(lan8720_pwrctl(phy, true) == ESP_OK, "power control failed", err);
     /* Reset Ethernet PHY */
-    PHY_CHECK(lan8720_reset(phy) == ESP_OK, "reset Ethernet PHY failed", err);
+    PHY_CHECK(lan8720_reset(phy) == ESP_OK, "reset failed", err);
     /* Check PHY ID */
     phyidr1_reg_t id1;
     phyidr2_reg_t id2;
-    PHY_CHECK(eth->phy_reg_read(eth, lan8720->addr, ETH_PHY_IDR1_REG_ADDR, &(id1.val)) == ESP_OK, "read ID1 failed", err);
-    PHY_CHECK(eth->phy_reg_read(eth, lan8720->addr, ETH_PHY_IDR2_REG_ADDR, &(id2.val)) == ESP_OK, "read ID2 failed", err);
-    PHY_CHECK(id1.oui_msb == 0x7 && id2.oui_lsb == 0x30 && id2.vendor_model == 0xF, "wrong PHY chip ID", err);
+    PHY_CHECK(eth->phy_reg_read(eth, lan8720->addr, ETH_PHY_IDR1_REG_ADDR, &(id1.val)) == ESP_OK,
+              "read ID1 failed", err);
+    PHY_CHECK(eth->phy_reg_read(eth, lan8720->addr, ETH_PHY_IDR2_REG_ADDR, &(id2.val)) == ESP_OK,
+              "read ID2 failed", err);
+    PHY_CHECK(id1.oui_msb == 0x7 && id2.oui_lsb == 0x30 && id2.vendor_model == 0xF, "wrong chip ID", err);
     return ESP_OK;
 err:
     return ESP_FAIL;
@@ -352,7 +369,7 @@ err:
 static esp_err_t lan8720_deinit(esp_eth_phy_t *phy)
 {
     /* Power off Ethernet PHY */
-    PHY_CHECK(lan8720_pwrctl(phy, false) == ESP_OK, "power off Ethernet PHY failed", err);
+    PHY_CHECK(lan8720_pwrctl(phy, false) == ESP_OK, "power control failed", err);
     return ESP_OK;
 err:
     return ESP_FAIL;
@@ -362,8 +379,7 @@ esp_eth_phy_t *esp_eth_phy_new_lan8720(const eth_phy_config_t *config)
 {
     PHY_CHECK(config, "can't set phy config to null", err);
     phy_lan8720_t *lan8720 = calloc(1, sizeof(phy_lan8720_t));
-    PHY_CHECK(lan8720, "calloc lan8720 object failed", err);
-    lan8720->name = "lan8720";
+    PHY_CHECK(lan8720, "calloc lan8720 failed", err);
     lan8720->addr = config->phy_addr;
     lan8720->reset_timeout_ms = config->reset_timeout_ms;
     lan8720->link_status = ETH_LINK_DOWN;
index b927ed5c9cc5b1c5f826de9838acb2cdcc82b57d..874449c67ca1c503f611c067312fc3946ef51e2e 100644 (file)
@@ -63,7 +63,6 @@ typedef union {
 typedef struct {
     esp_eth_phy_t parent;
     esp_eth_mediator_t *eth;
-    const char *name;
     uint32_t addr;
     uint32_t reset_timeout_ms;
     uint32_t autonego_timeout_ms;
@@ -82,9 +81,50 @@ err:
     return ESP_FAIL;
 }
 
+static esp_err_t rtl8201_update_link_duplex_speed(phy_rtl8201_t *rtl8201)
+{
+    esp_eth_mediator_t *eth = rtl8201->eth;
+    eth_speed_t speed = ETH_SPEED_10M;
+    eth_duplex_t duplex = ETH_DUPLEX_HALF;
+    bmcr_reg_t bmcr;
+    bmsr_reg_t bmsr;
+    PHY_CHECK(rtl8201_page_select(rtl8201, 0) == ESP_OK, "select page 0 failed", err);
+    PHY_CHECK(eth->phy_reg_read(eth, rtl8201->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK,
+              "read BMSR failed", err);
+    eth_link_t link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
+    /* check if link status changed */
+    if (rtl8201->link_status != link) {
+        /* when link up, read negotiation result */
+        if (link == ETH_LINK_UP) {
+            PHY_CHECK(eth->phy_reg_read(eth, rtl8201->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK,
+                      "read BMCR failed", err);
+            if (bmcr.speed_select) {
+                speed = ETH_SPEED_100M;
+            } else {
+                speed = ETH_SPEED_10M;
+            }
+            if (bmcr.duplex_mode) {
+                duplex = ETH_DUPLEX_FULL;
+            } else {
+                duplex = ETH_DUPLEX_HALF;
+            }
+            PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_SPEED, (void *)speed) == ESP_OK,
+                      "change speed failed", err);
+            PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_DUPLEX, (void *)duplex) == ESP_OK,
+                      "change duplex failed", err);
+        }
+        PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)link) == ESP_OK,
+                  "change link failed", err);
+        rtl8201->link_status = link;
+    }
+    return ESP_OK;
+err:
+    return ESP_FAIL;
+}
+
 static esp_err_t rtl8201_set_mediator(esp_eth_phy_t *phy, esp_eth_mediator_t *eth)
 {
-    PHY_CHECK(eth, "can't set mediator for rtl8201 to null", err);
+    PHY_CHECK(eth, "can't set mediator to null", err);
     phy_rtl8201_t *rtl8201 = __containerof(phy, phy_rtl8201_t, parent);
     rtl8201->eth = eth;
     return ESP_OK;
@@ -95,19 +135,8 @@ err:
 static esp_err_t rtl8201_get_link(esp_eth_phy_t *phy)
 {
     phy_rtl8201_t *rtl8201 = __containerof(phy, phy_rtl8201_t, parent);
-    esp_eth_mediator_t *eth = rtl8201->eth;
-    bmsr_reg_t bmsr;
-
-    PHY_CHECK(eth->phy_reg_read(eth, rtl8201->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK, "read BMSR failed", err);
-    eth_link_t link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
-    if (rtl8201->link_status != link) {
-        if (link == ETH_LINK_UP) {
-            phy->negotiate(phy);
-        } else {
-            PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)link) == ESP_OK, "send link event failed", err);
-            rtl8201->link_status = link;
-        }
-    }
+    /* Updata information about link, speed, duplex */
+    PHY_CHECK(rtl8201_update_link_duplex_speed(rtl8201) == ESP_OK, "update link duplex speed failed", err);
     return ESP_OK;
 err:
     return ESP_FAIL;
@@ -118,17 +147,19 @@ static esp_err_t rtl8201_reset(esp_eth_phy_t *phy)
     phy_rtl8201_t *rtl8201 = __containerof(phy, phy_rtl8201_t, parent);
     esp_eth_mediator_t *eth = rtl8201->eth;
     bmcr_reg_t bmcr = {.reset = 1};
-    PHY_CHECK(eth->phy_reg_write(eth, rtl8201->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK, "write BMCR failed", err);
+    PHY_CHECK(eth->phy_reg_write(eth, rtl8201->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK,
+              "write BMCR failed", err);
     /* Wait for reset complete */
     uint32_t to = 0;
     for (to = 0; to < rtl8201->reset_timeout_ms / 10; to++) {
         vTaskDelay(pdMS_TO_TICKS(10));
-        PHY_CHECK(eth->phy_reg_read(eth, rtl8201->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK, "read BMCR failed", err);
+        PHY_CHECK(eth->phy_reg_read(eth, rtl8201->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK,
+                  "read BMCR failed", err);
         if (!bmcr.reset) {
             break;
         }
     }
-    PHY_CHECK(to < rtl8201->reset_timeout_ms / 10, "PHY reset timeout", err);
+    PHY_CHECK(to < rtl8201->reset_timeout_ms / 10, "reset timeout", err);
     return ESP_OK;
 err:
     return ESP_FAIL;
@@ -138,51 +169,32 @@ static esp_err_t rtl8201_negotiate(esp_eth_phy_t *phy)
 {
     phy_rtl8201_t *rtl8201 = __containerof(phy, phy_rtl8201_t, parent);
     esp_eth_mediator_t *eth = rtl8201->eth;
-    /* Start auto negotiation */
+    /* Restart auto negotiation */
     bmcr_reg_t bmcr = {
         .speed_select = 1,     /* 100Mbps */
         .duplex_mode = 1,      /* Full Duplex */
         .en_auto_nego = 1,     /* Auto Negotiation */
         .restart_auto_nego = 1 /* Restart Auto Negotiation */
     };
-    PHY_CHECK(eth->phy_reg_write(eth, rtl8201->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK, "write BMCR failed", err);
+    PHY_CHECK(eth->phy_reg_write(eth, rtl8201->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK,
+              "write BMCR failed", err);
     /* Wait for auto negotiation complete */
     bmsr_reg_t bmsr;
     uint32_t to = 0;
     for (to = 0; to < rtl8201->autonego_timeout_ms / 10; to++) {
         vTaskDelay(pdMS_TO_TICKS(10));
-        PHY_CHECK(eth->phy_reg_read(eth, rtl8201->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK, "read BMSR failed", err);
+        PHY_CHECK(eth->phy_reg_read(eth, rtl8201->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK,
+                  "read BMSR failed", err);
         if (bmsr.auto_nego_complete) {
             break;
         }
     }
     /* Auto negotiation failed, maybe no network cable plugged in, so output a warning */
     if (to >= rtl8201->autonego_timeout_ms / 10) {
-        ESP_LOGW(TAG, "Ethernet PHY auto negotiation timeout");
+        ESP_LOGW(TAG, "auto negotiation timeout");
     }
-    PHY_CHECK(rtl8201_page_select(rtl8201, 0) == ESP_OK, "select page failed", err);
     /* Updata information about link, speed, duplex */
-    PHY_CHECK(eth->phy_reg_read(eth, rtl8201->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK, "read BMCR failed", err);
-    PHY_CHECK(eth->phy_reg_read(eth, rtl8201->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK, "read BMSR failed", err);
-    eth_link_t link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
-    eth_speed_t speed = ETH_SPEED_10M;
-    eth_duplex_t duplex = ETH_DUPLEX_HALF;
-    if (bmcr.speed_select) {
-        speed = ETH_SPEED_100M;
-    } else {
-        speed = ETH_SPEED_10M;
-    }
-    if (bmcr.duplex_mode) {
-        duplex = ETH_DUPLEX_FULL;
-    } else {
-        duplex = ETH_DUPLEX_HALF;
-    }
-    PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_SPEED, (void *)speed) == ESP_OK, "send speed event failed", err);
-    PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_DUPLEX, (void *)duplex) == ESP_OK, "send duplex event failed", err);
-    if (rtl8201->link_status != link) {
-        PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)link) == ESP_OK, "send link event failed", err);
-        rtl8201->link_status = link;
-    }
+    PHY_CHECK(rtl8201_update_link_duplex_speed(rtl8201) == ESP_OK, "update link duplex speed failed", err);
     return ESP_OK;
 err:
     return ESP_FAIL;
@@ -193,7 +205,8 @@ static esp_err_t rtl8201_pwrctl(esp_eth_phy_t *phy, bool enable)
     phy_rtl8201_t *rtl8201 = __containerof(phy, phy_rtl8201_t, parent);
     esp_eth_mediator_t *eth = rtl8201->eth;
     bmcr_reg_t bmcr;
-    PHY_CHECK(eth->phy_reg_read(eth, rtl8201->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK, "read BMCR failed", err);
+    PHY_CHECK(eth->phy_reg_read(eth, rtl8201->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK,
+              "read BMCR failed", err);
     if (!enable) {
         /* Enable IEEE Power Down Mode */
         bmcr.power_down = 1;
@@ -201,8 +214,10 @@ static esp_err_t rtl8201_pwrctl(esp_eth_phy_t *phy, bool enable)
         /* Disable IEEE Power Down Mode */
         bmcr.power_down = 0;
     }
-    PHY_CHECK(eth->phy_reg_write(eth, rtl8201->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK, "write BMCR failed", err);
-    PHY_CHECK(eth->phy_reg_read(eth, rtl8201->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK, "read BMCR failed", err);
+    PHY_CHECK(eth->phy_reg_write(eth, rtl8201->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK,
+              "write BMCR failed", err);
+    PHY_CHECK(eth->phy_reg_read(eth, rtl8201->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK,
+              "read BMCR failed", err);
     if (!enable) {
         PHY_CHECK(bmcr.power_down == 1, "power down failed", err);
     } else {
@@ -222,7 +237,7 @@ static esp_err_t rtl8201_set_addr(esp_eth_phy_t *phy, uint32_t addr)
 
 static esp_err_t rtl8201_get_addr(esp_eth_phy_t *phy, uint32_t *addr)
 {
-    PHY_CHECK(addr, "get phy address failed", err);
+    PHY_CHECK(addr, "addr can't be null", err);
     phy_rtl8201_t *rtl8201 = __containerof(phy, phy_rtl8201_t, parent);
     *addr = rtl8201->addr;
     return ESP_OK;
@@ -242,15 +257,18 @@ static esp_err_t rtl8201_init(esp_eth_phy_t *phy)
     phy_rtl8201_t *rtl8201 = __containerof(phy, phy_rtl8201_t, parent);
     esp_eth_mediator_t *eth = rtl8201->eth;
     /* Power on Ethernet PHY */
-    PHY_CHECK(rtl8201_pwrctl(phy, true) == ESP_OK, "power on Ethernet PHY failed", err);
+    PHY_CHECK(rtl8201_pwrctl(phy, true) == ESP_OK, "power control failed", err);
     /* Reset Ethernet PHY */
-    PHY_CHECK(rtl8201_reset(phy) == ESP_OK, "reset Ethernet PHY failed", err);
+    PHY_CHECK(rtl8201_reset(phy) == ESP_OK, "reset failed", err);
     /* Check PHY ID */
     phyidr1_reg_t id1;
     phyidr2_reg_t id2;
-    PHY_CHECK(eth->phy_reg_read(eth, rtl8201->addr, ETH_PHY_IDR1_REG_ADDR, &(id1.val)) == ESP_OK, "read ID1 failed", err);
-    PHY_CHECK(eth->phy_reg_read(eth, rtl8201->addr, ETH_PHY_IDR2_REG_ADDR, &(id2.val)) == ESP_OK, "read ID2 failed", err);
-    PHY_CHECK(id1.oui_msb == 0x1C && id2.oui_lsb == 0x32 && id2.vendor_model == 0x1, "wrong PHY chip ID", err);
+    PHY_CHECK(eth->phy_reg_read(eth, rtl8201->addr, ETH_PHY_IDR1_REG_ADDR, &(id1.val)) == ESP_OK,
+              "read ID1 failed", err);
+    PHY_CHECK(eth->phy_reg_read(eth, rtl8201->addr, ETH_PHY_IDR2_REG_ADDR, &(id2.val)) == ESP_OK,
+              "read ID2 failed", err);
+    PHY_CHECK(id1.oui_msb == 0x1C && id2.oui_lsb == 0x32 && id2.vendor_model == 0x1,
+              "wrong chip ID", err);
     return ESP_OK;
 err:
     return ESP_FAIL;
@@ -259,7 +277,7 @@ err:
 static esp_err_t rtl8201_deinit(esp_eth_phy_t *phy)
 {
     /* Power off Ethernet PHY */
-    PHY_CHECK(rtl8201_pwrctl(phy, false) == ESP_OK, "power off Ethernet PHY failed", err);
+    PHY_CHECK(rtl8201_pwrctl(phy, false) == ESP_OK, "power control failed", err);
     return ESP_OK;
 err:
     return ESP_FAIL;
@@ -269,8 +287,7 @@ esp_eth_phy_t *esp_eth_phy_new_rtl8201(const eth_phy_config_t *config)
 {
     PHY_CHECK(config, "can't set phy config to null", err);
     phy_rtl8201_t *rtl8201 = calloc(1, sizeof(phy_rtl8201_t));
-    PHY_CHECK(rtl8201, "calloc rtl8201 object failed", err);
-    rtl8201->name = "rtl8201";
+    PHY_CHECK(rtl8201, "calloc rtl8201 failed", err);
     rtl8201->addr = config->phy_addr;
     rtl8201->reset_timeout_ms = config->reset_timeout_ms;
     rtl8201->link_status = ETH_LINK_DOWN;
index f5d1557c6a9b53f662a85a515cd943f6ab02dfdc..36a325a0adfd6defaca822d6230d3bbcd42400b2 100644 (file)
@@ -81,7 +81,7 @@ TEST_CASE("esp32 ethernet io test", "[ethernet][test_env=UT_T2_Ethernet]")
     uint8_t mac_addr[6];
     memset(mac_addr, 0, sizeof(mac_addr));
     TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr));
-    ESP_LOGI(TAG, "Ethernet MAC Address: %d:%d:%d:%d:%d:%d",
+    ESP_LOGI(TAG, "Ethernet MAC Address: %02x:%02x:%02x:%02x:%02x:%02x",
              mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
     TEST_ASSERT(mac_addr[0] != 0);
     /* get PHY address */
index 121bc53269753d7c2531c393b35607f24a559fd6..4e39e17bdd36cdb45ef99e21cb773063cbf59c43 100644 (file)
@@ -482,7 +482,7 @@ void emac_hal_transmit_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t len
     hal->dma_regs->dmatxpolldemand = 0;
 }
 
-uint32_t emac_hal_receive_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t *frames_remain)
+uint32_t emac_hal_receive_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t size, uint32_t *frames_remain)
 {
     eth_dma_rx_descriptor_t *desc_iter = NULL;
     eth_dma_rx_descriptor_t *first_desc = NULL;
@@ -501,6 +501,12 @@ uint32_t emac_hal_receive_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t
         if (desc_iter->RDES0.LastDescriptor) {
             /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */
             len = desc_iter->RDES0.FrameLength - ETH_CRC_LENGTH;
+            /* check if the buffer can store the whole frame */
+            if (len > size) {
+                /* return the real size that we want */
+                /* user need to compare the return value to the size they prepared when this function returned */
+                return len;
+            }
             /* update unhandled frame count */
             frame_count++;
         }
index 1b21897b6a9c683dc88df517a73ef8eb129fe70a..824b8963278eda1ae4a79a1cbabd38779daebe16 100644 (file)
@@ -380,7 +380,7 @@ uint32_t emac_hal_get_tx_desc_owner(emac_hal_context_t *hal);
 
 void emac_hal_transmit_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t length);
 
-uint32_t emac_hal_receive_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t *frames_remain);
+uint32_t emac_hal_receive_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t size, uint32_t *frames_remain);
 
 void emac_hal_isr(void *arg);