From 33103306a6e5eef36f6d92af4ecbe110824a6703 Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Thu, 24 Oct 2024 13:39:05 +0800 Subject: [PATCH] feat(ledc): added a multi device test for testing ledc output in sleep --- .../test_apps/ledc/main/CMakeLists.txt | 5 +- .../test_apps/ledc/main/idf_component.yml | 3 + .../test_apps/ledc/main/test_ledc_sleep.c | 64 ++++++++++++++++++- .../test_apps/ledc/main/test_ledc_utils.h | 3 +- .../test_apps/ledc/pytest_ledc.py | 16 +++++ 5 files changed, 87 insertions(+), 4 deletions(-) create mode 100644 components/esp_driver_ledc/test_apps/ledc/main/idf_component.yml diff --git a/components/esp_driver_ledc/test_apps/ledc/main/CMakeLists.txt b/components/esp_driver_ledc/test_apps/ledc/main/CMakeLists.txt index 0348cc26f6..8aeea8c40d 100644 --- a/components/esp_driver_ledc/test_apps/ledc/main/CMakeLists.txt +++ b/components/esp_driver_ledc/test_apps/ledc/main/CMakeLists.txt @@ -1,8 +1,11 @@ set(srcs "test_app_main.c" "test_ledc.c" - "test_ledc_sleep.c" "test_ledc_utils.c") +if(CONFIG_SOC_LIGHT_SLEEP_SUPPORTED) + list(APPEND srcs "test_ledc_sleep.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( diff --git a/components/esp_driver_ledc/test_apps/ledc/main/idf_component.yml b/components/esp_driver_ledc/test_apps/ledc/main/idf_component.yml new file mode 100644 index 0000000000..f5001494e2 --- /dev/null +++ b/components/esp_driver_ledc/test_apps/ledc/main/idf_component.yml @@ -0,0 +1,3 @@ +dependencies: + test_utils: + path: ${IDF_PATH}/tools/unit-test-app/components/test_utils diff --git a/components/esp_driver_ledc/test_apps/ledc/main/test_ledc_sleep.c b/components/esp_driver_ledc/test_apps/ledc/main/test_ledc_sleep.c index 55d3e99a21..c3c57a4e03 100644 --- a/components/esp_driver_ledc/test_apps/ledc/main/test_ledc_sleep.c +++ b/components/esp_driver_ledc/test_apps/ledc/main/test_ledc_sleep.c @@ -5,6 +5,7 @@ */ #include "unity.h" +#include "test_utils.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/ledc.h" @@ -15,6 +16,7 @@ #include "esp_private/esp_pmu.h" #include "soc/ledc_periph.h" #include "esp_private/sleep_retention.h" +#include "esp_rom_uart.h" // Note. Test cases in this file cannot run one after another without reset @@ -51,7 +53,7 @@ static void test_ledc_sleep_retention(bool allow_pd) #endif TEST_ESP_OK(esp_sleep_enable_timer_wakeup(2 * 1000 * 1000)); - printf("go to light sleep for 2 seconds\n"); + printf("Go to light sleep for 2 seconds\n"); TEST_ESP_OK(esp_light_sleep_start()); printf("Waked up! Let's see if LEDC peripheral can still work...\n"); @@ -59,7 +61,7 @@ static void test_ledc_sleep_retention(bool allow_pd) TEST_ESP_OK(sleep_cpu_configure(false)); #endif - printf("check if the sleep happened as expected\r\n"); + printf("Check if the sleep happened as expected\r\n"); TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result); #if SOC_PMU_SUPPORTED // check if the TOP power domain on/off as desired @@ -97,3 +99,61 @@ TEST_CASE("ledc can output after light sleep (LEDC power domain pd)", "[ledc]") sleep_retention_module_deinit(module); } #endif + +#if SOC_PCNT_SUPPORTED +static const ledc_clk_src_t test_ledc_clk_in_slp[] = { + LEDC_USE_RC_FAST_CLK, +#if SOC_LEDC_SUPPORT_XTAL_CLOCK + LEDC_USE_XTAL_CLK, +#endif +}; + +static const int test_clks_num = sizeof(test_ledc_clk_in_slp) / sizeof(test_ledc_clk_in_slp[0]); + +static void ledc_output_monitor(void) +{ + setup_testbench(); + + for (int i = 0; i < test_clks_num; i++) { + unity_wait_for_signal("Go to light sleep for 3 seconds"); + vTaskDelay(500 / portTICK_PERIOD_MS); + int pulse_count = wave_count(1000); + uint32_t acceptable_delta = (test_ledc_clk_in_slp[i] == (ledc_clk_src_t)LEDC_USE_RC_FAST_CLK) ? 20 : 5; // RC_FAST as the clk src has a bigger error range is reasonable + TEST_ASSERT_UINT32_WITHIN(acceptable_delta, TEST_PWM_LOW_FREQ, pulse_count); + unity_wait_for_signal("Waked up!"); + } + + tear_testbench(); +} + +static void ledc_output_in_sleep(void) +{ + TEST_ESP_OK(esp_sleep_enable_timer_wakeup(3 * 1000 * 1000)); + + ledc_channel_config_t ledc_ch_config = initialize_channel_config(); + ledc_ch_config.speed_mode = LEDC_LOW_SPEED_MODE; + ledc_ch_config.sleep_mode = LEDC_SLEEP_MODE_KEEP_ALIVE; + TEST_ESP_OK(ledc_channel_config(&ledc_ch_config)); + + for (int i = 0; i < test_clks_num; i++) { + ledc_timer_config_t ledc_time_config = create_default_timer_config(); + ledc_time_config.speed_mode = LEDC_LOW_SPEED_MODE; + ledc_time_config.clk_cfg = test_ledc_clk_in_slp[i]; + ledc_time_config.freq_hz = TEST_PWM_LOW_FREQ; + TEST_ESP_OK(ledc_timer_config(&ledc_time_config)); + + TEST_ESP_OK(ledc_update_duty(ledc_ch_config.speed_mode, ledc_ch_config.channel)); + + unity_send_signal("Go to light sleep for 3 seconds"); + esp_rom_output_tx_wait_idle(CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM); // wait until the signal sent + TEST_ESP_OK(esp_light_sleep_start()); + unity_send_signal("Waked up!"); + + TEST_ESP_OK(ledc_timer_pause(ledc_time_config.speed_mode, ledc_time_config.timer_num)); + ledc_time_config.deconfigure = 1; + TEST_ESP_OK(ledc_timer_config(&ledc_time_config)); + } +} + +TEST_CASE_MULTIPLE_DEVICES("ledc can output during light sleep", "[ledc][test_env=generic_multi_device]", ledc_output_in_sleep, ledc_output_monitor); +#endif // SOC_PCNT_SUPPORTED diff --git a/components/esp_driver_ledc/test_apps/ledc/main/test_ledc_utils.h b/components/esp_driver_ledc/test_apps/ledc/main/test_ledc_utils.h index 23043b2f72..d3c3c7e643 100644 --- a/components/esp_driver_ledc/test_apps/ledc/main/test_ledc_utils.h +++ b/components/esp_driver_ledc/test_apps/ledc/main/test_ledc_utils.h @@ -9,7 +9,8 @@ #define PULSE_IO 5 -#define TEST_PWM_FREQ 2000 +#define TEST_PWM_FREQ 2000 +#define TEST_PWM_LOW_FREQ 200 #if SOC_LEDC_SUPPORT_HS_MODE #define TEST_SPEED_MODE LEDC_HIGH_SPEED_MODE diff --git a/components/esp_driver_ledc/test_apps/ledc/pytest_ledc.py b/components/esp_driver_ledc/test_apps/ledc/pytest_ledc.py index 0b7ae925e9..22687a67fc 100644 --- a/components/esp_driver_ledc/test_apps/ledc/pytest_ledc.py +++ b/components/esp_driver_ledc/test_apps/ledc/pytest_ledc.py @@ -32,3 +32,19 @@ def test_ledc(dut: IdfDut) -> None: ) def test_ledc_psram(dut: IdfDut) -> None: dut.run_all_single_board_cases(reset=True) + + +@pytest.mark.supported_targets +@pytest.mark.temp_skip_ci(targets=['esp32s3', 'esp32c61'], + reason='s3 multi device runner has no psram, c61 lack of runner IDF-10949') +@pytest.mark.generic_multi_device +@pytest.mark.parametrize( + 'count, config', + [ + (2, 'iram_safe',), + (2, 'release',), + ], + indirect=True +) +def test_ledc_multi_device(case_tester) -> None: # type: ignore + case_tester.run_all_multi_dev_cases(reset=True)