From d6cda1b6e11e8e8d3461e6d35b64c2db096fb84d Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Mon, 11 Sep 2023 15:37:22 +0800 Subject: [PATCH] ci(esp_hw_support): add test case for gpio output internal clock feature ci --- .../main/CMakeLists.txt | 4 + .../main/test_esp_clock_output.c | 148 ++++++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_esp_clock_output.c diff --git a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/CMakeLists.txt b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/CMakeLists.txt index 982a32fa20..0f499f0d84 100644 --- a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/CMakeLists.txt +++ b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/CMakeLists.txt @@ -8,6 +8,10 @@ set(srcs "test_app_main.c" "test_random.c" ) +if(CONFIG_SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX OR CONFIG_SOC_GPIO_CLOCKOUT_BY_IO_MUX) + list(APPEND srcs "test_esp_clock_output.c") +endif() + # In order for the cases defined by `TEST_CASE` to be linked into the final elf, # the component can be registered as WHOLE_ARCHIVE idf_component_register(SRCS ${srcs} diff --git a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_esp_clock_output.c b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_esp_clock_output.c new file mode 100644 index 0000000000..e3e189283e --- /dev/null +++ b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_esp_clock_output.c @@ -0,0 +1,148 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "unity.h" +#include "driver/gpio.h" +#include "esp_err.h" +#include "esp_clock_output.h" +#include "hal/gpio_hal.h" + +#include "soc/rtc.h" + +#define TEST_LOOPS 100 + +#if CONFIG_IDF_TARGET_ESP32 +static const int test_clk_out_io[] = {0, 1, 3}; +#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 +static const int test_clk_out_io[] = {18, 19, 20}; +#else +static const int test_clk_out_io[] = {3, 4, 5, 6}; +#endif + +static soc_clkout_sig_id_t test_clk_out_sig[] = {CLKOUT_SIG_XTAL, CLKOUT_SIG_RC_SLOW, CLKOUT_SIG_RC_FAST, CLKOUT_SIG_INVALID}; + +static SemaphoreHandle_t test_done_semphr; + +void output_clock_1(void *pvParameter) +{ + esp_clock_output_mapping_handle_t clkout_mapping_hdl; + for (int i = 0; i < TEST_LOOPS; ++i) { + TEST_ESP_OK(esp_clock_output_start(test_clk_out_sig[0], test_clk_out_io[0], &clkout_mapping_hdl)); + vTaskDelay(3); + TEST_ESP_OK(esp_clock_output_stop(clkout_mapping_hdl)); + vTaskDelay(7); + } + xSemaphoreGive(test_done_semphr); + vTaskDelete(NULL); +} + +void output_clock_2(void *pvParameter) +{ + esp_clock_output_mapping_handle_t clkout_mapping_hdl; + for (int i = 0; i < TEST_LOOPS; ++i) { + TEST_ESP_OK(esp_clock_output_start(test_clk_out_sig[1], test_clk_out_io[1], &clkout_mapping_hdl)); + vTaskDelay(4); + TEST_ESP_OK(esp_clock_output_stop(clkout_mapping_hdl)); + vTaskDelay(6); + } + xSemaphoreGive(test_done_semphr); + vTaskDelete(NULL); +} + +void output_clock_3(void *pvParameter) +{ + rtc_dig_clk8m_enable(); + esp_clock_output_mapping_handle_t clkout_mapping_hdl; + for (int i = 0; i < TEST_LOOPS; ++i) { + TEST_ESP_OK(esp_clock_output_start(test_clk_out_sig[2], test_clk_out_io[2], &clkout_mapping_hdl)); + vTaskDelay(5); + TEST_ESP_OK(esp_clock_output_stop(clkout_mapping_hdl)); + vTaskDelay(5); + } + xSemaphoreGive(test_done_semphr); + vTaskDelete(NULL); +} + + +// This case is now tested only manually +TEST_CASE("GPIO output internal clock", "[gpio_output_clock][ignore]") +{ + test_done_semphr = xSemaphoreCreateCounting(3, 0); + xTaskCreate(&output_clock_1, "output_clock_1", 4096, NULL, 4, NULL); + xTaskCreate(&output_clock_2, "output_clock_2", 4096, NULL, 4, NULL); + xTaskCreate(&output_clock_3, "output_clock_3", 4096, NULL, 4, NULL); + + int cnt = 0; + while (cnt < 3) { + if (xSemaphoreTake(test_done_semphr, portMAX_DELAY) == pdTRUE) { + cnt++; + } + } + vTaskDelay(1); + + vSemaphoreDelete(test_done_semphr); + gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_U0RXD); + gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_U0TXD); +} + +#if SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX +TEST_CASE("GPIO output internal clock one-to-many", "[gpio_output_clock][ignore]") +{ + // Test NULL handle assertion + TEST_ESP_ERR(esp_clock_output_start(test_clk_out_sig[0], test_clk_out_io[0], NULL), ESP_ERR_INVALID_ARG); + + // Test first mapping + esp_clock_output_mapping_handle_t clkout_mapping_hdl_0; + TEST_ESP_OK(esp_clock_output_start(test_clk_out_sig[0], test_clk_out_io[0], &clkout_mapping_hdl_0)); // [0]:0(1) [1]:x [2]:x + + // Test the same mapping allocate the same handle + esp_clock_output_mapping_handle_t clkout_mapping_hdl_1; + TEST_ESP_OK(esp_clock_output_start(test_clk_out_sig[0], test_clk_out_io[0], &clkout_mapping_hdl_1)); // [0]:0(2) [1]:x [2]:x + TEST_ASSERT(clkout_mapping_hdl_0 == clkout_mapping_hdl_1); + + // Test map multi signal to one IO assertion + esp_clock_output_mapping_handle_t clkout_mapping_hdl_2; + TEST_ESP_ERR(esp_clock_output_start(test_clk_out_sig[1], test_clk_out_io[0], &clkout_mapping_hdl_2), ESP_ERR_INVALID_ARG); + + // Test the same signal mapping to multi GPIO + TEST_ESP_OK(esp_clock_output_start(test_clk_out_sig[0], test_clk_out_io[1], &clkout_mapping_hdl_2)); // [0]:0(2) 1 [1]:x [2]:x + esp_clock_output_mapping_handle_t clkout_mapping_hdl_3; + TEST_ESP_OK(esp_clock_output_start(test_clk_out_sig[0], test_clk_out_io[2], &clkout_mapping_hdl_3)); // [0]:0(2) 1 2 [1]:x [2]:x + + // Test the clkout mapping ref_cnt validity + esp_clock_output_stop(clkout_mapping_hdl_0); // [0]:0(1) 1 2 [1]:x [2]:x + esp_clock_output_mapping_handle_t clkout_mapping_hdl_4; + TEST_ESP_ERR(esp_clock_output_start(test_clk_out_sig[1], test_clk_out_io[0], &clkout_mapping_hdl_4), ESP_ERR_INVALID_ARG); + esp_clock_output_stop(clkout_mapping_hdl_1); // [0]:1 2 [1]:x [2]:x + TEST_ESP_OK(esp_clock_output_start(test_clk_out_sig[1], test_clk_out_io[0], &clkout_mapping_hdl_4)); // [0]:1 2 [1]:0 [2]:x + +#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 + test_clk_out_sig[3] = CLKOUT_SIG_PLL_F80M; +#else + test_clk_out_sig[3] = CLKOUT_SIG_RC_32K; +#endif + + // Test the excess clock channel request assertion + esp_clock_output_stop(clkout_mapping_hdl_3); // [0]:1 [1]:0 [2]:x + esp_clock_output_mapping_handle_t clkout_mapping_hdl_5; + TEST_ESP_OK(esp_clock_output_start(test_clk_out_sig[2], test_clk_out_io[2], &clkout_mapping_hdl_5)); // [0]:1 [1]:0 [2]:2 + esp_clock_output_mapping_handle_t clkout_mapping_hdl_6; + TEST_ASSERT(ESP_FAIL == esp_clock_output_start(test_clk_out_sig[3], test_clk_out_io[3], &clkout_mapping_hdl_6)); + + // Test the clock out channel recycle + esp_clock_output_stop(clkout_mapping_hdl_4); // [0]:1 [1]:x [2]:2 + esp_clock_output_mapping_handle_t clkout_mapping_hdl_7; + TEST_ESP_OK(esp_clock_output_start(test_clk_out_sig[3], test_clk_out_io[0], &clkout_mapping_hdl_7)); // [0]:1 [1]:0 [2]:2 + + // Stop all + esp_clock_output_stop(clkout_mapping_hdl_2); + esp_clock_output_stop(clkout_mapping_hdl_5); + esp_clock_output_stop(clkout_mapping_hdl_6); + esp_clock_output_stop(clkout_mapping_hdl_7); +} +#endif