mirror of
https://github.com/espressif/esp-idf.git
synced 2025-09-30 19:19:21 +00:00
esp_eth: add loopback test, change chip drivers to reflect chip specific behaviour
In esp_eth_test_apps.c: Add test of loopback functionality. Change speed/duplex/autonegotiation test - remove need to enable loopback (required for it to work on some phys supported by ESP-IDF) In Kconfig.projbuild: Add parameters to select which configuration is used - standard or custom. Add for custom configuration parameters to select MDC and MDIO pins (required to work with WESP-32 and other boards that use non-standard pin assignments). In esp_eth_test_common.c: Add code to support changes made in Kconfig In sdkconfig.ci.default_rtl8201: Change config which is used. Now custom is used and MDC is gpio 16, MDIO is gpio 17. Reuqired to work with WESP-32 In esp_eth_phy_802_3.h: Make 802.3 API public. In esp_eth_phy_802_3.c: Add loopback check in eth_phy_802_3_set_duplex(). Now ESP_ERR_INVALID_STATE is invoked on attempt to set duplex to half when loopback is enabled. Remove static property from esp_eth_phy_802_3_autonego_ctrl and esp_eth_phy_802_3_loopback. In esp_eth_phy_dm9051.c: Add dm9051_loopback() because DM9051 requires setting additional bit to enable auto-negotiation loopback for data to be received. Add dm9051_set_speed() which invokes ESP_ERR_INVALID_STATE on attempt to set speed to 10 Mbps when loopback is enabled because such speed configuration is unsupported. In esp_eth_phy_ksz80xx.c: Add ksz80xx_set_speed() which invokes ESP_ERR_INVALID_STATE on attempt to set speed to 10 Mbps when loopback is enabled because such speed configuration is unsupported. In esp_eth_phy_ksz8851snl.c: Change phy_ksz8851_set_duplex() to invoke ESP_ERR_INVALID_STATE on attempt to set duplex to half when loopback is enabled. In esp_eth_phy_dp83848.c, esp_eth_phy_rtl8201.c: Add autonego_ctrl implementation which prevents enabling autonegotiation when loopback is enabled. Add loopback implementation which disables autonegotiation prior to enabling loopback. In esp_eth_phy_lan87xx.c: Add autonego_ctrl implementation which prevents enabling autonegotiation when loopback is enabled. Add loopback implementation which disables autonegotiation prior to enabling loopback. Fix link indicating being down when loopback is enabled by force setting link up.
This commit is contained in:
@@ -13,6 +13,7 @@ menu "esp_eth TEST_APPS Configuration"
|
||||
help
|
||||
Use internal Ethernet MAC controller.
|
||||
|
||||
|
||||
config TARGET_USE_SPI_ETHERNET
|
||||
bool "SPI Ethernet"
|
||||
select ETH_USE_SPI_ETHERNET
|
||||
@@ -38,6 +39,20 @@ menu "esp_eth TEST_APPS Configuration"
|
||||
config TARGET_ETH_PHY_DEVICE_DP83848
|
||||
bool "DP83848"
|
||||
endchoice # TARGET_ETH_PHY_DEVICE
|
||||
|
||||
config TARGET_USE_DEFAULT_EMAC_CONFIG
|
||||
default y
|
||||
bool "Use default EMAC config"
|
||||
|
||||
if !TARGET_USE_DEFAULT_EMAC_CONFIG
|
||||
config TARGET_IO_MDC
|
||||
int "SMI MDC GPIO number"
|
||||
default 23
|
||||
config TARGET_IO_MDIO
|
||||
int "SMI MDIO GPIO number"
|
||||
default 18
|
||||
endif
|
||||
|
||||
endif # TARGET_USE_INTERNAL_ETHERNET
|
||||
|
||||
if TARGET_USE_SPI_ETHERNET
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
@@ -14,6 +14,8 @@
|
||||
#include "esp_rom_md5.h"
|
||||
#include "esp_eth_test_common.h"
|
||||
|
||||
#define LOOPBACK_TEST_PACKET_SIZE 256
|
||||
|
||||
static const char *TAG = "esp32_eth_test";
|
||||
|
||||
extern const char dl_espressif_com_root_cert_pem_start[] asm("_binary_dl_espressif_com_root_cert_pem_start");
|
||||
@@ -92,13 +94,13 @@ TEST_CASE("ethernet io test", "[ethernet]")
|
||||
extra_cleanup();
|
||||
}
|
||||
|
||||
// This test expects autonegotiation to be enabled on the other node.
|
||||
TEST_CASE("ethernet io speed/duplex/autonegotiation", "[ethernet]")
|
||||
{
|
||||
EventBits_t bits = 0;
|
||||
EventGroupHandle_t eth_event_group = xEventGroupCreate();
|
||||
TEST_ASSERT(eth_event_group != NULL);
|
||||
TEST_ESP_OK(esp_event_loop_create_default());
|
||||
TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_group));
|
||||
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
|
||||
mac_config.flags = ETH_MAC_FLAG_PIN_TO_CORE; // pin to core
|
||||
esp_eth_mac_t *mac = mac_init(NULL, &mac_config);
|
||||
@@ -109,13 +111,7 @@ TEST_CASE("ethernet io speed/duplex/autonegotiation", "[ethernet]")
|
||||
esp_eth_handle_t eth_handle = NULL;
|
||||
TEST_ESP_OK(esp_eth_driver_install(ð_config, ð_handle));
|
||||
extra_eth_config(eth_handle);
|
||||
|
||||
// Set PHY to loopback mode so we do not have to take care about link configuration of the other node.
|
||||
// The reason behind is improbable, however, if the other node was configured to e.g. 100 Mbps and we
|
||||
// tried to change the speed at ESP node to 10 Mbps, we could get into trouble to establish a link.
|
||||
// TODO: this test in this configuration may not work for all the chips (JIRA IDF-6186)
|
||||
bool loopback_en = true;
|
||||
esp_eth_ioctl(eth_handle, ETH_CMD_S_PHY_LOOPBACK, &loopback_en);
|
||||
TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_group));
|
||||
|
||||
// this test only test layer2, so don't need to register input callback (i.e. esp_eth_update_input_path)
|
||||
TEST_ESP_OK(esp_eth_start(eth_handle));
|
||||
@@ -274,6 +270,146 @@ TEST_CASE("ethernet io speed/duplex/autonegotiation", "[ethernet]")
|
||||
vEventGroupDelete(eth_event_group);
|
||||
}
|
||||
|
||||
static SemaphoreHandle_t loopback_test_case_data_received;
|
||||
static esp_err_t loopback_test_case_incoming_handler(esp_eth_handle_t eth_handle, uint8_t *buffer, uint32_t length, void *priv)
|
||||
{
|
||||
TEST_ASSERT(memcmp(priv, buffer, LOOPBACK_TEST_PACKET_SIZE) == 0)
|
||||
xSemaphoreGive(loopback_test_case_data_received);
|
||||
free(buffer);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
TEST_CASE("ethernet io loopback", "[ethernet]")
|
||||
{
|
||||
loopback_test_case_data_received = xSemaphoreCreateBinary();
|
||||
// init everything else
|
||||
EventBits_t bits = 0;
|
||||
EventGroupHandle_t eth_event_group = xEventGroupCreate();
|
||||
TEST_ASSERT(eth_event_group != NULL);
|
||||
TEST_ESP_OK(esp_event_loop_create_default());
|
||||
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
|
||||
mac_config.flags = ETH_MAC_FLAG_PIN_TO_CORE; // pin to core
|
||||
esp_eth_mac_t *mac = mac_init(NULL, &mac_config);
|
||||
TEST_ASSERT_NOT_NULL(mac);
|
||||
esp_eth_phy_t *phy = phy_init(NULL);
|
||||
TEST_ASSERT_NOT_NULL(phy);
|
||||
esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(mac, phy);
|
||||
esp_eth_handle_t eth_handle = NULL;
|
||||
TEST_ESP_OK(esp_eth_driver_install(ð_config, ð_handle));
|
||||
extra_eth_config(eth_handle);
|
||||
// Disable autonegotiation to manually set speed and duplex mode
|
||||
bool auto_nego_en = false;
|
||||
TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_S_AUTONEGO, &auto_nego_en));
|
||||
bool loopback_en = true;
|
||||
// *** W5500 deviation ***
|
||||
// Rationale: does not support loopback
|
||||
#ifdef CONFIG_TARGET_ETH_PHY_DEVICE_W5500
|
||||
TEST_ASSERT(esp_eth_ioctl(eth_handle, ETH_CMD_S_PHY_LOOPBACK, &loopback_en) == ESP_ERR_NOT_SUPPORTED);
|
||||
goto cleanup;
|
||||
#else
|
||||
TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_S_PHY_LOOPBACK, &loopback_en));
|
||||
#endif
|
||||
|
||||
eth_duplex_t duplex_modes[] = {ETH_DUPLEX_HALF, ETH_DUPLEX_FULL};
|
||||
eth_speed_t speeds[] = {ETH_SPEED_10M, ETH_SPEED_100M};
|
||||
emac_frame_t* test_packet = malloc(LOOPBACK_TEST_PACKET_SIZE);
|
||||
esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, test_packet->src);
|
||||
esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, test_packet->dest);
|
||||
for(size_t i = 0; i < LOOPBACK_TEST_PACKET_SIZE-ETH_HEADER_LEN; i++){
|
||||
test_packet->data[i] = rand() & 0xff;
|
||||
}
|
||||
TEST_ESP_OK(esp_eth_update_input_path(eth_handle, loopback_test_case_incoming_handler, test_packet));
|
||||
TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_group));
|
||||
|
||||
for (int i = 0; i < sizeof(speeds) / sizeof(eth_speed_t); i++) {
|
||||
eth_speed_t expected_speed = speeds[i];
|
||||
for (int j = 0; j < sizeof(duplex_modes) / sizeof(eth_duplex_t); j++) {
|
||||
eth_duplex_t expected_duplex = duplex_modes[j];
|
||||
ESP_LOGI(TAG, "Test with %s Mbps %s duplex.", expected_speed == ETH_SPEED_10M ? "10" : "100", expected_duplex == ETH_DUPLEX_HALF ? "half" : "full");
|
||||
// *** KSZ80XX, KSZ8851SNL and DM9051 deviation ***
|
||||
// Rationale: do not support loopback at 10 Mbps
|
||||
#if defined(CONFIG_TARGET_ETH_PHY_DEVICE_KSZ80XX) || defined(CONFIG_TARGET_ETH_PHY_DEVICE_DM9051)
|
||||
if ((expected_speed == ETH_SPEED_10M)) {
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, esp_eth_ioctl(eth_handle, ETH_CMD_S_SPEED, &expected_speed));
|
||||
continue;
|
||||
} else if (expected_speed == ETH_SPEED_100M) {
|
||||
TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_S_SPEED, &expected_speed));
|
||||
}
|
||||
#else
|
||||
TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_S_SPEED, &expected_speed));
|
||||
#endif
|
||||
if ((expected_duplex == ETH_DUPLEX_HALF)) {
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, esp_eth_ioctl(eth_handle, ETH_CMD_S_DUPLEX_MODE, &expected_duplex));
|
||||
continue;
|
||||
} else if (expected_duplex == ETH_DUPLEX_FULL) {
|
||||
TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_S_DUPLEX_MODE, &expected_duplex));
|
||||
}
|
||||
|
||||
TEST_ESP_OK(esp_eth_start(eth_handle));
|
||||
bits = xEventGroupWaitBits(eth_event_group, ETH_CONNECT_BIT, true, true, pdMS_TO_TICKS(ETH_CONNECT_TIMEOUT_MS));
|
||||
|
||||
eth_speed_t actual_speed = -1;
|
||||
TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_SPEED, &actual_speed));
|
||||
TEST_ASSERT_EQUAL(expected_speed, actual_speed);
|
||||
|
||||
eth_duplex_t actual_duplex = -1;
|
||||
TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_DUPLEX_MODE, &actual_duplex));
|
||||
TEST_ASSERT_EQUAL(expected_duplex, actual_duplex);
|
||||
|
||||
TEST_ESP_OK(esp_eth_transmit(eth_handle, test_packet, LOOPBACK_TEST_PACKET_SIZE));
|
||||
TEST_ASSERT(xSemaphoreTake(loopback_test_case_data_received, pdMS_TO_TICKS(10000)) == pdTRUE);
|
||||
TEST_ESP_OK(esp_eth_stop(eth_handle));
|
||||
}
|
||||
}
|
||||
|
||||
// Test enabling autonegotiation when loopback is disabled
|
||||
ESP_LOGI(TAG, "Test enabling autonegotiation without loopback.");
|
||||
loopback_en = false;
|
||||
auto_nego_en = true;
|
||||
TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_S_PHY_LOOPBACK, &loopback_en));
|
||||
TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_S_AUTONEGO, &auto_nego_en));
|
||||
auto_nego_en = false;
|
||||
loopback_en = true;
|
||||
TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_S_AUTONEGO, &auto_nego_en));
|
||||
TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_S_PHY_LOOPBACK, &loopback_en));
|
||||
// Test with enabled autonegotiaton
|
||||
ESP_LOGI(TAG, "Test with enabled autonegotiation.");
|
||||
auto_nego_en = true;
|
||||
// *** RTL8201, DP83848 and LAN87xx deviation ***
|
||||
// Rationale: do not support autonegotiation with loopback enabled.
|
||||
#if defined(CONFIG_TARGET_ETH_PHY_DEVICE_RTL8201) || defined(CONFIG_TARGET_ETH_PHY_DEVICE_DP83848) || \
|
||||
defined(CONFIG_TARGET_ETH_PHY_DEVICE_LAN87XX)
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, esp_eth_ioctl(eth_handle, ETH_CMD_S_AUTONEGO, &auto_nego_en));
|
||||
goto cleanup;
|
||||
#endif
|
||||
TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_S_AUTONEGO, &auto_nego_en));
|
||||
TEST_ESP_OK(esp_eth_start(eth_handle));
|
||||
bits = xEventGroupWaitBits(eth_event_group, ETH_CONNECT_BIT, true, true, pdMS_TO_TICKS(ETH_CONNECT_TIMEOUT_MS));
|
||||
|
||||
TEST_ESP_OK(esp_eth_transmit(eth_handle, test_packet, LOOPBACK_TEST_PACKET_SIZE));
|
||||
TEST_ASSERT(xSemaphoreTake(loopback_test_case_data_received, pdMS_TO_TICKS(ETH_CONNECT_TIMEOUT_MS)) == pdTRUE);
|
||||
|
||||
free(test_packet);
|
||||
loopback_en = false;
|
||||
TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_S_PHY_LOOPBACK, &loopback_en));
|
||||
TEST_ESP_OK(esp_eth_stop(eth_handle));
|
||||
bits = xEventGroupWaitBits(eth_event_group, ETH_STOP_BIT, true, true, pdMS_TO_TICKS(ETH_STOP_TIMEOUT_MS));
|
||||
TEST_ASSERT((bits & ETH_STOP_BIT) == ETH_STOP_BIT);
|
||||
// *** W5500, LAN87xx, RTL8201 and DP83848 deviation ***
|
||||
// Rationale: in those cases 'goto cleanup' is used to skip part of the test code. Incasing in #if block is done to prevent unused label error
|
||||
#if defined(CONFIG_TARGET_ETH_PHY_DEVICE_W5500) || defined(CONFIG_TARGET_ETH_PHY_DEVICE_LAN87XX) || \
|
||||
defined(CONFIG_TARGET_ETH_PHY_DEVICE_RTL8201) || defined(CONFIG_TARGET_ETH_PHY_DEVICE_DP83848)
|
||||
cleanup:
|
||||
#endif
|
||||
TEST_ESP_OK(esp_eth_driver_uninstall(eth_handle));
|
||||
TEST_ESP_OK(phy->del(phy));
|
||||
TEST_ESP_OK(mac->del(mac));
|
||||
TEST_ESP_OK(esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler));
|
||||
TEST_ESP_OK(esp_event_loop_delete_default());
|
||||
extra_cleanup();
|
||||
vEventGroupDelete(eth_event_group);
|
||||
}
|
||||
|
||||
TEST_CASE("ethernet event test", "[ethernet]")
|
||||
{
|
||||
EventBits_t bits = 0;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
@@ -35,6 +35,10 @@ esp_eth_mac_t *mac_init(void *vendor_emac_config, eth_mac_config_t *mac_config)
|
||||
}
|
||||
#if CONFIG_TARGET_USE_INTERNAL_ETHERNET
|
||||
eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG();
|
||||
#if !CONFIG_TARGET_USE_DEFAULT_EMAC_CONFIG
|
||||
esp32_emac_config.smi_mdc_gpio_num = CONFIG_TARGET_IO_MDC;
|
||||
esp32_emac_config.smi_mdio_gpio_num = CONFIG_TARGET_IO_MDIO;
|
||||
#endif // CONFIG_TARGET_USE_DEFAULT_EMAC_CONFIG
|
||||
if (vendor_emac_config == NULL) {
|
||||
vendor_emac_config = &esp32_emac_config;
|
||||
}
|
||||
|
@@ -7,3 +7,7 @@ CONFIG_ESP_TASK_WDT=n
|
||||
|
||||
CONFIG_TARGET_USE_INTERNAL_ETHERNET=y
|
||||
CONFIG_TARGET_ETH_PHY_DEVICE_RTL8201=y
|
||||
|
||||
CONFIG_TARGET_USE_DEFAULT_EMAC_CONFIG=n
|
||||
CONFIG_TARGET_IO_MDC=16
|
||||
CONFIG_TARGET_IO_MDIO=17
|
||||
|
Reference in New Issue
Block a user