-
Notifications
You must be signed in to change notification settings - Fork 7.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'feature/ledc_sleep_retention_support' into 'master'
feat(ledc): support ledc sleep mode selection Closes IDFGH-12713, IDF-9740, IDF-9769, IDF-9909, IDF-10372, IDF-10394, IDF-8472, and IDFCI-2450 See merge request espressif/esp-idf!34097
- Loading branch information
Showing
64 changed files
with
1,463 additions
and
177 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
99 changes: 99 additions & 0 deletions
99
components/esp_driver_ledc/test_apps/ledc/main/test_ledc_sleep.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include "unity.h" | ||
#include "freertos/FreeRTOS.h" | ||
#include "freertos/task.h" | ||
#include "driver/ledc.h" | ||
#include "test_ledc_utils.h" | ||
#include "esp_sleep.h" | ||
#include "esp_private/sleep_cpu.h" | ||
#include "esp_private/esp_sleep_internal.h" | ||
#include "esp_private/esp_pmu.h" | ||
#include "soc/ledc_periph.h" | ||
#include "esp_private/sleep_retention.h" | ||
|
||
// Note. Test cases in this file cannot run one after another without reset | ||
|
||
/** | ||
* @brief Test LEDC can still output PWM signal after light sleep | ||
* | ||
* @param allow_pd Whether to allow powering down the peripheral in light sleep | ||
*/ | ||
static void test_ledc_sleep_retention(bool allow_pd) | ||
{ | ||
int pulse_count __attribute__((unused)) = 0; | ||
|
||
ledc_timer_config_t ledc_time_config = create_default_timer_config(); | ||
TEST_ESP_OK(ledc_timer_config(&ledc_time_config)); | ||
|
||
ledc_channel_config_t ledc_ch_config = initialize_channel_config(); | ||
ledc_ch_config.sleep_mode = (allow_pd ? LEDC_SLEEP_MODE_NO_ALIVE_ALLOW_PD : LEDC_SLEEP_MODE_NO_ALIVE_NO_PD); | ||
TEST_ESP_OK(ledc_channel_config(&ledc_ch_config)); | ||
|
||
vTaskDelay(50 / portTICK_PERIOD_MS); | ||
|
||
#if SOC_PCNT_SUPPORTED | ||
setup_testbench(); | ||
pulse_count = wave_count(1000); | ||
TEST_ASSERT_UINT32_WITHIN(5, TEST_PWM_FREQ, pulse_count); | ||
tear_testbench(); // tear down so that PCNT won't affect TOP PD | ||
#endif | ||
|
||
esp_sleep_context_t sleep_ctx; | ||
esp_sleep_set_sleep_context(&sleep_ctx); | ||
|
||
#if ESP_SLEEP_POWER_DOWN_CPU | ||
TEST_ESP_OK(sleep_cpu_configure(true)); | ||
#endif | ||
TEST_ESP_OK(esp_sleep_enable_timer_wakeup(2 * 1000 * 1000)); | ||
|
||
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"); | ||
|
||
#if ESP_SLEEP_POWER_DOWN_CPU | ||
TEST_ESP_OK(sleep_cpu_configure(false)); | ||
#endif | ||
|
||
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 | ||
TEST_ASSERT_EQUAL(allow_pd ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP); | ||
#endif | ||
esp_sleep_set_sleep_context(NULL); | ||
|
||
if (allow_pd) { | ||
// check if the RO duty_r register field get synced back | ||
TEST_ASSERT_EQUAL(4000, ledc_get_duty(TEST_SPEED_MODE, LEDC_CHANNEL_0)); | ||
} | ||
|
||
#if SOC_PCNT_SUPPORTED | ||
setup_testbench(); | ||
pulse_count = wave_count(1000); | ||
TEST_ASSERT_UINT32_WITHIN(5, TEST_PWM_FREQ, pulse_count); | ||
tear_testbench(); | ||
#endif | ||
} | ||
|
||
TEST_CASE("ledc can output after light sleep (LEDC power domain xpd)", "[ledc]") | ||
{ | ||
test_ledc_sleep_retention(false); | ||
} | ||
|
||
#if SOC_LEDC_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP | ||
TEST_CASE("ledc can output after light sleep (LEDC power domain pd)", "[ledc]") | ||
{ | ||
// test retention feature | ||
test_ledc_sleep_retention(true); | ||
|
||
// ledc driver does not have channel release, we will do retention release here to avoid memory leak | ||
sleep_retention_module_t module = ledc_reg_retention_info.module_id; | ||
sleep_retention_module_free(module); | ||
sleep_retention_module_deinit(module); | ||
} | ||
#endif |
84 changes: 84 additions & 0 deletions
84
components/esp_driver_ledc/test_apps/ledc/main/test_ledc_utils.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <string.h> | ||
#include "unity.h" | ||
#include "freertos/FreeRTOS.h" | ||
#include "freertos/task.h" | ||
#include "test_ledc_utils.h" | ||
#include "soc/soc_caps.h" | ||
|
||
ledc_channel_config_t initialize_channel_config(void) | ||
{ | ||
ledc_channel_config_t config; | ||
memset(&config, 0, sizeof(ledc_channel_config_t)); | ||
config.gpio_num = PULSE_IO; | ||
config.speed_mode = TEST_SPEED_MODE; | ||
config.channel = LEDC_CHANNEL_0; | ||
config.intr_type = LEDC_INTR_DISABLE; | ||
config.timer_sel = LEDC_TIMER_0; | ||
config.duty = 4000; | ||
config.hpoint = 0; | ||
return config; | ||
} | ||
|
||
ledc_timer_config_t create_default_timer_config(void) | ||
{ | ||
ledc_timer_config_t ledc_time_config; | ||
memset(&ledc_time_config, 0, sizeof(ledc_timer_config_t)); | ||
ledc_time_config.speed_mode = TEST_SPEED_MODE; | ||
ledc_time_config.duty_resolution = LEDC_TIMER_13_BIT; | ||
ledc_time_config.timer_num = LEDC_TIMER_0; | ||
ledc_time_config.freq_hz = TEST_PWM_FREQ; | ||
ledc_time_config.clk_cfg = TEST_DEFAULT_CLK_CFG; | ||
return ledc_time_config; | ||
} | ||
|
||
// use PCNT to test the waveform of LEDC | ||
#if SOC_PCNT_SUPPORTED | ||
#include "driver/pulse_cnt.h" | ||
|
||
#define HIGHEST_LIMIT 10000 | ||
#define LOWEST_LIMIT -10000 | ||
|
||
static pcnt_unit_handle_t pcnt_unit; | ||
static pcnt_channel_handle_t pcnt_chan; | ||
|
||
void setup_testbench(void) | ||
{ | ||
pcnt_unit_config_t unit_config = { | ||
.high_limit = HIGHEST_LIMIT, | ||
.low_limit = LOWEST_LIMIT, | ||
}; | ||
TEST_ESP_OK(pcnt_new_unit(&unit_config, &pcnt_unit)); | ||
pcnt_chan_config_t chan_config = { | ||
.edge_gpio_num = PULSE_IO, | ||
.level_gpio_num = -1, | ||
}; | ||
TEST_ESP_OK(pcnt_new_channel(pcnt_unit, &chan_config, &pcnt_chan)); | ||
TEST_ESP_OK(pcnt_channel_set_level_action(pcnt_chan, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_KEEP)); | ||
TEST_ESP_OK(pcnt_channel_set_edge_action(pcnt_chan, PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD)); | ||
TEST_ESP_OK(pcnt_unit_enable(pcnt_unit)); | ||
} | ||
|
||
void tear_testbench(void) | ||
{ | ||
TEST_ESP_OK(pcnt_unit_disable(pcnt_unit)); | ||
TEST_ESP_OK(pcnt_del_channel(pcnt_chan)); | ||
TEST_ESP_OK(pcnt_del_unit(pcnt_unit)); | ||
} | ||
|
||
int wave_count(int last_time) | ||
{ | ||
int test_counter = 0; | ||
TEST_ESP_OK(pcnt_unit_clear_count(pcnt_unit)); | ||
TEST_ESP_OK(pcnt_unit_start(pcnt_unit)); | ||
vTaskDelay(pdMS_TO_TICKS(last_time)); | ||
TEST_ESP_OK(pcnt_unit_stop(pcnt_unit)); | ||
TEST_ESP_OK(pcnt_unit_get_count(pcnt_unit, &test_counter)); | ||
return test_counter; | ||
} | ||
#endif |
Oops, something went wrong.