From 39d7a6a022f37d046222d255cf416062bf6f6d82 Mon Sep 17 00:00:00 2001 From: Ondrej Kosta Date: Tue, 11 Aug 2026 13:57:08 +0200 Subject: [PATCH] fix(esp_eth): fixed Ethernet PHY HW reset timing in common PHY code --- .../esp_eth/src/phy/esp_eth_phy_802_3.c | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/components/esp_eth/src/phy/esp_eth_phy_802_3.c b/components/esp_eth/src/phy/esp_eth_phy_802_3.c index 7d5d407d029..a7a10d6aa8a 100644 --- a/components/esp_eth/src/phy/esp_eth_phy_802_3.c +++ b/components/esp_eth/src/phy/esp_eth_phy_802_3.c @@ -484,6 +484,20 @@ esp_err_t esp_eth_phy_802_3_del(phy_802_3_t *phy_802_3) return ESP_OK; } +/* Delays for at least delay_us. Anything shorter than a FreeRTOS tick has to be busy waited since + the scheduler cannot express it. Longer delays are slept off by a single vTaskDelay which returns + after n-1 to n tick periods, because the call is placed somewhere inside an already running tick, + hence one extra tick is requested to not undershoot the delay. */ +static void phy_802_3_delay_us(uint32_t delay_us) +{ + uint32_t tick_period_us = portTICK_PERIOD_MS * 1000; + if (delay_us < tick_period_us) { + esp_rom_delay_us(delay_us); + } else { + vTaskDelay((delay_us + tick_period_us - 1) / tick_period_us + 1); + } +} + esp_err_t esp_eth_phy_802_3_reset_hw(phy_802_3_t *phy_802_3) { esp_err_t ret = ESP_OK; @@ -491,14 +505,10 @@ esp_err_t esp_eth_phy_802_3_reset_hw(phy_802_3_t *phy_802_3) gpio_func_sel(phy_802_3->reset_gpio_num, PIN_FUNC_GPIO); gpio_set_level(phy_802_3->reset_gpio_num, 0); gpio_output_enable(phy_802_3->reset_gpio_num); - if (phy_802_3->hw_reset_assert_time_us < 10000) { - esp_rom_delay_us(phy_802_3->hw_reset_assert_time_us); - } else { - vTaskDelay(pdMS_TO_TICKS(phy_802_3->hw_reset_assert_time_us/1000)); - } + phy_802_3_delay_us(phy_802_3->hw_reset_assert_time_us); gpio_set_level(phy_802_3->reset_gpio_num, 1); if (phy_802_3->post_hw_reset_delay_ms > 0) { - vTaskDelay(pdMS_TO_TICKS(phy_802_3->post_hw_reset_delay_ms)); + phy_802_3_delay_us((uint32_t)phy_802_3->post_hw_reset_delay_ms * 1000); } return ESP_OK; }