From c40e4eb4996cd16785cb5a4485f8b62fab57ad4e Mon Sep 17 00:00:00 2001 From: Ondrej Date: Tue, 8 Nov 2022 16:53:16 +0000 Subject: [PATCH 1/2] esp_eth: DM9051 stop/start issue fixed --- components/esp_eth/src/esp_eth_mac_dm9051.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components/esp_eth/src/esp_eth_mac_dm9051.c b/components/esp_eth/src/esp_eth_mac_dm9051.c index 55885826f6..9a1fe6e285 100644 --- a/components/esp_eth/src/esp_eth_mac_dm9051.c +++ b/components/esp_eth/src/esp_eth_mac_dm9051.c @@ -314,12 +314,8 @@ static esp_err_t dm9051_setup_default(emac_dm9051_t *emac) ESP_GOTO_ON_ERROR(dm9051_register_write(emac, DM9051_RLENCR, 0x00), err, TAG, "write RLENCR failed"); /* 3K-byte for TX and 13K-byte for RX */ ESP_GOTO_ON_ERROR(dm9051_register_write(emac, DM9051_MEMSCR, 0x00), err, TAG, "write MEMSCR failed"); - /* reset tx and rx memory pointer */ - ESP_GOTO_ON_ERROR(dm9051_register_write(emac, DM9051_MPTRCR, MPTRCR_RST_RX | MPTRCR_RST_TX), err, TAG, "write MPTRCR failed"); /* clear network status: wakeup event, tx complete */ ESP_GOTO_ON_ERROR(dm9051_register_write(emac, DM9051_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END), err, TAG, "write NSR failed"); - /* clear interrupt status */ - ESP_GOTO_ON_ERROR(dm9051_register_write(emac, DM9051_ISR, ISR_CLR_STATUS), err, TAG, "write ISR failed"); return ESP_OK; err: return ret; @@ -351,6 +347,10 @@ static esp_err_t emac_dm9051_start(esp_eth_mac_t *mac) { esp_err_t ret = ESP_OK; emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent); + /* reset tx and rx memory pointer */ + ESP_GOTO_ON_ERROR(dm9051_register_write(emac, DM9051_MPTRCR, MPTRCR_RST_RX | MPTRCR_RST_TX), err, TAG, "write MPTRCR failed"); + /* clear interrupt status */ + ESP_GOTO_ON_ERROR(dm9051_register_write(emac, DM9051_ISR, ISR_CLR_STATUS), err, TAG, "write ISR failed"); /* enable only Rx related interrupts as others are processed synchronously */ ESP_GOTO_ON_ERROR(dm9051_register_write(emac, DM9051_IMR, IMR_PAR | IMR_PRI), err, TAG, "write IMR failed"); /* enable rx */ From 2bf7255285b054af8e1e5d0711e1c41c2f5d0a85 Mon Sep 17 00:00:00 2001 From: Ondrej Date: Tue, 8 Nov 2022 16:54:39 +0000 Subject: [PATCH 2/2] Ethernet related tests improvements esp_eth: tests migrated to pytest and added support of multiple Ethernet devices esp_netif: l2tap test migrated to pytest --- .gitlab/ci/target-test.yml | 8 + components/esp_eth/test/CMakeLists.txt | 5 - components/esp_eth/test_apps/CMakeLists.txt | 2 + components/esp_eth/test_apps/README.md | 4 +- .../esp_eth/test_apps/main/CMakeLists.txt | 11 +- .../esp_eth/test_apps/main/Kconfig.projbuild | 72 +++- .../main}/dl_espressif_com_root_cert.pem | 0 .../esp_eth/test_apps/main/esp_eth_test.c | 408 ------------------ .../main/esp_eth_test_apps.c} | 223 ++++------ .../test_apps/main/esp_eth_test_common.c | 173 ++++++++ .../test_apps/main/esp_eth_test_common.h | 42 ++ .../esp_eth/test_apps/main/esp_eth_test_hal.c | 255 +++++++++++ .../esp_eth/test_apps/main/esp_eth_test_l2.c | 277 ++++++++++++ .../test_apps/main/esp_eth_test_main.c | 11 + .../esp_eth/test_apps/pytest_esp_eth.py | 85 +++- .../test_apps/sdkconfig.ci.default_dm9051 | 8 + .../test_apps/sdkconfig.ci.default_dp83848 | 9 + ...ig.ci.ip101 => sdkconfig.ci.default_ip101} | 2 + .../test_apps/sdkconfig.ci.default_ksz80xx | 11 + .../test_apps/sdkconfig.ci.default_ksz8851snl | 8 + ...i.lan8720 => sdkconfig.ci.default_lan8720} | 2 + .../test_apps/sdkconfig.ci.default_rtl8201 | 9 + .../test_apps/sdkconfig.ci.default_w5500 | 8 + .../test_apps/sdkconfig.ci.release_ip101 | 12 + .../test_apps/sdkconfig.ci.single_core_ip101 | 13 + components/esp_netif/.build-test-rules.yml | 8 +- .../{ => test_app_esp_netif}/CMakeLists.txt | 0 .../{ => test_app_esp_netif}/README.md | 0 .../main/CMakeLists.txt | 0 .../main/esp_netif_test.c | 5 + .../pytest_esp_netif.py | 0 .../sdkconfig.defaults | 0 .../test_app_vfs_l2tap/CMakeLists.txt | 10 + .../test_apps/test_app_vfs_l2tap/README.md | 2 + .../test_app_vfs_l2tap/main/CMakeLists.txt | 3 + .../test_app_vfs_l2tap/main}/test_vfs_l2tap.c | 31 +- .../pytest_esp_vfs_l2tap.py | 15 + .../test_app_vfs_l2tap/sdkconfig.defaults | 4 + .../components/ethernet_init/ethernet_init.c | 4 +- tools/unit-test-app/configs/netif_l2tap | 3 - 40 files changed, 1143 insertions(+), 600 deletions(-) delete mode 100644 components/esp_eth/test/CMakeLists.txt rename components/esp_eth/{test => test_apps/main}/dl_espressif_com_root_cert.pem (100%) delete mode 100644 components/esp_eth/test_apps/main/esp_eth_test.c rename components/esp_eth/{test/test_emac.c => test_apps/main/esp_eth_test_apps.c} (72%) create mode 100644 components/esp_eth/test_apps/main/esp_eth_test_common.c create 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_hal.c create mode 100644 components/esp_eth/test_apps/main/esp_eth_test_l2.c create mode 100644 components/esp_eth/test_apps/main/esp_eth_test_main.c create mode 100644 components/esp_eth/test_apps/sdkconfig.ci.default_dm9051 create mode 100644 components/esp_eth/test_apps/sdkconfig.ci.default_dp83848 rename components/esp_eth/test_apps/{sdkconfig.ci.ip101 => sdkconfig.ci.default_ip101} (82%) create mode 100644 components/esp_eth/test_apps/sdkconfig.ci.default_ksz80xx create mode 100644 components/esp_eth/test_apps/sdkconfig.ci.default_ksz8851snl rename components/esp_eth/test_apps/{sdkconfig.ci.lan8720 => sdkconfig.ci.default_lan8720} (86%) create mode 100644 components/esp_eth/test_apps/sdkconfig.ci.default_rtl8201 create mode 100644 components/esp_eth/test_apps/sdkconfig.ci.default_w5500 create mode 100644 components/esp_eth/test_apps/sdkconfig.ci.release_ip101 create mode 100644 components/esp_eth/test_apps/sdkconfig.ci.single_core_ip101 rename components/esp_netif/test_apps/{ => test_app_esp_netif}/CMakeLists.txt (100%) rename components/esp_netif/test_apps/{ => test_app_esp_netif}/README.md (100%) rename components/esp_netif/test_apps/{ => test_app_esp_netif}/main/CMakeLists.txt (100%) rename components/esp_netif/test_apps/{ => test_app_esp_netif}/main/esp_netif_test.c (98%) rename components/esp_netif/test_apps/{ => test_app_esp_netif}/pytest_esp_netif.py (100%) rename components/esp_netif/test_apps/{ => test_app_esp_netif}/sdkconfig.defaults (100%) create mode 100644 components/esp_netif/test_apps/test_app_vfs_l2tap/CMakeLists.txt create mode 100644 components/esp_netif/test_apps/test_app_vfs_l2tap/README.md create mode 100644 components/esp_netif/test_apps/test_app_vfs_l2tap/main/CMakeLists.txt rename components/esp_netif/{test => test_apps/test_app_vfs_l2tap/main}/test_vfs_l2tap.c (98%) create mode 100644 components/esp_netif/test_apps/test_app_vfs_l2tap/pytest_esp_vfs_l2tap.py create mode 100644 components/esp_netif/test_apps/test_app_vfs_l2tap/sdkconfig.defaults delete mode 100644 tools/unit-test-app/configs/netif_l2tap diff --git a/.gitlab/ci/target-test.yml b/.gitlab/ci/target-test.yml index 9f72b08eb2..70be80b17a 100644 --- a/.gitlab/ci/target-test.yml +++ b/.gitlab/ci/target-test.yml @@ -346,6 +346,14 @@ component_ut_pytest_esp32_lan8720: - build_pytest_components_esp32 tags: [ esp32, lan8720 ] +component_ut_pytest_esp32_ethernet: + extends: + - .pytest_components_dir_template + - .rules:test:component_ut-esp32 + needs: + - build_pytest_components_esp32 + tags: [ esp32, ethernet ] + component_ut_pytest_esp32_flash_encryption: extends: - .pytest_components_dir_template diff --git a/components/esp_eth/test/CMakeLists.txt b/components/esp_eth/test/CMakeLists.txt deleted file mode 100644 index c90a0534ed..0000000000 --- a/components/esp_eth/test/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -idf_component_register(SRC_DIRS . - PRIV_INCLUDE_DIRS . - PRIV_REQUIRES cmock test_utils esp_eth esp_http_client esp_netif - EMBED_TXTFILES dl_espressif_com_root_cert.pem) -target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format") diff --git a/components/esp_eth/test_apps/CMakeLists.txt b/components/esp_eth/test_apps/CMakeLists.txt index 060c819aaa..7e4b7ad8d3 100644 --- a/components/esp_eth/test_apps/CMakeLists.txt +++ b/components/esp_eth/test_apps/CMakeLists.txt @@ -1,6 +1,8 @@ # 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 a65add8cb4..0e2cf8cb13 100644 --- a/components/esp_eth/test_apps/README.md +++ b/components/esp_eth/test_apps/README.md @@ -2,10 +2,8 @@ | Supported Targets | ESP32 | | ----------------- | ----- | -This test app is used to test MAC layer behavior with different PHY chips: +This test app is used to test Ethernet MAC behavior with different chips. -- IP101 -- LAN8720 ## Prerequisites Install third part Python packages: diff --git a/components/esp_eth/test_apps/main/CMakeLists.txt b/components/esp_eth/test_apps/main/CMakeLists.txt index 3c5afe17b8..95df0f1a17 100644 --- a/components/esp_eth/test_apps/main/CMakeLists.txt +++ b/components/esp_eth/test_apps/main/CMakeLists.txt @@ -1,5 +1,10 @@ -idf_component_register(SRCS "esp_eth_test.c" +idf_component_register(SRCS "esp_eth_test_apps.c" + "esp_eth_test_l2.c" + "esp_eth_test_hal.c" + "esp_eth_test_common.c" + "esp_eth_test_main.c" INCLUDE_DIRS "." PRIV_INCLUDE_DIRS "." - PRIV_REQUIRES unity esp_eth esp_netif) -target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format") + PRIV_REQUIRES unity test_utils esp_eth esp_netif esp_http_client + 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 b5b4cfabaa..119bf8b3c3 100644 --- a/components/esp_eth/test_apps/main/Kconfig.projbuild +++ b/components/esp_eth/test_apps/main/Kconfig.projbuild @@ -1,14 +1,70 @@ menu "esp_eth TEST_APPS Configuration" - choice TARGET_ETH_PHY_DEVICE + choice TARGET_ETH_CONFIG prompt "Ethernet peripheral device" - default TARGET_ETH_PHY_DEVICE_IP101 + default TARGET_USE_INTERNAL_ETHERNET help - Select one of the devices listed here + Select type of Ethernet interface. + + 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 TARGET_USE_SPI_ETHERNET + bool "SPI Ethernet" + select ETH_USE_SPI_ETHERNET + help + Use external SPI-Ethernet module(s). + endchoice # TARGET_ETH_CONFIG + + 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 TARGET_ETH_PHY_DEVICE_IP101 + bool "IP101" + config TARGET_ETH_PHY_DEVICE_LAN87XX + bool "LAN8720" + config TARGET_ETH_PHY_DEVICE_KSZ80XX + bool "KSZ80xx" + config TARGET_ETH_PHY_DEVICE_RTL8201 + bool "RTL8201" + config TARGET_ETH_PHY_DEVICE_DP83848 + bool "DP83848" + endchoice # TARGET_ETH_PHY_DEVICE + 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 12 + help + Set the clock speed (MHz) of SPI interface. + + endif # TARGET_USE_SPI_ETHERNET - config TARGET_ETH_PHY_DEVICE_IP101 - bool "IP101" - config TARGET_ETH_PHY_DEVICE_LAN87XX - bool "LAN8720" - endchoice endmenu diff --git a/components/esp_eth/test/dl_espressif_com_root_cert.pem b/components/esp_eth/test_apps/main/dl_espressif_com_root_cert.pem similarity index 100% rename from components/esp_eth/test/dl_espressif_com_root_cert.pem rename to components/esp_eth/test_apps/main/dl_espressif_com_root_cert.pem diff --git a/components/esp_eth/test_apps/main/esp_eth_test.c b/components/esp_eth/test_apps/main/esp_eth_test.c deleted file mode 100644 index d8b5b097a5..0000000000 --- a/components/esp_eth/test_apps/main/esp_eth_test.c +++ /dev/null @@ -1,408 +0,0 @@ -#include -#include -#include "freertos/FreeRTOS.h" -#include "freertos/event_groups.h" -#include "esp_event.h" -#include "unity.h" -#include "esp_netif.h" -#include "esp_eth.h" -#include "sdkconfig.h" -#include "lwip/sockets.h" - -#define ETH_START_BIT BIT(0) -#define ETH_STOP_BIT BIT(1) -#define ETH_CONNECT_BIT BIT(2) - -#define ETH_BROADCAST_RECV_BIT BIT(0) -#define ETH_MULTICAST_RECV_BIT BIT(1) -#define ETH_UNICAST_RECV_BIT BIT(2) - -#define POKE_REQ 0xFA -#define POKE_RESP 0xFB -#define DUMMY_TRAFFIC 0xFF - -typedef struct { - uint8_t dest[6]; - uint8_t src[6]; - uint16_t proto; - uint8_t data[]; -} __attribute__((__packed__)) emac_frame_t; - -static 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: - xEventGroupSetBits(eth_event_group, ETH_CONNECT_BIT); - break; - case ETHERNET_EVENT_DISCONNECTED: - break; - case ETHERNET_EVENT_START: - xEventGroupSetBits(eth_event_group, ETH_START_BIT); - break; - case ETHERNET_EVENT_STOP: - xEventGroupSetBits(eth_event_group, ETH_STOP_BIT); - break; - default: - break; - } -} - -TEST_CASE("start_and_stop", "[esp_eth]") -{ - EventGroupHandle_t eth_event_group = xEventGroupCreate(); - TEST_ASSERT(eth_event_group != NULL); - - eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); // apply default MAC configuration - eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG(); - esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); // create MAC instance - TEST_ASSERT_NOT_NULL(mac); - eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); // apply default PHY configuration -#if defined(CONFIG_TARGET_ETH_PHY_DEVICE_IP101) - esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config); // create PHY instance -#elif defined(CONFIG_TARGET_ETH_PHY_DEVICE_LAN87XX) - esp_eth_phy_t *phy = esp_eth_phy_new_lan87xx(&phy_config); -#endif - 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_ASSERT_EQUAL(ESP_OK, esp_eth_driver_install(&config, ð_handle)); // install driver - TEST_ASSERT_NOT_NULL(eth_handle); - TEST_ASSERT_EQUAL(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)); - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_start(eth_handle)); // start Ethernet driver state machine - - EventBits_t bits = 0; - bits = xEventGroupWaitBits(eth_event_group, ETH_START_BIT, true, true, pdMS_TO_TICKS(3000)); - TEST_ASSERT((bits & ETH_START_BIT) == ETH_START_BIT); - - TEST_ASSERT_EQUAL(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); - - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete_default()); - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_driver_uninstall(eth_handle)); - phy->del(phy); - mac->del(mac); - vEventGroupDelete(eth_event_group); -} - -TEST_CASE("get_set_mac", "[esp_eth]") -{ - EventGroupHandle_t eth_event_group = xEventGroupCreate(); - TEST_ASSERT(eth_event_group != NULL); - - eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); // apply default MAC configuration - eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG(); - esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); // create MAC instance - TEST_ASSERT_NOT_NULL(mac); - eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); // apply default PHY configuration -#if defined(CONFIG_TARGET_ETH_PHY_DEVICE_IP101) - esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config); // create PHY instance -#elif defined(CONFIG_TARGET_ETH_PHY_DEVICE_LAN87XX) - esp_eth_phy_t *phy = esp_eth_phy_new_lan87xx(&phy_config); -#endif - 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_ASSERT_EQUAL(ESP_OK, esp_eth_driver_install(&config, ð_handle)); // install driver - TEST_ASSERT_NOT_NULL(eth_handle); - TEST_ASSERT_EQUAL(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)); - TEST_ASSERT_EQUAL(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(3000)); - TEST_ASSERT((bits & ETH_CONNECT_BIT) == ETH_CONNECT_BIT); - - uint8_t mac_addr[6] = {}; - TEST_ASSERT_EQUAL(ESP_OK, mac->get_addr(mac, mac_addr)); - TEST_ASSERT_BITS(0b00000011, 0b00, mac_addr[0]); // Check UL&IG, should be UI - mac_addr[5] ^= mac_addr[4]; - TEST_ASSERT_EQUAL(ESP_OK, mac->set_addr(mac, mac_addr)); - uint8_t new_mac_addr[6] = {}; - TEST_ASSERT_EQUAL(ESP_OK, mac->get_addr(mac, new_mac_addr)); - TEST_ASSERT_EQUAL(0, memcmp(mac_addr, new_mac_addr, 6)); - - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_stop(eth_handle)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete_default()); - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_driver_uninstall(eth_handle)); - phy->del(phy); - mac->del(mac); - vEventGroupDelete(eth_event_group); -} - -TEST_CASE("ethernet_broadcast_transmit", "[esp_eth]") -{ - EventGroupHandle_t eth_event_group = xEventGroupCreate(); - TEST_ASSERT(eth_event_group != NULL); - - eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); // apply default MAC configuration - eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG(); - esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); // create MAC instance - TEST_ASSERT_NOT_NULL(mac); - eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); // apply default PHY configuration -#if defined(CONFIG_TARGET_ETH_PHY_DEVICE_IP101) - esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config); // create PHY instance -#elif defined(CONFIG_TARGET_ETH_PHY_DEVICE_LAN87XX) - esp_eth_phy_t *phy = esp_eth_phy_new_lan87xx(&phy_config); -#endif - 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_ASSERT_EQUAL(ESP_OK, esp_eth_driver_install(&config, ð_handle)); // install driver - TEST_ASSERT_NOT_NULL(eth_handle); - TEST_ASSERT_EQUAL(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)); - TEST_ASSERT_EQUAL(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(3000)); - TEST_ASSERT((bits & ETH_CONNECT_BIT) == ETH_CONNECT_BIT); - // even if PHY (IP101) indicates autonegotiation done and link up, it sometimes may miss few packets after atonego reset, hence wait a bit - vTaskDelay(pdMS_TO_TICKS(100)); - - emac_frame_t *pkt = malloc(1024); - pkt->proto = 0x2222; - memset(pkt->dest, 0xff, 6); // broadcast addr - for (int i = 0; i < (1024 - ETH_HEADER_LEN); ++i){ - pkt->data[i] = i & 0xff; - } - - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_transmit(eth_handle, pkt, 1024)); - vTaskDelay(pdMS_TO_TICKS(100)); - free(pkt); - - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_stop(eth_handle)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete_default()); - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_driver_uninstall(eth_handle)); - phy->del(phy); - mac->del(mac); - vEventGroupDelete(eth_event_group); -} - -static uint8_t local_mac_addr[6] = {}; - -esp_err_t l2_packet_txrx_test_cb(esp_eth_handle_t hdl, uint8_t *buffer, uint32_t length, void *priv) { - EventGroupHandle_t eth_event_group = (EventGroupHandle_t)priv; - emac_frame_t *pkt = (emac_frame_t *) buffer; - // check header - if (pkt->proto == 0x2222 && length == 1024) { - // check content - for (int i = 0; i < (length - ETH_HEADER_LEN); ++i) { - if (pkt->data[i] != (i & 0xff)) { - printf("payload mismatch\n"); - return ESP_OK; - } - } - if (memcmp(pkt->dest, "\xff\xff\xff\xff\xff\xff", 6) == 0) { - printf("broadcast received...\n"); - xEventGroupSetBits(eth_event_group, ETH_BROADCAST_RECV_BIT); - } else if (pkt->dest[0] & 0x1) { - printf("multicast received...\n"); - xEventGroupSetBits(eth_event_group, ETH_MULTICAST_RECV_BIT); - } else if (memcmp(pkt->dest, local_mac_addr, 6) == 0) { - printf("unicast received...\n"); - xEventGroupSetBits(eth_event_group, ETH_UNICAST_RECV_BIT); - } - } else { - printf("unexpected frame (protocol: 0x%x, length: %u)\n", pkt->proto, length); - } - return ESP_OK; -}; - -TEST_CASE("recv_pkt", "[esp_eth]") -{ - EventGroupHandle_t eth_event_group = xEventGroupCreate(); - TEST_ASSERT(eth_event_group != NULL); - - eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); // apply default MAC configuration - eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG(); - esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); // create MAC instance - TEST_ASSERT_NOT_NULL(mac); - eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); // apply default PHY configuration -#if defined(CONFIG_TARGET_ETH_PHY_DEVICE_IP101) - esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config); // create PHY instance -#elif defined(CONFIG_TARGET_ETH_PHY_DEVICE_LAN87XX) - esp_eth_phy_t *phy = esp_eth_phy_new_lan87xx(&phy_config); -#endif - 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_ASSERT_EQUAL(ESP_OK, esp_eth_driver_install(&config, ð_handle)); // install driver - TEST_ASSERT_NOT_NULL(eth_handle); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create_default()); - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_start(eth_handle)); // start Ethernet driver state machine - - TEST_ASSERT_EQUAL(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_ASSERT_EQUAL(ESP_OK, esp_eth_update_input_path(eth_handle, l2_packet_txrx_test_cb, eth_event_group)); - - EventBits_t bits = 0; - bits = xEventGroupWaitBits(eth_event_group, ETH_BROADCAST_RECV_BIT | ETH_MULTICAST_RECV_BIT | ETH_UNICAST_RECV_BIT, - true, true, pdMS_TO_TICKS(5000)); - 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_ASSERT_EQUAL(ESP_OK, esp_eth_stop(eth_handle)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete_default()); - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_driver_uninstall(eth_handle)); - phy->del(phy); - mac->del(mac); - vEventGroupDelete(eth_event_group); -} - -typedef struct -{ - SemaphoreHandle_t mutex; - int rx_pkt_cnt; -} recv_info_t; - -static esp_err_t eth_recv_cb(esp_eth_handle_t hdl, uint8_t *buffer, uint32_t length, void *priv) -{ - emac_frame_t *pkt = (emac_frame_t *)buffer; - recv_info_t *recv_info = (recv_info_t *)priv; - - if (pkt->proto == 0x2222) { - switch (pkt->data[0]) - { - case POKE_RESP: - xSemaphoreGive(recv_info->mutex); - break; - - case DUMMY_TRAFFIC: - (recv_info->rx_pkt_cnt)++; - break; - default: - break; - } - } - free(buffer); - return ESP_OK; -} - -TEST_CASE("start_stop_stress_test", "[esp_eth]") -{ - recv_info_t recv_info; - recv_info.mutex = xSemaphoreCreateBinary(); - TEST_ASSERT_NOT_NULL(recv_info.mutex); - recv_info.rx_pkt_cnt = 0; - - eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); // apply default MAC configuration - eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG(); - esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); // create MAC instance - TEST_ASSERT_NOT_NULL(mac); - eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); // apply default PHY configuration -#if defined(CONFIG_TARGET_ETH_PHY_DEVICE_IP101) - esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config); // create PHY instance -#elif defined(CONFIG_TARGET_ETH_PHY_DEVICE_LAN87XX) - esp_eth_phy_t *phy = esp_eth_phy_new_lan87xx(&phy_config); -#endif - 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_ASSERT_EQUAL(ESP_OK, esp_eth_driver_install(&config, ð_handle)); // install driver - TEST_ASSERT_NOT_NULL(eth_handle); - - TEST_ASSERT_EQUAL(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, eth_recv_cb, &recv_info)); - - 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)); - - // create a control frame to control test flow between the UT and the Python test script - emac_frame_t *ctrl_pkt = calloc(1, 60); - ctrl_pkt->proto = 0x2222; - memset(ctrl_pkt->dest, 0xff, 6); // broadcast addr - memcpy(ctrl_pkt->src, local_mac_addr, 6); - - // create dummy data packet used for traffic generation - emac_frame_t *pkt = calloc(1, 1500); - pkt->proto = 0x2222; - // we don't care about dest MAC address much, however it is better to not be broadcast or multifcast to not flood - // other network nodes - memset(pkt->dest, 0xBA, 6); - memcpy(pkt->src, local_mac_addr, 6); - - printf("EMAC start/stop stress test under heavy Tx traffic\n"); - for (int tx_i = 0; tx_i < 10; tx_i++) { - TEST_ASSERT_EQUAL(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(3000)); - TEST_ASSERT((bits & ETH_CONNECT_BIT) == ETH_CONNECT_BIT); - // even if PHY (IP101) indicates autonegotiation done and link up, it sometimes may miss few packets after atonego reset, hence wait a bit - vTaskDelay(pdMS_TO_TICKS(100)); - - // at first, check that Tx/Rx path works as expected by poking the test script - // this also serves as main PASS/FAIL criteria - ctrl_pkt->data[0] = POKE_REQ; - ctrl_pkt->data[1] = tx_i; - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_transmit(eth_handle, ctrl_pkt, 60)); - TEST_ASSERT(xSemaphoreTake(recv_info.mutex, pdMS_TO_TICKS(3000))); - printf("Tx Test iteration %d\n", tx_i); - - // generate heavy Tx traffic - printf("Note: transmit errors are expected...\n"); - 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[0] = j & 0xFF; - esp_eth_transmit(eth_handle, pkt, 1500); - } - TEST_ASSERT_EQUAL(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("Ethernet stopped\n"); - } - - printf("EMAC start/stop stress test under heavy Rx traffic\n"); - for (int rx_i = 0; rx_i < 10; rx_i++) { - recv_info.rx_pkt_cnt = 0; - TEST_ASSERT_EQUAL(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(3000)); - TEST_ASSERT((bits & ETH_CONNECT_BIT) == ETH_CONNECT_BIT); - // even if PHY (IP101) indicates autonegotiation done and link up, it sometimes may miss few packets after atonego reset, hence wait a bit - vTaskDelay(pdMS_TO_TICKS(100)); - - ctrl_pkt->data[0] = POKE_REQ; - ctrl_pkt->data[1] = rx_i; - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_transmit(eth_handle, ctrl_pkt, 60)); - TEST_ASSERT(xSemaphoreTake(recv_info.mutex, pdMS_TO_TICKS(3000))); - printf("Rx Test iteration %d\n", rx_i); - - vTaskDelay(pdMS_TO_TICKS(500)); - - TEST_ASSERT_EQUAL(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", recv_info.rx_pkt_cnt); - TEST_ASSERT_GREATER_THAN_INT32(0, recv_info.rx_pkt_cnt); - printf("Ethernet stopped\n"); - } - - free(ctrl_pkt); - free(pkt); - - TEST_ESP_OK(esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler)); - TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete_default()); - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_driver_uninstall(eth_handle)); - phy->del(phy); - mac->del(mac); - vEventGroupDelete(eth_event_group); - vSemaphoreDelete(recv_info.mutex); -} - -void app_main(void) -{ - unity_run_menu(); -} diff --git a/components/esp_eth/test/test_emac.c b/components/esp_eth/test_apps/main/esp_eth_test_apps.c similarity index 72% rename from components/esp_eth/test/test_emac.c rename to components/esp_eth/test_apps/main/esp_eth_test_apps.c index 72364fb0ae..6a49315ecf 100644 --- a/components/esp_eth/test/test_emac.c +++ b/components/esp_eth/test_apps/main/esp_eth_test_apps.c @@ -5,34 +5,17 @@ */ #include #include +#include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/event_groups.h" -#include "unity.h" -#include "test_utils.h" -#include "esp_event.h" -#include "esp_netif.h" -#include "esp_eth.h" #include "esp_log.h" #include "esp_http_client.h" #include "esp_rom_md5.h" -#include "soc/soc_caps.h" - -#if SOC_EMAC_SUPPORTED +#include "esp_eth_test_common.h" static const char *TAG = "esp32_eth_test"; -#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) - extern const char dl_espressif_com_root_cert_pem_start[] asm("_binary_dl_espressif_com_root_cert_pem_start"); extern const char dl_espressif_com_root_cert_pem_end[] asm("_binary_dl_espressif_com_root_cert_pem_end"); @@ -40,48 +23,6 @@ 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]; -/** Event handler for Ethernet events */ -static 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: - xEventGroupSetBits(eth_event_group, ETH_CONNECT_BIT); - ESP_LOGI(TAG, "Ethernet Link Up"); - break; - case ETHERNET_EVENT_DISCONNECTED: - ESP_LOGI(TAG, "Ethernet Link Down"); - break; - case ETHERNET_EVENT_START: - xEventGroupSetBits(eth_event_group, ETH_START_BIT); - ESP_LOGI(TAG, "Ethernet Started"); - break; - case ETHERNET_EVENT_STOP: - xEventGroupSetBits(eth_event_group, ETH_STOP_BIT); - ESP_LOGI(TAG, "Ethernet Stopped"); - break; - default: - break; - } -} - -/** Event handler for IP_EVENT_ETH_GOT_IP */ -static 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); -} - static esp_err_t test_uninstall_driver(esp_eth_handle_t eth_hdl, uint32_t ms_to_wait) { int i = 0; @@ -99,37 +40,59 @@ static esp_err_t test_uninstall_driver(esp_eth_handle_t eth_hdl, uint32_t ms_to_ } } -TEST_CASE("esp32 ethernet io test", "[ethernet][test_env=UT_T2_Ethernet]") +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 - eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG(); - esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); - eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); - // auto detect PHY address - phy_config.phy_addr = ESP_ETH_PHY_ADDR_AUTO; - esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config); + 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)); - /* get MAC address */ - uint8_t mac_addr[6]; + extra_eth_config(eth_handle); + + /* get default MAC address */ + uint8_t mac_addr[ETH_ADDR_LEN]; memset(mac_addr, 0, sizeof(mac_addr)); TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr)); ESP_LOGI(TAG, "Ethernet MAC Address: %02x:%02x:%02x:%02x:%02x:%02x", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); 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 + TEST_ASSERT_BITS(0b00000011, 0b00, mac_addr[0]); // Check UL&IG, should be UI +#endif + + /* set different MAC address */ + mac_addr[5] ^= mac_addr[4]; + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_S_MAC_ADDR, mac_addr)); + /* get new MAC address */ + uint8_t mac_addr_new[ETH_ADDR_LEN] = { 0 }; + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr_new)); + ESP_LOGI(TAG, "Ethernet MAC Address: %02x:%02x:%02x:%02x:%02x:%02x", + mac_addr_new[0], mac_addr_new[1], mac_addr_new[2], mac_addr_new[3], mac_addr_new[4], mac_addr_new[5]); + TEST_ASSERT_EQUAL_UINT8_ARRAY(mac_addr_new, mac_addr, ETH_ADDR_LEN); + +// *** 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 /* 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(); } -TEST_CASE("esp32 ethernet speed/duplex/autonegotiation", "[ethernet][test_env=UT_T2_Ethernet]") +TEST_CASE("ethernet io speed/duplex/autonegotiation", "[ethernet]") { EventBits_t bits = 0; EventGroupHandle_t eth_event_group = xEventGroupCreate(); @@ -138,19 +101,19 @@ TEST_CASE("esp32 ethernet speed/duplex/autonegotiation", "[ethernet][test_env=UT TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_group)); eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); mac_config.flags = ETH_MAC_FLAG_PIN_TO_CORE; // pin to core - eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG(); - esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); - eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); - // auto detect PHY address - phy_config.phy_addr = ESP_ETH_PHY_ADDR_AUTO; - esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config); + 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); // Set PHY to loopback mode so we do not have to take care about link configuration of the other node. // The reason behind is improbable, however, if the other node was configured to e.g. 100 Mbps and we // tried to change the speed at ESP node to 10 Mbps, we could get into trouble to establish a link. + // TODO: this test in this configuration may not work for all the chips (JIRA IDF-6186) bool loopback_en = true; esp_eth_ioctl(eth_handle, ETH_CMD_S_PHY_LOOPBACK, &loopback_en); @@ -173,13 +136,13 @@ TEST_CASE("esp32 ethernet speed/duplex/autonegotiation", "[ethernet][test_env=UT TEST_ASSERT_EQUAL(ETH_SPEED_100M, exp_speed); bool exp_autoneg_en; - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_ioctl(eth_handle, ETH_CMD_G_AUTONEGO, &exp_autoneg_en)); + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_AUTONEGO, &exp_autoneg_en)); TEST_ASSERT_EQUAL(true, exp_autoneg_en); ESP_LOGI(TAG, "try to change autonegotiation when driver is started..."); bool auto_nego_en = false; TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, esp_eth_ioctl(eth_handle, ETH_CMD_S_AUTONEGO, &auto_nego_en)); - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_ioctl(eth_handle, ETH_CMD_G_AUTONEGO, &exp_autoneg_en)); + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_AUTONEGO, &exp_autoneg_en)); TEST_ASSERT_EQUAL(true, exp_autoneg_en); ESP_LOGI(TAG, "stop the Ethernet driver and..."); @@ -195,22 +158,22 @@ TEST_CASE("esp32 ethernet speed/duplex/autonegotiation", "[ethernet][test_env=UT // Disable autonegotiation and change speed to 10 Mbps and duplex to half ESP_LOGI(TAG, "disable the autonegotiation and change the speed/duplex..."); auto_nego_en = false; - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_ioctl(eth_handle, ETH_CMD_S_AUTONEGO, &auto_nego_en)); - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_ioctl(eth_handle, ETH_CMD_G_AUTONEGO, &exp_autoneg_en)); + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_S_AUTONEGO, &auto_nego_en)); + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_AUTONEGO, &exp_autoneg_en)); TEST_ASSERT_EQUAL(false, exp_autoneg_en); // set new duplex mode - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_ioctl(eth_handle, ETH_CMD_S_DUPLEX_MODE, &duplex)); + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_S_DUPLEX_MODE, &duplex)); // set new speed - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_ioctl(eth_handle, ETH_CMD_S_SPEED, &speed)); + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_S_SPEED, &speed)); // start the driver and wait for connection establish esp_eth_start(eth_handle); 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); - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_ioctl(eth_handle, ETH_CMD_G_DUPLEX_MODE, &exp_duplex)); - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_ioctl(eth_handle, ETH_CMD_G_SPEED, &exp_speed)); + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_DUPLEX_MODE, &exp_duplex)); + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_SPEED, &exp_speed)); TEST_ASSERT_EQUAL(ETH_DUPLEX_HALF, exp_duplex); TEST_ASSERT_EQUAL(ETH_SPEED_10M, exp_speed); @@ -219,14 +182,14 @@ TEST_CASE("esp32 ethernet speed/duplex/autonegotiation", "[ethernet][test_env=UT esp_eth_stop(eth_handle); ESP_LOGI(TAG, "change speed again..."); speed = ETH_SPEED_100M; - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_ioctl(eth_handle, ETH_CMD_S_SPEED, &speed)); + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_S_SPEED, &speed)); // start the driver and wait for connection establish esp_eth_start(eth_handle); 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); - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_ioctl(eth_handle, ETH_CMD_G_SPEED, &exp_speed)); - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_ioctl(eth_handle, ETH_CMD_G_DUPLEX_MODE, &exp_duplex)); + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_SPEED, &exp_speed)); + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_DUPLEX_MODE, &exp_duplex)); TEST_ASSERT_EQUAL(ETH_DUPLEX_HALF, exp_duplex); TEST_ASSERT_EQUAL(ETH_SPEED_100M, exp_speed); @@ -234,14 +197,14 @@ TEST_CASE("esp32 ethernet speed/duplex/autonegotiation", "[ethernet][test_env=UT esp_eth_stop(eth_handle); ESP_LOGI(TAG, "change duplex again..."); duplex = ETH_DUPLEX_FULL; - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_ioctl(eth_handle, ETH_CMD_S_DUPLEX_MODE, &duplex)); + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_S_DUPLEX_MODE, &duplex)); // start the driver and wait for connection establish esp_eth_start(eth_handle); 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); - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_ioctl(eth_handle, ETH_CMD_G_DUPLEX_MODE, &exp_duplex)); - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_ioctl(eth_handle, ETH_CMD_G_SPEED, &exp_speed)); + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_DUPLEX_MODE, &exp_duplex)); + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_SPEED, &exp_speed)); TEST_ASSERT_EQUAL(ETH_DUPLEX_FULL, exp_duplex); TEST_ASSERT_EQUAL(ETH_SPEED_100M, exp_speed); @@ -253,8 +216,8 @@ TEST_CASE("esp32 ethernet speed/duplex/autonegotiation", "[ethernet][test_env=UT TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, esp_eth_ioctl(eth_handle, ETH_CMD_S_DUPLEX_MODE, &duplex)); TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, esp_eth_ioctl(eth_handle, ETH_CMD_S_SPEED, &speed)); - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_ioctl(eth_handle, ETH_CMD_G_DUPLEX_MODE, &exp_duplex)); - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_ioctl(eth_handle, ETH_CMD_G_SPEED, &exp_speed)); + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_DUPLEX_MODE, &exp_duplex)); + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_SPEED, &exp_speed)); TEST_ASSERT_EQUAL(ETH_DUPLEX_FULL, exp_duplex); TEST_ASSERT_EQUAL(ETH_SPEED_100M, exp_speed); @@ -265,17 +228,17 @@ TEST_CASE("esp32 ethernet speed/duplex/autonegotiation", "[ethernet][test_env=UT duplex = ETH_DUPLEX_HALF; // set new duplex mode - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_ioctl(eth_handle, ETH_CMD_S_DUPLEX_MODE, &duplex)); + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_S_DUPLEX_MODE, &duplex)); // set new speed - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_ioctl(eth_handle, ETH_CMD_S_SPEED, &speed)); + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_S_SPEED, &speed)); // start the driver and wait for connection establish esp_eth_start(eth_handle); 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); - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_ioctl(eth_handle, ETH_CMD_G_DUPLEX_MODE, &exp_duplex)); - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_ioctl(eth_handle, ETH_CMD_G_SPEED, &exp_speed)); + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_DUPLEX_MODE, &exp_duplex)); + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_SPEED, &exp_speed)); TEST_ASSERT_EQUAL(ETH_DUPLEX_HALF, exp_duplex); TEST_ASSERT_EQUAL(ETH_SPEED_10M, exp_speed); @@ -287,11 +250,11 @@ TEST_CASE("esp32 ethernet speed/duplex/autonegotiation", "[ethernet][test_env=UT 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); - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_ioctl(eth_handle, ETH_CMD_G_AUTONEGO, &exp_autoneg_en)); + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_AUTONEGO, &exp_autoneg_en)); TEST_ASSERT_EQUAL(true, exp_autoneg_en); - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_ioctl(eth_handle, ETH_CMD_G_DUPLEX_MODE, &exp_duplex)); - TEST_ASSERT_EQUAL(ESP_OK, esp_eth_ioctl(eth_handle, ETH_CMD_G_SPEED, &exp_speed)); + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_DUPLEX_MODE, &exp_duplex)); + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_SPEED, &exp_speed)); // verify autonegotiation result (expecting the best link configuration) TEST_ASSERT_EQUAL(ETH_DUPLEX_FULL, exp_duplex); @@ -307,24 +270,25 @@ TEST_CASE("esp32 ethernet speed/duplex/autonegotiation", "[ethernet][test_env=UT 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("esp32 ethernet event test", "[ethernet][test_env=UT_T2_Ethernet]") +TEST_CASE("ethernet event test", "[ethernet]") { EventBits_t bits = 0; EventGroupHandle_t eth_event_group = xEventGroupCreate(); TEST_ASSERT(eth_event_group != NULL); TEST_ESP_OK(esp_event_loop_create_default()); TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_group)); - eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); - eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG(); - esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); - eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); - esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config); + 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 */ @@ -344,10 +308,11 @@ TEST_CASE("esp32 ethernet event test", "[ethernet][test_env=UT_T2_Ethernet]") 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("esp32 ethernet dhcp test", "[ethernet][test_env=UT_T2_Ethernet]") +TEST_CASE("ethernet dhcp test", "[ethernet]") { EventBits_t bits = 0; EventGroupHandle_t eth_event_group = xEventGroupCreate(); @@ -357,16 +322,15 @@ TEST_CASE("esp32 ethernet dhcp test", "[ethernet][test_env=UT_T2_Ethernet]") // 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_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); - eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG(); - esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); - eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); - esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config); + 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)); @@ -392,10 +356,11 @@ TEST_CASE("esp32 ethernet dhcp test", "[ethernet][test_env=UT_T2_Ethernet]") 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("esp32 ethernet start/stop stress test", "[ethernet][test_env=UT_T2_Ethernet][timeout=240]") +TEST_CASE("ethernet start/stop stress test with IP stack", "[ethernet]") { EventBits_t bits = 0; EventGroupHandle_t eth_event_group = xEventGroupCreate(); @@ -405,16 +370,15 @@ TEST_CASE("esp32 ethernet start/stop stress test", "[ethernet][test_env=UT_T2_Et // 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_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); - eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG(); - esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); - eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); - esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config); + 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)); @@ -444,6 +408,7 @@ TEST_CASE("esp32 ethernet start/stop stress test", "[ethernet][test_env=UT_T2_Et 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); } @@ -494,7 +459,7 @@ static void eth_start_download(void) esp_rom_md5_final(digest, &md5_context); } -TEST_CASE("esp32 ethernet download test", "[ethernet][test_env=UT_T2_Ethernet][timeout=240]") +TEST_CASE("ethernet download test", "[ethernet]") { EventBits_t bits = 0; EventGroupHandle_t eth_event_group = xEventGroupCreate(); @@ -504,16 +469,15 @@ TEST_CASE("esp32 ethernet download test", "[ethernet][test_env=UT_T2_Ethernet][t // 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_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); - eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG(); - esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); - eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); - esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config); + 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)); @@ -535,7 +499,7 @@ TEST_CASE("esp32 ethernet download test", "[ethernet][test_env=UT_T2_Ethernet][t printf("%d ", digest[i]); } printf("\r\n"); - TEST_ASSERT(memcmp(expect_digest, digest, sizeof(digest)) == 0); + TEST_ASSERT_EQUAL_UINT8_ARRAY(expect_digest, digest, sizeof(digest)); // stop Ethernet driver TEST_ESP_OK(esp_eth_stop(eth_handle)); @@ -551,7 +515,6 @@ TEST_CASE("esp32 ethernet download test", "[ethernet][test_env=UT_T2_Ethernet][t 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); } - -#endif // SOC_EMAC_SUPPORTED 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 new file mode 100644 index 0000000000..e45c29b942 --- /dev/null +++ b/components/esp_eth/test_apps/main/esp_eth_test_common.c @@ -0,0 +1,173 @@ +/* + * SPDX-FileCopyrightText: 2022 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 (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 modlues 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 (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); + ksz8851snl_config.int_gpio_num = 4; + 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 (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); +#elif CONFIG_TARGET_ETH_PHY_DEVICE_LAN87XX + phy = esp_eth_phy_new_lan87xx(phy_config); +#elif CONFIG_TARGET_ETH_PHY_DEVICE_KSZ80XX + phy = esp_eth_phy_new_ksz80xx(phy_config); +#elif CONFIG_TARGET_ETH_PHY_DEVICE_RTL8201 + phy = esp_eth_phy_new_rtl8201(phy_config); +#elif CONFIG_TARGET_ETH_PHY_DEVICE_DP83848 + phy = esp_eth_phy_new_dp83848(phy_config); +#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); +#elif CONFIG_TARGET_ETH_PHY_DEVICE_KSZ8851SNL + phy = esp_eth_phy_new_ksz8851snl(phy_config); +#elif CONFIG_TARGET_ETH_PHY_DEVICE_DM9051 + phy = esp_eth_phy_new_dm9051(phy_config); +#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: + xEventGroupSetBits(eth_event_group, ETH_CONNECT_BIT); + break; + case ETHERNET_EVENT_DISCONNECTED: + break; + case ETHERNET_EVENT_START: + xEventGroupSetBits(eth_event_group, ETH_START_BIT); + break; + case ETHERNET_EVENT_STOP: + 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 new file mode 100644 index 0000000000..e0b0e16a6e --- /dev/null +++ b/components/esp_eth/test_apps/main/esp_eth_test_common.h @@ -0,0 +1,42 @@ +/* + * 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_hal.c b/components/esp_eth/test_apps/main/esp_eth_test_hal.c new file mode 100644 index 0000000000..89f0f959f4 --- /dev/null +++ b/components/esp_eth/test_apps/main/esp_eth_test_hal.c @@ -0,0 +1,255 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/event_groups.h" +#include "esp_log.h" +#include "esp_eth_test_common.h" + +#define ETHERTYPE_TX_STD 0x2222 // frame transmitted via emac_hal_transmit_frame +#define ETHERTYPE_TX_MULTI_2 0x2223 // frame transmitted via emac_hal_transmit_multiple_buf_frame (2 buffers) +#define ETHERTYPE_TX_MULTI_3 0x2224 // frame transmitted via emac_hal_transmit_multiple_buf_frame (3 buffers) + +static const char *TAG = "esp32_eth_test_hal"; + +typedef struct +{ + SemaphoreHandle_t mutex; + uint16_t expected_size; + uint16_t expected_size_2; + uint16_t expected_size_3; +} recv_hal_check_info_t; + +static esp_err_t eth_recv_hal_check_cb(esp_eth_handle_t hdl, uint8_t *buffer, uint32_t length, void *priv) +{ + emac_frame_t *pkt = (emac_frame_t *)buffer; + recv_hal_check_info_t *recv_info = (recv_hal_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 emac_hal_transmit_frame + if (pkt->proto == ETHERTYPE_TX_STD) { + for (int i = 0; i < recv_info->expected_size - ETH_HEADER_LEN; i++) { + TEST_ASSERT_EQUAL(pkt->data[i], i & 0xFF); + } + // frame transmitted via emac_hal_transmit_multiple_buf_frame (2 buffers) + } else if (pkt->proto == ETHERTYPE_TX_MULTI_2) { + uint8_t *data_p = pkt->data; + for (int i = 0; i < recv_info->expected_size - ETH_HEADER_LEN; i++) { + TEST_ASSERT_EQUAL(*(data_p++), i & 0xFF); + } + int j = ETH_MAX_PAYLOAD_LEN; + for (int i = 0; i < recv_info->expected_size_2; i++) { + TEST_ASSERT_EQUAL(*(data_p++), j & 0xFF); + j--; + } + // frame transmitted via emac_hal_transmit_multiple_buf_frame (3 buffers) + } else if (pkt->proto == ETHERTYPE_TX_MULTI_3) { + uint8_t *data_p = pkt->data; + for (int i = 0; i < recv_info->expected_size - ETH_HEADER_LEN; i++) { + TEST_ASSERT_EQUAL(*(data_p++), i & 0xFF); + } + int j = ETH_MAX_PAYLOAD_LEN; + for (int i = 0; i < recv_info->expected_size_2; i++) { + TEST_ASSERT_EQUAL(*(data_p++), j & 0xFF); + j--; + } + for (int i = 0; i < recv_info->expected_size_3; i++) { + TEST_ASSERT_EQUAL(*(data_p++), i & 0xFF); + } + } else { + TEST_FAIL(); + } + memset(buffer, 0, length); + free(buffer); + xSemaphoreGive(recv_info->mutex); + return ESP_OK; +} + +TEST_CASE("hal receive/transmit", "[emac_hal]") +{ + recv_hal_check_info_t recv_info; + recv_info.mutex = xSemaphoreCreateBinary(); + 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 + bool loopback_en = true; + esp_eth_ioctl(eth_handle, ETH_CMD_S_PHY_LOOPBACK, &loopback_en); + + TEST_ESP_OK(esp_eth_update_input_path(eth_handle, eth_recv_hal_check_cb, &recv_info)); + + // start the driver + TEST_ESP_OK(esp_eth_start(eth_handle)); + // wait for connection 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 connection establish + 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); + 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 }; + TEST_ESP_OK(esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, local_mac_addr)); + memcpy(test_pkt->src, local_mac_addr, ETH_ADDR_LEN); + // fill with data + for (int i = 0; i < ETH_MAX_PAYLOAD_LEN; i++) { + test_pkt->data[i] = i & 0xFF; + } + + // verify that HAL driver correctly processes frame from EMAC descriptors + uint16_t transmit_size = CONFIG_ETH_DMA_BUFFER_SIZE; + ESP_LOGI(TAG, "transmit frame size: %" PRIu16, transmit_size); + recv_info.expected_size = transmit_size; + TEST_ESP_OK(esp_eth_transmit(eth_handle, test_pkt, transmit_size)); + TEST_ASSERT(xSemaphoreTake(recv_info.mutex, pdMS_TO_TICKS(500))); + + transmit_size = CONFIG_ETH_DMA_BUFFER_SIZE - 1; + ESP_LOGI(TAG, "transmit frame size: %" PRIu16, transmit_size); + recv_info.expected_size = transmit_size; + TEST_ESP_OK(esp_eth_transmit(eth_handle, test_pkt, transmit_size)); + TEST_ASSERT(xSemaphoreTake(recv_info.mutex, pdMS_TO_TICKS(500))); + + transmit_size = CONFIG_ETH_DMA_BUFFER_SIZE + 1; + ESP_LOGI(TAG, "transmit frame size: %" PRIu16, transmit_size); + recv_info.expected_size = transmit_size; + TEST_ESP_OK(esp_eth_transmit(eth_handle, test_pkt, transmit_size)); + TEST_ASSERT(xSemaphoreTake(recv_info.mutex, pdMS_TO_TICKS(500))); + + transmit_size = 2 * CONFIG_ETH_DMA_BUFFER_SIZE; + ESP_LOGI(TAG, "transmit frame size: %" PRIu16, transmit_size); + recv_info.expected_size = transmit_size; + TEST_ESP_OK(esp_eth_transmit(eth_handle, test_pkt, transmit_size)); + TEST_ASSERT(xSemaphoreTake(recv_info.mutex, pdMS_TO_TICKS(500))); + + transmit_size = 2 * CONFIG_ETH_DMA_BUFFER_SIZE - 1; + ESP_LOGI(TAG, "transmit frame size: %" PRIu16, transmit_size); + recv_info.expected_size = transmit_size; + TEST_ESP_OK(esp_eth_transmit(eth_handle, test_pkt, transmit_size)); + TEST_ASSERT(xSemaphoreTake(recv_info.mutex, pdMS_TO_TICKS(500))); + + transmit_size = 2 * CONFIG_ETH_DMA_BUFFER_SIZE + 1; + ESP_LOGI(TAG, "transmit frame size: %" PRIu16, transmit_size); + recv_info.expected_size = transmit_size; + TEST_ESP_OK(esp_eth_transmit(eth_handle, test_pkt, transmit_size)); + TEST_ASSERT(xSemaphoreTake(recv_info.mutex, pdMS_TO_TICKS(500))); + + // verify transmission of multiple buffers + uint16_t transmit_size_2; + // allocated the second buffer + uint8_t *pkt_data_2 = malloc(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++) { + pkt_data_2[i] = j & 0xFF; + j--; + } + // change protocol number so the cb function is aware that frame was joint from two buffers + test_pkt->proto = ETHERTYPE_TX_MULTI_2; + transmit_size = CONFIG_ETH_DMA_BUFFER_SIZE; + transmit_size_2 = CONFIG_ETH_DMA_BUFFER_SIZE; + recv_info.expected_size = transmit_size; + recv_info.expected_size_2 = transmit_size_2; + ESP_LOGI(TAG, "transmit joint frame size: %" PRIu16, transmit_size + transmit_size_2); + TEST_ESP_OK(esp_eth_transmit_vargs(eth_handle, 2, test_pkt, transmit_size, pkt_data_2, transmit_size_2)); + TEST_ASSERT(xSemaphoreTake(recv_info.mutex, pdMS_TO_TICKS(500))); + + transmit_size = CONFIG_ETH_DMA_BUFFER_SIZE - 1; + transmit_size_2 = CONFIG_ETH_DMA_BUFFER_SIZE; + recv_info.expected_size = transmit_size; + recv_info.expected_size_2 = transmit_size_2; + ESP_LOGI(TAG, "transmit joint frame size: %" PRIu16, transmit_size + transmit_size_2); + TEST_ESP_OK(esp_eth_transmit_vargs(eth_handle, 2, test_pkt, transmit_size, pkt_data_2, transmit_size_2)); + TEST_ASSERT(xSemaphoreTake(recv_info.mutex, pdMS_TO_TICKS(500))); + + transmit_size = CONFIG_ETH_DMA_BUFFER_SIZE + 1; + transmit_size_2 = CONFIG_ETH_DMA_BUFFER_SIZE; + recv_info.expected_size = transmit_size; + recv_info.expected_size_2 = transmit_size_2; + ESP_LOGI(TAG, "transmit joint frame size: %" PRIu16, transmit_size + transmit_size_2); + TEST_ESP_OK(esp_eth_transmit_vargs(eth_handle, 2, test_pkt, transmit_size, pkt_data_2, transmit_size_2)); + TEST_ASSERT(xSemaphoreTake(recv_info.mutex, pdMS_TO_TICKS(500))); + + uint16_t transmit_size_3 = 256; + // allocated the third buffer + uint8_t *pkt_data_3 = malloc(256); + // fill with data + for (int i = 0; i < 256; i++) { + pkt_data_3[i] = i & 0xFF; + } + // change protocol number so the cb function is aware that frame was joint from three buffers + test_pkt->proto = ETHERTYPE_TX_MULTI_3; + transmit_size = CONFIG_ETH_DMA_BUFFER_SIZE; + transmit_size_2 = CONFIG_ETH_DMA_BUFFER_SIZE; + transmit_size_3 = 256; + recv_info.expected_size = transmit_size; + recv_info.expected_size_2 = transmit_size_2; + recv_info.expected_size_3 = transmit_size_3; + ESP_LOGI(TAG, "transmit joint frame size (3 buffs): %" PRIu16, transmit_size + transmit_size_2 + transmit_size_3); + 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))); + + transmit_size = CONFIG_ETH_DMA_BUFFER_SIZE - 1; + transmit_size_2 = CONFIG_ETH_DMA_BUFFER_SIZE; + transmit_size_3 = 256; + recv_info.expected_size = transmit_size; + recv_info.expected_size_2 = transmit_size_2; + recv_info.expected_size_3 = transmit_size_3; + ESP_LOGI(TAG, "transmit joint frame size (3 buffs): %" PRIu16, transmit_size + transmit_size_2 + transmit_size_3); + 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))); + + transmit_size = CONFIG_ETH_DMA_BUFFER_SIZE + 1; + transmit_size_2 = CONFIG_ETH_DMA_BUFFER_SIZE; + transmit_size_3 = 256; + recv_info.expected_size = transmit_size; + recv_info.expected_size_2 = transmit_size_2; + recv_info.expected_size_3 = transmit_size_3; + ESP_LOGI(TAG, "transmit joint frame size (3 buffs): %" PRIu16, transmit_size + transmit_size_2 + transmit_size_3); + 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); +} 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 new file mode 100644 index 0000000000..c094c12e78 --- /dev/null +++ b/components/esp_eth/test_apps/main/esp_eth_test_l2.c @@ -0,0 +1,277 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "esp_eth_test_common.h" + +#define ETH_BROADCAST_RECV_BIT BIT(0) +#define ETH_MULTICAST_RECV_BIT BIT(1) +#define ETH_UNICAST_RECV_BIT BIT(2) + +#define POKE_REQ 0xFA +#define POKE_RESP 0xFB +#define DUMMY_TRAFFIC 0xFF + +TEST_CASE("ethernet broadcast transmit", "[ethernet_l2]") +{ + EventGroupHandle_t eth_event_group = xEventGroupCreate(); + TEST_ASSERT(eth_event_group != NULL); + + 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()); + TEST_ESP_OK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, eth_event_group)); + 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(3000)); + 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) + vTaskDelay(pdMS_TO_TICKS(1000)); + + emac_frame_t *pkt = malloc(1024); + pkt->proto = 0x2222; + 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)); + vTaskDelay(pdMS_TO_TICKS(100)); + 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_group); +} + +static uint8_t local_mac_addr[ETH_ADDR_LEN] = {}; + +esp_err_t l2_packet_txrx_test_cb(esp_eth_handle_t hdl, uint8_t *buffer, uint32_t length, void *priv) { + EventGroupHandle_t eth_event_group = (EventGroupHandle_t)priv; + emac_frame_t *pkt = (emac_frame_t *) buffer; + // check header + if (pkt->proto == 0x2222 && length == 1024) { + // check content + for (int i = 0; i < (length - ETH_HEADER_LEN); ++i) { + if (pkt->data[i] != (i & 0xff)) { + printf("payload mismatch\n"); + return ESP_OK; + } + } + if (memcmp(pkt->dest, "\xff\xff\xff\xff\xff\xff", ETH_ADDR_LEN) == 0) { + printf("broadcast received...\n"); + xEventGroupSetBits(eth_event_group, ETH_BROADCAST_RECV_BIT); + } else if (pkt->dest[0] & 0x1) { + printf("multicast received...\n"); + xEventGroupSetBits(eth_event_group, ETH_MULTICAST_RECV_BIT); + } else if (memcmp(pkt->dest, local_mac_addr, ETH_ADDR_LEN) == 0) { + printf("unicast received...\n"); + xEventGroupSetBits(eth_event_group, ETH_UNICAST_RECV_BIT); + } + } else { + printf("unexpected frame (protocol: 0x%x, length: %" PRIu32 ")\n", pkt->proto, length); + } + return ESP_OK; +}; + +TEST_CASE("ethernet recv_pkt", "[ethernet_l2]") +{ + EventGroupHandle_t eth_event_group = xEventGroupCreate(); + TEST_ASSERT(eth_event_group != NULL); + + 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()); + TEST_ESP_OK(esp_eth_start(eth_handle)); // start Ethernet driver state machine + + 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, eth_event_group)); + + EventBits_t bits = 0; + bits = xEventGroupWaitBits(eth_event_group, ETH_BROADCAST_RECV_BIT | ETH_MULTICAST_RECV_BIT | ETH_UNICAST_RECV_BIT, + true, true, pdMS_TO_TICKS(5000)); + 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_group); +} + +typedef struct +{ + SemaphoreHandle_t mutex; + int rx_pkt_cnt; +} recv_info_t; + +static esp_err_t eth_recv_cb(esp_eth_handle_t hdl, uint8_t *buffer, uint32_t length, void *priv) +{ + emac_frame_t *pkt = (emac_frame_t *)buffer; + recv_info_t *recv_info = (recv_info_t *)priv; + + if (pkt->proto == 0x2222) { + switch (pkt->data[0]) + { + case POKE_RESP: + xSemaphoreGive(recv_info->mutex); + break; + + case DUMMY_TRAFFIC: + (recv_info->rx_pkt_cnt)++; + break; + default: + break; + } + } + free(buffer); + return ESP_OK; +} + +TEST_CASE("ethernet start/stop stress test under heavy traffic", "[ethernet_l2]") +{ + recv_info_t recv_info; + recv_info.mutex = xSemaphoreCreateBinary(); + TEST_ASSERT_NOT_NULL(recv_info.mutex); + recv_info.rx_pkt_cnt = 0; + + 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(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, eth_recv_cb, &recv_info)); + + 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)); + + // create a control frame to control test flow between the UT and the Python test script + emac_frame_t *ctrl_pkt = calloc(1, 60); + ctrl_pkt->proto = 0x2222; + memset(ctrl_pkt->dest, 0xff, ETH_ADDR_LEN); // broadcast addr + memcpy(ctrl_pkt->src, local_mac_addr, ETH_ADDR_LEN); + + // create dummy data packet used for traffic generation + emac_frame_t *pkt = calloc(1, 1500); + pkt->proto = 0x2222; + // we don't care about dest MAC address much, however it is better to not be broadcast or multifcast to not flood + // other network nodes + memset(pkt->dest, 0xBA, ETH_ADDR_LEN); + 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++) { + 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(3000)); + 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) + vTaskDelay(pdMS_TO_TICKS(1000)); + + // at first, check that Tx/Rx path works as expected by poking the test script + // this also serves as main PASS/FAIL criteria + ctrl_pkt->data[0] = POKE_REQ; + ctrl_pkt->data[1] = tx_i; + TEST_ESP_OK(esp_eth_transmit(eth_handle, ctrl_pkt, 60)); + TEST_ASSERT(xSemaphoreTake(recv_info.mutex, pdMS_TO_TICKS(3000))); + printf("Tx Test iteration %d\n", tx_i); + + // generate heavy Tx traffic + printf("Note: transmit errors are expected...\n"); + 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[0] = 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("Ethernet stopped\n"); + } + + printf("EMAC start/stop stress test under heavy Rx traffic\n"); + for (int rx_i = 0; rx_i < 10; rx_i++) { + recv_info.rx_pkt_cnt = 0; + 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(3000)); + 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) + vTaskDelay(pdMS_TO_TICKS(1000)); + + ctrl_pkt->data[0] = POKE_REQ; + ctrl_pkt->data[1] = rx_i; + TEST_ESP_OK(esp_eth_transmit(eth_handle, ctrl_pkt, 60)); + TEST_ASSERT(xSemaphoreTake(recv_info.mutex, pdMS_TO_TICKS(3000))); + printf("Rx Test iteration %d\n", rx_i); + + 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", recv_info.rx_pkt_cnt); + TEST_ASSERT_GREATER_THAN_INT32(0, recv_info.rx_pkt_cnt); + printf("Ethernet stopped\n"); + } + + free(ctrl_pkt); + free(pkt); + + 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_group); + vSemaphoreDelete(recv_info.mutex); +} 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 new file mode 100644 index 0000000000..82ff3526c5 --- /dev/null +++ b/components/esp_eth/test_apps/main/esp_eth_test_main.c @@ -0,0 +1,11 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include "test_utils.h" + +void app_main(void) +{ + unity_run_menu(); +} diff --git a/components/esp_eth/test_apps/pytest_esp_eth.py b/components/esp_eth/test_apps/pytest_esp_eth.py index b7d6971e99..da28328c81 100644 --- a/components/esp_eth/test_apps/pytest_esp_eth.py +++ b/components/esp_eth/test_apps/pytest_esp_eth.py @@ -5,6 +5,7 @@ import contextlib import logging import os import socket +import time from multiprocessing import Pipe, Process, connection from typing import Iterator @@ -16,28 +17,34 @@ ETH_TYPE = 0x2222 class EthTestIntf(object): - def __init__(self, eth_type: int): + def __init__(self, eth_type: int, my_if: str = ''): self.target_if = '' self.eth_type = eth_type + self.find_target_if(my_if) - def find_target_if(self) -> None: + def find_target_if(self, my_if: str = '') -> None: # try to determine which interface to use netifs = os.listdir('/sys/class/net/') logging.info('detected interfaces: %s', str(netifs)) for netif in netifs: - if netif.find('eth') == 0 or netif.find('enp') == 0 or netif.find('eno') == 0: - self.target_if = netif - break + # if no interface defined, try to find it automatically + if my_if == '': + if netif.find('eth') == 0 or netif.find('enp') == 0 or netif.find('eno') == 0: + self.target_if = netif + break + else: + if netif.find(my_if) == 0: + self.target_if = my_if + break if self.target_if == '': - raise Exception('no network interface found') + raise Exception('network interface not found') logging.info('Use %s for testing', self.target_if) @contextlib.contextmanager def configure_eth_if(self) -> Iterator[socket.socket]: so = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(self.eth_type)) so.bind((self.target_if, 0)) - try: yield so finally: @@ -83,25 +90,34 @@ class EthTestIntf(object): raise e -def actual_test(dut: Dut) -> None: - target_if = EthTestIntf(ETH_TYPE) - target_if.find_target_if() - +def ethernet_test(dut: Dut) -> None: dut.expect_exact('Press ENTER to see the list of tests') dut.write('\n') dut.expect_exact('Enter test for running.') - dut.write('"start_and_stop"') + dut.write('[ethernet]') + dut.expect_unity_test_output(timeout=980) + + +def ethernet_int_emac_hal_test(dut: Dut) -> None: + dut.expect_exact('Press ENTER to see the list of tests') + dut.write('\n') + + dut.expect_exact('Enter test for running.') + dut.write('[emac_hal]') dut.expect_unity_test_output() - dut.expect_exact("Enter next test, or 'enter' to see menu") - dut.write('"get_set_mac"') - dut.expect_unity_test_output() - dut.expect_exact("Enter next test, or 'enter' to see menu") +def ethernet_l2_test(dut: Dut) -> None: + target_if = EthTestIntf(ETH_TYPE) + + dut.expect_exact('Press ENTER to see the list of tests') + dut.write('\n') + dut.expect_exact('Enter test for running.') + with target_if.configure_eth_if() as so: so.settimeout(30) - dut.write('"ethernet_broadcast_transmit"') + dut.write('"ethernet broadcast transmit"') eth_frame = Ether(so.recv(1024)) for i in range(0, 1010): if eth_frame.load[i] != i & 0xff: @@ -109,18 +125,19 @@ def actual_test(dut: Dut) -> None: dut.expect_unity_test_output() dut.expect_exact("Enter next test, or 'enter' to see menu") - dut.write('"recv_pkt"') + dut.write('"ethernet recv_pkt"') res = dut.expect( r'([\s\S]*)' 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})' ) + time.sleep(1) target_if.send_eth_packet('ff:ff:ff:ff:ff:ff') # broadcast frame target_if.send_eth_packet('01:00:00:00:00:00') # multicast frame target_if.send_eth_packet(res.group(2)) # unicast frame dut.expect_unity_test_output(extra_before=res.group(1)) dut.expect_exact("Enter next test, or 'enter' to see menu") - dut.write('"start_stop_stress_test"') + dut.write('"ethernet start/stop stress test under heavy traffic"') res = dut.expect( r'([\s\S]*)' 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})' @@ -144,21 +161,43 @@ def actual_test(dut: Dut) -> None: dut.expect_unity_test_output(extra_before=res.group(1)) +@pytest.mark.esp32 +@pytest.mark.ethernet +@pytest.mark.parametrize('config', [ + 'default_ip101', + 'release_ip101', + 'single_core_ip101' +], indirect=True) +@pytest.mark.flaky(reruns=3, reruns_delay=5) +def test_esp_ethernet(dut: Dut) -> None: + ethernet_test(dut) + + +@pytest.mark.esp32 +@pytest.mark.ethernet +@pytest.mark.parametrize('config', [ + 'default_ip101', +], indirect=True) +@pytest.mark.flaky(reruns=3, reruns_delay=5) +def test_esp_emac_hal(dut: Dut) -> None: + ethernet_int_emac_hal_test(dut) + + @pytest.mark.esp32 @pytest.mark.ip101 @pytest.mark.parametrize('config', [ - 'ip101', + 'default_ip101', ], indirect=True) @pytest.mark.flaky(reruns=3, reruns_delay=5) def test_esp_eth_ip101(dut: Dut) -> None: - actual_test(dut) + ethernet_l2_test(dut) @pytest.mark.esp32 @pytest.mark.lan8720 @pytest.mark.parametrize('config', [ - 'lan8720', + 'default_lan8720', ], indirect=True) @pytest.mark.flaky(reruns=3, reruns_delay=5) def test_esp_eth_lan8720(dut: Dut) -> None: - actual_test(dut) + ethernet_l2_test(dut) diff --git a/components/esp_eth/test_apps/sdkconfig.ci.default_dm9051 b/components/esp_eth/test_apps/sdkconfig.ci.default_dm9051 new file mode 100644 index 0000000000..08b79b5332 --- /dev/null +++ b/components/esp_eth/test_apps/sdkconfig.ci.default_dm9051 @@ -0,0 +1,8 @@ +CONFIG_IDF_TARGET="esp32" + +CONFIG_UNITY_ENABLE_FIXTURE=y +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +CONFIG_ESP_TASK_WDT=n + +CONFIG_TARGET_USE_SPI_ETHERNET=y +CONFIG_TARGET_ETH_PHY_DEVICE_DM9051=y diff --git a/components/esp_eth/test_apps/sdkconfig.ci.default_dp83848 b/components/esp_eth/test_apps/sdkconfig.ci.default_dp83848 new file mode 100644 index 0000000000..5d2b6a4687 --- /dev/null +++ b/components/esp_eth/test_apps/sdkconfig.ci.default_dp83848 @@ -0,0 +1,9 @@ +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_TARGET_USE_INTERNAL_ETHERNET=y +CONFIG_TARGET_ETH_PHY_DEVICE_DP83848=y diff --git a/components/esp_eth/test_apps/sdkconfig.ci.ip101 b/components/esp_eth/test_apps/sdkconfig.ci.default_ip101 similarity index 82% rename from components/esp_eth/test_apps/sdkconfig.ci.ip101 rename to components/esp_eth/test_apps/sdkconfig.ci.default_ip101 index a09d07030c..90222ab0e9 100644 --- a/components/esp_eth/test_apps/sdkconfig.ci.ip101 +++ b/components/esp_eth/test_apps/sdkconfig.ci.default_ip101 @@ -1,7 +1,9 @@ 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_TARGET_USE_INTERNAL_ETHERNET=y CONFIG_TARGET_ETH_PHY_DEVICE_IP101=y diff --git a/components/esp_eth/test_apps/sdkconfig.ci.default_ksz80xx b/components/esp_eth/test_apps/sdkconfig.ci.default_ksz80xx new file mode 100644 index 0000000000..f81cc10f95 --- /dev/null +++ b/components/esp_eth/test_apps/sdkconfig.ci.default_ksz80xx @@ -0,0 +1,11 @@ +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_TARGET_USE_INTERNAL_ETHERNET=y +CONFIG_TARGET_ETH_PHY_DEVICE_KSZ80XX=y +CONFIG_ETH_RMII_CLK_OUTPUT=y +CONFIG_ETH_RMII_CLK_OUT_GPIO=17 diff --git a/components/esp_eth/test_apps/sdkconfig.ci.default_ksz8851snl b/components/esp_eth/test_apps/sdkconfig.ci.default_ksz8851snl new file mode 100644 index 0000000000..2e869b6be8 --- /dev/null +++ b/components/esp_eth/test_apps/sdkconfig.ci.default_ksz8851snl @@ -0,0 +1,8 @@ +CONFIG_IDF_TARGET="esp32" + +CONFIG_UNITY_ENABLE_FIXTURE=y +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +CONFIG_ESP_TASK_WDT=n + +CONFIG_TARGET_USE_SPI_ETHERNET=y +CONFIG_TARGET_ETH_PHY_DEVICE_KSZ8851SNL=y diff --git a/components/esp_eth/test_apps/sdkconfig.ci.lan8720 b/components/esp_eth/test_apps/sdkconfig.ci.default_lan8720 similarity index 86% rename from components/esp_eth/test_apps/sdkconfig.ci.lan8720 rename to components/esp_eth/test_apps/sdkconfig.ci.default_lan8720 index a061347db0..82bdea14ec 100644 --- a/components/esp_eth/test_apps/sdkconfig.ci.lan8720 +++ b/components/esp_eth/test_apps/sdkconfig.ci.default_lan8720 @@ -1,9 +1,11 @@ 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_TARGET_USE_INTERNAL_ETHERNET=y CONFIG_TARGET_ETH_PHY_DEVICE_LAN87XX=y CONFIG_ETH_RMII_CLK_OUTPUT=y CONFIG_ETH_RMII_CLK_OUT_GPIO=17 diff --git a/components/esp_eth/test_apps/sdkconfig.ci.default_rtl8201 b/components/esp_eth/test_apps/sdkconfig.ci.default_rtl8201 new file mode 100644 index 0000000000..d9730475ac --- /dev/null +++ b/components/esp_eth/test_apps/sdkconfig.ci.default_rtl8201 @@ -0,0 +1,9 @@ +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_TARGET_USE_INTERNAL_ETHERNET=y +CONFIG_TARGET_ETH_PHY_DEVICE_RTL8201=y diff --git a/components/esp_eth/test_apps/sdkconfig.ci.default_w5500 b/components/esp_eth/test_apps/sdkconfig.ci.default_w5500 new file mode 100644 index 0000000000..c60a0a7227 --- /dev/null +++ b/components/esp_eth/test_apps/sdkconfig.ci.default_w5500 @@ -0,0 +1,8 @@ +CONFIG_IDF_TARGET="esp32" + +CONFIG_UNITY_ENABLE_FIXTURE=y +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +CONFIG_ESP_TASK_WDT=n + +CONFIG_TARGET_USE_SPI_ETHERNET=y +CONFIG_TARGET_ETH_PHY_DEVICE_W5500=y diff --git a/components/esp_eth/test_apps/sdkconfig.ci.release_ip101 b/components/esp_eth/test_apps/sdkconfig.ci.release_ip101 new file mode 100644 index 0000000000..baa48405c5 --- /dev/null +++ b/components/esp_eth/test_apps/sdkconfig.ci.release_ip101 @@ -0,0 +1,12 @@ +CONFIG_IDF_TARGET="esp32" +CONFIG_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +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_TARGET_USE_INTERNAL_ETHERNET=y +CONFIG_TARGET_ETH_PHY_DEVICE_IP101=y diff --git a/components/esp_eth/test_apps/sdkconfig.ci.single_core_ip101 b/components/esp_eth/test_apps/sdkconfig.ci.single_core_ip101 new file mode 100644 index 0000000000..8cb1c3d758 --- /dev/null +++ b/components/esp_eth/test_apps/sdkconfig.ci.single_core_ip101 @@ -0,0 +1,13 @@ +CONFIG_IDF_TARGET="esp32" +CONFIG_MEMMAP_SMP=n +CONFIG_FREERTOS_UNICORE=y +CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY=y +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_TARGET_USE_INTERNAL_ETHERNET=y +CONFIG_TARGET_ETH_PHY_DEVICE_IP101=y diff --git a/components/esp_netif/.build-test-rules.yml b/components/esp_netif/.build-test-rules.yml index 4684f184cf..841108a8c9 100644 --- a/components/esp_netif/.build-test-rules.yml +++ b/components/esp_netif/.build-test-rules.yml @@ -1,6 +1,6 @@ # Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps -components/esp_netif/test_apps: +components/esp_netif/test_apps/test_app_esp_netif: disable: - if: IDF_TARGET == "esp32c6" temporary: true @@ -9,3 +9,9 @@ components/esp_netif/test_apps: - if: IDF_TARGET != "esp32s2" temporary: true reason: lack of runners + +components/esp_netif/test_apps/test_app_vfs_l2tap: + disable: + - if: SOC_EMAC_SUPPORTED != 1 + temporary: false + reason: test uses internal EMAC diff --git a/components/esp_netif/test_apps/CMakeLists.txt b/components/esp_netif/test_apps/test_app_esp_netif/CMakeLists.txt similarity index 100% rename from components/esp_netif/test_apps/CMakeLists.txt rename to components/esp_netif/test_apps/test_app_esp_netif/CMakeLists.txt diff --git a/components/esp_netif/test_apps/README.md b/components/esp_netif/test_apps/test_app_esp_netif/README.md similarity index 100% rename from components/esp_netif/test_apps/README.md rename to components/esp_netif/test_apps/test_app_esp_netif/README.md diff --git a/components/esp_netif/test_apps/main/CMakeLists.txt b/components/esp_netif/test_apps/test_app_esp_netif/main/CMakeLists.txt similarity index 100% rename from components/esp_netif/test_apps/main/CMakeLists.txt rename to components/esp_netif/test_apps/test_app_esp_netif/main/CMakeLists.txt diff --git a/components/esp_netif/test_apps/main/esp_netif_test.c b/components/esp_netif/test_apps/test_app_esp_netif/main/esp_netif_test.c similarity index 98% rename from components/esp_netif/test_apps/main/esp_netif_test.c rename to components/esp_netif/test_apps/test_app_esp_netif/main/esp_netif_test.c index 12bef72e57..0866eff446 100644 --- a/components/esp_netif/test_apps/main/esp_netif_test.c +++ b/components/esp_netif/test_apps/test_app_esp_netif/main/esp_netif_test.c @@ -1,3 +1,8 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ #include #include #include "unity.h" diff --git a/components/esp_netif/test_apps/pytest_esp_netif.py b/components/esp_netif/test_apps/test_app_esp_netif/pytest_esp_netif.py similarity index 100% rename from components/esp_netif/test_apps/pytest_esp_netif.py rename to components/esp_netif/test_apps/test_app_esp_netif/pytest_esp_netif.py diff --git a/components/esp_netif/test_apps/sdkconfig.defaults b/components/esp_netif/test_apps/test_app_esp_netif/sdkconfig.defaults similarity index 100% rename from components/esp_netif/test_apps/sdkconfig.defaults rename to components/esp_netif/test_apps/test_app_esp_netif/sdkconfig.defaults diff --git a/components/esp_netif/test_apps/test_app_vfs_l2tap/CMakeLists.txt b/components/esp_netif/test_apps/test_app_vfs_l2tap/CMakeLists.txt new file mode 100644 index 0000000000..859cfa803c --- /dev/null +++ b/components/esp_netif/test_apps/test_app_vfs_l2tap/CMakeLists.txt @@ -0,0 +1,10 @@ +# 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_vfs_l2tap_test) + +idf_component_get_property(lib esp_netif COMPONENT_LIB) +target_compile_options(${lib} PRIVATE "-fsanitize=undefined" "-fno-sanitize=shift-base") diff --git a/components/esp_netif/test_apps/test_app_vfs_l2tap/README.md b/components/esp_netif/test_apps/test_app_vfs_l2tap/README.md new file mode 100644 index 0000000000..f708a1985a --- /dev/null +++ b/components/esp_netif/test_apps/test_app_vfs_l2tap/README.md @@ -0,0 +1,2 @@ +| Supported Targets | ESP32 | +| ----------------- | ----- | diff --git a/components/esp_netif/test_apps/test_app_vfs_l2tap/main/CMakeLists.txt b/components/esp_netif/test_apps/test_app_vfs_l2tap/main/CMakeLists.txt new file mode 100644 index 0000000000..d36d43f5fb --- /dev/null +++ b/components/esp_netif/test_apps/test_app_vfs_l2tap/main/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRC_DIRS "." + PRIV_INCLUDE_DIRS "." + PRIV_REQUIRES cmock test_utils esp_netif driver esp_eth) diff --git a/components/esp_netif/test/test_vfs_l2tap.c b/components/esp_netif/test_apps/test_app_vfs_l2tap/main/test_vfs_l2tap.c similarity index 98% rename from components/esp_netif/test/test_vfs_l2tap.c rename to components/esp_netif/test_apps/test_app_vfs_l2tap/main/test_vfs_l2tap.c index 5fbd7f844d..0dfcfdbb1c 100644 --- a/components/esp_netif/test/test_vfs_l2tap.c +++ b/components/esp_netif/test_apps/test_app_vfs_l2tap/main/test_vfs_l2tap.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/event_groups.h" @@ -29,8 +30,6 @@ #include "esp_vfs_l2tap.h" -#if CONFIG_ESP_NETIF_L2_TAP - #define ETH_FILTER_LE 0x7A05 #define ETH_FILTER_BE 0x057A @@ -240,7 +239,7 @@ static void send_task(void *task_param) * @brief Verifies vfs register/unregister functions * */ -TEST_CASE("esp32 l2tap - vfs register", "[ethernet][test_env=UT_T2_Ethernet]") +TEST_CASE("esp32 l2tap - vfs register", "[ethernet]") { int eth_tap_fd; @@ -344,7 +343,7 @@ static void close_task(void *task_param) vTaskDelete(NULL); } -TEST_CASE("esp32 l2tap - open/close", "[ethernet][test_env=UT_T2_Ethernet]") +TEST_CASE("esp32 l2tap - open/close", "[ethernet]") { test_vfs_eth_network_t eth_network_hndls; @@ -415,7 +414,7 @@ TEST_CASE("esp32 l2tap - open/close", "[ethernet][test_env=UT_T2_Ethernet]") * @brief Verifies that read does not block when fd is opened in non-blocking mode * */ -TEST_CASE("esp32 l2tap - non blocking read", "[ethernet][test_env=UT_T2_Ethernet]") +TEST_CASE("esp32 l2tap - non blocking read", "[ethernet]") { test_vfs_eth_network_t eth_network_hndls; int eth_tap_fd; @@ -536,7 +535,7 @@ TEST_CASE("esp32 l2tap - non blocking read", "[ethernet][test_env=UT_T2_Ethernet * @brief Verifies that read blocks when fd opened in blocking mode * */ -TEST_CASE("esp32 l2tap - blocking read", "[ethernet][test_env=UT_T2_Ethernet]") +TEST_CASE("esp32 l2tap - blocking read", "[ethernet]") { test_vfs_eth_network_t eth_network_hndls; int eth_tap_fd; @@ -599,7 +598,7 @@ TEST_CASE("esp32 l2tap - blocking read", "[ethernet][test_env=UT_T2_Ethernet]") * @brief Verifies write * */ -TEST_CASE("esp32 l2tap - write", "[ethernet][test_env=UT_T2_Ethernet]") +TEST_CASE("esp32 l2tap - write", "[ethernet]") { test_vfs_eth_network_t eth_network_hndls; int eth_tap_fd; @@ -718,12 +717,12 @@ static void multi_fds_task (void *task_param) for (int i = 0; i < sizeof(eth_tap_fds) / sizeof(int); i++) { TEST_ASSERT_EQUAL(0, close(eth_tap_fds[i])); } - ESP_LOGI(TAG, "multi_fds_task %u done", task_info->task_id); + ESP_LOGI(TAG, "multi_fds_task %" PRIu16 "done", task_info->task_id); xSemaphoreGive(task_info->semaphore); vTaskDelete(NULL); } -TEST_CASE("esp32 l2tap - read/write multiple fd's used by multiple tasks", "[ethernet][test_env=UT_T2_Ethernet]") +TEST_CASE("esp32 l2tap - read/write multiple fd's used by multiple tasks", "[ethernet]") { test_vfs_eth_network_t eth_network_hndls; @@ -752,7 +751,7 @@ TEST_CASE("esp32 l2tap - read/write multiple fd's used by multiple tasks", "[eth * @brief Verifies proper functionality of ioctl RCV_FILTER option * */ -TEST_CASE("esp32 l2tap - ioctl - RCV_FILTER", "[ethernet][test_env=UT_T2_Ethernet]") +TEST_CASE("esp32 l2tap - ioctl - RCV_FILTER", "[ethernet]") { test_vfs_eth_network_t eth_network_hndls; int eth_tap_fd; @@ -849,7 +848,7 @@ TEST_CASE("esp32 l2tap - ioctl - RCV_FILTER", "[ethernet][test_env=UT_T2_Etherne * @brief Verifies proper functionality of ioctl INTF_DEVICE option * */ -TEST_CASE("esp32 l2tap - ioctl - INTF_DEVICE/DEVICE_DRV_HNDL", "[ethernet][test_env=UT_T2_Ethernet]") +TEST_CASE("esp32 l2tap - ioctl - INTF_DEVICE/DEVICE_DRV_HNDL", "[ethernet]") { test_vfs_eth_network_t eth_network_hndls; int eth_tap_fd; @@ -939,7 +938,7 @@ TEST_CASE("esp32 l2tap - ioctl - INTF_DEVICE/DEVICE_DRV_HNDL", "[ethernet][test_ * @brief Verifies proper functionality of ioctl unknown option * */ -TEST_CASE("esp32 l2tap - ioctl - unknown", "[ethernet][test_env=UT_T2_Ethernet]") +TEST_CASE("esp32 l2tap - ioctl - unknown", "[ethernet]") { test_vfs_eth_network_t eth_network_hndls; int eth_tap_fd; @@ -964,7 +963,7 @@ TEST_CASE("esp32 l2tap - ioctl - unknown", "[ethernet][test_env=UT_T2_Ethernet]" * @brief Verifies proper functionality of fcntl * */ -TEST_CASE("esp32 l2tap - fcntl", "[ethernet][test_env=UT_T2_Ethernet]") +TEST_CASE("esp32 l2tap - fcntl", "[ethernet]") { test_vfs_eth_network_t eth_network_hndls; int eth_tap_fd; @@ -1064,4 +1063,8 @@ TEST_CASE("esp32 l2tap - fcntl", "[ethernet][test_env=UT_T2_Ethernet]") TEST_ASSERT_EQUAL(ESP_OK, esp_vfs_l2tap_intf_unregister(NULL)); ethernet_deinit(ð_network_hndls); } -#endif // CONFIG_ESP_NETIF_L2_TAP + +void app_main(void) +{ + unity_run_menu(); +} diff --git a/components/esp_netif/test_apps/test_app_vfs_l2tap/pytest_esp_vfs_l2tap.py b/components/esp_netif/test_apps/test_app_vfs_l2tap/pytest_esp_vfs_l2tap.py new file mode 100644 index 0000000000..de7bed11ee --- /dev/null +++ b/components/esp_netif/test_apps/test_app_vfs_l2tap/pytest_esp_vfs_l2tap.py @@ -0,0 +1,15 @@ +# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: CC0-1.0 + +import pytest +from pytest_embedded import Dut + + +@pytest.mark.esp32 +@pytest.mark.ethernet +def test_esp_netif(dut: Dut) -> None: + dut.expect_exact('Press ENTER to see the list of tests') + dut.write('\n') + dut.expect_exact('Enter test for running.') + dut.write('*') + dut.expect_unity_test_output() diff --git a/components/esp_netif/test_apps/test_app_vfs_l2tap/sdkconfig.defaults b/components/esp_netif/test_apps/test_app_vfs_l2tap/sdkconfig.defaults new file mode 100644 index 0000000000..5cec6ae4f0 --- /dev/null +++ b/components/esp_netif/test_apps/test_app_vfs_l2tap/sdkconfig.defaults @@ -0,0 +1,4 @@ +CONFIG_UNITY_ENABLE_FIXTURE=y +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y + +CONFIG_ESP_NETIF_L2_TAP=y diff --git a/examples/ethernet/basic/components/ethernet_init/ethernet_init.c b/examples/ethernet/basic/components/ethernet_init/ethernet_init.c index 238fa1acdc..ffb4e3f837 100644 --- a/examples/ethernet/basic/components/ethernet_init/ethernet_init.c +++ b/examples/ethernet/basic/components/ethernet_init/ethernet_init.c @@ -255,12 +255,12 @@ esp_err_t example_eth_init(esp_eth_handle_t *eth_handles_out[], uint8_t *eth_cnt // Note that Locally Administered OUI range should be used only when testing on a LAN under your control! uint8_t base_mac_addr[ETH_ADDR_LEN]; ESP_GOTO_ON_ERROR(esp_efuse_mac_get_default(base_mac_addr), err, TAG, "get EFUSE MAC failed"); - u_int8_t local_mac_1[ETH_ADDR_LEN]; + uint8_t local_mac_1[ETH_ADDR_LEN]; esp_derive_local_mac(local_mac_1, base_mac_addr); spi_eth_module_config[0].mac_addr = local_mac_1; #if CONFIG_EXAMPLE_SPI_ETHERNETS_NUM > 1 INIT_SPI_ETH_MODULE_CONFIG(spi_eth_module_config, 1); - u_int8_t local_mac_2[ETH_ADDR_LEN]; + uint8_t local_mac_2[ETH_ADDR_LEN]; base_mac_addr[ETH_ADDR_LEN - 1] += 1; esp_derive_local_mac(local_mac_2, base_mac_addr); spi_eth_module_config[1].mac_addr = local_mac_2; diff --git a/tools/unit-test-app/configs/netif_l2tap b/tools/unit-test-app/configs/netif_l2tap deleted file mode 100644 index 235a1831e9..0000000000 --- a/tools/unit-test-app/configs/netif_l2tap +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_IDF_TARGET="esp32" -TEST_COMPONENTS=esp_netif -CONFIG_ESP_NETIF_L2_TAP=y