diff --git a/components/esp_eth/src/esp_eth_mac_esp32.c b/components/esp_eth/src/esp_eth_mac_esp32.c index 778ca422b2..344a44c71a 100644 --- a/components/esp_eth/src/esp_eth_mac_esp32.c +++ b/components/esp_eth/src/esp_eth_mac_esp32.c @@ -506,3 +506,15 @@ IRAM_ATTR void emac_hal_rx_unavail_cb(void *arg) emac->isr_need_yield = true; } } + +IRAM_ATTR void emac_hal_rx_early_cb(void *arg) +{ + emac_hal_context_t *hal = (emac_hal_context_t *)arg; + emac_esp32_t *emac = __containerof(hal, emac_esp32_t, hal); + BaseType_t high_task_wakeup; + /* notify receive task */ + vTaskNotifyGiveFromISR(emac->rx_task_hdl, &high_task_wakeup); + if (high_task_wakeup == pdTRUE) { + emac->isr_need_yield = true; + } +} diff --git a/components/esp_eth/src/esp_eth_phy_dm9051.c b/components/esp_eth/src/esp_eth_phy_dm9051.c index 8dbe3876df..9f9a405852 100644 --- a/components/esp_eth/src/esp_eth_phy_dm9051.c +++ b/components/esp_eth/src/esp_eth_phy_dm9051.c @@ -250,12 +250,22 @@ static esp_err_t dm9051_pwrctl(esp_eth_phy_t *phy, bool enable) } 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(eth->phy_reg_read(eth, dm9051->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK, + "read BMCR failed", err); PHY_CHECK(bmcr.power_down == 1, "power down failed", err); } else { - PHY_CHECK(bmcr.power_down == 0, "power up failed", err); + /* wait for power up 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); + if (bmcr.power_down == 0) { + break; + } + } + PHY_CHECK(to < dm9051->reset_timeout_ms / 10, "power up timeout", err); } return ESP_OK; err: diff --git a/components/esp_eth/src/esp_eth_phy_dp83848.c b/components/esp_eth/src/esp_eth_phy_dp83848.c index 9bcfeeda18..2aebea3dfa 100644 --- a/components/esp_eth/src/esp_eth_phy_dp83848.c +++ b/components/esp_eth/src/esp_eth_phy_dp83848.c @@ -240,12 +240,22 @@ static esp_err_t dp83848_pwrctl(esp_eth_phy_t *phy, bool enable) } 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(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK, + "read BMCR failed", err); PHY_CHECK(bmcr.power_down == 1, "power down failed", err); } else { - PHY_CHECK(bmcr.power_down == 0, "power up failed", err); + /* wait for power up 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); + if (bmcr.power_down == 0) { + break; + } + } + PHY_CHECK(to < dp83848->reset_timeout_ms / 10, "power up timeout", err); } return ESP_OK; err: diff --git a/components/esp_eth/src/esp_eth_phy_ip101.c b/components/esp_eth/src/esp_eth_phy_ip101.c index c3ea8a1b01..3ee1dd43e4 100644 --- a/components/esp_eth/src/esp_eth_phy_ip101.c +++ b/components/esp_eth/src/esp_eth_phy_ip101.c @@ -277,12 +277,22 @@ static esp_err_t ip101_pwrctl(esp_eth_phy_t *phy, bool enable) } 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(eth->phy_reg_read(eth, ip101->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK, + "read BMCR failed", err); PHY_CHECK(bmcr.power_down == 1, "power down failed", err); } else { - PHY_CHECK(bmcr.power_down == 0, "power up failed", err); + /* wait for power up complete */ + 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); + if (bmcr.power_down == 0) { + break; + } + } + PHY_CHECK(to < ip101->reset_timeout_ms / 10, "power up timeout", err); } return ESP_OK; err: diff --git a/components/esp_eth/src/esp_eth_phy_lan8720.c b/components/esp_eth/src/esp_eth_phy_lan8720.c index b6480a6649..ea9378d93e 100644 --- a/components/esp_eth/src/esp_eth_phy_lan8720.c +++ b/components/esp_eth/src/esp_eth_phy_lan8720.c @@ -324,12 +324,22 @@ static esp_err_t lan8720_pwrctl(esp_eth_phy_t *phy, bool enable) } 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(eth->phy_reg_read(eth, lan8720->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK, + "read BMCR failed", err); PHY_CHECK(bmcr.power_down == 1, "power down failed", err); } else { - PHY_CHECK(bmcr.power_down == 0, "power up failed", err); + /* wait for power up 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); + if (bmcr.power_down == 0) { + break; + } + } + PHY_CHECK(to < lan8720->reset_timeout_ms / 10, "power up timeout", err); } return ESP_OK; err: diff --git a/components/esp_eth/src/esp_eth_phy_rtl8201.c b/components/esp_eth/src/esp_eth_phy_rtl8201.c index 2a5808a22c..0c1667cb38 100644 --- a/components/esp_eth/src/esp_eth_phy_rtl8201.c +++ b/components/esp_eth/src/esp_eth_phy_rtl8201.c @@ -231,12 +231,22 @@ static esp_err_t rtl8201_pwrctl(esp_eth_phy_t *phy, bool enable) } 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(eth->phy_reg_read(eth, rtl8201->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)) == ESP_OK, + "read BMCR failed", err); PHY_CHECK(bmcr.power_down == 1, "power down failed", err); } else { - PHY_CHECK(bmcr.power_down == 0, "power up failed", err); + /* wait for power up 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); + if (bmcr.power_down == 0) { + break; + } + } + PHY_CHECK(to < rtl8201->reset_timeout_ms / 10, "power up timeout", err); } return ESP_OK; err: diff --git a/components/soc/esp32/emac_hal.c b/components/soc/esp32/emac_hal.c index 06640fa99f..08f123e9e8 100644 --- a/components/soc/esp32/emac_hal.c +++ b/components/soc/esp32/emac_hal.c @@ -451,44 +451,55 @@ uint32_t emac_hal_transmit_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t if (lastlen) { bufcount++; } + if (bufcount > CONFIG_ETH_DMA_TX_BUFFER_NUM) { + goto err; + } + + eth_dma_tx_descriptor_t *desc_iter = hal->tx_desc; /* A frame is transmitted in multiple descriptor */ - for (uint32_t i = 0; i < bufcount; i++) { + for (int i = 0; i < bufcount; i++) { /* Check if the descriptor is owned by the Ethernet DMA (when 1) or CPU (when 0) */ - if (hal->tx_desc->TDES0.Own != EMAC_DMADESC_OWNER_CPU) { + if (desc_iter->TDES0.Own != EMAC_DMADESC_OWNER_CPU) { goto err; } /* Clear FIRST and LAST segment bits */ - hal->tx_desc->TDES0.FirstSegment = 0; - hal->tx_desc->TDES0.LastSegment = 0; + desc_iter->TDES0.FirstSegment = 0; + desc_iter->TDES0.LastSegment = 0; + desc_iter->TDES0.InterruptOnComplete = 0; if (i == 0) { /* Setting the first segment bit */ - hal->tx_desc->TDES0.FirstSegment = 1; + desc_iter->TDES0.FirstSegment = 1; } if (i == (bufcount - 1)) { /* Setting the last segment bit */ - hal->tx_desc->TDES0.LastSegment = 1; + desc_iter->TDES0.LastSegment = 1; /* Enable transmit interrupt */ - hal->tx_desc->TDES0.InterruptOnComplete = 1; + desc_iter->TDES0.InterruptOnComplete = 1; /* Program size */ - hal->tx_desc->TDES1.TransmitBuffer1Size = lastlen; + desc_iter->TDES1.TransmitBuffer1Size = lastlen; /* copy data from uplayer stack buffer */ - memcpy((void *)(hal->tx_desc->Buffer1Addr), buf + i * CONFIG_ETH_DMA_BUFFER_SIZE, lastlen); + memcpy((void *)(desc_iter->Buffer1Addr), buf + i * CONFIG_ETH_DMA_BUFFER_SIZE, lastlen); sentout += lastlen; } else { /* Program size */ - hal->tx_desc->TDES1.TransmitBuffer1Size = CONFIG_ETH_DMA_BUFFER_SIZE; + desc_iter->TDES1.TransmitBuffer1Size = CONFIG_ETH_DMA_BUFFER_SIZE; /* copy data from uplayer stack buffer */ - memcpy((void *)(hal->tx_desc->Buffer1Addr), buf + i * CONFIG_ETH_DMA_BUFFER_SIZE, CONFIG_ETH_DMA_BUFFER_SIZE); + memcpy((void *)(desc_iter->Buffer1Addr), buf + i * CONFIG_ETH_DMA_BUFFER_SIZE, CONFIG_ETH_DMA_BUFFER_SIZE); sentout += CONFIG_ETH_DMA_BUFFER_SIZE; } - /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */ - hal->tx_desc->TDES0.Own = EMAC_DMADESC_OWNER_DMA; /* Point to next descriptor */ + desc_iter = (eth_dma_tx_descriptor_t *)(desc_iter->Buffer2NextDescAddr); + } + + /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */ + for (int i = 0; i < bufcount; i++) { + hal->tx_desc->TDES0.Own = EMAC_DMADESC_OWNER_DMA; hal->tx_desc = (eth_dma_tx_descriptor_t *)(hal->tx_desc->Buffer2NextDescAddr); } -err: hal->dma_regs->dmatxpolldemand = 0; return sentout; +err: + return 0; } uint32_t emac_hal_receive_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t size, uint32_t *frames_remain) @@ -562,70 +573,56 @@ IRAM_ATTR void emac_hal_isr(void *arg) { emac_hal_context_t *hal = (emac_hal_context_t *)arg; typeof(hal->dma_regs->dmastatus) dma_status = hal->dma_regs->dmastatus; + hal->dma_regs->dmastatus.val = dma_status.val; /* DMA Normal Interrupt */ if (dma_status.norm_int_summ) { /* Transmit Interrupt */ if (dma_status.trans_int) { emac_hal_tx_complete_cb(arg); - hal->dma_regs->dmastatus.trans_int = 1; } /* Transmit Buffer Unavailable */ if (dma_status.trans_buf_unavail) { emac_hal_tx_unavail_cb(arg); - hal->dma_regs->dmastatus.trans_buf_unavail = 1; } /* Receive Interrupt */ if (dma_status.recv_int) { emac_hal_rx_complete_cb(arg); - hal->dma_regs->dmastatus.recv_int = 1; } /* Early Receive Interrupt */ if (dma_status.early_recv_int) { emac_hal_rx_early_cb(arg); - hal->dma_regs->dmastatus.early_recv_int = 1; } - hal->dma_regs->dmastatus.norm_int_summ = 1; } /* DMA Abnormal Interrupt */ if (dma_status.abn_int_summ) { /* Transmit Process Stopped */ if (dma_status.trans_proc_stop) { - hal->dma_regs->dmastatus.trans_proc_stop = 1; } /* Transmit Jabber Timeout */ if (dma_status.trans_jabber_to) { - hal->dma_regs->dmastatus.trans_jabber_to = 1; } /* Receive FIFO Overflow */ if (dma_status.recv_ovflow) { - hal->dma_regs->dmastatus.recv_ovflow = 1; } /* Transmit Underflow */ if (dma_status.trans_undflow) { - hal->dma_regs->dmastatus.trans_undflow = 1; } /* Receive Buffer Unavailable */ if (dma_status.recv_buf_unavail) { emac_hal_rx_unavail_cb(arg); - hal->dma_regs->dmastatus.recv_buf_unavail = 1; } /* Receive Process Stopped */ if (dma_status.recv_proc_stop) { - hal->dma_regs->dmastatus.recv_proc_stop = 1; } /* Receive Watchdog Timeout */ if (dma_status.recv_wdt_to) { - hal->dma_regs->dmastatus.recv_wdt_to = 1; } /* Early Transmit Interrupt */ if (dma_status.early_trans_int) { - hal->dma_regs->dmastatus.early_trans_int = 1; } /* Fatal Bus Error */ if (dma_status.fatal_bus_err_int) { - hal->dma_regs->dmastatus.fatal_bus_err_int = 1; } - hal->dma_regs->dmastatus.abn_int_summ = 1; } }