]> granicus.if.org Git - esp-idf/commitdiff
ethernet: Add convenience functions esp_eth_smi_wait_value() & esp_eth_smi_wait_set()
authorAngus Gratton <angus@espressif.com>
Wed, 19 Apr 2017 03:43:25 +0000 (13:43 +1000)
committerAngus Gratton <gus@projectgus.com>
Thu, 20 Apr 2017 08:03:00 +0000 (18:03 +1000)
Covers the common case of waiting for a particular PHY register to have a particular value.

components/ethernet/emac_main.c
components/ethernet/eth_phy/phy_lan8720.c
components/ethernet/eth_phy/phy_tlk110.c
components/ethernet/include/esp_eth.h
docs/api/ethernet/esp_eth.rst

index 501fd3ef2f16a94cd65a848909dbc661b7f5f657..7e299be9440ddb3f1117da98a9596600d1cdcce9 100644 (file)
@@ -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;
index 28dfed56edb43fb92de23569f070acefc1efd65d..b0f793b33d8a95ee5f605fc03dd1c49e7574d2ba 100644 (file)
 #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);
index 7c91a7652983ebf00e3ae6ea315996d6f7598fe8..020329a2673daf596612704e685bef1520952b73 100644 (file)
@@ -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);
index 24187e305f74102190fc38378c7a4f2c65fe226d..a7f92ad4badd6fdbd576b9972430273d459bd9d3 100644 (file)
@@ -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.
  *
index dc10b7b41aadcf417f7f960d3a4f8dff683822e2..223c7b2267c115d091b66fdc3de1dfc6f8c81b00 100644 (file)
@@ -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