diff --git a/components/esp_eth/src/esp_eth.c b/components/esp_eth/src/esp_eth.c index 868dddad3f..a021247552 100644 --- a/components/esp_eth/src/esp_eth.c +++ b/components/esp_eth/src/esp_eth.c @@ -1,16 +1,8 @@ -// Copyright 2019-2021 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -270,13 +262,11 @@ esp_err_t esp_eth_start(esp_eth_handle_t hdl) esp_eth_driver_t *eth_driver = (esp_eth_driver_t *)hdl; ESP_GOTO_ON_FALSE(eth_driver, ESP_ERR_INVALID_ARG, err, TAG, "ethernet driver handle can't be null"); esp_eth_phy_t *phy = eth_driver->phy; - esp_eth_mac_t *mac = eth_driver->mac; // check if driver has stopped esp_eth_fsm_t expected_fsm = ESP_ETH_FSM_STOP; ESP_GOTO_ON_FALSE(atomic_compare_exchange_strong(ð_driver->fsm, &expected_fsm, ESP_ETH_FSM_START), ESP_ERR_INVALID_STATE, err, TAG, "driver started already"); ESP_GOTO_ON_ERROR(phy->negotiate(phy), err, TAG, "phy negotiation failed"); - ESP_GOTO_ON_ERROR(mac->start(mac), err, TAG, "start mac failed"); ESP_GOTO_ON_ERROR(esp_event_post(ETH_EVENT, ETHERNET_EVENT_START, ð_driver, sizeof(esp_eth_driver_t *), 0), err, TAG, "send ETHERNET_EVENT_START event failed"); ESP_GOTO_ON_ERROR(phy->get_link(phy), err, TAG, "phy get link status failed"); diff --git a/components/esp_eth/src/esp_eth_mac_esp.c b/components/esp_eth/src/esp_eth_mac_esp.c index 278d9ae4de..4b13c9f120 100644 --- a/components/esp_eth/src/esp_eth_mac_esp.c +++ b/components/esp_eth/src/esp_eth_mac_esp.c @@ -1,16 +1,8 @@ -// Copyright 2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include #include @@ -41,7 +33,7 @@ static const char *TAG = "esp.emac"; #define PHY_OPERATION_TIMEOUT_US (1000) -#define MAC_STOP_TIMEOUT_MS (100) +#define MAC_STOP_TIMEOUT_US (250) #define FLOW_CONTROL_LOW_WATER_MARK (CONFIG_ETH_DMA_RX_BUFFER_NUM / 3) #define FLOW_CONTROL_HIGH_WATER_MARK (FLOW_CONTROL_LOW_WATER_MARK * 2) @@ -72,6 +64,8 @@ typedef struct { static esp_err_t esp_emac_alloc_driver_obj(const eth_mac_config_t *config, emac_esp32_t **emac_out_hdl, void **out_descriptors); static void esp_emac_free_driver_obj(emac_esp32_t *emac, void *descriptors); +static esp_err_t emac_esp32_start(esp_eth_mac_t *mac); +static esp_err_t emac_esp32_stop(esp_eth_mac_t *mac); static esp_err_t emac_esp32_set_mediator(esp_eth_mac_t *mac, esp_eth_mediator_t *eth) { @@ -158,11 +152,11 @@ static esp_err_t emac_esp32_set_link(esp_eth_mac_t *mac, eth_link_t link) switch (link) { case ETH_LINK_UP: ESP_GOTO_ON_ERROR(esp_intr_enable(emac->intr_hdl), err, TAG, "enable interrupt failed"); - emac_hal_start(&emac->hal); + emac_esp32_start(mac); break; case ETH_LINK_DOWN: ESP_GOTO_ON_ERROR(esp_intr_disable(emac->intr_hdl), err, TAG, "disable interrupt failed"); - emac_hal_stop(&emac->hal); + emac_esp32_stop(mac); break; default: ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "unknown link status"); @@ -404,9 +398,9 @@ static esp_err_t emac_esp32_stop(esp_eth_mac_t *mac) if ((ret = emac_hal_stop(&emac->hal)) == ESP_OK) { break; } - to += 20; - vTaskDelay(pdMS_TO_TICKS(20)); - } while (to < MAC_STOP_TIMEOUT_MS); + to += 25; + esp_rom_delay_us(25); + } while (to < MAC_STOP_TIMEOUT_US); return ret; } diff --git a/components/hal/emac_hal.c b/components/hal/emac_hal.c index df9d0901b6..22f39987bd 100644 --- a/components/hal/emac_hal.c +++ b/components/hal/emac_hal.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -337,17 +337,16 @@ void emac_hal_start(emac_hal_context_t *hal) /* Flush Transmit FIFO */ emac_ll_flush_trans_fifo_enable(hal->dma_regs, true); - /* Flush Receive FIFO */ - emac_ll_flush_recv_frame_enable(hal->dma_regs, true); + + /* Start DMA transmission */ + emac_ll_start_stop_dma_transmit(hal->dma_regs, true); + /* Start DMA reception */ + emac_ll_start_stop_dma_receive(hal->dma_regs, true); /* Enable transmit state machine of the MAC for transmission on the MII */ emac_ll_transmit_enable(hal->mac_regs, true); /* Enable receive state machine of the MAC for reception from the MII */ emac_ll_receive_enable(hal->mac_regs, true); - /* Start DMA transmission */ - emac_ll_start_stop_dma_transmit(hal->dma_regs, true); - /* Start DMA reception */ - emac_ll_start_stop_dma_receive(hal->dma_regs, true); /* Clear all pending interrupts */ emac_ll_clear_all_pending_intr(hal->dma_regs); @@ -357,18 +356,24 @@ esp_err_t emac_hal_stop(emac_hal_context_t *hal) { /* Stop DMA transmission */ emac_ll_start_stop_dma_transmit(hal->dma_regs, false); - /* Stop DMA reception */ - emac_ll_start_stop_dma_receive(hal->dma_regs, false); if (emac_ll_transmit_frame_ctrl_status(hal->mac_regs) != 0x0) { /* Previous transmit in progress */ return ESP_ERR_INVALID_STATE; } - /* Disable receive state machine of the MAC for reception from the MII */ - emac_ll_transmit_enable(hal->mac_regs, false); /* Disable transmit state machine of the MAC for transmission on the MII */ emac_ll_receive_enable(hal->mac_regs, false); + /* Disable receive state machine of the MAC for reception from the MII */ + emac_ll_transmit_enable(hal->mac_regs, false); + + if (emac_ll_receive_read_ctrl_state(hal->mac_regs) != 0x0) { + /* Previous receive copy in progress */ + return ESP_ERR_INVALID_STATE; + } + + /* Stop DMA reception */ + emac_ll_start_stop_dma_receive(hal->dma_regs, false); /* Disable Ethernet MAC and DMA Interrupt */ emac_ll_disable_all_intr(hal->dma_regs); diff --git a/components/hal/esp32/include/hal/emac_ll.h b/components/hal/esp32/include/hal/emac_ll.h index bea18961bc..cd341b1c5f 100644 --- a/components/hal/esp32/include/hal/emac_ll.h +++ b/components/hal/esp32/include/hal/emac_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -342,6 +342,11 @@ static inline uint32_t emac_ll_transmit_frame_ctrl_status(emac_mac_dev_t *mac_re return mac_regs->emacdebug.mactfcs; } +static inline uint32_t emac_ll_receive_read_ctrl_state(emac_mac_dev_t *mac_regs) +{ + return mac_regs->emacdebug.mtlrfrcs; +} + /* emacmiidata */ static inline void emac_ll_set_phy_data(emac_mac_dev_t *mac_regs, uint32_t data) { diff --git a/components/hal/include/hal/emac_hal.h b/components/hal/include/hal/emac_hal.h index 4f332811ab..27cd38456d 100644 --- a/components/hal/include/hal/emac_hal.h +++ b/components/hal/include/hal/emac_hal.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -225,7 +225,7 @@ void emac_hal_start(emac_hal_context_t *hal); * @param hal EMAC HAL context infostructure * @return * - ESP_OK: succeed - * - ESP_ERR_INVALID_STATE: previous frame transmission is not completed. When this error occurs, + * - ESP_ERR_INVALID_STATE: previous frame transmission/reception is not completed. When this error occurs, * wait and reapeat the EMAC stop again. */ esp_err_t emac_hal_stop(emac_hal_context_t *hal);