From 0fe61ada78be4acd11dc3d30c03042daf0f9545c Mon Sep 17 00:00:00 2001 From: Ondrej Kosta Date: Fri, 23 Jan 2026 16:45:14 +0100 Subject: [PATCH] feat(esp_eth): Ethernet test refactor ETH tests use setUp-tearDown to init/deinit resources --- components/esp_eth/test_apps/CMakeLists.txt | 2 - components/esp_eth/test_apps/README.md | 172 +++++- .../esp_eth/test_apps/main/CMakeLists.txt | 7 +- .../esp_eth/test_apps/main/Kconfig.projbuild | 164 +++--- .../test_apps/main/esp_eth_test_apps.c | 368 +++--------- .../test_apps/main/esp_eth_test_common.c | 206 ------- .../test_apps/main/esp_eth_test_common.h | 42 -- .../test_apps/main/esp_eth_test_esp_emac.c | 238 ++++---- .../esp_eth/test_apps/main/esp_eth_test_l2.c | 532 ++++++++---------- .../test_apps/main/esp_eth_test_main.c | 14 +- .../test_apps/main/esp_eth_test_utils.c | 322 +++++++++++ .../test_apps/main/esp_eth_test_utils.h | 133 +++++ .../esp_eth/test_apps/main/idf_component.yml | 4 + .../esp_eth/test_apps/pytest_esp_eth.py | 21 +- .../test_apps/sdkconfig.ci.default_dm9051 | 22 +- .../test_apps/sdkconfig.ci.default_dp83848 | 18 +- .../test_apps/sdkconfig.ci.default_ip101 | 9 +- .../sdkconfig.ci.default_ip101_esp32p4 | 10 +- .../test_apps/sdkconfig.ci.default_ksz8041 | 12 +- .../test_apps/sdkconfig.ci.default_ksz8851snl | 21 +- .../test_apps/sdkconfig.ci.default_lan8720 | 18 +- .../test_apps/sdkconfig.ci.default_rtl8201 | 19 +- .../test_apps/sdkconfig.ci.default_w5500 | 23 +- .../test_apps/sdkconfig.ci.poll_dm9051 | 25 +- .../test_apps/sdkconfig.ci.poll_ksz8851snl | 24 +- .../esp_eth/test_apps/sdkconfig.ci.poll_w5500 | 26 +- .../test_apps/sdkconfig.ci.release_ip101 | 11 +- .../test_apps/sdkconfig.ci.rmii_clko_esp32p4 | 16 +- .../test_apps/sdkconfig.ci.single_core_ip101 | 11 +- tools/ci/ignore_build_warnings.txt | 1 + 30 files changed, 1322 insertions(+), 1169 deletions(-) delete mode 100644 components/esp_eth/test_apps/main/esp_eth_test_common.c delete mode 100644 components/esp_eth/test_apps/main/esp_eth_test_common.h create mode 100644 components/esp_eth/test_apps/main/esp_eth_test_utils.c create mode 100644 components/esp_eth/test_apps/main/esp_eth_test_utils.h create mode 100644 components/esp_eth/test_apps/main/idf_component.yml diff --git a/components/esp_eth/test_apps/CMakeLists.txt b/components/esp_eth/test_apps/CMakeLists.txt index 66d496fdf0..da19b265e5 100644 --- a/components/esp_eth/test_apps/CMakeLists.txt +++ b/components/esp_eth/test_apps/CMakeLists.txt @@ -1,8 +1,6 @@ # This is the project CMakeLists.txt file for the test subproject cmake_minimum_required(VERSION 3.16) -set(EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/unit-test-app/components") - include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(esp_eth_test) diff --git a/components/esp_eth/test_apps/README.md b/components/esp_eth/test_apps/README.md index 9747c000db..b31dd517e5 100644 --- a/components/esp_eth/test_apps/README.md +++ b/components/esp_eth/test_apps/README.md @@ -1,9 +1,9 @@ -# EMAC Test | Supported Targets | ESP32 | ESP32-P4 | | ----------------- | ----- | -------- | -This test app is used to test Ethernet MAC behavior with different chips. +# Ethernet Test +This test app is used to test Ethernet MAC behavior with different chips. ## Prerequisites Install third part Python packages: @@ -11,3 +11,171 @@ Install third part Python packages: ```bash pip install scapy ``` + +## Chip-Specific Configuration + +Different Ethernet chips may have deviations from the standard behavior or may not support certain features. To accommodate these chip-specific differences, the test framework provides Kconfig options that allow disabling or modifying specific tests that are incompatible with certain chips. + +For example, some chips may not support 10 Mbps loopback mode, or may have known errata that require workarounds. These Kconfig options are defined in `main/Kconfig.projbuild` and can be configured through the ESP-IDF menuconfig system to adjust test behavior for the specific chip under test. + +Refer to `main/Kconfig.projbuild` for the complete list of available configuration options and their descriptions. + +## Test Framework Overview + +The test framework provides common initialization and helper functions through `esp_eth_test_utils.h` and `esp_eth_test_utils.c`. These modules handle Ethernet initialization, event registration, and resource management automatically using Unity's `setUp()` and `tearDown()` functions. + +### Unity setUp() and tearDown() + +The `setUp()` function automatically performs the following initialization before each test case: + +1. **Sets up event handling** (creates event group and default event loop) +2. **Initializes the Ethernet driver** by calling `esp_eth_test_eth_init()` (uses Ethernet init component by default, can be customized - see [Customizing Ethernet Initialization](#customizing-ethernet-initialization) section below) +3. **Optionally sets up esp-netif** if the `[esp-netif]` marker is used (see [Markers](#test-markers) section below) +4. **Registers event handlers**: + - `eth_test_default_event_handler()` for ETH_EVENT events (ETHERNET_EVENT_START, ETHERNET_EVENT_STOP, ETHERNET_EVENT_CONNECTED, ETHERNET_EVENT_DISCONNECTED) + - `eth_test_got_ip_event_handler()` for IP_EVENT_ETH_GOT_IP events (only when `[esp-netif]` marker is used) + +The `tearDown()` function automatically performs cleanup after each test case: + +1. **Frees all allocated memory** tracked by the test framework +2. **Unregisters event handlers** +3. **Stops and deinitializes the Ethernet driver** by calling `esp_eth_test_eth_deinit()` (uses Ethernet init component by default, can be customized - see [Customizing Ethernet Initialization](#customizing-ethernet-initialization) section below) +4. **Destroys the event loop and event group** + +### Customizing Ethernet Initialization + +By default, the test framework initializes Ethernet using the **Ethernet init component**. This provides initialization of Ethernet hardware based on Kconfig settings. + +For test cases that require custom Ethernet initialization (e.g., chip not supported by Ethernet init component, specific MAC/PHY configurations, multiple Ethernet ports, or custom hardware setup), you can override the weak functions: + +- **`esp_eth_test_eth_init(esp_eth_handle_t *eth_handle)`**: Override this function to provide custom Ethernet initialization. The function should initialize the Ethernet driver and return the handle via the `eth_handle` parameter. + + > [!IMPORTANT] + > Initialization function must print DUT PHY identification string as it is expected by `pytest` script. The PHY identification message must be in the following format: + > ```c + > printf("DUT PHY: %s", my_phy_str); + >``` + +- **`esp_eth_test_eth_deinit(esp_eth_handle_t eth_handle)`**: Override this function to provide custom Ethernet deinitialization. The function should clean up the Ethernet driver resources. + +### Test Markers + +Test cases can use markers in their Unity test identifiers to control initialization behavior: + +#### `[esp-netif]` Marker + +When this marker is included in the test case identifier, `setUp()` will additionally initialize TCP/IP stack by: + +- Creating an ESP-NETIF interface using `ESP_NETIF_DEFAULT_ETH()` configuration +- Attaching the Ethernet driver to the netif using `esp_eth_new_netif_glue()` +- Registering the `eth_test_got_ip_event_handler()` for IP_EVENT_ETH_GOT_IP events + +**Example:** +```c +TEST_CASE("ethernet dhcp test", "[ethernet][esp-netif]") +{ + esp_eth_handle_t eth_handle = eth_test_get_eth_handle(); + EventGroupHandle_t eth_event_group = eth_test_get_default_event_group(); + esp_netif_t *netif = eth_test_get_netif(); // Valid when [esp-netif] is used + + // Test code using TCP/IP stack... +} +``` + +#### `[skip_setup_teardown]` Marker + +When this marker is included, `setUp()` and `tearDown()` will skip all automatic initialization and cleanup. This allows the test to perform its own custom initialization and cleanup procedures. + +> [!IMPORTANT] +> When using this marker, you must manually: +> - Register event handlers using `eth_test_default_event_handler()` and/or `eth_test_got_ip_event_handler()` +> - Initialize and deinitialize all resources except for memory allocated by `eth_test_alloc()` + +> [!NOTE] +> Memory allocated through `eth_test_alloc()` is automatically freed by `tearDown()` even when using this marker. + +**Example:** +```c +TEST_CASE("internal emac interrupt priority", "[esp_emac][skip_setup_teardown]") +{ + // Manual initialization + EventGroupHandle_t eth_event_group = xEventGroupCreate(); + TEST_ESP_OK(esp_event_loop_create_default()); + // Register handlers manually if needed + // ... custom test code ... +} +``` + +### Helper Functions + +#### Getting Initialized Handles + +- **`eth_test_get_eth_handle()`**: Returns the Ethernet handle initialized by `setUp()`. Returns `NULL` if initialization failed or if `[skip_setup_teardown]` marker is used. +- **`eth_test_get_default_event_group()`**: Returns the event group handle created by `setUp()`. Use this to wait for Ethernet events using `xEventGroupWaitBits()` with the predefined bits (ETH_START_BIT, ETH_STOP_BIT, ETH_CONNECT_BIT, ETH_GOT_IP_BIT). +- **`eth_test_get_netif()`**: Returns the ESP-NETIF handle initialized by `setUp()`. **Only valid when `[esp-netif]` marker is used**, otherwise returns `NULL`. + +#### PHY Register Manipulation + +- **`eth_test_set_phy_reg_bits()`**: Sets specific bits in a PHY register with retry logic. Useful for configuring PHY behavior during tests. +- **`eth_test_clear_phy_reg_bits()`**: Clears specific bits in a PHY register with retry logic. + +Both functions include automatic retry logic with configurable maximum attempts and delays between attempts. + +#### Memory Management + +- **`eth_test_alloc(size)`**: Allocates memory from the heap. The framework automatically tracks all allocations and frees them in `tearDown()`. Maximum of `MAX_HEAP_ALLOCATION_POINTERS` (20) allocations are supported. +- **`eth_test_free(ptr)`**: Frees a specific allocation. Generally not needed as `tearDown()` automatically frees all tracked allocations. +- **`eth_test_free_all()`**: Frees all tracked allocations. Called automatically by `tearDown()`. + +#### Event Handlers + +- **`eth_test_default_event_handler()`**: Default handler for ETH_EVENT events. Automatically registered by `setUp()` unless `[skip_setup_teardown]` is used. Sets event bits in the event group for: + - ETHERNET_EVENT_START → ETH_START_BIT + - ETHERNET_EVENT_STOP → ETH_STOP_BIT + - ETHERNET_EVENT_CONNECTED → ETH_CONNECT_BIT + +- **`eth_test_got_ip_event_handler()`**: Handler for IP_EVENT_ETH_GOT_IP events. Automatically registered by `setUp()` when `[esp-netif]` marker is used. Sets ETH_GOT_IP_BIT in the event group and logs IP configuration. + +### Usage Example + +```c +TEST_CASE("ethernet basic test", "[ethernet][esp-netif]") +{ + // Get handles initialized by setUp() + esp_eth_handle_t eth_handle = eth_test_get_eth_handle(); + EventGroupHandle_t eth_event_group = eth_test_get_default_event_group(); + esp_netif_t *netif = eth_test_get_netif(); + + EventBits_t bits = 0; + + // Start Ethernet driver + TEST_ESP_OK(esp_eth_start(eth_handle)); + + // Wait for Ethernet to start + bits = xEventGroupWaitBits(eth_event_group, ETH_START_BIT, true, true, + pdMS_TO_TICKS(ETH_START_TIMEOUT_MS)); + TEST_ASSERT((bits & ETH_START_BIT) == ETH_START_BIT); + + // Wait for link connection + bits = xEventGroupWaitBits(eth_event_group, ETH_CONNECT_BIT, true, true, + pdMS_TO_TICKS(ETH_CONNECT_TIMEOUT_MS)); + TEST_ASSERT((bits & ETH_CONNECT_BIT) == ETH_CONNECT_BIT); + + // Wait for IP address (only when [esp-netif] is used) + bits = xEventGroupWaitBits(eth_event_group, ETH_GOT_IP_BIT, true, true, + pdMS_TO_TICKS(ETH_GET_IP_TIMEOUT_MS)); + TEST_ASSERT((bits & ETH_GOT_IP_BIT) == ETH_GOT_IP_BIT); + + // Test code here... + + // Stop Ethernet driver + TEST_ESP_OK(esp_eth_stop(eth_handle)); + + // Wait for stop event + 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); + + // tearDown() will automatically clean up everything +} +``` \ No newline at end of file diff --git a/components/esp_eth/test_apps/main/CMakeLists.txt b/components/esp_eth/test_apps/main/CMakeLists.txt index ff51914b32..81ce01987d 100644 --- a/components/esp_eth/test_apps/main/CMakeLists.txt +++ b/components/esp_eth/test_apps/main/CMakeLists.txt @@ -1,10 +1,11 @@ -idf_component_register(SRCS "esp_eth_test_apps.c" +idf_component_register(SRCS "esp_eth_test_main.c" + "esp_eth_test_apps.c" "esp_eth_test_l2.c" + "esp_eth_test_utils.c" "esp_eth_test_esp_emac.c" - "esp_eth_test_common.c" "esp_eth_test_main.c" INCLUDE_DIRS "." PRIV_INCLUDE_DIRS "." - PRIV_REQUIRES unity test_utils esp_eth esp_netif esp_http_client esp_driver_gpio + PRIV_REQUIRES unity esp_eth esp_netif esp_http_client esp_driver_gpio EMBED_TXTFILES dl_espressif_com_root_cert.pem WHOLE_ARCHIVE) diff --git a/components/esp_eth/test_apps/main/Kconfig.projbuild b/components/esp_eth/test_apps/main/Kconfig.projbuild index 3314787871..9c6ffa81a7 100644 --- a/components/esp_eth/test_apps/main/Kconfig.projbuild +++ b/components/esp_eth/test_apps/main/Kconfig.projbuild @@ -1,105 +1,91 @@ menu "esp_eth TEST_APPS Configuration" - choice TARGET_ETH_CONFIG - prompt "Ethernet peripheral device" - default TARGET_USE_INTERNAL_ETHERNET + config ETH_TEST_UNITY_TEST_TASK_PRIO + int "Unity test task priority" + range 0 25 + default 5 help - Select type of Ethernet interface. + Unity test task priority. - config TARGET_USE_INTERNAL_ETHERNET - depends on SOC_EMAC_SUPPORTED - select ETH_USE_ESP32_EMAC - bool "Internal EMAC" - help - Use internal Ethernet MAC controller. + config ETH_TEST_UNITY_TEST_TASK_STACK + int "Unity test task stack size" + default 4096 + help + Unity test task stack size in B. + config ETH_TEST_MAC_ADDR_UI + bool "Expect Universal & Individual MAC address" + default y + help + Enable this option to expect Universal & Individual MAC address. + This should be disabled for SPI Ethernet devices. - config TARGET_USE_SPI_ETHERNET - bool "SPI Ethernet" - select ETH_USE_SPI_ETHERNET - help - Use external SPI-Ethernet module(s). - endchoice # TARGET_ETH_CONFIG + config ETH_TEST_PHY_ADDRESS_DISABLED + bool "Disable PHY address test" + default n + help + Disable PHY address testing. + This should be disabled for SPI Ethernet devices. - if TARGET_USE_INTERNAL_ETHERNET - choice TARGET_ETH_PHY_DEVICE - prompt "Ethernet PHY" - default TARGET_ETH_PHY_DEVICE_IP101 - help - Select one of the devices listed here + config ETH_TEST_LOOPBACK_DISABLED + bool "Disable loopback test" + default n + help + Disable loopback testing as some chips may not support it. - config TARGET_ETH_PHY_DEVICE_IP101 - bool "IP101" - config TARGET_ETH_PHY_DEVICE_LAN8720 - bool "LAN8720" - config TARGET_ETH_PHY_DEVICE_KSZ8041 - bool "KSZ8041" - config TARGET_ETH_PHY_DEVICE_RTL8201 - bool "RTL8201" - config TARGET_ETH_PHY_DEVICE_DP83848 - bool "DP83848" - endchoice # TARGET_ETH_PHY_DEVICE + config ETH_TEST_10MB_LOOPBACK_DISABLED + depends on !ETH_TEST_LOOPBACK_DISABLED + bool "Disable 10MB loopback test" + default n + help + Disable 10MB loopback testing as some chips may not support it. - config TARGET_USE_DEFAULT_EMAC_CONFIG - default y - bool "Use default EMAC config" + config ETH_TEST_10MB_LOOPBACK_IGNORE_FAILURES + depends on !ETH_TEST_LOOPBACK_DISABLED + bool "Ignore 10MB loopback test failures" + default y + help + Ignore failures in 10MB loopback tests. - 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 + config ETH_TEST_LOOPBACK_WITH_AUTONEGOTIATION_DISABLED + depends on !ETH_TEST_LOOPBACK_DISABLED + bool "Disable loopback with autonegotiation test" + default n + help + Disable loopback testing with autonegotiation. - config TARGET_RMII_CLK_OUT - bool "REF RMII CLK output" - default n + config ETH_TEST_FILL_RX_BUFFER_ITERATIONS + int "Number of iterations for fill RX buffer test" + range 1 100 + default 10 + help + Number of iterations to fill RX buffer of module under test. + For internal EMAC, it should be set as ETH_DMA_RX_BUFFER_NUM. + For SPI modules, it should be set as RX_MEM_SIZE / ETH_MAX_PACKET_SIZE, where RX_MEM_SIZE is + module specific RX buffer size in bytes as defined in datasheet. - if TARGET_RMII_CLK_OUT - config TARGET_RMII_CLK_OUT_GPIO - int "REF RMII CLK Output GPIO" - default 23 + config ETH_TEST_LAN8720_ERRATA_ENABLED + bool "Enable LAN8720 errata workaround" + default n + help + Enable workaround for LAN8720 errata. + Enable only when LAN8720 is under test!! - config TARGET_RMII_CLK_IN_GPIO - int "REF RMII CLK Input GPIO" - default 32 - endif # TARGET_RMII_CLK_OUT + config ETH_TEST_W5500_IP6_MCAST_DEVIATION_ENABLED + bool "Enable W5500 IPv6 multicast deviation test" + default n + help + W5500 always receives IPv6 multicast packets, even if the filter is set to block multicast. + Enable only when W5500 is under test!! - endif # TARGET_USE_INTERNAL_ETHERNET - - if TARGET_USE_SPI_ETHERNET - choice TARGET_ETH_SPI_DEVICE - prompt "Ethernet SPI Module" - default TARGET_ETH_PHY_DEVICE_W5500 - help - Select one of the devices listed here - - config TARGET_ETH_PHY_DEVICE_W5500 - bool "W5500" - select ETH_SPI_ETHERNET_W5500 - config TARGET_ETH_PHY_DEVICE_KSZ8851SNL - bool "KSZ8851SNL" - select ETH_SPI_ETHERNET_KSZ8851SNL - config TARGET_ETH_PHY_DEVICE_DM9051 - bool "DM9051" - select ETH_SPI_ETHERNET_DM9051 - endchoice # TARGET_ETH_SPI_DEVICE - - config TARGET_SPI_CLOCK_MHZ - int "SPI clock speed (MHz)" - range 5 80 - default 20 - help - Set the clock speed (MHz) of SPI interface. - - config TARGET_ETH_SPI_POLL_MS - int "SPI Ethernet Polling period in msec" - default 0 - help - SPI Ethernet module polling period. - - endif # TARGET_USE_SPI_ETHERNET + config ETH_TEST_STRESS_TEST_TASK_PRIO + int "Start/stop stress test task priority" + range -1 25 + default -1 + help + The Rx Task may occupy all the resources under heavy Rx traffic and it would not be possible + to access the Ethernet module to stop it. Therefore, the test task priority can be set higher than + the Rx task to be able to preempt the Rx task. + This option should be set for SPI Ethernet modules (>15), otherwise set -1 to use default priority. endmenu diff --git a/components/esp_eth/test_apps/main/esp_eth_test_apps.c b/components/esp_eth/test_apps/main/esp_eth_test_apps.c index 886d21df80..bda8a0730d 100644 --- a/components/esp_eth/test_apps/main/esp_eth_test_apps.c +++ b/components/esp_eth/test_apps/main/esp_eth_test_apps.c @@ -12,7 +12,7 @@ #include "esp_log.h" #include "esp_http_client.h" #include "esp_rom_md5.h" -#include "esp_eth_test_common.h" +#include "esp_eth_test_utils.h" #include "unity.h" #define LOOPBACK_TEST_PACKET_SIZE 256 @@ -26,35 +26,19 @@ extern const char dl_espressif_com_root_cert_pem_end[] asm("_binary_dl_espress static md5_context_t md5_context; static uint8_t digest[16]; -static esp_err_t test_uninstall_driver(esp_eth_handle_t eth_hdl, uint32_t ms_to_wait) +// Basic test to verify that the Ethernet driver can be initialized and deinitialized +TEST_CASE("ethernet init/deinit test", "[ethernet],[skip_setup_teardown]") { - int i = 0; - ms_to_wait += 100; - for (i = 0; i < ms_to_wait / 100; i++) { - vTaskDelay(pdMS_TO_TICKS(100)); - if (esp_eth_driver_uninstall(eth_hdl) == ESP_OK) { - break; - } - } - if (i < ms_to_wait / 100) { - return ESP_OK; - } else { - return ESP_FAIL; - } + esp_eth_handle_t eth_handle = NULL; + + TEST_ESP_OK(esp_eth_test_eth_init(ð_handle)); + TEST_ESP_OK(esp_eth_test_eth_deinit(eth_handle)); } TEST_CASE("ethernet io test", "[ethernet]") { - 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); + // get handles from common module initialized by setUp() + esp_eth_handle_t eth_handle = eth_test_get_eth_handle(); /* get default MAC address */ uint8_t mac_addr[ETH_ADDR_LEN]; @@ -65,8 +49,10 @@ TEST_CASE("ethernet io test", "[ethernet]") TEST_ASSERT(mac_addr[0] != 0); // *** SPI Ethernet modules deviation *** // Rationale: The SPI Ethernet modules don't have a burned default factory MAC address hence local MAC is used -#if !CONFIG_TARGET_USE_SPI_ETHERNET +#if CONFIG_ETH_TEST_MAC_ADDR_UI TEST_ASSERT_BITS(0b00000011, 0b00, mac_addr[0]); // Check UL&IG, should be UI +#else + TEST_ASSERT_BITS(0b00000011, 0b10, mac_addr[0]); // Check UL&IG, should be U #endif /* set different MAC address */ @@ -82,114 +68,23 @@ TEST_CASE("ethernet io test", "[ethernet]") // *** SPI Ethernet modules deviation *** // Rationale: SPI Ethernet modules PHYs and MACs are statically configured at one die, hence there is no need for PHY address // from user's point of view -#if !CONFIG_TARGET_USE_SPI_ETHERNET +#if CONFIG_ETH_TEST_PHY_ADDRESS_DISABLED /* get PHY address */ int phy_addr = -1; TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_PHY_ADDR, &phy_addr)); ESP_LOGI(TAG, "Ethernet PHY Address: %d", phy_addr); TEST_ASSERT(phy_addr >= 0 && phy_addr <= 31); #endif - TEST_ESP_OK(esp_eth_driver_uninstall(eth_handle)); - TEST_ESP_OK(phy->del(phy)); - TEST_ESP_OK(mac->del(mac)); - extra_cleanup(); } -#ifdef CONFIG_TARGET_ETH_PHY_DEVICE_LAN8720 -esp_err_t set_phy_reg_bits(esp_eth_handle_t eth_handle, uint32_t reg_addr, uint32_t bitmask, uint32_t max_attempts) -{ - esp_eth_phy_reg_rw_data_t reg = { - .reg_addr = reg_addr, - .reg_value_p = NULL - }; - uint32_t reg_value, reg_value_rb; - - for (uint32_t i = 0; i < max_attempts; i++) { - reg.reg_value_p = ®_value; - esp_err_t ret = esp_eth_ioctl(eth_handle, ETH_CMD_READ_PHY_REG, ®); - if (ret != ESP_OK) { - return ret; - } - reg_value |= bitmask; - ret = esp_eth_ioctl(eth_handle, ETH_CMD_WRITE_PHY_REG, ®); - if (ret != ESP_OK) { - return ret; - } - reg.reg_value_p = ®_value_rb; - ret = esp_eth_ioctl(eth_handle, ETH_CMD_READ_PHY_REG, ®); - if (ret != ESP_OK) { - return ret; - } - // Check if the write was successful - if ((reg_value_rb & bitmask) == bitmask) { - return ESP_OK; - } - // Add delay only if not the last attempt - if (i < max_attempts - 1) { - ESP_LOGW(TAG, "Setting PHY register %04"PRIx32" failed, retrying... (attempt %"PRIu32" of %"PRIu32")", reg_addr, i + 1, max_attempts); - vTaskDelay(pdMS_TO_TICKS(10)); - } - } - return ESP_ERR_TIMEOUT; -} - -esp_err_t clear_phy_reg_bits(esp_eth_handle_t eth_handle, uint32_t reg_addr, uint32_t bitmask, uint32_t max_attempts) -{ - esp_eth_phy_reg_rw_data_t reg = { - .reg_addr = reg_addr, - .reg_value_p = NULL - }; - uint32_t reg_value, reg_value_rb; - - for (uint32_t i = 0; i < max_attempts; i++) { - reg.reg_value_p = ®_value; - esp_err_t ret = esp_eth_ioctl(eth_handle, ETH_CMD_READ_PHY_REG, ®); - if (ret != ESP_OK) { - return ret; - } - reg_value &= ~bitmask; - ret = esp_eth_ioctl(eth_handle, ETH_CMD_WRITE_PHY_REG, ®); - if (ret != ESP_OK) { - return ret; - } - reg.reg_value_p = ®_value_rb; - ret = esp_eth_ioctl(eth_handle, ETH_CMD_READ_PHY_REG, ®); - if (ret != ESP_OK) { - return ret; - } - // Check if the write was successful - if ((reg_value_rb & bitmask) == 0) { - return ESP_OK; - } - // Add delay only if not the last attempt - if (i < max_attempts - 1) { - ESP_LOGW(TAG, "Clearing PHY register %04"PRIx32" failed, retrying... (attempt %"PRIu32" of %"PRIu32")", reg_addr, i + 1, max_attempts); - vTaskDelay(pdMS_TO_TICKS(10)); - } - } - return ESP_ERR_TIMEOUT; -} -#endif // CONFIG_TARGET_ETH_PHY_DEVICE_LAN8720 - // 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()); - 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); - TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_group)); + // get handles from common module initialized by setUp() + esp_eth_handle_t eth_handle = eth_test_get_eth_handle(); + EventGroupHandle_t eth_event_group = eth_test_get_default_event_group(); + EventBits_t bits = 0; // 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)); // wait for connection start @@ -244,8 +139,8 @@ TEST_CASE("ethernet io speed/duplex/autonegotiation", "[ethernet]") // *** LAN8720 deviation *** // Rationale: When the device is in manual 100BASE-TX or 10BASE-T modes with Auto-MDIX enabled, the PHY does not link to a // link partner that is configured for auto-negotiation. See LAN8720 errata for more details. -#ifdef CONFIG_TARGET_ETH_PHY_DEVICE_LAN8720 - TEST_ESP_OK(set_phy_reg_bits(eth_handle, 27, 0x8000, 3)); +#if CONFIG_ETH_TEST_LAN8720_ERRATA_ENABLED + TEST_ESP_OK(eth_test_set_phy_reg_bits(eth_handle, 27, 0x8000, 3)); #endif // start the driver and wait for connection establish @@ -330,7 +225,7 @@ TEST_CASE("ethernet io speed/duplex/autonegotiation", "[ethernet]") // *** LAN8720 deviation *** // Rationale: See above #ifdef CONFIG_TARGET_ETH_PHY_DEVICE_LAN8720 - TEST_ESP_OK(clear_phy_reg_bits(eth_handle, 27, 0x8000, 3)); + TEST_ESP_OK(eth_test_clear_phy_reg_bits(eth_handle, 27, 0x8000, 3)); #endif esp_eth_start(eth_handle); @@ -352,16 +247,11 @@ TEST_CASE("ethernet io speed/duplex/autonegotiation", "[ethernet]") /* wait for connection stop */ 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); - 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); } +// use static semaphore to avoid dynamic allocation and so need for de-allocation in case of test failure static SemaphoreHandle_t loopback_test_case_data_received; +static StaticSemaphore_t loopback_test_case_data_received_buffer; 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); @@ -372,54 +262,43 @@ static esp_err_t loopback_test_case_incoming_handler(esp_eth_handle_t eth_handle TEST_CASE("ethernet io loopback", "[ethernet]") { - loopback_test_case_data_received = xSemaphoreCreateBinary(); - // init everything else + // get handles from common module initialized by setUp() + esp_eth_handle_t eth_handle = eth_test_get_eth_handle(); + EventGroupHandle_t eth_event_group = eth_test_get_default_event_group(); + + loopback_test_case_data_received = xSemaphoreCreateBinaryStatic(&loopback_test_case_data_received_buffer); 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 +// *** PHY loopback not supported deviation *** +// Rationale: Some PHYs do not support loopback at all +#if CONFIG_ETH_TEST_LOOPBACK_DISABLED TEST_ASSERT(esp_eth_ioctl(eth_handle, ETH_CMD_S_PHY_LOOPBACK, &loopback_en) == ESP_ERR_NOT_SUPPORTED); - goto cleanup; + return; #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_100M, ETH_SPEED_10M}; - emac_frame_t* test_packet = malloc(LOOPBACK_TEST_PACKET_SIZE); + emac_frame_t* test_packet = (emac_frame_t*)eth_test_alloc(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_KSZ8041) || defined(CONFIG_TARGET_ETH_PHY_DEVICE_DM9051) +// *** 10 Mbps loopback disabled deviation *** +// Rationale: Some PHYs do not support loopback at 10 Mbps +#if CONFIG_ETH_TEST_10MB_LOOPBACK_DISABLED 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; @@ -465,7 +344,11 @@ TEST_CASE("ethernet io loopback", "[ethernet]") break; } } +// *** 10 Mbps loopback ignore failures deviation *** +// Rationale: 10 Mbps loopback may be supported by PHY but the test is not reliable. +#if !CONFIG_ETH_TEST_10MB_LOOPBACK_IGNORE_FAILURES TEST_ASSERT_LESS_THAN(3, i); +#endif } else { TEST_ASSERT(xSemaphoreTake(loopback_test_case_data_received, pdMS_TO_TICKS(1000)) == pdTRUE); } @@ -486,12 +369,12 @@ TEST_CASE("ethernet io loopback", "[ethernet]") // 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_LAN8720) +// *** Loopback with autonegotiation deviation *** +// Rationale: Some PHYs do not support autonegotiation with loopback enabled. +#if CONFIG_ETH_TEST_LOOPBACK_WITH_AUTONEGOTIATION_DISABLED TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, esp_eth_ioctl(eth_handle, ETH_CMD_S_AUTONEGO, &auto_nego_en)); - goto cleanup; + // Test passes - these devices correctly report autonegotiation is not supported with loopback + return; #endif TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_S_AUTONEGO, &auto_nego_en)); TEST_ESP_OK(esp_eth_start(eth_handle)); @@ -500,45 +383,20 @@ TEST_CASE("ethernet io loopback", "[ethernet]") 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_LAN8720) || \ - 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)); -#ifndef CONFIG_TARGET_ETH_PHY_DEVICE_W5500 -// only unregister events if the device != W5500, since w5500 doesn't support loopback and we don't register the event - TEST_ESP_OK(esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler)); -#endif - TEST_ESP_OK(esp_event_loop_delete_default()); - extra_cleanup(); - vEventGroupDelete(eth_event_group); } TEST_CASE("ethernet event test", "[ethernet]") { + // get handles from common module initialized by setUp() + esp_eth_handle_t eth_handle = eth_test_get_eth_handle(); + EventGroupHandle_t eth_event_group = eth_test_get_default_event_group(); + 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)); - esp_eth_mac_t *mac = mac_init(NULL, NULL); - 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); // this test only test layer2 event, so don't need to register input callback (i.e. esp_eth_update_input_path) TEST_ESP_OK(esp_eth_start(eth_handle)); /* wait for connection start */ @@ -552,41 +410,15 @@ TEST_CASE("ethernet event test", "[ethernet]") /* wait for connection stop */ 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); - /* driver should be uninstalled within 2 seconds */ - TEST_ESP_OK(test_uninstall_driver(eth_handle, 2000)); - 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 dhcp test", "[ethernet]") +TEST_CASE("ethernet dhcp test", "[ethernet][esp-netif]") { + // get handles from common module initialized by setUp() + esp_eth_handle_t eth_handle = eth_test_get_eth_handle(); + EventGroupHandle_t eth_event_group = eth_test_get_default_event_group(); + EventBits_t bits = 0; - EventGroupHandle_t eth_event_group = xEventGroupCreate(); - TEST_ASSERT(eth_event_group != NULL); - test_case_uses_tcpip(); - TEST_ESP_OK(esp_event_loop_create_default()); - // create TCP/IP netif - esp_netif_config_t netif_cfg = ESP_NETIF_DEFAULT_ETH(); - esp_netif_t *eth_netif = esp_netif_new(&netif_cfg); - esp_eth_mac_t *mac = mac_init(NULL, NULL); - 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; - // install Ethernet driver - TEST_ESP_OK(esp_eth_driver_install(ð_config, ð_handle)); - extra_eth_config(eth_handle); - // combine driver with netif - esp_eth_netif_glue_handle_t glue = esp_eth_new_netif_glue(eth_handle); - TEST_ESP_OK(esp_netif_attach(eth_netif, glue)); - // register user defined event handers - TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_group)); - TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, eth_event_group)); // start Ethernet driver TEST_ESP_OK(esp_eth_start(eth_handle)); /* wait for IP lease */ @@ -597,44 +429,15 @@ TEST_CASE("ethernet dhcp test", "[ethernet]") /* wait for connection stop */ 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); - TEST_ESP_OK(esp_eth_del_netif_glue(glue)); - /* driver should be uninstalled within 2 seconds */ - TEST_ESP_OK(test_uninstall_driver(eth_handle, 2000)); - TEST_ESP_OK(phy->del(phy)); - TEST_ESP_OK(mac->del(mac)); - TEST_ESP_OK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, got_ip_event_handler)); - TEST_ESP_OK(esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler)); - esp_netif_destroy(eth_netif); - TEST_ESP_OK(esp_event_loop_delete_default()); - extra_cleanup(); - vEventGroupDelete(eth_event_group); } -TEST_CASE("ethernet start/stop stress test with IP stack", "[ethernet]") +TEST_CASE("ethernet start/stop stress test with IP stack", "[ethernet][esp-netif]") { + // get handles from common module initialized by setUp() + esp_eth_handle_t eth_handle = eth_test_get_eth_handle(); + EventGroupHandle_t eth_event_group = eth_test_get_default_event_group(); + EventBits_t bits = 0; - EventGroupHandle_t eth_event_group = xEventGroupCreate(); - TEST_ASSERT(eth_event_group != NULL); - test_case_uses_tcpip(); - TEST_ESP_OK(esp_event_loop_create_default()); - // create TCP/IP netif - esp_netif_config_t netif_cfg = ESP_NETIF_DEFAULT_ETH(); - esp_netif_t *eth_netif = esp_netif_new(&netif_cfg); - esp_eth_mac_t *mac = mac_init(NULL, NULL); - 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; - // install Ethernet driver - TEST_ESP_OK(esp_eth_driver_install(ð_config, ð_handle)); - extra_eth_config(eth_handle); - // combine driver with netif - esp_eth_netif_glue_handle_t glue = esp_eth_new_netif_glue(eth_handle); - TEST_ESP_OK(esp_netif_attach(eth_netif, glue)); - // register user defined event handers - TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_group)); - TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, eth_event_group)); for(int j = 0; j < 2; j++) { // run the start/stop test with disabled auto-negotiation @@ -648,8 +451,8 @@ TEST_CASE("ethernet start/stop stress test with IP stack", "[ethernet]") // *** LAN8720 deviation *** // Rationale: When the device is in manual 100BASE-TX or 10BASE-T modes with Auto-MDIX enabled, the PHY does not link to a // link partner that is configured for auto-negotiation. See LAN8720 errata for more details. -#ifdef CONFIG_TARGET_ETH_PHY_DEVICE_LAN8720 - TEST_ESP_OK(set_phy_reg_bits(eth_handle, 27, 0x8000, 3)); +#if CONFIG_ETH_TEST_LAN8720_ERRATA_ENABLED + TEST_ESP_OK(eth_test_set_phy_reg_bits(eth_handle, 27, 0x8000, 3)); #endif } for (int i = 0; i < 10; i++) { @@ -665,18 +468,6 @@ TEST_CASE("ethernet start/stop stress test with IP stack", "[ethernet]") TEST_ASSERT((bits & ETH_STOP_BIT) == ETH_STOP_BIT); } } - - TEST_ESP_OK(esp_eth_del_netif_glue(glue)); - /* driver should be uninstalled within 2 seconds */ - TEST_ESP_OK(test_uninstall_driver(eth_handle, 2000)); - TEST_ESP_OK(phy->del(phy)); - TEST_ESP_OK(mac->del(mac)); - TEST_ESP_OK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, got_ip_event_handler)); - TEST_ESP_OK(esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler)); - esp_netif_destroy(eth_netif); - TEST_ESP_OK(esp_event_loop_delete_default()); - extra_cleanup(); - vEventGroupDelete(eth_event_group); } esp_err_t http_event_handle(esp_http_client_event_t *evt) @@ -726,31 +517,13 @@ static void eth_start_download(void) esp_rom_md5_final(digest, &md5_context); } -TEST_CASE("ethernet download test", "[ethernet]") +TEST_CASE("ethernet download test", "[ethernet][esp-netif]") { + // get handles from common module initialized by setUp() + esp_eth_handle_t eth_handle = eth_test_get_eth_handle(); + EventGroupHandle_t eth_event_group = eth_test_get_default_event_group(); + EventBits_t bits = 0; - EventGroupHandle_t eth_event_group = xEventGroupCreate(); - TEST_ASSERT(eth_event_group != NULL); - test_case_uses_tcpip(); - TEST_ESP_OK(esp_event_loop_create_default()); - // create TCP/IP netif - esp_netif_config_t netif_cfg = ESP_NETIF_DEFAULT_ETH(); - esp_netif_t *eth_netif = esp_netif_new(&netif_cfg); - esp_eth_mac_t *mac = mac_init(NULL, NULL); - 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; - // install Ethernet driver - TEST_ESP_OK(esp_eth_driver_install(ð_config, ð_handle)); - extra_eth_config(eth_handle); - // combine driver with netif - esp_eth_netif_glue_handle_t glue = esp_eth_new_netif_glue(eth_handle); - TEST_ESP_OK(esp_netif_attach(eth_netif, glue)); - // register user defined event handers - TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_group)); - TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, eth_event_group)); // start Ethernet driver TEST_ESP_OK(esp_eth_start(eth_handle)); /* wait for IP lease */ @@ -773,15 +546,4 @@ TEST_CASE("ethernet download test", "[ethernet]") /* wait for connection stop */ 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); - TEST_ESP_OK(esp_eth_del_netif_glue(glue)); - /* driver should be uninstalled within 2 seconds */ - TEST_ESP_OK(test_uninstall_driver(eth_handle, 2000)); - TEST_ESP_OK(phy->del(phy)); - TEST_ESP_OK(mac->del(mac)); - TEST_ESP_OK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, got_ip_event_handler)); - TEST_ESP_OK(esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler)); - esp_netif_destroy(eth_netif); - TEST_ESP_OK(esp_event_loop_delete_default()); - extra_cleanup(); - vEventGroupDelete(eth_event_group); } diff --git a/components/esp_eth/test_apps/main/esp_eth_test_common.c b/components/esp_eth/test_apps/main/esp_eth_test_common.c deleted file mode 100644 index 392bccb73e..0000000000 --- a/components/esp_eth/test_apps/main/esp_eth_test_common.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ -#include "freertos/FreeRTOS.h" -#include "freertos/event_groups.h" -#include "esp_event.h" -#include "esp_log.h" -#if CONFIG_TARGET_USE_SPI_ETHERNET -#include "driver/spi_master.h" -#include "driver/gpio.h" -#include "esp_mac.h" -#endif // CONFIG_TARGET_USE_SPI_ETHERNET -#include "sdkconfig.h" -#include "esp_eth_test_common.h" - -#if CONFIG_TARGET_USE_SPI_ETHERNET -#define DEFAULT_TARGET_SPI_HOST 1 -#define DEFAULT_TARGET_SPI_MISO_GPIO 12 -#define DEFAULT_TARGET_SPI_MOSI_GPIO 13 -#define DEFAULT_TARGET_SPI_SCLK_GPIO 14 -#define DEFAULT_TARGET_SPI_CS_GPIO 15 -#endif // CONFIG_TARGET_USE_SPI_ETHERNET - -static const char *TAG = "esp32_eth_test_common"; - -esp_eth_mac_t *mac_init(void *vendor_emac_config, eth_mac_config_t *mac_config) -{ - esp_eth_mac_t *mac = NULL; - - eth_mac_config_t mac_config_default = ETH_MAC_DEFAULT_CONFIG(); - if (mac_config == NULL) { - mac_config = &mac_config_default; - } -#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_gpio.mdc_num = CONFIG_TARGET_IO_MDC; - esp32_emac_config.smi_gpio.mdio_num = CONFIG_TARGET_IO_MDIO; -#endif // CONFIG_TARGET_USE_DEFAULT_EMAC_CONFIG -#if CONFIG_TARGET_RMII_CLK_OUT - esp32_emac_config.clock_config.rmii.clock_mode = EMAC_CLK_OUT; - esp32_emac_config.clock_config.rmii.clock_gpio = CONFIG_TARGET_RMII_CLK_OUT_GPIO; - esp32_emac_config.clock_config_out_in.rmii.clock_mode = EMAC_CLK_EXT_IN; - esp32_emac_config.clock_config_out_in.rmii.clock_gpio = CONFIG_TARGET_RMII_CLK_IN_GPIO; -#endif // CONFIG_TARGET_TEST_RMII_CLK_OUT - if (vendor_emac_config == NULL) { - vendor_emac_config = &esp32_emac_config; - } - mac = esp_eth_mac_new_esp32(vendor_emac_config, mac_config); -#elif CONFIG_TARGET_USE_SPI_ETHERNET - // Install GPIO ISR handler to be able to service SPI Eth modules interrupts - gpio_install_isr_service(0); - - spi_bus_config_t buscfg = { - .miso_io_num = DEFAULT_TARGET_SPI_MISO_GPIO, - .mosi_io_num = DEFAULT_TARGET_SPI_MOSI_GPIO, - .sclk_io_num = DEFAULT_TARGET_SPI_SCLK_GPIO, - .quadwp_io_num = -1, - .quadhd_io_num = -1, - }; - TEST_ESP_OK(spi_bus_initialize(DEFAULT_TARGET_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO)); - spi_device_interface_config_t devcfg = { - .mode = 0, - .spics_io_num = DEFAULT_TARGET_SPI_CS_GPIO, - .clock_speed_hz = CONFIG_TARGET_SPI_CLOCK_MHZ * 1000 * 1000, - .queue_size = 20 - }; -#if CONFIG_TARGET_ETH_PHY_DEVICE_W5500 - eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(DEFAULT_TARGET_SPI_HOST, &devcfg); -#if CONFIG_TARGET_ETH_SPI_POLL_MS > 0 - w5500_config.int_gpio_num = -1; - w5500_config.poll_period_ms = CONFIG_TARGET_ETH_SPI_POLL_MS; -#endif - if (vendor_emac_config == NULL) { - vendor_emac_config = &w5500_config; - } - mac = esp_eth_mac_new_w5500(vendor_emac_config, mac_config); -#elif CONFIG_TARGET_ETH_PHY_DEVICE_KSZ8851SNL - eth_ksz8851snl_config_t ksz8851snl_config = ETH_KSZ8851SNL_DEFAULT_CONFIG(DEFAULT_TARGET_SPI_HOST, &devcfg); -#if CONFIG_TARGET_ETH_SPI_POLL_MS > 0 - ksz8851snl_config.int_gpio_num = -1; - ksz8851snl_config.poll_period_ms = CONFIG_TARGET_ETH_SPI_POLL_MS; -#endif - if (vendor_emac_config == NULL) { - vendor_emac_config = &ksz8851snl_config; - } - mac = esp_eth_mac_new_ksz8851snl(vendor_emac_config, mac_config); -#elif CONFIG_TARGET_ETH_PHY_DEVICE_DM9051 - eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(DEFAULT_TARGET_SPI_HOST, &devcfg); -#if CONFIG_TARGET_ETH_SPI_POLL_MS > 0 - dm9051_config.int_gpio_num = -1; - dm9051_config.poll_period_ms = CONFIG_TARGET_ETH_SPI_POLL_MS; -#endif - if (vendor_emac_config == NULL) { - vendor_emac_config = &dm9051_config ; - } - mac = esp_eth_mac_new_dm9051(vendor_emac_config, mac_config); -#endif // CONFIG_TARGET_ETH_PHY_DEVICE_W5500 -#endif // CONFIG_TARGET_USE_INTERNAL_ETHERNET - return mac; -} - -esp_eth_phy_t *phy_init(eth_phy_config_t *phy_config) -{ - esp_eth_phy_t *phy = NULL; - eth_phy_config_t phy_config_default = ETH_PHY_DEFAULT_CONFIG(); - if (phy_config == NULL) { - phy_config = &phy_config_default; - } -#if CONFIG_TARGET_USE_INTERNAL_ETHERNET - phy_config->phy_addr = ESP_ETH_PHY_ADDR_AUTO; -#if CONFIG_TARGET_ETH_PHY_DEVICE_IP101 - phy = esp_eth_phy_new_ip101(phy_config); - ESP_LOGI(TAG, "DUT PHY: IP101"); -#elif CONFIG_TARGET_ETH_PHY_DEVICE_LAN8720 - phy = esp_eth_phy_new_lan87xx(phy_config); - ESP_LOGI(TAG, "DUT PHY: LAN8720"); -#elif CONFIG_TARGET_ETH_PHY_DEVICE_KSZ8041 - phy = esp_eth_phy_new_ksz80xx(phy_config); - ESP_LOGI(TAG, "DUT PHY: KSZ8041"); -#elif CONFIG_TARGET_ETH_PHY_DEVICE_RTL8201 - phy = esp_eth_phy_new_rtl8201(phy_config); - ESP_LOGI(TAG, "DUT PHY: RTL8201"); -#elif CONFIG_TARGET_ETH_PHY_DEVICE_DP83848 - phy = esp_eth_phy_new_dp83848(phy_config); - ESP_LOGI(TAG, "DUT PHY: DP83848"); -#endif // CONFIG_TARGET_ETH_PHY_DEVICE_IP101 -#elif CONFIG_TARGET_USE_SPI_ETHERNET - phy_config->reset_gpio_num = -1; -#if CONFIG_TARGET_ETH_PHY_DEVICE_W5500 - phy = esp_eth_phy_new_w5500(phy_config); - ESP_LOGI(TAG, "DUT PHY: W5500"); -#elif CONFIG_TARGET_ETH_PHY_DEVICE_KSZ8851SNL - phy = esp_eth_phy_new_ksz8851snl(phy_config); - ESP_LOGI(TAG, "DUT PHY: KSZ8851SNL"); -#elif CONFIG_TARGET_ETH_PHY_DEVICE_DM9051 - phy = esp_eth_phy_new_dm9051(phy_config); - ESP_LOGI(TAG, "DUT PHY: DM9051"); -#endif // CONFIG_TARGET_ETH_PHY_DEVICE_W5500 -#endif // CONFIG_TARGET_USE_INTERNAL_ETHERNET - return phy; -} - -void extra_eth_config(esp_eth_handle_t eth_handle) -{ -// *** SPI Ethernet modules deviation *** -// Rationale: The SPI Ethernet modules don't have a burned default factory MAC address -#if CONFIG_TARGET_USE_SPI_ETHERNET - uint8_t base_mac_addr[ETH_ADDR_LEN]; - TEST_ESP_OK(esp_efuse_mac_get_default(base_mac_addr)); - uint8_t local_mac[ETH_ADDR_LEN]; - TEST_ESP_OK(esp_derive_local_mac(local_mac, base_mac_addr)); - TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_S_MAC_ADDR, local_mac)); -#endif -} - -void extra_cleanup(void) -{ -#if CONFIG_TARGET_USE_SPI_ETHERNET - TEST_ESP_OK(spi_bus_free(DEFAULT_TARGET_SPI_HOST)); -#endif -} - -/** Event handler for Ethernet events */ -void eth_event_handler(void *arg, esp_event_base_t event_base, - int32_t event_id, void *event_data) -{ - EventGroupHandle_t eth_event_group = (EventGroupHandle_t)arg; - switch (event_id) { - case ETHERNET_EVENT_CONNECTED: - ESP_LOGI(TAG, "Ethernet Link Up"); - xEventGroupSetBits(eth_event_group, ETH_CONNECT_BIT); - break; - case ETHERNET_EVENT_DISCONNECTED: - ESP_LOGI(TAG, "Ethernet Link Down"); - break; - case ETHERNET_EVENT_START: - ESP_LOGI(TAG, "Ethernet Started"); - xEventGroupSetBits(eth_event_group, ETH_START_BIT); - break; - case ETHERNET_EVENT_STOP: - ESP_LOGI(TAG, "Ethernet Stopped"); - xEventGroupSetBits(eth_event_group, ETH_STOP_BIT); - break; - default: - break; - } -} - -/** Event handler for IP_EVENT_ETH_GOT_IP */ -void got_ip_event_handler(void *arg, esp_event_base_t event_base, - int32_t event_id, void *event_data) -{ - EventGroupHandle_t eth_event_group = (EventGroupHandle_t)arg; - ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data; - const esp_netif_ip_info_t *ip_info = &event->ip_info; - ESP_LOGI(TAG, "Ethernet Got IP Address"); - ESP_LOGI(TAG, "~~~~~~~~~~~"); - ESP_LOGI(TAG, "ETHIP:" IPSTR, IP2STR(&ip_info->ip)); - ESP_LOGI(TAG, "ETHMASK:" IPSTR, IP2STR(&ip_info->netmask)); - ESP_LOGI(TAG, "ETHGW:" IPSTR, IP2STR(&ip_info->gw)); - ESP_LOGI(TAG, "~~~~~~~~~~~"); - xEventGroupSetBits(eth_event_group, ETH_GOT_IP_BIT); -} diff --git a/components/esp_eth/test_apps/main/esp_eth_test_common.h b/components/esp_eth/test_apps/main/esp_eth_test_common.h deleted file mode 100644 index e0b0e16a6e..0000000000 --- a/components/esp_eth/test_apps/main/esp_eth_test_common.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ -#pragma once - -#include "unity.h" -#include "test_utils.h" -#include "esp_event.h" -#include "esp_netif.h" -#include "esp_eth.h" - -#define ETH_START_BIT BIT(0) -#define ETH_STOP_BIT BIT(1) -#define ETH_CONNECT_BIT BIT(2) -#define ETH_GOT_IP_BIT BIT(3) - -#define ETH_START_TIMEOUT_MS (10000) -#define ETH_CONNECT_TIMEOUT_MS (40000) -#define ETH_STOP_TIMEOUT_MS (10000) -#define ETH_GET_IP_TIMEOUT_MS (60000) -#define ETH_DOWNLOAD_END_TIMEOUT_MS (240000) - -typedef struct { - uint8_t dest[ETH_ADDR_LEN]; - uint8_t src[ETH_ADDR_LEN]; - uint16_t proto; - uint8_t data[]; -} __attribute__((__packed__)) emac_frame_t; - -esp_eth_mac_t *mac_init(void *vendor_emac_config, eth_mac_config_t *mac_config); -esp_eth_phy_t *phy_init(eth_phy_config_t *phy_config); -void extra_eth_config(esp_eth_handle_t eth_handle); -void extra_cleanup(void); - -/** Event handler for Ethernet events */ -void eth_event_handler(void *arg, esp_event_base_t event_base, - int32_t event_id, void *event_data); -/** Event handler for IP_EVENT_ETH_GOT_IP */ -void got_ip_event_handler(void *arg, esp_event_base_t event_base, - int32_t event_id, void *event_data); diff --git a/components/esp_eth/test_apps/main/esp_eth_test_esp_emac.c b/components/esp_eth/test_apps/main/esp_eth_test_esp_emac.c index 33c9ec1410..f075e7ad69 100644 --- a/components/esp_eth/test_apps/main/esp_eth_test_esp_emac.c +++ b/components/esp_eth/test_apps/main/esp_eth_test_esp_emac.c @@ -1,14 +1,18 @@ /* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ + +// This module tests the internal ESP EMAC (Ethernet MAC) only. Tests target EMAC HAL/LL +// behavior and do not depend on a specific PHY, so they need not be run with different PHY combinations. + #include #include #include "freertos/FreeRTOS.h" #include "freertos/event_groups.h" #include "esp_log.h" -#include "esp_eth_test_common.h" +#include "esp_eth_test_utils.h" #include "hal/emac_hal.h" // for MAC_HAL_TDES0_* control bits #define ETHERTYPE_TX_STD 0x2222 // frame transmitted via _transmit_frame @@ -31,10 +35,14 @@ typedef struct static esp_err_t eth_recv_esp_emac_check_cb(esp_eth_handle_t hdl, uint8_t *buffer, uint32_t length, void *priv) { - emac_frame_t *pkt = (emac_frame_t *)buffer; + // Copy to a static buffer to avoid memory leak when TEST_ASSERT fails (`static` to avoid large stack allocation) + static uint8_t buf_copy[ETH_MAX_PACKET_SIZE]; + memcpy(buf_copy, buffer, length); + free(buffer); + emac_frame_t *pkt = (emac_frame_t *)buf_copy; + recv_esp_emac_check_info_t *recv_info = (recv_esp_emac_check_info_t *)priv; uint16_t expected_size = recv_info->expected_size + recv_info->expected_size_2 + recv_info->expected_size_3; - ESP_LOGI(TAG, "recv frame size: %" PRIu16, expected_size); TEST_ASSERT_EQUAL(expected_size, length); // frame transmitted via _transmit_frame @@ -70,37 +78,24 @@ static esp_err_t eth_recv_esp_emac_check_cb(esp_eth_handle_t hdl, uint8_t *buffe } else { TEST_FAIL(); } - memset(buffer, 0, length); - free(buffer); xSemaphoreGive(recv_info->mutex); return ESP_OK; } TEST_CASE("internal emac receive/transmit", "[esp_emac]") { + // get handles from common module initialized by setUp() + esp_eth_handle_t eth_handle = eth_test_get_eth_handle(); + EventGroupHandle_t eth_event_group = eth_test_get_default_event_group(); + + static StaticSemaphore_t recv_info_mutex_buffer; recv_esp_emac_check_info_t recv_info; - recv_info.mutex = xSemaphoreCreateBinary(); + recv_info.mutex = xSemaphoreCreateBinaryStatic(&recv_info_mutex_buffer); TEST_ASSERT_NOT_NULL(recv_info.mutex); recv_info.expected_size = 0; recv_info.expected_size_2 = 0; recv_info.expected_size_3 = 0; - 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)); - - esp_eth_mac_t *mac = mac_init(NULL, NULL); - TEST_ASSERT_NOT_NULL(mac); - esp_eth_phy_t *phy = phy_init(NULL); - TEST_ASSERT_NOT_NULL(phy); - esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); // apply default driver configuration - esp_eth_handle_t eth_handle = NULL; // after driver installed, we will get the handle of the driver - TEST_ESP_OK(esp_eth_driver_install(&config, ð_handle)); // install driver - TEST_ASSERT_NOT_NULL(eth_handle); - extra_eth_config(eth_handle); - // --------------------------------------- // Loopback greatly simplifies the test !! // --------------------------------------- @@ -112,6 +107,7 @@ TEST_CASE("internal emac receive/transmit", "[esp_emac]") // start the driver TEST_ESP_OK(esp_eth_start(eth_handle)); // wait for connection start + EventBits_t bits = 0; bits = xEventGroupWaitBits(eth_event_group, ETH_START_BIT, true, true, pdMS_TO_TICKS(ETH_START_TIMEOUT_MS)); TEST_ASSERT((bits & ETH_START_BIT) == ETH_START_BIT); // wait for connection establish @@ -119,7 +115,7 @@ TEST_CASE("internal emac receive/transmit", "[esp_emac]") TEST_ASSERT((bits & ETH_CONNECT_BIT) == ETH_CONNECT_BIT); // create test frame - emac_frame_t *test_pkt = calloc(1, ETH_MAX_PACKET_SIZE); + emac_frame_t *test_pkt = (emac_frame_t *)eth_test_alloc(ETH_MAX_PACKET_SIZE); test_pkt->proto = ETHERTYPE_TX_STD; memset(test_pkt->dest, 0xff, ETH_ADDR_LEN); // broadcast addr uint8_t local_mac_addr[ETH_ADDR_LEN] = { 0 }; @@ -194,7 +190,7 @@ TEST_CASE("internal emac receive/transmit", "[esp_emac]") ESP_LOGI(TAG, "-- Verify transmission from multiple buffers --"); uint16_t transmit_size_2; // allocated the second buffer - uint8_t *pkt_data_2 = malloc(ETH_MAX_PAYLOAD_LEN); + uint8_t *pkt_data_2 = (uint8_t *)eth_test_alloc(ETH_MAX_PAYLOAD_LEN); // fill with data (reverse order to differentiate the buffers) int j = ETH_MAX_PAYLOAD_LEN; for (int i = 0; i < ETH_MAX_PAYLOAD_LEN; i++) { @@ -242,7 +238,7 @@ TEST_CASE("internal emac receive/transmit", "[esp_emac]") uint16_t transmit_size_3 = 256; // allocated the third buffer - uint8_t *pkt_data_3 = malloc(256); + uint8_t *pkt_data_3 = (uint8_t *)eth_test_alloc(256); // fill with data for (int i = 0; i < 256; i++) { pkt_data_3[i] = i & 0xFF; @@ -279,83 +275,11 @@ TEST_CASE("internal emac receive/transmit", "[esp_emac]") TEST_ESP_OK(esp_eth_transmit_vargs(eth_handle, 3, test_pkt, transmit_size, pkt_data_2, transmit_size_2, pkt_data_3, transmit_size_3)); TEST_ASSERT(xSemaphoreTake(recv_info.mutex, pdMS_TO_TICKS(500))); - free(test_pkt); - free(pkt_data_2); - free(pkt_data_3); - // stop Ethernet driver TEST_ESP_OK(esp_eth_stop(eth_handle)); /* wait for connection stop */ 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); - 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); - vSemaphoreDelete(recv_info.mutex); -} - -TEST_CASE("internal emac interrupt priority", "[esp_emac]") -{ - EventBits_t bits = 0; - EventGroupHandle_t eth_event_group = xEventGroupCreate(); - TEST_ASSERT(eth_event_group != NULL); - test_case_uses_tcpip(); - TEST_ESP_OK(esp_event_loop_create_default()); - for (int i = -1; i <= 4; i++) { - // create TCP/IP netif - esp_netif_config_t netif_cfg = ESP_NETIF_DEFAULT_ETH(); - esp_netif_t *eth_netif = esp_netif_new(&netif_cfg); - eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG(); - esp32_emac_config.intr_priority = i; - ESP_LOGI(TAG, "set interrupt priority %i: ", i); - esp_eth_mac_t *mac = mac_init(&esp32_emac_config, NULL); - if (i >= 4) { - TEST_ASSERT_NULL(mac); - } - else { - 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; - // install Ethernet driver - TEST_ESP_OK(esp_eth_driver_install(ð_config, ð_handle)); - extra_eth_config(eth_handle); - // combine driver with netif - esp_eth_netif_glue_handle_t glue = esp_eth_new_netif_glue(eth_handle); - TEST_ESP_OK(esp_netif_attach(eth_netif, glue)); - // register user defined event handers - TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_group)); - TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, eth_event_group)); - - // start Ethernet driver - TEST_ESP_OK(esp_eth_start(eth_handle)); - /* wait for IP lease */ - bits = xEventGroupWaitBits(eth_event_group, ETH_GOT_IP_BIT, true, true, pdMS_TO_TICKS(ETH_GET_IP_TIMEOUT_MS)); - TEST_ASSERT((bits & ETH_GOT_IP_BIT) == ETH_GOT_IP_BIT); - // stop Ethernet driveresp_event_handler_unregister - TEST_ESP_OK(esp_eth_stop(eth_handle)); - /* wait for connection stop */ - 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); - - TEST_ESP_OK(esp_eth_del_netif_glue(glue)); - /* driver should be uninstalled within 2 seconds */ - 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(IP_EVENT, IP_EVENT_ETH_GOT_IP, got_ip_event_handler)); - TEST_ESP_OK(esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler)); - extra_cleanup(); - } - esp_netif_destroy(eth_netif); - } - TEST_ESP_OK(esp_event_loop_delete_default()); - vEventGroupDelete(eth_event_group); } #define TEST_FRAMES_NUM CONFIG_ETH_DMA_RX_BUFFER_NUM @@ -374,25 +298,14 @@ static esp_err_t eth_recv_esp_emac_err_check_cb(esp_eth_handle_t hdl, uint8_t *b TEST_CASE("internal emac erroneous frames", "[esp_emac]") { - SemaphoreHandle_t mutex = xSemaphoreCreateBinary(); + // get handles from common module initialized by setUp() + esp_eth_handle_t eth_handle = eth_test_get_eth_handle(); + EventGroupHandle_t eth_event_group = eth_test_get_default_event_group(); + + static StaticSemaphore_t mutex_buffer; + SemaphoreHandle_t mutex = xSemaphoreCreateBinaryStatic(&mutex_buffer); TEST_ASSERT_NOT_NULL(mutex); - 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)); - - esp_eth_mac_t *mac = mac_init(NULL, NULL); - TEST_ASSERT_NOT_NULL(mac); - esp_eth_phy_t *phy = phy_init(NULL); - TEST_ASSERT_NOT_NULL(phy); - esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); // apply default driver configuration - esp_eth_handle_t eth_handle = NULL; // after driver installed, we will get the handle of the driver - TEST_ESP_OK(esp_eth_driver_install(&config, ð_handle)); // install driver - TEST_ASSERT_NOT_NULL(eth_handle); - extra_eth_config(eth_handle); - // loopback greatly simplifies the test bool loopback_en = true; esp_eth_ioctl(eth_handle, ETH_CMD_S_PHY_LOOPBACK, &loopback_en); @@ -402,6 +315,7 @@ TEST_CASE("internal emac erroneous frames", "[esp_emac]") // start the driver TEST_ESP_OK(esp_eth_start(eth_handle)); // wait for connection start + EventBits_t bits = 0; bits = xEventGroupWaitBits(eth_event_group, ETH_START_BIT, true, true, pdMS_TO_TICKS(ETH_START_TIMEOUT_MS)); TEST_ASSERT((bits & ETH_START_BIT) == ETH_START_BIT); // wait for connection establish @@ -409,7 +323,7 @@ TEST_CASE("internal emac erroneous frames", "[esp_emac]") TEST_ASSERT((bits & ETH_CONNECT_BIT) == ETH_CONNECT_BIT); // create test frame - emac_frame_t *test_pkt = calloc(1, ETH_MAX_PACKET_SIZE); + emac_frame_t *test_pkt = (emac_frame_t *)eth_test_alloc(ETH_MAX_PACKET_SIZE); test_pkt->proto = ETHERTYPE_TX_STD; memset(test_pkt->dest, 0xff, ETH_ADDR_LEN); // broadcast addr uint8_t local_mac_addr[ETH_ADDR_LEN] = { 0 }; @@ -441,7 +355,7 @@ TEST_CASE("internal emac erroneous frames", "[esp_emac]") for (i = 0; i < s_recv_frames_cnt; i++) { emac_frame_t *recv_frame = (emac_frame_t *)s_recv_frames[i]; ESP_LOGI(TAG, "recv frame id %" PRIu8, recv_frame->data[0]); - free(recv_frame); + free(recv_frame); // free buffer allocated by emac driver } TEST_ASSERT_EQUAL_UINT8(TEST_FRAMES_NUM, s_recv_frames_cnt); s_recv_frames_cnt = 0; @@ -467,7 +381,7 @@ TEST_CASE("internal emac erroneous frames", "[esp_emac]") for (i = 0; i < s_recv_frames_cnt; i++) { emac_frame_t *recv_frame = (emac_frame_t *)s_recv_frames[i]; ESP_LOGI(TAG, "recv frame id %" PRIu8, recv_frame->data[0]); - free(recv_frame); + free(recv_frame); // free buffer allocated by emac driver } TEST_ASSERT_EQUAL_UINT8(TEST_FRAMES_NUM / 2, s_recv_frames_cnt); s_recv_frames_cnt = 0; @@ -495,7 +409,7 @@ TEST_CASE("internal emac erroneous frames", "[esp_emac]") for (i = 0; i < s_recv_frames_cnt; i++) { emac_frame_t *recv_frame = (emac_frame_t *)s_recv_frames[i]; ESP_LOGI(TAG, "recv frame id %" PRIu8, recv_frame->data[0]); - free(recv_frame); + free(recv_frame); // free buffer allocated by emac driver } TEST_ASSERT_EQUAL_INT(CONFIG_ETH_DMA_RX_BUFFER_NUM - 1, s_recv_frames_cnt); // one frame is missing due to "Descriptor Error" s_recv_frames_cnt = 0; @@ -505,33 +419,75 @@ TEST_CASE("internal emac erroneous frames", "[esp_emac]") // wait for connection stop 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); - free(test_pkt); - 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); - vSemaphoreDelete(mutex); } TEST_CASE("internal emac ref rmii clk out", "[esp_emac_clk_out]") { - esp_eth_mac_t *mac = mac_init(NULL, NULL); - 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; - // install Ethernet driver + // Ethernet driver is initialized and installed in the setUp() function // This is a simple test and it only verifies the REF RMII output CLK is configured and started, and the internal // EMAC is clocked by it. It does not verify the whole system functionality. As such, it can be executed on the same // test boards which are configured to input REF RMII CLK by default with only minor HW modification. - TEST_ESP_OK(esp_eth_driver_install(ð_config, ð_handle)); - extra_eth_config(eth_handle); - TEST_ESP_OK(esp_eth_driver_uninstall(eth_handle)); - TEST_ESP_OK(phy->del(phy)); - TEST_ESP_OK(mac->del(mac)); - extra_cleanup(); +} + +// This test skips Ethernet initialization in the setUp and tearDown since different EMAC configurations are tested. +// As such, allocated resources may not be freed in the tearDown when the test fails. Therefore the tets is run as +// the last test in the suite to not affect other tests. +TEST_CASE("internal emac interrupt priority", "[esp_emac][skip_setup_teardown]") +{ + EventBits_t bits = 0; + EventGroupHandle_t eth_event_group = xEventGroupCreate(); + TEST_ASSERT(eth_event_group != NULL); + esp_netif_init(); + TEST_ESP_OK(esp_event_loop_create_default()); + for (int i = -1; i <= 4; i++) { + // create TCP/IP netif + esp_netif_config_t netif_cfg = ESP_NETIF_DEFAULT_ETH(); + esp_netif_t *eth_netif = esp_netif_new(&netif_cfg); + // Init common MAC and PHY configs to default + eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); + eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); + eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG(); + esp32_emac_config.intr_priority = i; + ESP_LOGI(TAG, "set interrupt priority %i: ", i); + esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); + if (i >= 4) { + TEST_ASSERT_NULL(mac); + } else { + TEST_ASSERT_NOT_NULL(mac); + esp_eth_phy_t *phy = esp_eth_phy_new_generic(&phy_config); + TEST_ASSERT_NOT_NULL(phy); + esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(mac, phy); + esp_eth_handle_t eth_handle = NULL; + // install Ethernet driver + TEST_ESP_OK(esp_eth_driver_install(ð_config, ð_handle)); + // combine driver with netif + esp_eth_netif_glue_handle_t glue = esp_eth_new_netif_glue(eth_handle); + TEST_ESP_OK(esp_netif_attach(eth_netif, glue)); + // register user defined event handlers + TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_test_default_event_handler, eth_event_group)); + TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, ð_test_got_ip_event_handler, eth_event_group)); + + // start Ethernet driver + TEST_ESP_OK(esp_eth_start(eth_handle)); + /* wait for IP lease */ + bits = xEventGroupWaitBits(eth_event_group, ETH_GOT_IP_BIT, true, true, pdMS_TO_TICKS(ETH_GET_IP_TIMEOUT_MS)); + TEST_ASSERT((bits & ETH_GOT_IP_BIT) == ETH_GOT_IP_BIT); + // stop Ethernet driveresp_event_handler_unregister + TEST_ESP_OK(esp_eth_stop(eth_handle)); + /* wait for connection stop */ + 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); + + TEST_ESP_OK(esp_eth_del_netif_glue(glue)); + /* driver should be uninstalled within 2 seconds */ + 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(IP_EVENT, IP_EVENT_ETH_GOT_IP, eth_test_got_ip_event_handler)); + TEST_ESP_OK(esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, eth_test_default_event_handler)); + } + esp_netif_destroy(eth_netif); + } + TEST_ESP_OK(esp_event_loop_delete_default()); + vEventGroupDelete(eth_event_group); } diff --git a/components/esp_eth/test_apps/main/esp_eth_test_l2.c b/components/esp_eth/test_apps/main/esp_eth_test_l2.c index 087505e7df..28c9ab5334 100644 --- a/components/esp_eth/test_apps/main/esp_eth_test_l2.c +++ b/components/esp_eth/test_apps/main/esp_eth_test_l2.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -8,7 +8,7 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/event_groups.h" -#include "esp_eth_test_common.h" +#include "esp_eth_test_utils.h" #include "arpa/inet.h" // for ntohs, etc. #include "esp_log.h" @@ -28,10 +28,6 @@ #define POKE_RESP (0xFB) #define DUMMY_TRAFFIC (0xFF) -#define W5500_RX_MEM_SIZE (0x4000) -#define DM9051_RX_MEM_SIZE (0x4000) -#define KSZ8851SNL_RX_MEM_SIZE (0x3000) - static const char *TAG = "esp32_eth_test_l2"; typedef struct { @@ -110,9 +106,13 @@ void poke_and_wait(esp_eth_handle_t eth_handle, void *data, uint16_t size, uint8 uint32_t tmo; uint32_t i; + esp_err_t tx_err = ESP_OK; for(tmo = 0, i = 1; tmo < WAIT_AFTER_CONN_TMO_MS; tmo += WAIT_AFTER_CONN_MS, i++) { printf("Poke attempt #%" PRIu32 "\n", i); - TEST_ESP_OK(esp_eth_transmit(eth_handle, ctrl_pkt, 60)); + tx_err = esp_eth_transmit(eth_handle, ctrl_pkt, 60); + if (tx_err != ESP_OK) { + break; + } EventBits_t bits = xEventGroupWaitBits(eth_event_group, ETH_POKE_RESP_RECV_BIT, true, true, pdMS_TO_TICKS(WAIT_AFTER_CONN_MS)); if ((bits & ETH_POKE_RESP_RECV_BIT) == ETH_POKE_RESP_RECV_BIT) { @@ -122,271 +122,21 @@ void poke_and_wait(esp_eth_handle_t eth_handle, void *data, uint16_t size, uint8 break; } } - TEST_ASSERT(tmo < WAIT_AFTER_CONN_TMO_MS); free(ctrl_pkt); + // assert only after the allocated memory is freed + TEST_ASSERT(tmo < WAIT_AFTER_CONN_TMO_MS); + TEST_ASSERT_EQUAL_INT_MESSAGE(ESP_OK, tx_err, "esp_eth_transmit failed"); } TEST_CASE("ethernet broadcast transmit", "[ethernet_l2]") { - esp_eth_mac_t *mac = mac_init(NULL, NULL); - TEST_ASSERT_NOT_NULL(mac); - esp_eth_phy_t *phy = phy_init(NULL); - TEST_ASSERT_NOT_NULL(phy); - esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); // apply default driver configuration - esp_eth_handle_t eth_handle = NULL; // after driver installed, we will get the handle of the driver - TEST_ESP_OK(esp_eth_driver_install(&config, ð_handle)); // install driver - TEST_ASSERT_NOT_NULL(eth_handle); - extra_eth_config(eth_handle); + // assign values to variables from common module initialized by setUp() + esp_eth_handle_t eth_handle = eth_test_get_eth_handle(); + EventGroupHandle_t eth_event_group = eth_test_get_default_event_group(); - TEST_ESP_OK(esp_event_loop_create_default()); - EventGroupHandle_t eth_event_state_group = xEventGroupCreate(); - TEST_ASSERT(eth_event_state_group != NULL); - TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_state_group)); - EventGroupHandle_t eth_event_rx_group = xEventGroupCreate(); - TEST_ASSERT(eth_event_rx_group != NULL); - - s_recv_info.eth_event_group = eth_event_rx_group; - s_recv_info.check_rx_data = false; - s_recv_info.unicast_rx_cnt = 0; - s_recv_info.multicast_rx_cnt = 0; - s_recv_info.brdcast_rx_cnt = 0; - - uint8_t local_mac_addr[ETH_ADDR_LEN] = {}; - TEST_ESP_OK(mac->get_addr(mac, local_mac_addr)); - // test app will parse the DUT MAC from this line of log output - printf("DUT MAC: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", local_mac_addr[0], local_mac_addr[1], local_mac_addr[2], - local_mac_addr[3], local_mac_addr[4], local_mac_addr[5]); - - TEST_ESP_OK(esp_eth_update_input_path(eth_handle, l2_packet_txrx_test_cb, &s_recv_info)); - TEST_ESP_OK(esp_eth_start(eth_handle)); // start Ethernet driver state machine - - EventBits_t bits = 0; - bits = xEventGroupWaitBits(eth_event_state_group, ETH_CONNECT_BIT, true, true, pdMS_TO_TICKS(WAIT_FOR_CONN_TMO_MS)); - TEST_ASSERT((bits & ETH_CONNECT_BIT) == ETH_CONNECT_BIT); - // if DUT is connected in network with switch: even if link is indicated up, it may take some time the switch - // starts switching the associated port (e.g. it runs RSTP at first) - poke_and_wait(eth_handle, NULL, 0, NULL, eth_event_rx_group); - - emac_frame_t *pkt = malloc(1024); - pkt->proto = htons(TEST_ETH_TYPE); - TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, pkt->src)); - memset(pkt->dest, 0xff, ETH_ADDR_LEN); // broadcast addr - for (int i = 0; i < (1024 - ETH_HEADER_LEN); ++i){ - pkt->data[i] = i & 0xff; - } - - TEST_ESP_OK(esp_eth_transmit(eth_handle, pkt, 1024)); - // give it some time to complete transmit - vTaskDelay(pdMS_TO_TICKS(500)); - free(pkt); - - TEST_ESP_OK(esp_eth_stop(eth_handle)); - TEST_ESP_OK(esp_event_loop_delete_default()); - TEST_ESP_OK(esp_eth_driver_uninstall(eth_handle)); - phy->del(phy); - mac->del(mac); - extra_cleanup(); - vEventGroupDelete(eth_event_rx_group); - vEventGroupDelete(eth_event_state_group); -} - -TEST_CASE("ethernet recv_pkt", "[ethernet_l2]") -{ - esp_eth_mac_t *mac = mac_init(NULL, NULL); - TEST_ASSERT_NOT_NULL(mac); - esp_eth_phy_t *phy = phy_init(NULL); - TEST_ASSERT_NOT_NULL(phy); - esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); // apply default driver configuration - esp_eth_handle_t eth_handle = NULL; // after driver installed, we will get the handle of the driver - TEST_ESP_OK(esp_eth_driver_install(&config, ð_handle)); // install driver - TEST_ASSERT_NOT_NULL(eth_handle); - extra_eth_config(eth_handle); - - TEST_ESP_OK(esp_event_loop_create_default()); - EventGroupHandle_t eth_event_state_group = xEventGroupCreate(); - TEST_ASSERT(eth_event_state_group != NULL); - TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_state_group)); - EventGroupHandle_t eth_event_rx_group = xEventGroupCreate(); - TEST_ASSERT(eth_event_rx_group != NULL); - - s_recv_info.eth_event_group = eth_event_rx_group; - s_recv_info.check_rx_data = true; - s_recv_info.unicast_rx_cnt = 0; - s_recv_info.multicast_rx_cnt = 0; - s_recv_info.brdcast_rx_cnt = 0; - - uint8_t local_mac_addr[ETH_ADDR_LEN] = {}; - TEST_ESP_OK(mac->get_addr(mac, local_mac_addr)); - // test app will parse the DUT MAC from this line of log output - printf("DUT MAC: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", local_mac_addr[0], local_mac_addr[1], local_mac_addr[2], - local_mac_addr[3], local_mac_addr[4], local_mac_addr[5]); - - TEST_ESP_OK(esp_eth_update_input_path(eth_handle, l2_packet_txrx_test_cb, &s_recv_info)); - TEST_ESP_OK(esp_eth_start(eth_handle)); // start Ethernet driver state machine - - EventBits_t bits = 0; - bits = xEventGroupWaitBits(eth_event_state_group, ETH_CONNECT_BIT, true, true, pdMS_TO_TICKS(WAIT_FOR_CONN_TMO_MS)); - TEST_ASSERT((bits & ETH_CONNECT_BIT) == ETH_CONNECT_BIT); - // if DUT is connected in network with switch: even if link is indicated up, it may take some time the switch - // starts switching the associated port (e.g. it runs RSTP at first) - poke_and_wait(eth_handle, NULL, 0, NULL, eth_event_rx_group); - - bits = 0; - bits = xEventGroupWaitBits(eth_event_rx_group, ETH_BROADCAST_RECV_BIT | ETH_MULTICAST_RECV_BIT | ETH_UNICAST_RECV_BIT, - true, true, pdMS_TO_TICKS(5000)); - printf("bits = 0x%" PRIu32 "\n", (uint32_t)bits & (ETH_BROADCAST_RECV_BIT | ETH_MULTICAST_RECV_BIT | ETH_UNICAST_RECV_BIT)); - TEST_ASSERT((bits & (ETH_BROADCAST_RECV_BIT | ETH_MULTICAST_RECV_BIT | ETH_UNICAST_RECV_BIT)) == - (ETH_BROADCAST_RECV_BIT | ETH_MULTICAST_RECV_BIT | ETH_UNICAST_RECV_BIT)); - - TEST_ESP_OK(esp_eth_stop(eth_handle)); - TEST_ESP_OK(esp_event_loop_delete_default()); - TEST_ESP_OK(esp_eth_driver_uninstall(eth_handle)); - phy->del(phy); - mac->del(mac); - extra_cleanup(); - vEventGroupDelete(eth_event_state_group); - vEventGroupDelete(eth_event_rx_group); -} - - -TEST_CASE("ethernet start/stop stress test under heavy traffic", "[ethernet_l2]") -{ -// *** SPI Ethernet modules deviation *** -// Rationale: The SPI bus is bottleneck when reading received frames from the module. The Rx Task would -// occupy all the resources under heavy Rx traffic and it would not be possible to access -// the Ethernet module to stop it. Therfore, the Rx task priority is set lower than "test" task -// to be able to be preempted. -#if CONFIG_TARGET_USE_SPI_ETHERNET - eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); - mac_config.rx_task_prio = uxTaskPriorityGet(NULL) - 1; - esp_eth_mac_t *mac = mac_init(NULL, &mac_config); -#else - esp_eth_mac_t *mac = mac_init(NULL, NULL); -#endif // CONFIG_TARGET_USE_SPI_ETHERNET - TEST_ASSERT_NOT_NULL(mac); - esp_eth_phy_t *phy = phy_init(NULL); - TEST_ASSERT_NOT_NULL(phy); - esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); // apply default driver configuration - esp_eth_handle_t eth_handle = NULL; // after driver installed, we will get the handle of the driver - TEST_ESP_OK(esp_eth_driver_install(&config, ð_handle)); // install driver - TEST_ASSERT_NOT_NULL(eth_handle); - extra_eth_config(eth_handle); - - TEST_ESP_OK(esp_event_loop_create_default()); - EventBits_t bits = 0; - EventGroupHandle_t eth_event_state_group = xEventGroupCreate(); - TEST_ASSERT(eth_event_state_group != NULL); - TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_state_group)); - EventGroupHandle_t eth_event_rx_group = xEventGroupCreate(); - TEST_ASSERT(eth_event_rx_group != NULL); - - s_recv_info.eth_event_group = eth_event_rx_group; - s_recv_info.check_rx_data = false; - s_recv_info.unicast_rx_cnt = 0; - s_recv_info.multicast_rx_cnt = 0; - s_recv_info.brdcast_rx_cnt = 0; - - uint8_t local_mac_addr[ETH_ADDR_LEN] = {}; - uint8_t dest_mac_addr[ETH_ADDR_LEN] = {}; - TEST_ESP_OK(mac->get_addr(mac, local_mac_addr)); - // test app will parse the DUT MAC from this line of log output - printf("DUT MAC: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", local_mac_addr[0], local_mac_addr[1], local_mac_addr[2], - local_mac_addr[3], local_mac_addr[4], local_mac_addr[5]); - - TEST_ESP_OK(esp_eth_update_input_path(eth_handle, l2_packet_txrx_test_cb, &s_recv_info)); - - // create dummy data packet used for traffic generation - emac_frame_t *pkt = calloc(1, 1500); - pkt->proto = htons(TEST_ETH_TYPE); - memcpy(pkt->src, local_mac_addr, ETH_ADDR_LEN); - - printf("EMAC start/stop stress test under heavy Tx traffic\n"); - for (int tx_i = 0; tx_i < 10; tx_i++) { - printf("Tx Test iteration %d\n", tx_i); - TEST_ESP_OK(esp_eth_start(eth_handle)); // start Ethernet driver state machine - bits = xEventGroupWaitBits(eth_event_state_group, ETH_CONNECT_BIT, true, true, pdMS_TO_TICKS(WAIT_FOR_CONN_TMO_MS)); - TEST_ASSERT((bits & ETH_CONNECT_BIT) == ETH_CONNECT_BIT); - // at first, check that Tx/Rx path works as expected by poking the test script - // this also serves as main PASS/FAIL criteria - poke_and_wait(eth_handle, &tx_i, sizeof(tx_i), dest_mac_addr, eth_event_rx_group); - memcpy(pkt->dest, dest_mac_addr, ETH_ADDR_LEN); - -// *** SPI Ethernet modules deviation *** -// Rationale: Transmit errors are expected only for internal EMAC since it is possible to try to queue more -// data than it is able to process at a time. -#if !CONFIG_TARGET_USE_SPI_ETHERNET - printf("Note: transmit errors are expected...\n"); -#endif - // generate heavy Tx traffic - for (int j = 0; j < 150; j++) { - // return value is not checked on purpose since it is expected that it may fail time to time because - // we may try to queue more packets than hardware is able to handle - pkt->data[2] = j & 0xFF; // sequence number - esp_eth_transmit(eth_handle, pkt, 1500); - } - TEST_ESP_OK(esp_eth_stop(eth_handle)); - bits = xEventGroupWaitBits(eth_event_state_group, ETH_STOP_BIT, true, true, pdMS_TO_TICKS(3000)); - TEST_ASSERT((bits & ETH_STOP_BIT) == ETH_STOP_BIT); - } - - printf("EMAC start/stop stress test under heavy Rx traffic\n"); - for (int rx_i = 0; rx_i < 10; rx_i++) { - printf("Rx Test iteration %d\n", rx_i); - TEST_ESP_OK(esp_eth_start(eth_handle)); // start Ethernet driver state machine - bits = xEventGroupWaitBits(eth_event_state_group, ETH_CONNECT_BIT, true, true, pdMS_TO_TICKS(WAIT_FOR_CONN_TMO_MS)); - TEST_ASSERT((bits & ETH_CONNECT_BIT) == ETH_CONNECT_BIT); - poke_and_wait(eth_handle, &rx_i, sizeof(rx_i), NULL, eth_event_rx_group); - - // wait for dummy traffic - xEventGroupClearBits(eth_event_rx_group, ETH_UNICAST_RECV_BIT); - s_recv_info.unicast_rx_cnt = 0; - bits = xEventGroupWaitBits(eth_event_rx_group, ETH_UNICAST_RECV_BIT, true, true, pdMS_TO_TICKS(3000)); - TEST_ASSERT((bits & ETH_UNICAST_RECV_BIT) == ETH_UNICAST_RECV_BIT); - - vTaskDelay(pdMS_TO_TICKS(500)); - - TEST_ESP_OK(esp_eth_stop(eth_handle)); - bits = xEventGroupWaitBits(eth_event_state_group, ETH_STOP_BIT, true, true, pdMS_TO_TICKS(3000)); - TEST_ASSERT((bits & ETH_STOP_BIT) == ETH_STOP_BIT); - printf("Recv packets: %d\n", s_recv_info.unicast_rx_cnt); - TEST_ASSERT_GREATER_THAN_INT32(0, s_recv_info.unicast_rx_cnt); - } - - free(pkt); - - // Add an extra delay to be sure that there is no traffic generated by the test script during the driver un-installation. - // It was observed unintended behavior of the switch used in test environment when link is set down under heavy load. - vTaskDelay(pdMS_TO_TICKS(500)); - - TEST_ESP_OK(esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler)); - TEST_ESP_OK(esp_event_loop_delete_default()); - TEST_ESP_OK(esp_eth_driver_uninstall(eth_handle)); - phy->del(phy); - mac->del(mac); - extra_cleanup(); - vEventGroupDelete(eth_event_rx_group); - vEventGroupDelete(eth_event_state_group); -} - -#define MAX_HEAP_ALLOCATION_POINTERS (20) -TEST_CASE("heap utilization", "[ethernet_l2]") -{ - esp_eth_mac_t *mac = mac_init(NULL, NULL); - TEST_ASSERT_NOT_NULL(mac); - esp_eth_phy_t *phy = phy_init(NULL); - TEST_ASSERT_NOT_NULL(phy); - esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy); // apply default driver configuration - esp_eth_handle_t eth_handle = NULL; // after driver installed, we will get the handle of the driver - TEST_ESP_OK(esp_eth_driver_install(&config, ð_handle)); // install driver - TEST_ASSERT_NOT_NULL(eth_handle); - extra_eth_config(eth_handle); - - TEST_ESP_OK(esp_event_loop_create_default()); - EventBits_t bits = 0; - EventGroupHandle_t eth_event_state_group = xEventGroupCreate(); - TEST_ASSERT(eth_event_state_group != NULL); - TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_state_group)); - EventGroupHandle_t eth_event_rx_group = xEventGroupCreate(); + // use static event group to avoid dynamic memory allocation + StaticEventGroup_t eth_event_rx_group_buffer; + EventGroupHandle_t eth_event_rx_group = xEventGroupCreateStatic(ð_event_rx_group_buffer); TEST_ASSERT(eth_event_rx_group != NULL); s_recv_info.eth_event_group = eth_event_rx_group; @@ -402,28 +152,216 @@ TEST_CASE("heap utilization", "[ethernet_l2]") local_mac_addr[3], local_mac_addr[4], local_mac_addr[5]); TEST_ESP_OK(esp_eth_update_input_path(eth_handle, l2_packet_txrx_test_cb, &s_recv_info)); + TEST_ESP_OK(esp_eth_start(eth_handle)); // start Ethernet driver state machine -// *** W5500 deviation *** -// Rationale: W5500 SPI Ethernet module does not support internal loopback -#if !CONFIG_TARGET_ETH_PHY_DEVICE_W5500 + EventBits_t bits = 0; + bits = xEventGroupWaitBits(eth_event_group, ETH_CONNECT_BIT, true, true, pdMS_TO_TICKS(WAIT_FOR_CONN_TMO_MS)); + TEST_ASSERT((bits & ETH_CONNECT_BIT) == ETH_CONNECT_BIT); + // if DUT is connected in network with switch: even if link is indicated up, it may take some time the switch + // starts switching the associated port (e.g. it runs RSTP at first) + poke_and_wait(eth_handle, NULL, 0, NULL, eth_event_rx_group); + + emac_frame_t *pkt = (emac_frame_t *)eth_test_alloc(1024); + pkt->proto = htons(TEST_ETH_TYPE); + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, pkt->src)); + memset(pkt->dest, 0xff, ETH_ADDR_LEN); // broadcast addr + for (int i = 0; i < (1024 - ETH_HEADER_LEN); ++i){ + pkt->data[i] = i & 0xff; + } + + TEST_ESP_OK(esp_eth_transmit(eth_handle, pkt, 1024)); + // give it some time to complete transmit + vTaskDelay(pdMS_TO_TICKS(500)); + + TEST_ESP_OK(esp_eth_stop(eth_handle)); +} + +TEST_CASE("ethernet recv_pkt", "[ethernet_l2]") +{ + // get handles from common module initialized by setUp() + esp_eth_handle_t eth_handle = eth_test_get_eth_handle(); + EventGroupHandle_t eth_event_group = eth_test_get_default_event_group(); + + // use static event group to avoid dynamic memory allocation + StaticEventGroup_t eth_event_rx_group_buffer; + EventGroupHandle_t eth_event_rx_group = xEventGroupCreateStatic(ð_event_rx_group_buffer); + TEST_ASSERT(eth_event_rx_group != NULL); + + s_recv_info.eth_event_group = eth_event_rx_group; + s_recv_info.check_rx_data = true; + s_recv_info.unicast_rx_cnt = 0; + s_recv_info.multicast_rx_cnt = 0; + s_recv_info.brdcast_rx_cnt = 0; + + uint8_t local_mac_addr[ETH_ADDR_LEN] = {}; + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, local_mac_addr)); + // test app will parse the DUT MAC from this line of log output + printf("DUT MAC: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", local_mac_addr[0], local_mac_addr[1], local_mac_addr[2], + local_mac_addr[3], local_mac_addr[4], local_mac_addr[5]); + + TEST_ESP_OK(esp_eth_update_input_path(eth_handle, l2_packet_txrx_test_cb, &s_recv_info)); + TEST_ESP_OK(esp_eth_start(eth_handle)); // start Ethernet driver state machine + + EventBits_t bits = 0; + bits = xEventGroupWaitBits(eth_event_group, ETH_CONNECT_BIT, true, true, pdMS_TO_TICKS(WAIT_FOR_CONN_TMO_MS)); + TEST_ASSERT((bits & ETH_CONNECT_BIT) == ETH_CONNECT_BIT); + // if DUT is connected in network with switch: even if link is indicated up, it may take some time the switch + // starts switching the associated port (e.g. it runs RSTP at first) + poke_and_wait(eth_handle, NULL, 0, NULL, eth_event_rx_group); + + bits = 0; + bits = xEventGroupWaitBits(eth_event_rx_group, ETH_BROADCAST_RECV_BIT | ETH_MULTICAST_RECV_BIT | ETH_UNICAST_RECV_BIT, + true, true, pdMS_TO_TICKS(5000)); + printf("bits = 0x%" PRIu32 "\n", (uint32_t)bits & (ETH_BROADCAST_RECV_BIT | ETH_MULTICAST_RECV_BIT | ETH_UNICAST_RECV_BIT)); + TEST_ASSERT((bits & (ETH_BROADCAST_RECV_BIT | ETH_MULTICAST_RECV_BIT | ETH_UNICAST_RECV_BIT)) == + (ETH_BROADCAST_RECV_BIT | ETH_MULTICAST_RECV_BIT | ETH_UNICAST_RECV_BIT)); + + TEST_ESP_OK(esp_eth_stop(eth_handle)); +} + + +TEST_CASE("ethernet start/stop stress test under heavy traffic", "[ethernet_l2]") +{ +// *** SPI Ethernet modules deviation *** +// Rationale: The SPI bus is bottleneck when reading received frames from the module. The Rx Task would +// occupy all the resources under heavy Rx traffic and it would not be possible to access +// the Ethernet module to stop it. Therefore, the test task priority is set higher than the Rx task +// to be able to preempt the Rx task. +#if CONFIG_ETH_TEST_STRESS_TEST_TASK_PRIO > -1 + printf("task priority: %d\n", uxTaskPriorityGet(NULL)); + vTaskPrioritySet(NULL, CONFIG_ETH_TEST_STRESS_TEST_TASK_PRIO); +#endif // CONFIG_ETH_TEST_STRESS_TEST_TASK_PRIO > 0 + // get handles from common module initialized by setUp() + esp_eth_handle_t eth_handle = eth_test_get_eth_handle(); + EventGroupHandle_t eth_event_group = eth_test_get_default_event_group(); + + // use static event group to avoid dynamic memory allocation + StaticEventGroup_t eth_event_rx_group_buffer; + EventGroupHandle_t eth_event_rx_group = xEventGroupCreateStatic(ð_event_rx_group_buffer); + TEST_ASSERT(eth_event_rx_group != NULL); + + s_recv_info.eth_event_group = eth_event_rx_group; + s_recv_info.check_rx_data = false; + s_recv_info.unicast_rx_cnt = 0; + s_recv_info.multicast_rx_cnt = 0; + s_recv_info.brdcast_rx_cnt = 0; + + uint8_t local_mac_addr[ETH_ADDR_LEN] = {}; + uint8_t dest_mac_addr[ETH_ADDR_LEN] = {}; + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, local_mac_addr)); + // test app will parse the DUT MAC from this line of log output + printf("DUT MAC: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", local_mac_addr[0], local_mac_addr[1], local_mac_addr[2], + local_mac_addr[3], local_mac_addr[4], local_mac_addr[5]); + + TEST_ESP_OK(esp_eth_update_input_path(eth_handle, l2_packet_txrx_test_cb, &s_recv_info)); + + // create dummy data packet used for traffic generation + emac_frame_t *pkt = (emac_frame_t *)eth_test_alloc(1500); + pkt->proto = htons(TEST_ETH_TYPE); + memcpy(pkt->src, local_mac_addr, ETH_ADDR_LEN); + + EventBits_t bits = 0; + printf("EMAC start/stop stress test under heavy Tx traffic\n"); + for (int tx_i = 0; tx_i < 10; tx_i++) { + printf("Tx Test iteration %d\n", tx_i); + TEST_ESP_OK(esp_eth_start(eth_handle)); // start Ethernet driver state machine + bits = xEventGroupWaitBits(eth_event_group, ETH_CONNECT_BIT, true, true, pdMS_TO_TICKS(WAIT_FOR_CONN_TMO_MS)); + TEST_ASSERT((bits & ETH_CONNECT_BIT) == ETH_CONNECT_BIT); + // at first, check that Tx/Rx path works as expected by poking the test script + // this also serves as main PASS/FAIL criteria + poke_and_wait(eth_handle, &tx_i, sizeof(tx_i), dest_mac_addr, eth_event_rx_group); + memcpy(pkt->dest, dest_mac_addr, ETH_ADDR_LEN); + + // generate heavy Tx traffic + for (int j = 0; j < 150; j++) { + // return value is not checked on purpose since it is expected that it may fail time to time because + // we may try to queue more packets than hardware is able to handle + pkt->data[2] = j & 0xFF; // sequence number + esp_eth_transmit(eth_handle, pkt, 1500); + } + TEST_ESP_OK(esp_eth_stop(eth_handle)); + bits = xEventGroupWaitBits(eth_event_group, ETH_STOP_BIT, true, true, pdMS_TO_TICKS(3000)); + TEST_ASSERT((bits & ETH_STOP_BIT) == ETH_STOP_BIT); + } + + printf("EMAC start/stop stress test under heavy Rx traffic\n"); + for (int rx_i = 0; rx_i < 10; rx_i++) { + printf("Rx Test iteration %d\n", rx_i); + TEST_ESP_OK(esp_eth_start(eth_handle)); // start Ethernet driver state machine + bits = xEventGroupWaitBits(eth_event_group, ETH_CONNECT_BIT, true, true, pdMS_TO_TICKS(WAIT_FOR_CONN_TMO_MS)); + TEST_ASSERT((bits & ETH_CONNECT_BIT) == ETH_CONNECT_BIT); + poke_and_wait(eth_handle, &rx_i, sizeof(rx_i), NULL, eth_event_rx_group); + + // wait for dummy traffic + xEventGroupClearBits(eth_event_rx_group, ETH_UNICAST_RECV_BIT); + s_recv_info.unicast_rx_cnt = 0; + bits = xEventGroupWaitBits(eth_event_rx_group, ETH_UNICAST_RECV_BIT, true, true, pdMS_TO_TICKS(3000)); + TEST_ASSERT((bits & ETH_UNICAST_RECV_BIT) == ETH_UNICAST_RECV_BIT); + + vTaskDelay(pdMS_TO_TICKS(500)); + + TEST_ESP_OK(esp_eth_stop(eth_handle)); + bits = xEventGroupWaitBits(eth_event_group, ETH_STOP_BIT, true, true, pdMS_TO_TICKS(3000)); + TEST_ASSERT((bits & ETH_STOP_BIT) == ETH_STOP_BIT); + printf("Recv packets: %d\n", s_recv_info.unicast_rx_cnt); + TEST_ASSERT_GREATER_THAN_INT32(0, s_recv_info.unicast_rx_cnt); + } + // Add an extra delay to be sure that there is no traffic generated by the test script during the driver un-installation. + // It was observed unintended behavior of the switch used in test environment when link is set down under heavy load. + vTaskDelay(pdMS_TO_TICKS(500)); +} + +TEST_CASE("heap utilization", "[ethernet_l2]") +{ + // get handles from common module initialized by setUp() + esp_eth_handle_t eth_handle = eth_test_get_eth_handle(); + EventGroupHandle_t eth_event_group = eth_test_get_default_event_group(); + + // use static event group to avoid dynamic memory allocation + StaticEventGroup_t eth_event_rx_group_buffer; + EventGroupHandle_t eth_event_rx_group = xEventGroupCreateStatic(ð_event_rx_group_buffer); + TEST_ASSERT(eth_event_rx_group != NULL); + + s_recv_info.eth_event_group = eth_event_rx_group; + s_recv_info.check_rx_data = false; + s_recv_info.unicast_rx_cnt = 0; + s_recv_info.multicast_rx_cnt = 0; + s_recv_info.brdcast_rx_cnt = 0; + +// *** PHY loopback not supported deviation *** +// Rationale: Some Ethernet modules do not support internal loopback +#if !CONFIG_ETH_TEST_LOOPBACK_DISABLED // --------------------------------------- // Loopback greatly simplifies the test !! // --------------------------------------- bool loopback_en = true; TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_S_PHY_LOOPBACK, &loopback_en)); + printf("PHY loopback is enabled\n"); +#else + printf("PHY loopback is disabled\n"); #endif + uint8_t local_mac_addr[ETH_ADDR_LEN] = {}; + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, local_mac_addr)); + // test app will parse the DUT MAC from this line of log output + printf("DUT MAC: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", local_mac_addr[0], local_mac_addr[1], local_mac_addr[2], + local_mac_addr[3], local_mac_addr[4], local_mac_addr[5]); + + TEST_ESP_OK(esp_eth_update_input_path(eth_handle, l2_packet_txrx_test_cb, &s_recv_info)); + // start the driver TEST_ESP_OK(esp_eth_start(eth_handle)); // wait for connection start - bits = xEventGroupWaitBits(eth_event_state_group, ETH_START_BIT, true, true, pdMS_TO_TICKS(ETH_START_TIMEOUT_MS)); + EventBits_t bits = 0; + bits = xEventGroupWaitBits(eth_event_group, ETH_START_BIT, true, true, pdMS_TO_TICKS(ETH_START_TIMEOUT_MS)); TEST_ASSERT((bits & ETH_START_BIT) == ETH_START_BIT); // wait for connection establish - bits = xEventGroupWaitBits(eth_event_state_group, ETH_CONNECT_BIT, true, true, pdMS_TO_TICKS(ETH_CONNECT_TIMEOUT_MS)); + bits = xEventGroupWaitBits(eth_event_group, ETH_CONNECT_BIT, true, true, pdMS_TO_TICKS(ETH_CONNECT_TIMEOUT_MS)); TEST_ASSERT((bits & ETH_CONNECT_BIT) == ETH_CONNECT_BIT); // create test frame - emac_frame_t *test_pkt = calloc(1, ETH_MAX_PACKET_SIZE); + uint8_t test_pkt_buffer[ETH_MAX_PACKET_SIZE]; + emac_frame_t *test_pkt = (emac_frame_t *)test_pkt_buffer; test_pkt->proto = htons(TEST_ETH_TYPE); memcpy(test_pkt->dest, local_mac_addr, ETH_ADDR_LEN); // our addr so the frame is not filtered at loopback by MAC memcpy(test_pkt->src, local_mac_addr, ETH_ADDR_LEN); @@ -432,9 +370,9 @@ TEST_CASE("heap utilization", "[ethernet_l2]") test_pkt->data[i] = i & 0xFF; } -// *** W5500 deviation *** -// Rationale: W5500 SPI Ethernet module does not support internal loopback so we need to loop frames back at test PC side -#if CONFIG_TARGET_ETH_PHY_DEVICE_W5500 +// *** PHY loopback not supported deviation *** +// Rationale: Some Ethernet modules do not support internal loopback so we need to loop frames back at test PC side +#if CONFIG_ETH_TEST_LOOPBACK_DISABLED uint8_t dest_mac_addr[ETH_ADDR_LEN] = {}; poke_and_wait(eth_handle, NULL, 0, dest_mac_addr, eth_event_rx_group); memcpy(test_pkt->dest, dest_mac_addr, ETH_ADDR_LEN); // overwrite destination address with test PC addr @@ -442,36 +380,20 @@ TEST_CASE("heap utilization", "[ethernet_l2]") uint16_t transmit_size; size_t free_heap = 0; - uint8_t *memory_p[MAX_HEAP_ALLOCATION_POINTERS] = { 0 }; - int32_t mem_block; + uint8_t *p; ESP_LOGI(TAG, "Allocate all heap"); - for (mem_block = 0; mem_block < MAX_HEAP_ALLOCATION_POINTERS; mem_block++) { + do { free_heap = heap_caps_get_largest_free_block(MALLOC_CAP_DEFAULT); ESP_LOGD(TAG, "free heap: %i B", free_heap); - memory_p[mem_block] = malloc(free_heap); - if (free_heap < 1024) { - break; - } - } - free_heap = heap_caps_get_largest_free_block(MALLOC_CAP_DEFAULT); + p = eth_test_alloc(free_heap); + } while (p != NULL && free_heap > 1024); ESP_LOGI(TAG, "remaining free heap: %i B", free_heap); TEST_ASSERT_LESS_OR_EQUAL_INT(1024, free_heap); transmit_size = ETH_MAX_PAYLOAD_LEN; ESP_LOGI(TAG, "Verify that the driver is able to recover from `no mem` error"); // define number of iteration to fill device internal buffer (if driver's flush function didn't work as expected) - int32_t max_i = 10; // default value will be overwritten by module specific value -// *** Ethernet modules deviation *** -// Rationale: Each Ethernet module has different size of Rx buffer -#if CONFIG_TARGET_USE_INTERNAL_ETHERNET - max_i = CONFIG_ETH_DMA_RX_BUFFER_NUM + 2; -#elif CONFIG_TARGET_ETH_PHY_DEVICE_W5500 - max_i = W5500_RX_MEM_SIZE / ETH_MAX_PACKET_SIZE + 2; -#elif CONFIG_TARGET_ETH_PHY_DEVICE_DM9051 - max_i = DM9051_RX_MEM_SIZE / ETH_MAX_PACKET_SIZE + 2; -#elif CONFIG_TARGET_ETH_PHY_DEVICE_KSZ8851SNL - max_i = KSZ8851SNL_RX_MEM_SIZE / ETH_MAX_PACKET_SIZE + 2; -#endif + int32_t max_i = CONFIG_ETH_TEST_FILL_RX_BUFFER_ITERATIONS + 2; for (int32_t i = 0; i < max_i; i++) { // be sure to fill all the descriptors ESP_LOGI(TAG, "transmit frame size: %" PRIu16 ", i = %" PRIi32, transmit_size, i); @@ -483,10 +405,7 @@ TEST_CASE("heap utilization", "[ethernet_l2]") TEST_ASSERT(bits == 0); // we don't received the frame due to "no mem" } ESP_LOGI(TAG, "Free previously allocated heap"); - while(mem_block > 0) { - free(memory_p[mem_block]); - mem_block--; - } + eth_test_free_all(); free_heap = heap_caps_get_largest_free_block(MALLOC_CAP_DEFAULT); ESP_LOGI(TAG, "free heap: %i B", free_heap); for (int32_t i = 0; i < max_i; i++) { @@ -498,16 +417,7 @@ TEST_CASE("heap utilization", "[ethernet_l2]") bits = xEventGroupWaitBits(eth_event_rx_group, ETH_UNICAST_RECV_BIT, true, true, pdMS_TO_TICKS(200)); TEST_ASSERT((bits & ETH_UNICAST_RECV_BIT) == ETH_UNICAST_RECV_BIT); // now, we should be able to receive frames again } - - free(test_pkt); TEST_ESP_OK(esp_eth_stop(eth_handle)); - - TEST_ESP_OK(esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler)); - TEST_ESP_OK(esp_event_loop_delete_default()); - TEST_ESP_OK(esp_eth_driver_uninstall(eth_handle)); - phy->del(phy); - mac->del(mac); - extra_cleanup(); - vEventGroupDelete(eth_event_rx_group); - vEventGroupDelete(eth_event_state_group); + bits = xEventGroupWaitBits(eth_event_group, ETH_STOP_BIT, true, true, pdMS_TO_TICKS(3000)); + TEST_ASSERT((bits & ETH_STOP_BIT) == ETH_STOP_BIT); } diff --git a/components/esp_eth/test_apps/main/esp_eth_test_main.c b/components/esp_eth/test_apps/main/esp_eth_test_main.c index 82ff3526c5..944fcdcc3c 100644 --- a/components/esp_eth/test_apps/main/esp_eth_test_main.c +++ b/components/esp_eth/test_apps/main/esp_eth_test_main.c @@ -1,11 +1,19 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ -#include "test_utils.h" +#include "unity.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "sdkconfig.h" -void app_main(void) +void test_task(void *pvParameters) { unity_run_menu(); } + +void app_main(void) +{ + xTaskCreatePinnedToCore(test_task, "testTask", CONFIG_ETH_TEST_UNITY_TEST_TASK_STACK, NULL, CONFIG_ETH_TEST_UNITY_TEST_TASK_PRIO, NULL, tskNO_AFFINITY); +} diff --git a/components/esp_eth/test_apps/main/esp_eth_test_utils.c b/components/esp_eth/test_apps/main/esp_eth_test_utils.c new file mode 100644 index 0000000000..8647b07b85 --- /dev/null +++ b/components/esp_eth/test_apps/main/esp_eth_test_utils.c @@ -0,0 +1,322 @@ +/* + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include +#include +#include "esp_eth_driver.h" +#include "freertos/FreeRTOS.h" +#include "freertos/event_groups.h" +#include "esp_event.h" +#include "esp_log.h" +#include "sdkconfig.h" +#include "esp_eth_test_utils.h" +#include "esp_check.h" +#include "ethernet_init.h" + +// Local override of TEST_ASSERT and TEST_ESP_OK to fix Unity file name reporting +// when assertions are in a different file than the test. This temporarily sets Unity. +// TestFile to __FILE__ so the correct file name is reported on assertion failure. +#define ETH_TEST_ASSERT(condition) do { \ + const char* _unity_test_file_save = Unity.TestFile; \ + Unity.TestFile = __FILE__; \ + TEST_ASSERT(condition); \ + Unity.TestFile = _unity_test_file_save; \ +} while(0) + +#define ETH_TEST_ESP_OK(rc) do { \ + const char* _unity_test_file_save = Unity.TestFile; \ + Unity.TestFile = __FILE__; \ + TEST_ASSERT_EQUAL_HEX32(ESP_OK, rc); \ + Unity.TestFile = _unity_test_file_save; \ +} while(0) + +static const char *TAG = "esp32_eth_test_common"; + +static esp_eth_handle_t *s_eth_handles; // only because we use Ethernet Init component + +static EventGroupHandle_t s_eth_event_group; +static esp_eth_handle_t s_eth_handle; +static esp_netif_t *s_eth_netif; +static esp_eth_netif_glue_handle_t s_eth_glue; +static void *s_memory_p[MAX_HEAP_ALLOCATION_POINTERS]; + +esp_err_t eth_test_set_phy_reg_bits(esp_eth_handle_t eth_handle, uint32_t reg_addr, uint32_t bitmask, uint32_t max_attempts) +{ + + esp_eth_phy_reg_rw_data_t reg = { + .reg_addr = reg_addr, + .reg_value_p = NULL + }; + uint32_t reg_value, reg_value_rb; + + for (uint32_t i = 0; i < max_attempts; i++) { + reg.reg_value_p = ®_value; + esp_err_t ret = esp_eth_ioctl(eth_handle, ETH_CMD_READ_PHY_REG, ®); + if (ret != ESP_OK) { + return ret; + } + reg_value |= bitmask; + ret = esp_eth_ioctl(eth_handle, ETH_CMD_WRITE_PHY_REG, ®); + if (ret != ESP_OK) { + return ret; + } + reg.reg_value_p = ®_value_rb; + ret = esp_eth_ioctl(eth_handle, ETH_CMD_READ_PHY_REG, ®); + if (ret != ESP_OK) { + return ret; + } + // Check if the write was successful + if ((reg_value_rb & bitmask) == bitmask) { + return ESP_OK; + } + // Add delay only if not the last attempt + if (i < max_attempts - 1) { + ESP_LOGW(TAG, "Setting PHY register %04"PRIx32" failed, retrying... (attempt %"PRIu32" of %"PRIu32")", reg_addr, i + 1, max_attempts); + vTaskDelay(pdMS_TO_TICKS(10)); + } + } + return ESP_ERR_TIMEOUT; +} + +esp_err_t eth_test_clear_phy_reg_bits(esp_eth_handle_t eth_handle, uint32_t reg_addr, uint32_t bitmask, uint32_t max_attempts) +{ + esp_eth_phy_reg_rw_data_t reg = { + .reg_addr = reg_addr, + .reg_value_p = NULL + }; + uint32_t reg_value, reg_value_rb; + + for (uint32_t i = 0; i < max_attempts; i++) { + reg.reg_value_p = ®_value; + esp_err_t ret = esp_eth_ioctl(eth_handle, ETH_CMD_READ_PHY_REG, ®); + if (ret != ESP_OK) { + return ret; + } + reg_value &= ~bitmask; + ret = esp_eth_ioctl(eth_handle, ETH_CMD_WRITE_PHY_REG, ®); + if (ret != ESP_OK) { + return ret; + } + reg.reg_value_p = ®_value_rb; + ret = esp_eth_ioctl(eth_handle, ETH_CMD_READ_PHY_REG, ®); + if (ret != ESP_OK) { + return ret; + } + // Check if the write was successful + if ((reg_value_rb & bitmask) == 0) { + return ESP_OK; + } + // Add delay only if not the last attempt + if (i < max_attempts - 1) { + ESP_LOGW(TAG, "Clearing PHY register %04"PRIx32" failed, retrying... (attempt %"PRIu32" of %"PRIu32")", reg_addr, i + 1, max_attempts); + vTaskDelay(pdMS_TO_TICKS(10)); + } + } + return ESP_ERR_TIMEOUT; +} + +__attribute__((weak)) esp_err_t esp_eth_test_eth_init(esp_eth_handle_t *eth_handle) +{ + esp_err_t ret = ESP_OK; + uint8_t eth_port_cnt = 0; + ESP_LOGI(TAG, "Default Ethernet Initialization..."); + ESP_GOTO_ON_ERROR(ethernet_init_all(&s_eth_handles, ð_port_cnt), err, TAG, "Failed to initialize Ethernet"); + ESP_GOTO_ON_FALSE(eth_port_cnt == 1, ESP_FAIL, err, TAG, "Multiple Ethernet devices detected, the test cannot continue..."); + *eth_handle = s_eth_handles[0]; +err: + return ret; +} + +__attribute__((weak)) esp_err_t esp_eth_test_eth_deinit(esp_eth_handle_t eth_handle) +{ + esp_err_t ret = ESP_OK; + ESP_LOGI(TAG, "Default Ethernet Deinitialization..."); + ESP_GOTO_ON_FALSE(s_eth_handles[0] == eth_handle, ESP_FAIL, err, TAG, "Ethernet handle does not match"); + ESP_GOTO_ON_ERROR(ethernet_deinit_all(s_eth_handles), err, TAG, "Failed to deinitialize Ethernet"); +err: + return ret; +} + +void setUp(void) +{ + if (strstr(Unity.CurrentDetail1, "[skip_setup_teardown]") != NULL) { + return; + } + // Use Unity to check if the initialization is successful, it's intended to fail the test if initialization fails + s_eth_event_group = xEventGroupCreate(); + ETH_TEST_ASSERT(s_eth_event_group != NULL); + ETH_TEST_ESP_OK(esp_event_loop_create_default()); + ETH_TEST_ESP_OK(esp_eth_test_eth_init(&s_eth_handle)); + eth_dev_info_t phy_info = ethernet_init_get_dev_info(s_eth_handle); + ESP_LOGI(TAG, "DUT PHY: %s", phy_info.name); + if (strstr(Unity.CurrentDetail1, "[esp-netif]") != NULL) { + esp_netif_init(); + // create TCP/IP netif + esp_netif_config_t netif_cfg = ESP_NETIF_DEFAULT_ETH(); + s_eth_netif = esp_netif_new(&netif_cfg); + // combine driver with netif + s_eth_glue = esp_eth_new_netif_glue(s_eth_handle); + ETH_TEST_ESP_OK(esp_netif_attach(s_eth_netif, s_eth_glue)); + // register user defined event handlers + ETH_TEST_ESP_OK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, ð_test_got_ip_event_handler, s_eth_event_group)); + } + ETH_TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_test_default_event_handler, s_eth_event_group)); +} + +void tearDown(void) +{ + eth_test_free_all(); + + if (strstr(Unity.CurrentDetail1, "[skip_setup_teardown]") != NULL) { + return; + } + // Use regular error checking instead of ETH_TEST_ESP_OK to ensure cleanup always completes + // even if errors occur (e.g., if test failed and resources are in invalid state) + // This is critical because TEST_ASSERT failures use longjmp which can skip cleanup + esp_err_t ret; + + if (s_eth_glue != NULL) { + ret = esp_eth_del_netif_glue(s_eth_glue); + if (ret != ESP_OK) { + ESP_LOGW(TAG, "esp_eth_del_netif_glue failed: %s", esp_err_to_name(ret)); + } + s_eth_glue = NULL; + } + if (s_eth_netif != NULL) { + esp_netif_destroy(s_eth_netif); + s_eth_netif = NULL; + + ret = esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, eth_test_got_ip_event_handler); + if (ret != ESP_OK) { + ESP_LOGW(TAG, "esp_event_handler_unregister IP event failed: %s", esp_err_to_name(ret)); + } + } + + ret = esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, eth_test_default_event_handler); + if (ret != ESP_OK && ret != ESP_ERR_INVALID_STATE) { + // ESP_ERR_INVALID_STATE is OK - handler might already be unregistered + ESP_LOGW(TAG, "esp_event_handler_unregister failed: %s", esp_err_to_name(ret)); + } + + if (s_eth_handle != NULL) { + ret = esp_eth_test_eth_deinit(s_eth_handle); + if (ret != ESP_OK) { + ESP_LOGW(TAG, "esp_eth_test_eth_deinit failed: %s", esp_err_to_name(ret)); + ESP_LOGI(TAG, "Trying to stop Ethernet driver and deinitialize it again..."); + ret = esp_eth_stop(s_eth_handle); + vTaskDelay(pdMS_TO_TICKS(500)); + if (ret != ESP_OK) { + ESP_LOGW(TAG, "esp_eth_stop failed: %s", esp_err_to_name(ret)); + } + // try to deinitialize Ethernet driver again + ret = esp_eth_test_eth_deinit(s_eth_handle); + if (ret != ESP_OK) { + ESP_LOGW(TAG, "esp_eth_test_eth_deinit failed: %s", esp_err_to_name(ret)); + } + } + s_eth_handle = NULL; + } + + ret = esp_event_loop_delete_default(); + if (ret != ESP_OK && ret != ESP_ERR_INVALID_STATE) { + // ESP_ERR_INVALID_STATE is OK - loop might already be deleted + ESP_LOGW(TAG, "esp_event_loop_delete_default failed: %s", esp_err_to_name(ret)); + } + + if (s_eth_event_group != NULL) { + vEventGroupDelete(s_eth_event_group); + s_eth_event_group = NULL; + } +} + +esp_eth_handle_t eth_test_get_eth_handle(void) +{ + return s_eth_handle; +} + +EventGroupHandle_t eth_test_get_default_event_group(void) +{ + return s_eth_event_group; +} + +esp_netif_t *eth_test_get_netif(void) +{ + return s_eth_netif; +} + +void* eth_test_alloc(size_t size) +{ + for (int i = 0; i < MAX_HEAP_ALLOCATION_POINTERS; i++) { + if (s_memory_p[i] == NULL) { + s_memory_p[i] = malloc(size); + return s_memory_p[i]; + } + } + return NULL; +} + +void eth_test_free(void *ptr) +{ + for (int i = 0; i < MAX_HEAP_ALLOCATION_POINTERS; i++) { + if (s_memory_p[i] == ptr) { + free(s_memory_p[i]); + s_memory_p[i] = NULL; + return; + } + } + return; +} + +void eth_test_free_all(void) +{ + for (int i = 0; i < MAX_HEAP_ALLOCATION_POINTERS; i++) { + if (s_memory_p[i] != NULL) { + free(s_memory_p[i]); + s_memory_p[i] = NULL; + } + } +} + +/** Event handler for Ethernet events */ +void eth_test_default_event_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) +{ + EventGroupHandle_t eth_event_group = (EventGroupHandle_t)arg; + switch (event_id) { + case ETHERNET_EVENT_CONNECTED: + ESP_LOGI(TAG, "Ethernet Link Up"); + xEventGroupSetBits(eth_event_group, ETH_CONNECT_BIT); + break; + case ETHERNET_EVENT_DISCONNECTED: + ESP_LOGI(TAG, "Ethernet Link Down"); + break; + case ETHERNET_EVENT_START: + ESP_LOGI(TAG, "Ethernet Started"); + xEventGroupSetBits(eth_event_group, ETH_START_BIT); + break; + case ETHERNET_EVENT_STOP: + ESP_LOGI(TAG, "Ethernet Stopped"); + xEventGroupSetBits(eth_event_group, ETH_STOP_BIT); + break; + default: + break; + } +} + +/** Event handler for IP_EVENT_ETH_GOT_IP */ +void eth_test_got_ip_event_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) +{ + EventGroupHandle_t eth_event_group = (EventGroupHandle_t)arg; + ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data; + const esp_netif_ip_info_t *ip_info = &event->ip_info; + ESP_LOGI(TAG, "Ethernet Got IP Address"); + ESP_LOGI(TAG, "~~~~~~~~~~~"); + ESP_LOGI(TAG, "ETHIP:" IPSTR, IP2STR(&ip_info->ip)); + ESP_LOGI(TAG, "ETHMASK:" IPSTR, IP2STR(&ip_info->netmask)); + ESP_LOGI(TAG, "ETHGW:" IPSTR, IP2STR(&ip_info->gw)); + ESP_LOGI(TAG, "~~~~~~~~~~~"); + xEventGroupSetBits(eth_event_group, ETH_GOT_IP_BIT); +} diff --git a/components/esp_eth/test_apps/main/esp_eth_test_utils.h b/components/esp_eth/test_apps/main/esp_eth_test_utils.h new file mode 100644 index 0000000000..a94454634a --- /dev/null +++ b/components/esp_eth/test_apps/main/esp_eth_test_utils.h @@ -0,0 +1,133 @@ +/* + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#pragma once + +#include "esp_err.h" +#include "unity.h" +#include "esp_event.h" +#include "esp_netif.h" +#include "esp_eth.h" + +#define ETH_START_BIT BIT(0) +#define ETH_STOP_BIT BIT(1) +#define ETH_CONNECT_BIT BIT(2) +#define ETH_GOT_IP_BIT BIT(3) + +#define ETH_START_TIMEOUT_MS (10000) +#define ETH_CONNECT_TIMEOUT_MS (40000) +#define ETH_STOP_TIMEOUT_MS (10000) +#define ETH_GET_IP_TIMEOUT_MS (60000) +#define ETH_DOWNLOAD_END_TIMEOUT_MS (240000) + +#define MAX_HEAP_ALLOCATION_POINTERS 20 + +typedef struct { + uint8_t dest[ETH_ADDR_LEN]; + uint8_t src[ETH_ADDR_LEN]; + uint16_t proto; + uint8_t data[]; +} __attribute__((__packed__)) emac_frame_t; + +/** @brief Get the Ethernet handle initialized by setUp() + * + * @return esp_eth_handle_t The Ethernet handle, if initialized successfully, otherwise NULL + */ +esp_eth_handle_t eth_test_get_eth_handle(void); + +/** @brief Get the Event Group handle initialized by setUp() + * + * @return EventGroupHandle_t The Event Group handle, if initialized successfully, otherwise NULL + */ +EventGroupHandle_t eth_test_get_default_event_group(void); + +/** @brief Get the ESP-NETIF handle initialized by setUp() + * + * @note Valid output only available if the test case is using [esp-netif] identifier + * + * @return esp_netif_t The Network Interface handle if initialized successfully, otherwise NULL + */ +esp_netif_t *eth_test_get_netif(void); + +/** @brief Set the PHY register bits + * + * @param eth_handle The Ethernet handle + * @param reg_addr The PHY register address + * @param bitmask The bits to set + * @param max_attempts The maximum number of set attempts + * @return esp_err_t The error code + */ +esp_err_t eth_test_set_phy_reg_bits(esp_eth_handle_t eth_handle, uint32_t reg_addr, uint32_t bitmask, uint32_t max_attempts); + +/** @brief Clear the PHY register bits + * + * @param eth_handle The Ethernet handle + * @param reg_addr The PHY register address + * @param bitmask The bits to clear + * @param max_attempts The maximum number of clear attempts + * @return esp_err_t The error code + */ +esp_err_t eth_test_clear_phy_reg_bits(esp_eth_handle_t eth_handle, uint32_t reg_addr, uint32_t bitmask, uint32_t max_attempts); + +/** @brief Initialize Ethernet driver (default implementation uses ethernet_init component). + * + * @param[out] eth_handle Initialized Ethernet driver handle + * @return esp_err_t + */ +esp_err_t esp_eth_test_eth_init(esp_eth_handle_t *eth_handle); + +/** @brief Deinitialize Ethernet driver (default implementation uses ethernet_init component). + * + * @param eth_handle Ethernet driver handle to deinitialize + * @return esp_err_t + */ +esp_err_t esp_eth_test_eth_deinit(esp_eth_handle_t eth_handle); + +/** @brief Default event handler function header for Ethernet events to be registered by `esp_event_handler_register()` in the test + * with event base `ETH_EVENT` and event ID `ESP_EVENT_ANY_ID` + * + * @note This function is intended to be registered as a callback function only when [skip_setup_teardown] identifier is used. Otherwise, + * it's registered automatically by the Common test app during setUp() phase. + */ +void eth_test_default_event_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data); + +/** @brief Default event handler function header for IP_EVENT_ETH_GOT_IP events to be registered by `esp_event_handler_register()` in the test + * with event base `IP_EVENT` and event ID `IP_EVENT_ETH_GOT_IP` + * + * @note This function is intended to be registered as a callback function only when [skip_setup_teardown] identifier is used. Otherwise, + * it's registered automatically by the Common test app during setUp() phase. + */ +void eth_test_got_ip_event_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data); + +/** @brief Allocate memory from the heap + * + * @note The the Common test app keeps track of all allocated memory and frees it automatically during tearDown() phase. + * The maximum number of allocations is limited to `MAX_HEAP_ALLOCATION_POINTERS`. + * + * @param size The size of the memory to allocate + * @return void* The pointer to the allocated memory, NULL if allocation failed + */ +void* eth_test_alloc(size_t size); + +/** @brief Free memory from the heap + * + * @note All allocated memory is freed automatically during tearDown() phase. Use this function only when required by the test + * procedure. + * + * @param ptr The pointer to the memory to free + * @return void + */ +void eth_test_free(void *ptr); + +/** @brief Free all memory from the heap + * + * @note All allocated memory is freed automatically during tearDown() phase. Use this function only when required by the test + * procedure. + * + * @return void + */ +void eth_test_free_all(void); diff --git a/components/esp_eth/test_apps/main/idf_component.yml b/components/esp_eth/test_apps/main/idf_component.yml new file mode 100644 index 0000000000..b187568955 --- /dev/null +++ b/components/esp_eth/test_apps/main/idf_component.yml @@ -0,0 +1,4 @@ +## IDF Component Manager Manifest File +dependencies: + espressif/ethernet_init: + version: "^1.3.0" diff --git a/components/esp_eth/test_apps/pytest_esp_eth.py b/components/esp_eth/test_apps/pytest_esp_eth.py index f78842a95e..8d5240e556 100644 --- a/components/esp_eth/test_apps/pytest_esp_eth.py +++ b/components/esp_eth/test_apps/pytest_esp_eth.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import contextlib import logging @@ -195,8 +195,10 @@ def ethernet_l2_test(dut: IdfDut, test_if: str = '') -> None: pipe_rcv, pipe_send = Pipe(False) tx_proc = Process(target=target_if.traffic_gen, args=(dut_mac, pipe_rcv, )) tx_proc.start() - dut.expect_exact('Ethernet Stopped') - pipe_send.send(0) # just send some dummy data + try: + dut.expect_exact('Ethernet Stopped') + finally: + pipe_send.send(0) # just send some dummy data to stop traffic generation tx_proc.join(5) if tx_proc.exitcode is None: tx_proc.terminate() @@ -204,17 +206,16 @@ def ethernet_l2_test(dut: IdfDut, test_if: str = '') -> None: dut.expect_unity_test_output(extra_before=res.group(1)) -def ethernet_heap_alloc_test(dut: IdfDut) -> None: - target_if = EthTestIntf(ETH_TYPE) - +def ethernet_heap_alloc_test(dut: IdfDut, test_if: str = '') -> None: + target_if = EthTestIntf(ETH_TYPE, test_if) dut.expect_exact('Press ENTER to see the list of tests') dut.write('\n') dut.expect_exact('Enter test for running.') dut.write('"heap utilization"') - res = dut.expect(r'DUT PHY: (\w+)') - dut_phy = res.group(1).decode('utf-8') - # W5500 does not support internal loopback, we need to loopback for it - if 'W5500' in dut_phy: + res = dut.expect(r'PHY loopback is (enabled|disabled)') + phy_loopback = res.group(1).decode('utf-8') + # Some chips do not support internal loopback, we need to loopback at test PC side + if phy_loopback == 'disabled': logging.info('Starting loopback server...') res = dut.expect( r'DUT MAC: ([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})' diff --git a/components/esp_eth/test_apps/sdkconfig.ci.default_dm9051 b/components/esp_eth/test_apps/sdkconfig.ci.default_dm9051 index 08b79b5332..8a6c58bc86 100644 --- a/components/esp_eth/test_apps/sdkconfig.ci.default_dm9051 +++ b/components/esp_eth/test_apps/sdkconfig.ci.default_dm9051 @@ -2,7 +2,23 @@ CONFIG_IDF_TARGET="esp32" CONFIG_UNITY_ENABLE_FIXTURE=y CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y -CONFIG_ESP_TASK_WDT=n +CONFIG_ETH_USE_ESP32_EMAC=y +CONFIG_ESP_TASK_WDT_EN=n -CONFIG_TARGET_USE_SPI_ETHERNET=y -CONFIG_TARGET_ETH_PHY_DEVICE_DM9051=y +# Config Ethernet Init +CONFIG_ETHERNET_SPI_SUPPORT=y +CONFIG_ETHERNET_INTERNAL_SUPPORT=n +CONFIG_ETHERNET_SPI_DEV0_DM9051=y +CONFIG_ETHERNET_SPI_DEV1_NONE=y +CONFIG_ETHERNET_SPI_CLOCK_MHZ=20 +CONFIG_ETHERNET_DEFAULT_EVENT_HANDLER=n + +# SPI specific test configuration +CONFIG_ETH_TEST_MAC_ADDR_UI=n +CONFIG_ETH_TEST_PHY_ADDRESS_DISABLED=y +CONFIG_ETH_TEST_STRESS_TEST_TASK_PRIO=20 + +# W5500 specific test configuration +# FILL_RX_BUFFER_ITERATIONS = 16384 / 1522 = 10.8 +CONFIG_ETH_TEST_FILL_RX_BUFFER_ITERATIONS=11 +CONFIG_ETH_TEST_10MB_LOOPBACK_DISABLED=y diff --git a/components/esp_eth/test_apps/sdkconfig.ci.default_dp83848 b/components/esp_eth/test_apps/sdkconfig.ci.default_dp83848 index 20f63f4651..b1a9cf6d4e 100644 --- a/components/esp_eth/test_apps/sdkconfig.ci.default_dp83848 +++ b/components/esp_eth/test_apps/sdkconfig.ci.default_dp83848 @@ -3,9 +3,17 @@ CONFIG_IDF_TARGET="esp32" CONFIG_UNITY_ENABLE_FIXTURE=y CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y CONFIG_ETH_USE_ESP32_EMAC=y -CONFIG_ESP_TASK_WDT=n +CONFIG_ESP_TASK_WDT_EN=n -CONFIG_TARGET_USE_INTERNAL_ETHERNET=y -CONFIG_TARGET_ETH_PHY_DEVICE_DP83848=y -CONFIG_ETH_RMII_CLK_OUTPUT=y -CONFIG_ETH_RMII_CLK_OUT_GPIO=17 +# Config Ethernet Init +CONFIG_ETHERNET_INTERNAL_SUPPORT=y +CONFIG_ETHERNET_PHY_DP83848=y +CONFIG_ETHERNET_PHY_INTERFACE_RMII=y +CONFIG_ETHERNET_RMII_CLK_OUTPUT=y +CONFIG_ETHERNET_RMII_CLK_EXT_LOOPBACK_EN=n +CONFIG_ETHERNET_RMII_CLK_GPIO=17 +CONFIG_ETHERNET_DEFAULT_EVENT_HANDLER=n + +# DP83848 specific test configuration +CONFIG_ETH_TEST_FILL_RX_BUFFER_ITERATIONS=10 +CONFIG_ETH_TEST_LOOPBACK_WITH_AUTONEGOTIATION_DISABLED=y diff --git a/components/esp_eth/test_apps/sdkconfig.ci.default_ip101 b/components/esp_eth/test_apps/sdkconfig.ci.default_ip101 index 2d0f8ffc08..13e63f3d1d 100644 --- a/components/esp_eth/test_apps/sdkconfig.ci.default_ip101 +++ b/components/esp_eth/test_apps/sdkconfig.ci.default_ip101 @@ -5,5 +5,10 @@ CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y CONFIG_ETH_USE_ESP32_EMAC=y CONFIG_ESP_TASK_WDT_EN=n -CONFIG_TARGET_USE_INTERNAL_ETHERNET=y -CONFIG_TARGET_ETH_PHY_DEVICE_IP101=y +# interface configuration +CONFIG_ETHERNET_INTERNAL_SUPPORT=y +CONFIG_ETHERNET_PHY_GENERIC=y +CONFIG_ETHERNET_DEFAULT_EVENT_HANDLER=n + +# specific test configuration +CONFIG_ETH_TEST_FILL_RX_BUFFER_ITERATIONS=10 diff --git a/components/esp_eth/test_apps/sdkconfig.ci.default_ip101_esp32p4 b/components/esp_eth/test_apps/sdkconfig.ci.default_ip101_esp32p4 index a73773ba25..1627a4a9dd 100644 --- a/components/esp_eth/test_apps/sdkconfig.ci.default_ip101_esp32p4 +++ b/components/esp_eth/test_apps/sdkconfig.ci.default_ip101_esp32p4 @@ -5,7 +5,11 @@ CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y CONFIG_ETH_USE_ESP32_EMAC=y CONFIG_ESP_TASK_WDT_EN=n -CONFIG_TARGET_USE_INTERNAL_ETHERNET=y -CONFIG_TARGET_ETH_PHY_DEVICE_IP101=y +# interface configuration +CONFIG_ETHERNET_INTERNAL_SUPPORT=y +CONFIG_ETHERNET_PHY_GENERIC=y +CONFIG_ETHERNET_DEFAULT_EVENT_HANDLER=n -CONFIG_TARGET_USE_DEFAULT_EMAC_CONFIG=y +# specific test configuration +CONFIG_ETH_TEST_FILL_RX_BUFFER_ITERATIONS=10 +CONFIG_ETH_TEST_10MB_LOOPBACK_IGNORE_FAILURES=y diff --git a/components/esp_eth/test_apps/sdkconfig.ci.default_ksz8041 b/components/esp_eth/test_apps/sdkconfig.ci.default_ksz8041 index 6a6547adf7..4ef04aaa16 100644 --- a/components/esp_eth/test_apps/sdkconfig.ci.default_ksz8041 +++ b/components/esp_eth/test_apps/sdkconfig.ci.default_ksz8041 @@ -3,7 +3,13 @@ CONFIG_IDF_TARGET="esp32" CONFIG_UNITY_ENABLE_FIXTURE=y CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y CONFIG_ETH_USE_ESP32_EMAC=y -CONFIG_ESP_TASK_WDT=n +CONFIG_ESP_TASK_WDT_EN=n -CONFIG_TARGET_USE_INTERNAL_ETHERNET=y -CONFIG_TARGET_ETH_PHY_DEVICE_KSZ8041=y +# Config Ethernet Init +CONFIG_ETHERNET_INTERNAL_SUPPORT=y +CONFIG_ETHERNET_PHY_KSZ80XX=y +CONFIG_ETHERNET_DEFAULT_EVENT_HANDLER=n + +# KSZ8041 specific test configuration +CONFIG_ETH_TEST_FILL_RX_BUFFER_ITERATIONS=10 +CONFIG_ETH_TEST_10MB_LOOPBACK_DISABLED=y diff --git a/components/esp_eth/test_apps/sdkconfig.ci.default_ksz8851snl b/components/esp_eth/test_apps/sdkconfig.ci.default_ksz8851snl index 2e869b6be8..0c309d12ed 100644 --- a/components/esp_eth/test_apps/sdkconfig.ci.default_ksz8851snl +++ b/components/esp_eth/test_apps/sdkconfig.ci.default_ksz8851snl @@ -2,7 +2,22 @@ CONFIG_IDF_TARGET="esp32" CONFIG_UNITY_ENABLE_FIXTURE=y CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y -CONFIG_ESP_TASK_WDT=n +CONFIG_ETH_USE_ESP32_EMAC=y +CONFIG_ESP_TASK_WDT_EN=n -CONFIG_TARGET_USE_SPI_ETHERNET=y -CONFIG_TARGET_ETH_PHY_DEVICE_KSZ8851SNL=y +# Config Ethernet Init +CONFIG_ETHERNET_SPI_SUPPORT=y +CONFIG_ETHERNET_INTERNAL_SUPPORT=n +CONFIG_ETHERNET_SPI_DEV0_KSZ8851SNL=y +CONFIG_ETHERNET_SPI_DEV1_NONE=y +CONFIG_ETHERNET_SPI_CLOCK_MHZ=20 +CONFIG_ETHERNET_DEFAULT_EVENT_HANDLER=n + +# SPI specific test configuration +CONFIG_ETH_TEST_MAC_ADDR_UI=n +CONFIG_ETH_TEST_PHY_ADDRESS_DISABLED=y +CONFIG_ETH_TEST_STRESS_TEST_TASK_PRIO=20 + +# KSZ8851SNL specific test configuration +# FILL_RX_BUFFER_ITERATIONS = 12288 / 1522 = 8.1 +CONFIG_ETH_TEST_FILL_RX_BUFFER_ITERATIONS=9 diff --git a/components/esp_eth/test_apps/sdkconfig.ci.default_lan8720 b/components/esp_eth/test_apps/sdkconfig.ci.default_lan8720 index c13b8b5f2c..b6ed64ad58 100644 --- a/components/esp_eth/test_apps/sdkconfig.ci.default_lan8720 +++ b/components/esp_eth/test_apps/sdkconfig.ci.default_lan8720 @@ -5,7 +5,17 @@ CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y CONFIG_ETH_USE_ESP32_EMAC=y CONFIG_ESP_TASK_WDT_EN=n -CONFIG_TARGET_USE_INTERNAL_ETHERNET=y -CONFIG_TARGET_ETH_PHY_DEVICE_LAN8720=y -CONFIG_ETH_RMII_CLK_OUTPUT=y -CONFIG_ETH_RMII_CLK_OUT_GPIO=17 +# interface configuration +CONFIG_ETHERNET_INTERNAL_SUPPORT=y +CONFIG_ETHERNET_PHY_LAN87XX=y +CONFIG_ETHERNET_PHY_INTERFACE_RMII=y +CONFIG_ETHERNET_RMII_CLK_OUTPUT=y +CONFIG_ETHERNET_RMII_CLK_EXT_LOOPBACK_EN=n +CONFIG_ETHERNET_RMII_CLK_GPIO=17 +CONFIG_ETHERNET_PHY_ADDR=0 +CONFIG_ETHERNET_DEFAULT_EVENT_HANDLER=n + +# LAN8720 specific test configuration +CONFIG_ETH_TEST_FILL_RX_BUFFER_ITERATIONS=10 +CONFIG_ETH_TEST_LOOPBACK_WITH_AUTONEGOTIATION_DISABLED=y +CONFIG_ETH_TEST_LAN8720_ERRATA_ENABLED=y diff --git a/components/esp_eth/test_apps/sdkconfig.ci.default_rtl8201 b/components/esp_eth/test_apps/sdkconfig.ci.default_rtl8201 index 15be08d2fc..545e9154a4 100644 --- a/components/esp_eth/test_apps/sdkconfig.ci.default_rtl8201 +++ b/components/esp_eth/test_apps/sdkconfig.ci.default_rtl8201 @@ -3,11 +3,18 @@ CONFIG_IDF_TARGET="esp32" CONFIG_UNITY_ENABLE_FIXTURE=y CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y CONFIG_ETH_USE_ESP32_EMAC=y -CONFIG_ESP_TASK_WDT=n +CONFIG_ESP_TASK_WDT_EN=n -CONFIG_TARGET_USE_INTERNAL_ETHERNET=y -CONFIG_TARGET_ETH_PHY_DEVICE_RTL8201=y +# Config Ethernet Init +CONFIG_ETHERNET_PHY_RTL8201=y +CONFIG_ETHERNET_INTERNAL_SUPPORT=y +CONFIG_ETHERNET_RMII_CLK_INPUT=y +CONFIG_ETHERNET_MDC_GPIO=16 +CONFIG_ETHERNET_MDIO_GPIO=17 +CONFIG_ETHERNET_PHY_RST_GPIO=-1 +CONFIG_ETHERNET_PHY_ADDR=0 +CONFIG_ETHERNET_DEFAULT_EVENT_HANDLER=n -CONFIG_TARGET_USE_DEFAULT_EMAC_CONFIG=n -CONFIG_TARGET_IO_MDC=16 -CONFIG_TARGET_IO_MDIO=17 +# RTL8201 specific test configuration +CONFIG_ETH_TEST_FILL_RX_BUFFER_ITERATIONS=10 +CONFIG_ETH_TEST_LOOPBACK_WITH_AUTONEGOTIATION_DISABLED=y diff --git a/components/esp_eth/test_apps/sdkconfig.ci.default_w5500 b/components/esp_eth/test_apps/sdkconfig.ci.default_w5500 index c60a0a7227..5dcd27f41b 100644 --- a/components/esp_eth/test_apps/sdkconfig.ci.default_w5500 +++ b/components/esp_eth/test_apps/sdkconfig.ci.default_w5500 @@ -2,7 +2,24 @@ CONFIG_IDF_TARGET="esp32" CONFIG_UNITY_ENABLE_FIXTURE=y CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y -CONFIG_ESP_TASK_WDT=n +CONFIG_ETH_USE_ESP32_EMAC=y +CONFIG_ESP_TASK_WDT_EN=n -CONFIG_TARGET_USE_SPI_ETHERNET=y -CONFIG_TARGET_ETH_PHY_DEVICE_W5500=y +# Config Ethernet Init +CONFIG_ETHERNET_SPI_SUPPORT=y +CONFIG_ETHERNET_INTERNAL_SUPPORT=n +CONFIG_ETHERNET_SPI_DEV0_W5500=y +CONFIG_ETHERNET_SPI_DEV1_NONE=y +CONFIG_ETHERNET_SPI_CLOCK_MHZ=20 +CONFIG_ETHERNET_DEFAULT_EVENT_HANDLER=n + +# SPI specific test configuration +CONFIG_ETH_TEST_MAC_ADDR_UI=n +CONFIG_ETH_TEST_PHY_ADDRESS_DISABLED=y +CONFIG_ETH_TEST_STRESS_TEST_TASK_PRIO=20 + +# W5500 specific test configuration +# FILL_RX_BUFFER_ITERATIONS = 16384 / 1522 = 10.8 +CONFIG_ETH_TEST_FILL_RX_BUFFER_ITERATIONS=11 +CONFIG_ETH_TEST_LOOPBACK_DISABLED=y +CONFIG_ETH_TEST_W5500_IP6_MCAST_DEVIATION_ENABLED=y diff --git a/components/esp_eth/test_apps/sdkconfig.ci.poll_dm9051 b/components/esp_eth/test_apps/sdkconfig.ci.poll_dm9051 index 1ee1cbaf41..d5fa233e43 100644 --- a/components/esp_eth/test_apps/sdkconfig.ci.poll_dm9051 +++ b/components/esp_eth/test_apps/sdkconfig.ci.poll_dm9051 @@ -2,9 +2,26 @@ CONFIG_IDF_TARGET="esp32" CONFIG_UNITY_ENABLE_FIXTURE=y CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y -CONFIG_ESP_TASK_WDT=n +CONFIG_ESP_TASK_WDT_EN=n -CONFIG_TARGET_USE_SPI_ETHERNET=y -CONFIG_TARGET_ETH_PHY_DEVICE_DM9051=y +# Config Ethernet Init +CONFIG_ETHERNET_SPI_SUPPORT=y +CONFIG_ETHERNET_INTERNAL_SUPPORT=n +CONFIG_ETHERNET_SPI_DEV0_DM9051=y +CONFIG_ETHERNET_SPI_DEV1_NONE=y +CONFIG_ETHERNET_SPI_CLOCK_MHZ=20 +CONFIG_ETHERNET_DEFAULT_EVENT_HANDLER=n -CONFIG_TARGET_ETH_SPI_POLL_MS=10 +# Polling mode (interrupt GPIO -1 = polling, polling period 10 ms) +CONFIG_ETHERNET_SPI_INT0_GPIO=-1 +CONFIG_ETHERNET_SPI_POLLING0_MS_VAL=10 + +# SPI specific test configuration +CONFIG_ETH_TEST_MAC_ADDR_UI=n +CONFIG_ETH_TEST_PHY_ADDRESS_DISABLED=y +CONFIG_ETH_TEST_STRESS_TEST_TASK_PRIO=20 + +# W5500 specific test configuration +# FILL_RX_BUFFER_ITERATIONS = 16384 / 1522 = 10.8 +CONFIG_ETH_TEST_FILL_RX_BUFFER_ITERATIONS=11 +CONFIG_ETH_TEST_10MB_LOOPBACK_DISABLED=y diff --git a/components/esp_eth/test_apps/sdkconfig.ci.poll_ksz8851snl b/components/esp_eth/test_apps/sdkconfig.ci.poll_ksz8851snl index ef93590fed..91f0343f71 100644 --- a/components/esp_eth/test_apps/sdkconfig.ci.poll_ksz8851snl +++ b/components/esp_eth/test_apps/sdkconfig.ci.poll_ksz8851snl @@ -2,9 +2,25 @@ CONFIG_IDF_TARGET="esp32" CONFIG_UNITY_ENABLE_FIXTURE=y CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y -CONFIG_ESP_TASK_WDT=n +CONFIG_ESP_TASK_WDT_EN=n -CONFIG_TARGET_USE_SPI_ETHERNET=y -CONFIG_TARGET_ETH_PHY_DEVICE_KSZ8851SNL=y +# Config Ethernet Init +CONFIG_ETHERNET_SPI_SUPPORT=y +CONFIG_ETHERNET_INTERNAL_SUPPORT=n +CONFIG_ETHERNET_SPI_DEV0_KSZ8851SNL=y +CONFIG_ETHERNET_SPI_DEV1_NONE=y +CONFIG_ETHERNET_SPI_CLOCK_MHZ=20 +CONFIG_ETHERNET_DEFAULT_EVENT_HANDLER=n -CONFIG_TARGET_ETH_SPI_POLL_MS=10 +# Polling mode (interrupt GPIO -1 = polling, polling period 10 ms) +CONFIG_ETHERNET_SPI_INT0_GPIO=-1 +CONFIG_ETHERNET_SPI_POLLING0_MS_VAL=10 + +# SPI specific test configuration +CONFIG_ETH_TEST_MAC_ADDR_UI=n +CONFIG_ETH_TEST_PHY_ADDRESS_DISABLED=y +CONFIG_ETH_TEST_STRESS_TEST_TASK_PRIO=20 + +# KSZ8851SNL specific test configuration +# FILL_RX_BUFFER_ITERATIONS = 12288 / 1522 = 8.1 +CONFIG_ETH_TEST_FILL_RX_BUFFER_ITERATIONS=9 diff --git a/components/esp_eth/test_apps/sdkconfig.ci.poll_w5500 b/components/esp_eth/test_apps/sdkconfig.ci.poll_w5500 index e156de573c..bf58524555 100644 --- a/components/esp_eth/test_apps/sdkconfig.ci.poll_w5500 +++ b/components/esp_eth/test_apps/sdkconfig.ci.poll_w5500 @@ -2,9 +2,27 @@ CONFIG_IDF_TARGET="esp32" CONFIG_UNITY_ENABLE_FIXTURE=y CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y -CONFIG_ESP_TASK_WDT=n +CONFIG_ESP_TASK_WDT_EN=n -CONFIG_TARGET_USE_SPI_ETHERNET=y -CONFIG_TARGET_ETH_PHY_DEVICE_W5500=y +# Config Ethernet Init +CONFIG_ETHERNET_SPI_SUPPORT=y +CONFIG_ETHERNET_INTERNAL_SUPPORT=n +CONFIG_ETHERNET_SPI_DEV0_W5500=y +CONFIG_ETHERNET_SPI_DEV1_NONE=y +CONFIG_ETHERNET_SPI_CLOCK_MHZ=20 +CONFIG_ETHERNET_DEFAULT_EVENT_HANDLER=n -CONFIG_TARGET_ETH_SPI_POLL_MS=10 +# Polling mode (interrupt GPIO -1 = polling, polling period 10 ms) +CONFIG_ETHERNET_SPI_INT0_GPIO=-1 +CONFIG_ETHERNET_SPI_POLLING0_MS_VAL=10 + +# SPI specific test configuration +CONFIG_ETH_TEST_MAC_ADDR_UI=n +CONFIG_ETH_TEST_PHY_ADDRESS_DISABLED=y +CONFIG_ETH_TEST_STRESS_TEST_TASK_PRIO=20 + +# W5500 specific test configuration +# FILL_RX_BUFFER_ITERATIONS = 16384 / 1522 = 10.8 +CONFIG_ETH_TEST_FILL_RX_BUFFER_ITERATIONS=11 +CONFIG_ETH_TEST_LOOPBACK_DISABLED=y +CONFIG_ETH_TEST_W5500_IP6_MCAST_DEVIATION_ENABLED=y diff --git a/components/esp_eth/test_apps/sdkconfig.ci.release_ip101 b/components/esp_eth/test_apps/sdkconfig.ci.release_ip101 index baa48405c5..bb4413996d 100644 --- a/components/esp_eth/test_apps/sdkconfig.ci.release_ip101 +++ b/components/esp_eth/test_apps/sdkconfig.ci.release_ip101 @@ -6,7 +6,12 @@ CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y CONFIG_UNITY_ENABLE_FIXTURE=y CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y CONFIG_ETH_USE_ESP32_EMAC=y -CONFIG_ESP_TASK_WDT=n +CONFIG_ESP_TASK_WDT_EN=n -CONFIG_TARGET_USE_INTERNAL_ETHERNET=y -CONFIG_TARGET_ETH_PHY_DEVICE_IP101=y +# interface configuration +CONFIG_ETHERNET_INTERNAL_SUPPORT=y +CONFIG_ETHERNET_PHY_GENERIC=y +CONFIG_ETHERNET_DEFAULT_EVENT_HANDLER=n + +# specific test configuration +CONFIG_ETH_TEST_FILL_RX_BUFFER_ITERATIONS=10 diff --git a/components/esp_eth/test_apps/sdkconfig.ci.rmii_clko_esp32p4 b/components/esp_eth/test_apps/sdkconfig.ci.rmii_clko_esp32p4 index 5178abce87..c856cdc4ab 100644 --- a/components/esp_eth/test_apps/sdkconfig.ci.rmii_clko_esp32p4 +++ b/components/esp_eth/test_apps/sdkconfig.ci.rmii_clko_esp32p4 @@ -5,13 +5,15 @@ CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y CONFIG_ETH_USE_ESP32_EMAC=y CONFIG_ESP_TASK_WDT_EN=n -CONFIG_TARGET_USE_INTERNAL_ETHERNET=y -CONFIG_TARGET_ETH_PHY_DEVICE_IP101=y +# interface configuration +CONFIG_ETHERNET_INTERNAL_SUPPORT=y +CONFIG_ETHERNET_PHY_GENERIC=y +CONFIG_ETHERNET_DEFAULT_EVENT_HANDLER=n -CONFIG_TARGET_USE_DEFAULT_EMAC_CONFIG=y - -CONFIG_TARGET_RMII_CLK_OUT=y +CONFIG_ETHERNET_PHY_INTERFACE_RMII=y +CONFIG_ETHERNET_RMII_CLK_OUTPUT=y +CONFIG_ETHERNET_RMII_CLK_EXT_LOOPBACK_EN=y # Test board needs to be modified! # Connect GPIO23 to GPIO32 via wire. -CONFIG_TARGET_RMII_CLK_OUT_GPIO=23 -CONFIG_TARGET_RMII_CLK_IN_GPIO=32 +CONFIG_ETHERNET_RMII_CLK_GPIO=23 +CONFIG_ETHERNET_RMII_CLK_EXT_LOOPBACK_IN_GPIO=32 diff --git a/components/esp_eth/test_apps/sdkconfig.ci.single_core_ip101 b/components/esp_eth/test_apps/sdkconfig.ci.single_core_ip101 index 98601e1b09..00602fe29d 100644 --- a/components/esp_eth/test_apps/sdkconfig.ci.single_core_ip101 +++ b/components/esp_eth/test_apps/sdkconfig.ci.single_core_ip101 @@ -6,7 +6,12 @@ CONFIG_ESP32_RTCDATA_IN_FAST_MEM=y CONFIG_UNITY_ENABLE_FIXTURE=y CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y CONFIG_ETH_USE_ESP32_EMAC=y -CONFIG_ESP_TASK_WDT=n +CONFIG_ESP_TASK_WDT_EN=n -CONFIG_TARGET_USE_INTERNAL_ETHERNET=y -CONFIG_TARGET_ETH_PHY_DEVICE_IP101=y +# interface configuration +CONFIG_ETHERNET_INTERNAL_SUPPORT=y +CONFIG_ETHERNET_PHY_GENERIC=y +CONFIG_ETHERNET_DEFAULT_EVENT_HANDLER=n + +# specific test configuration +CONFIG_ETH_TEST_FILL_RX_BUFFER_ITERATIONS=10 diff --git a/tools/ci/ignore_build_warnings.txt b/tools/ci/ignore_build_warnings.txt index ca30cdaf9b..2b80a13215 100644 --- a/tools/ci/ignore_build_warnings.txt +++ b/tools/ci/ignore_build_warnings.txt @@ -41,3 +41,4 @@ warning: unknown kconfig symbol 'UNITY_FREERTOS_STACK_SIZE' assigned to '12288' warning: unknown kconfig symbol 'WPA3_SAE' assigned to 'y' in .*/components/wpa_supplicant/test_apps/sdkconfig.defaults ld: warning: ignoring duplicate libraries archive library: .+ the table of contents is empty +WARNING: The following Kconfig variables were used in "if" clauses