mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-30 10:47:19 +02:00
Merge branch 'bugfix/ethernet_handle_early_rx_interrupt_v4.1' into 'release/v4.1'
Bugfix/ethernet handle early rx interrupt (v4.1) See merge request espressif/esp-idf!10099
This commit is contained in:
@ -506,3 +506,15 @@ IRAM_ATTR void emac_hal_rx_unavail_cb(void *arg)
|
|||||||
emac->isr_need_yield = true;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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,
|
PHY_CHECK(eth->phy_reg_write(eth, dm9051->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK,
|
||||||
"write BMCR failed", err);
|
"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) {
|
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);
|
PHY_CHECK(bmcr.power_down == 1, "power down failed", err);
|
||||||
} else {
|
} 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;
|
return ESP_OK;
|
||||||
err:
|
err:
|
||||||
|
@ -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,
|
PHY_CHECK(eth->phy_reg_write(eth, dp83848->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK,
|
||||||
"write BMCR failed", err);
|
"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) {
|
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);
|
PHY_CHECK(bmcr.power_down == 1, "power down failed", err);
|
||||||
} else {
|
} 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;
|
return ESP_OK;
|
||||||
err:
|
err:
|
||||||
|
@ -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,
|
PHY_CHECK(eth->phy_reg_write(eth, ip101->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK,
|
||||||
"write BMCR failed", err);
|
"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) {
|
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);
|
PHY_CHECK(bmcr.power_down == 1, "power down failed", err);
|
||||||
} else {
|
} 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;
|
return ESP_OK;
|
||||||
err:
|
err:
|
||||||
|
@ -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,
|
PHY_CHECK(eth->phy_reg_write(eth, lan8720->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK,
|
||||||
"write BMCR failed", err);
|
"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) {
|
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);
|
PHY_CHECK(bmcr.power_down == 1, "power down failed", err);
|
||||||
} else {
|
} 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;
|
return ESP_OK;
|
||||||
err:
|
err:
|
||||||
|
@ -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,
|
PHY_CHECK(eth->phy_reg_write(eth, rtl8201->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val) == ESP_OK,
|
||||||
"write BMCR failed", err);
|
"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) {
|
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);
|
PHY_CHECK(bmcr.power_down == 1, "power down failed", err);
|
||||||
} else {
|
} 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;
|
return ESP_OK;
|
||||||
err:
|
err:
|
||||||
|
@ -451,44 +451,55 @@ uint32_t emac_hal_transmit_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t
|
|||||||
if (lastlen) {
|
if (lastlen) {
|
||||||
bufcount++;
|
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 */
|
/* 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) */
|
/* 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;
|
goto err;
|
||||||
}
|
}
|
||||||
/* Clear FIRST and LAST segment bits */
|
/* Clear FIRST and LAST segment bits */
|
||||||
hal->tx_desc->TDES0.FirstSegment = 0;
|
desc_iter->TDES0.FirstSegment = 0;
|
||||||
hal->tx_desc->TDES0.LastSegment = 0;
|
desc_iter->TDES0.LastSegment = 0;
|
||||||
|
desc_iter->TDES0.InterruptOnComplete = 0;
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
/* Setting the first segment bit */
|
/* Setting the first segment bit */
|
||||||
hal->tx_desc->TDES0.FirstSegment = 1;
|
desc_iter->TDES0.FirstSegment = 1;
|
||||||
}
|
}
|
||||||
if (i == (bufcount - 1)) {
|
if (i == (bufcount - 1)) {
|
||||||
/* Setting the last segment bit */
|
/* Setting the last segment bit */
|
||||||
hal->tx_desc->TDES0.LastSegment = 1;
|
desc_iter->TDES0.LastSegment = 1;
|
||||||
/* Enable transmit interrupt */
|
/* Enable transmit interrupt */
|
||||||
hal->tx_desc->TDES0.InterruptOnComplete = 1;
|
desc_iter->TDES0.InterruptOnComplete = 1;
|
||||||
/* Program size */
|
/* Program size */
|
||||||
hal->tx_desc->TDES1.TransmitBuffer1Size = lastlen;
|
desc_iter->TDES1.TransmitBuffer1Size = lastlen;
|
||||||
/* copy data from uplayer stack buffer */
|
/* 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;
|
sentout += lastlen;
|
||||||
} else {
|
} else {
|
||||||
/* Program size */
|
/* 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 */
|
/* 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;
|
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 */
|
/* 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);
|
hal->tx_desc = (eth_dma_tx_descriptor_t *)(hal->tx_desc->Buffer2NextDescAddr);
|
||||||
}
|
}
|
||||||
err:
|
|
||||||
hal->dma_regs->dmatxpolldemand = 0;
|
hal->dma_regs->dmatxpolldemand = 0;
|
||||||
return sentout;
|
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)
|
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;
|
emac_hal_context_t *hal = (emac_hal_context_t *)arg;
|
||||||
typeof(hal->dma_regs->dmastatus) dma_status = hal->dma_regs->dmastatus;
|
typeof(hal->dma_regs->dmastatus) dma_status = hal->dma_regs->dmastatus;
|
||||||
|
hal->dma_regs->dmastatus.val = dma_status.val;
|
||||||
/* DMA Normal Interrupt */
|
/* DMA Normal Interrupt */
|
||||||
if (dma_status.norm_int_summ) {
|
if (dma_status.norm_int_summ) {
|
||||||
/* Transmit Interrupt */
|
/* Transmit Interrupt */
|
||||||
if (dma_status.trans_int) {
|
if (dma_status.trans_int) {
|
||||||
emac_hal_tx_complete_cb(arg);
|
emac_hal_tx_complete_cb(arg);
|
||||||
hal->dma_regs->dmastatus.trans_int = 1;
|
|
||||||
}
|
}
|
||||||
/* Transmit Buffer Unavailable */
|
/* Transmit Buffer Unavailable */
|
||||||
if (dma_status.trans_buf_unavail) {
|
if (dma_status.trans_buf_unavail) {
|
||||||
emac_hal_tx_unavail_cb(arg);
|
emac_hal_tx_unavail_cb(arg);
|
||||||
hal->dma_regs->dmastatus.trans_buf_unavail = 1;
|
|
||||||
}
|
}
|
||||||
/* Receive Interrupt */
|
/* Receive Interrupt */
|
||||||
if (dma_status.recv_int) {
|
if (dma_status.recv_int) {
|
||||||
emac_hal_rx_complete_cb(arg);
|
emac_hal_rx_complete_cb(arg);
|
||||||
hal->dma_regs->dmastatus.recv_int = 1;
|
|
||||||
}
|
}
|
||||||
/* Early Receive Interrupt */
|
/* Early Receive Interrupt */
|
||||||
if (dma_status.early_recv_int) {
|
if (dma_status.early_recv_int) {
|
||||||
emac_hal_rx_early_cb(arg);
|
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 */
|
/* DMA Abnormal Interrupt */
|
||||||
if (dma_status.abn_int_summ) {
|
if (dma_status.abn_int_summ) {
|
||||||
/* Transmit Process Stopped */
|
/* Transmit Process Stopped */
|
||||||
if (dma_status.trans_proc_stop) {
|
if (dma_status.trans_proc_stop) {
|
||||||
hal->dma_regs->dmastatus.trans_proc_stop = 1;
|
|
||||||
}
|
}
|
||||||
/* Transmit Jabber Timeout */
|
/* Transmit Jabber Timeout */
|
||||||
if (dma_status.trans_jabber_to) {
|
if (dma_status.trans_jabber_to) {
|
||||||
hal->dma_regs->dmastatus.trans_jabber_to = 1;
|
|
||||||
}
|
}
|
||||||
/* Receive FIFO Overflow */
|
/* Receive FIFO Overflow */
|
||||||
if (dma_status.recv_ovflow) {
|
if (dma_status.recv_ovflow) {
|
||||||
hal->dma_regs->dmastatus.recv_ovflow = 1;
|
|
||||||
}
|
}
|
||||||
/* Transmit Underflow */
|
/* Transmit Underflow */
|
||||||
if (dma_status.trans_undflow) {
|
if (dma_status.trans_undflow) {
|
||||||
hal->dma_regs->dmastatus.trans_undflow = 1;
|
|
||||||
}
|
}
|
||||||
/* Receive Buffer Unavailable */
|
/* Receive Buffer Unavailable */
|
||||||
if (dma_status.recv_buf_unavail) {
|
if (dma_status.recv_buf_unavail) {
|
||||||
emac_hal_rx_unavail_cb(arg);
|
emac_hal_rx_unavail_cb(arg);
|
||||||
hal->dma_regs->dmastatus.recv_buf_unavail = 1;
|
|
||||||
}
|
}
|
||||||
/* Receive Process Stopped */
|
/* Receive Process Stopped */
|
||||||
if (dma_status.recv_proc_stop) {
|
if (dma_status.recv_proc_stop) {
|
||||||
hal->dma_regs->dmastatus.recv_proc_stop = 1;
|
|
||||||
}
|
}
|
||||||
/* Receive Watchdog Timeout */
|
/* Receive Watchdog Timeout */
|
||||||
if (dma_status.recv_wdt_to) {
|
if (dma_status.recv_wdt_to) {
|
||||||
hal->dma_regs->dmastatus.recv_wdt_to = 1;
|
|
||||||
}
|
}
|
||||||
/* Early Transmit Interrupt */
|
/* Early Transmit Interrupt */
|
||||||
if (dma_status.early_trans_int) {
|
if (dma_status.early_trans_int) {
|
||||||
hal->dma_regs->dmastatus.early_trans_int = 1;
|
|
||||||
}
|
}
|
||||||
/* Fatal Bus Error */
|
/* Fatal Bus Error */
|
||||||
if (dma_status.fatal_bus_err_int) {
|
if (dma_status.fatal_bus_err_int) {
|
||||||
hal->dma_regs->dmastatus.fatal_bus_err_int = 1;
|
|
||||||
}
|
}
|
||||||
hal->dma_regs->dmastatus.abn_int_summ = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user