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