Просмотр исходного кода

ci(esp_hw_support): add test case for gpio output internal clock feature ci

wuzhenghui 2 лет назад
Родитель
Сommit
d6cda1b6e1

+ 4 - 0
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}

+ 148 - 0
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