diff --git a/components/esp_coex/test_apps/.build-test-rules.yml b/components/esp_coex/test_apps/.build-test-rules.yml new file mode 100644 index 0000000000..164dd0b2dd --- /dev/null +++ b/components/esp_coex/test_apps/.build-test-rules.yml @@ -0,0 +1,6 @@ +# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps + +components/esp_coex/test_apps/: + disable: + - if: IDF_TARGET not in ["esp32s2", "esp32s3", "esp32c3", "esp32c2", "esp32c6", "esp32h2", "esp32c5", "esp32c61"] + reason: only supported with s2, s3, c3, c2, c6, h2, c5 and c61 diff --git a/components/esp_coex/test_apps/external_coex_function/CMakeLists.txt b/components/esp_coex/test_apps/external_coex_function/CMakeLists.txt new file mode 100644 index 0000000000..398e566225 --- /dev/null +++ b/components/esp_coex/test_apps/external_coex_function/CMakeLists.txt @@ -0,0 +1,10 @@ +#This is the project CMakeLists.txt file for the test subproject +cmake_minimum_required(VERSION 3.22) + +set(EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/test_apps/components") + +# "Trim" the build. Include the minimal set of components, main, and anything it depends on. +set(COMPONENTS main) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(external_coex_function) diff --git a/components/esp_coex/test_apps/external_coex_function/README.md b/components/esp_coex/test_apps/external_coex_function/README.md new file mode 100644 index 0000000000..703fb1bde3 --- /dev/null +++ b/components/esp_coex/test_apps/external_coex_function/README.md @@ -0,0 +1,3 @@ +| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S2 | ESP32-S3 | +| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | + diff --git a/components/esp_coex/test_apps/external_coex_function/main/CMakeLists.txt b/components/esp_coex/test_apps/external_coex_function/main/CMakeLists.txt new file mode 100644 index 0000000000..32eca2331e --- /dev/null +++ b/components/esp_coex/test_apps/external_coex_function/main/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register(SRC_DIRS . + PRIV_INCLUDE_DIRS . ${CMAKE_CURRENT_BINARY_DIR} + PRIV_REQUIRES cmock test_utils nvs_flash esp_common esp_wifi esp_event esp_coex + WHOLE_ARCHIVE) diff --git a/components/esp_coex/test_apps/external_coex_function/main/app_main.c b/components/esp_coex/test_apps/external_coex_function/main/app_main.c new file mode 100644 index 0000000000..ae9ef2316f --- /dev/null +++ b/components/esp_coex/test_apps/external_coex_function/main/app_main.c @@ -0,0 +1,48 @@ +/* + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include "unity.h" +#include "nvs_flash.h" +#include "nvs.h" +#include "esp_err.h" +#include "esp_netif.h" + +#include "esp_heap_caps.h" + +// Some resources are lazy allocated in wifi or event handler +#define TEST_MEMORY_LEAK_THRESHOLD (-1536) + +static size_t before_free_8bit; +static size_t before_free_32bit; + +static void check_leak(size_t before_free, size_t after_free, const char *type) +{ + ssize_t delta = after_free - before_free; + printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d)\n", type, before_free, after_free, delta); + TEST_ASSERT_MESSAGE(delta >= TEST_MEMORY_LEAK_THRESHOLD, "memory leak"); +} + +void setUp(void) +{ + before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT); + before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT); +} + +void tearDown(void) +{ + size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT); + size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT); + check_leak(before_free_8bit, after_free_8bit, "8BIT"); + check_leak(before_free_32bit, after_free_32bit, "32BIT"); +} + +void app_main(void) +{ + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + unity_run_menu(); + ESP_ERROR_CHECK(esp_netif_deinit()); + ESP_ERROR_CHECK(nvs_flash_deinit()); +} diff --git a/components/esp_coex/test_apps/external_coex_function/main/test_enable_extern_coex.c b/components/esp_coex/test_apps/external_coex_function/main/test_enable_extern_coex.c new file mode 100644 index 0000000000..11005c4099 --- /dev/null +++ b/components/esp_coex/test_apps/external_coex_function/main/test_enable_extern_coex.c @@ -0,0 +1,64 @@ +/* + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include "unity.h" +#include "esp_wifi.h" +#include "esp_coexist.h" +#include "soc/soc_caps.h" +#include "esp_log.h" +#include "test_utils.h" +#include "unity_test_utils.h" +#include "esp_private/periph_ctrl.h" + +#define TAG "test_external_coex" +#define EMPH_STR(s) "****** "s" ******" + +TEST_CASE("enable external coex", "[external_coex]") +{ +#if !SOC_MODEM_CLOCK_IS_INDEPENDENT && !CONFIG_IDF_TARGET_ESP32C2 + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + cfg.nvs_enable = false; + ESP_LOGI(TAG, EMPH_STR("esp_wifi_init")); + TEST_ESP_OK(esp_wifi_init(&cfg)); +#endif + +#if CONFIG_IDF_TARGET_ESP32S2 +#define EXTERNAL_COEX_CONF 0x60035118 +#define WDEV_RW_BT_COEX_EN (BIT(0)) +#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 +#define EXTERNAL_COEX_CONF 0x60035084 +#define WDEV_RW_BT_COEX_EN (BIT(0)) +#elif CONFIG_IDF_TARGET_ESP32C2 +#define EXTERNAL_COEX_CONF 0x6004C4A0 +#define WDEV_RW_BT_COEX_EN (BIT(9)) +#elif CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32C61 +#define EXTERNAL_COEX_CONF 0x600AF4A0 +#define WDEV_RW_BT_COEX_EN (BIT(9)) +#elif CONFIG_IDF_TARGET_ESP32H2 +#define EXTERNAL_COEX_CONF 0x600AD4A0 +#define WDEV_RW_BT_COEX_EN (BIT(9)) +#endif + + esp_extern_coex_work_mode_t mode = EXTERNAL_COEX_LEADER_ROLE; + external_coex_wire_t type = EXTERN_COEX_WIRE_3; + esp_external_coex_gpio_set_t gpio_pin = {.request = 0, .priority = 1, .grant = 2}; + TEST_ESP_OK(esp_external_coex_set_work_mode(mode)); + TEST_ESP_OK(esp_enable_extern_coex_gpio_pin(type, gpio_pin)); + + ESP_LOGI(TAG, "external coex config 0x%lx", REG_READ(EXTERNAL_COEX_CONF)); + TEST_ASSERT(REG_GET_BIT(EXTERNAL_COEX_CONF, WDEV_RW_BT_COEX_EN)); + + TEST_ESP_OK(esp_disable_extern_coex_gpio_pin()); + coex_module_enable(); + TEST_ASSERT(REG_GET_BIT(EXTERNAL_COEX_CONF, WDEV_RW_BT_COEX_EN) == 0); + coex_module_disable(); + +#if !SOC_MODEM_CLOCK_IS_INDEPENDENT && !CONFIG_IDF_TARGET_ESP32C2 + ESP_LOGI(TAG, EMPH_STR("esp_wifi_deinit")); + TEST_ESP_OK(esp_wifi_deinit()); +#endif + + ESP_LOGI(TAG, "test passed..."); +} diff --git a/components/esp_coex/test_apps/external_coex_function/pytest_external_coex_function.py b/components/esp_coex/test_apps/external_coex_function/pytest_external_coex_function.py new file mode 100644 index 0000000000..1e8ff63036 --- /dev/null +++ b/components/esp_coex/test_apps/external_coex_function/pytest_external_coex_function.py @@ -0,0 +1,56 @@ +# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Unlicense OR CC0-1.0 +import pytest +from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize + + +@pytest.mark.generic +@idf_parametrize( + 'target', ['esp32h2', 'esp32c3', 'esp32s2', 'esp32s3', 'esp32c6', 'esp32c61', 'esp32c5'], indirect=['target'] +) +def test_external_coex_unit_test(dut: Dut) -> None: + dut.run_all_single_board_cases() + + +@pytest.mark.xtal_26mhz +@pytest.mark.generic +@pytest.mark.parametrize( + 'config, baud', + [ + ('esp32c2_xtal26m', '74880'), + ], + indirect=True, +) +@idf_parametrize('target', ['esp32c2'], indirect=['target']) +def test_external_coex_unit_test_esp32c2_xtal26m(dut: Dut) -> None: + dut.run_all_single_board_cases() + + +@pytest.mark.esp32c2eco4 +@pytest.mark.xtal_26mhz +@pytest.mark.generic +@pytest.mark.parametrize( + 'config, baud', + [ + ('esp32c2eco4_xtal26m', '74880'), + ], + indirect=True, +) +@idf_parametrize('target', ['esp32c2'], indirect=['target']) +def test_external_coex_unit_test_esp32c2eco4_xtal26m(dut: Dut) -> None: + dut.run_all_single_board_cases() + + +@pytest.mark.esp32c3eco7 +@pytest.mark.generic +@pytest.mark.parametrize( + 'config', + [ + 'esp32c3eco7', + ], + indirect=True, +) +@idf_parametrize('target', ['esp32c3'], indirect=['target']) +def test_external_coex_unit_test_esp32c3eco7(dut: Dut) -> None: + dut.run_all_single_board_cases() diff --git a/components/esp_coex/test_apps/external_coex_function/sdkconfig.ci b/components/esp_coex/test_apps/external_coex_function/sdkconfig.ci new file mode 100644 index 0000000000..e69de29bb2 diff --git a/components/esp_coex/test_apps/external_coex_function/sdkconfig.ci.esp32c2_xtal26m b/components/esp_coex/test_apps/external_coex_function/sdkconfig.ci.esp32c2_xtal26m new file mode 100644 index 0000000000..172f022b67 --- /dev/null +++ b/components/esp_coex/test_apps/external_coex_function/sdkconfig.ci.esp32c2_xtal26m @@ -0,0 +1,2 @@ +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y diff --git a/components/esp_coex/test_apps/external_coex_function/sdkconfig.ci.esp32c2eco4_xtal26m b/components/esp_coex/test_apps/external_coex_function/sdkconfig.ci.esp32c2eco4_xtal26m new file mode 100644 index 0000000000..651a6cc578 --- /dev/null +++ b/components/esp_coex/test_apps/external_coex_function/sdkconfig.ci.esp32c2eco4_xtal26m @@ -0,0 +1,3 @@ +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_ESP32C2_REV_MIN_200=y diff --git a/components/esp_coex/test_apps/external_coex_function/sdkconfig.ci.esp32c3eco7 b/components/esp_coex/test_apps/external_coex_function/sdkconfig.ci.esp32c3eco7 new file mode 100644 index 0000000000..ad055155c9 --- /dev/null +++ b/components/esp_coex/test_apps/external_coex_function/sdkconfig.ci.esp32c3eco7 @@ -0,0 +1,2 @@ +CONFIG_IDF_TARGET="esp32c3" +CONFIG_ESP32C3_REV_MIN_101=y diff --git a/components/esp_coex/test_apps/external_coex_function/sdkconfig.defaults b/components/esp_coex/test_apps/external_coex_function/sdkconfig.defaults new file mode 100644 index 0000000000..3c07115d64 --- /dev/null +++ b/components/esp_coex/test_apps/external_coex_function/sdkconfig.defaults @@ -0,0 +1,4 @@ + +# ignore task watchdog triggered by unity_run_menu +CONFIG_ESP_TASK_WDT_EN=n +CONFIG_ESP_COEX_EXTERNAL_COEXIST_ENABLE=y