diff --git a/components/ethernet/emac_main.c b/components/ethernet/emac_main.c index 501fd3ef2f..7e299be944 100644 --- a/components/ethernet/emac_main.c +++ b/components/ethernet/emac_main.c @@ -204,6 +204,25 @@ uint16_t esp_eth_smi_read(uint32_t reg_num) return value; } +esp_err_t esp_eth_smi_wait_value(uint32_t reg_num, uint16_t value, uint16_t value_mask, int timeout_ms) +{ + unsigned start = xTaskGetTickCount(); + unsigned timeout_ticks = (timeout_ms + portTICK_PERIOD_MS - 1) / portTICK_PERIOD_MS; + uint16_t current_value = 0; + + while (timeout_ticks == 0 || (xTaskGetTickCount() - start < timeout_ticks)) { + current_value = esp_eth_smi_read(reg_num); + if ((current_value & value_mask) == (value & value_mask)) { + return ESP_OK; + } + vTaskDelay(1); + } + ESP_LOGE(TAG, "Timed out waiting for PHY register 0x%x to have value 0x%04x (mask 0x%04x). Current value 0x%04x", + reg_num, value, value_mask, current_value); + return ESP_ERR_TIMEOUT; +} + + static void emac_set_user_config_data(eth_config_t *config ) { emac_config.phy_addr = config->phy_addr; diff --git a/components/ethernet/eth_phy/phy_lan8720.c b/components/ethernet/eth_phy/phy_lan8720.c index 28dfed56ed..b0f793b33d 100644 --- a/components/ethernet/eth_phy/phy_lan8720.c +++ b/components/ethernet/eth_phy/phy_lan8720.c @@ -18,14 +18,12 @@ #include "eth_phy/phy_lan8720.h" #include "eth_phy/phy_reg.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" - /* Value of MII_PHY_IDENTIFIER_REGs for Microchip LAN8720 * (Except for bottom 4 bits of ID2, used for model revision) */ #define LAN8720_PHY_ID1 0x0007 #define LAN8720_PHY_ID2 0xc0f0 +#define LAN8720_PHY_ID2_MASK 0xFFF0 /* LAN8720-specific registers */ #define SW_STRAP_CONTROL_REG (0x9) @@ -55,12 +53,8 @@ void phy_lan8720_check_phy_init(void) { phy_lan8720_dump_registers(); - while((esp_eth_smi_read(MII_BASIC_MODE_STATUS_REG) & MII_AUTO_NEGOTIATION_COMPLETE ) == 0) { - vTaskDelay(1); - } - while((esp_eth_smi_read(PHY_SPECIAL_CONTROL_STATUS_REG) & AUTO_NEGOTIATION_DONE ) == 0) { - vTaskDelay(1); - } + esp_eth_smi_wait_set(MII_BASIC_MODE_STATUS_REG, MII_AUTO_NEGOTIATION_COMPLETE, 0); + esp_eth_smi_wait_set(PHY_SPECIAL_CONTROL_STATUS_REG, AUTO_NEGOTIATION_DONE, 0); } eth_speed_mode_t phy_lan8720_get_speed_mode(void) @@ -101,14 +95,12 @@ void phy_lan8720_init(void) esp_eth_smi_write(MII_BASIC_MODE_CONTROL_REG, MII_SOFTWARE_RESET); - unsigned phy_id1, phy_id2; + esp_err_t res1, res2; do { - vTaskDelay(1); - phy_id1 = esp_eth_smi_read(MII_PHY_IDENTIFIER_1_REG); - phy_id2 = esp_eth_smi_read(MII_PHY_IDENTIFIER_2_REG); - ESP_LOGD(TAG, "PHY ID 0x%04x 0x%04x", phy_id1, phy_id2); - phy_id2 &= 0xFFF0; // Remove model revision code - } while (phy_id1 != LAN8720_PHY_ID1 && phy_id2 != LAN8720_PHY_ID2); + // Call esp_eth_smi_wait_value() with a timeout so it prints an error periodically + res1 = esp_eth_smi_wait_value(MII_PHY_IDENTIFIER_1_REG, LAN8720_PHY_ID1, UINT16_MAX, 1000); + res2 = esp_eth_smi_wait_value(MII_PHY_IDENTIFIER_2_REG, LAN8720_PHY_ID2, LAN8720_PHY_ID2_MASK, 1000); + } while(res1 != ESP_OK || res2 != ESP_OK); esp_eth_smi_write(SW_STRAP_CONTROL_REG, DEFAULT_STRAP_CONFIG | SW_STRAP_CONFIG_DONE); diff --git a/components/ethernet/eth_phy/phy_tlk110.c b/components/ethernet/eth_phy/phy_tlk110.c index 7c91a76529..020329a267 100644 --- a/components/ethernet/eth_phy/phy_tlk110.c +++ b/components/ethernet/eth_phy/phy_tlk110.c @@ -26,6 +26,7 @@ */ #define TLK110_PHY_ID1 0x2000 #define TLK110_PHY_ID2 0xa210 +#define TLK110_PHY_ID2_MASK 0xFFF0 /* TLK110-specific registers */ #define SW_STRAP_CONTROL_REG (0x9) @@ -56,15 +57,9 @@ void phy_tlk110_check_phy_init(void) { phy_tlk110_dump_registers(); - while((esp_eth_smi_read(MII_BASIC_MODE_STATUS_REG) & MII_AUTO_NEGOTIATION_COMPLETE ) == 0) { - vTaskDelay(1); - } - while((esp_eth_smi_read(PHY_STATUS_REG) & AUTO_NEGOTIATION_STATUS ) == 0) { - vTaskDelay(1); - } - while((esp_eth_smi_read(CABLE_DIAGNOSTIC_CONTROL_REG) & DIAGNOSTIC_DONE ) == 0) { - vTaskDelay(1); - } + esp_eth_smi_wait_set(MII_BASIC_MODE_STATUS_REG, MII_AUTO_NEGOTIATION_COMPLETE, 0); + esp_eth_smi_wait_set(PHY_STATUS_REG, AUTO_NEGOTIATION_STATUS, 0); + esp_eth_smi_wait_set(CABLE_DIAGNOSTIC_CONTROL_REG, DIAGNOSTIC_DONE, 0); } eth_speed_mode_t phy_tlk110_get_speed_mode(void) @@ -106,14 +101,12 @@ void phy_tlk110_init(void) esp_eth_smi_write(PHY_RESET_CONTROL_REG, SOFTWARE_RESET); - unsigned phy_id1, phy_id2; + esp_err_t res1, res2; do { - vTaskDelay(1); - phy_id1 = esp_eth_smi_read(MII_PHY_IDENTIFIER_1_REG); - phy_id2 = esp_eth_smi_read(MII_PHY_IDENTIFIER_2_REG); - ESP_LOGD(TAG, "PHY ID 0x%04x 0x%04x", phy_id1, phy_id2); - phy_id2 &= 0xFFF0; // Remove model revision code - } while (phy_id1 != TLK110_PHY_ID1 && phy_id2 != TLK110_PHY_ID2); + // Call esp_eth_smi_wait_value() with a timeout so it prints an error periodically + res1 = esp_eth_smi_wait_value(MII_PHY_IDENTIFIER_1_REG, TLK110_PHY_ID1, UINT16_MAX, 1000); + res2 = esp_eth_smi_wait_value(MII_PHY_IDENTIFIER_2_REG, TLK110_PHY_ID2, TLK110_PHY_ID2_MASK, 1000); + } while(res1 != ESP_OK || res2 != ESP_OK); esp_eth_smi_write(SW_STRAP_CONTROL_REG, DEFAULT_STRAP_CONFIG | SW_STRAP_CONFIG_DONE); diff --git a/components/ethernet/include/esp_eth.h b/components/ethernet/include/esp_eth.h index 24187e305f..a7f92ad4ba 100644 --- a/components/ethernet/include/esp_eth.h +++ b/components/ethernet/include/esp_eth.h @@ -175,7 +175,7 @@ void esp_eth_get_mac(uint8_t mac[6]); void esp_eth_smi_write(uint32_t reg_num, uint16_t value); /** - * @brief Write phy reg with smi interface. + * @brief Read phy reg with smi interface. * * @note phy base addr must be right. * @@ -185,6 +185,35 @@ void esp_eth_smi_write(uint32_t reg_num, uint16_t value); */ uint16_t esp_eth_smi_read(uint32_t reg_num); +/** + * @brief Continuously read a PHY register over SMI interface, wait until the register has the desired value. + * + * @note PHY base address must be right. + * + * @param reg_num: PHY register number + * @param value: Value to wait for (masked with value_mask) + * @param value_mask: Mask of bits to match in the register. + * @param timeout_ms: Timeout to wait for this value (milliseconds). 0 means never timeout. + * + * @return ESP_OK if desired value matches, ESP_ERR_TIMEOUT if timed out. + */ +esp_err_t esp_eth_smi_wait_value(uint32_t reg_num, uint16_t value, uint16_t value_mask, int timeout_ms); + +/** + * @brief Continuously read a PHY register over SMI interface, wait until the register has all bits in a mask set. + * + * @note PHY base address must be right. + * + * @param reg_num: PHY register number + * @param value_mask: Value mask to wait for (all bits in this mask must be set) + * @param timeout_ms: Timeout to wait for this value (milliseconds). 0 means never timeout. + * + * @return ESP_OK if desired value matches, ESP_ERR_TIMEOUT if timed out. + */ +static inline esp_err_t esp_eth_smi_wait_set(uint32_t reg_num, uint16_t value_mask, int timeout_ms) { + return esp_eth_smi_wait_value(reg_num, value_mask, value_mask, timeout_ms); +} + /** * @brief Free emac rx buf. * diff --git a/docs/api/ethernet/esp_eth.rst b/docs/api/ethernet/esp_eth.rst index dc10b7b41a..223c7b2267 100644 --- a/docs/api/ethernet/esp_eth.rst +++ b/docs/api/ethernet/esp_eth.rst @@ -62,6 +62,8 @@ Functions .. doxygenfunction:: esp_eth_get_mac .. doxygenfunction:: esp_eth_smi_write .. doxygenfunction:: esp_eth_smi_read +.. doxygenfunction:: esp_eth_smi_wait_value +.. doxygenfunction:: esp_eth_smi_wait_set .. doxygenfunction:: esp_eth_free_rx_buf