Merge branch 'bugfix/ledc_consecutive_fade_v4.3' into 'release/v4.3'

ledc: Bugfixes for issues related to fade protection (backport v4.3)

See merge request espressif/esp-idf!16661
This commit is contained in:
Michael (XIAO Xufeng)
2022-02-19 17:38:15 +00:00
4 changed files with 130 additions and 66 deletions

View File

@ -61,6 +61,7 @@ esp_err_t ledc_timer_config(const ledc_timer_config_t* timer_conf);
* @brief LEDC update channel parameters * @brief LEDC update channel parameters
* @note Call this function to activate the LEDC updated parameters. * @note Call this function to activate the LEDC updated parameters.
* After ledc_set_duty, we need to call this function to update the settings. * After ledc_set_duty, we need to call this function to update the settings.
* And the new LEDC parameters don't take effect until the next PWM cycle.
* @note ledc_set_duty, ledc_set_duty_with_hpoint and ledc_update_duty are not thread-safe, do not call these functions to * @note ledc_set_duty, ledc_set_duty_with_hpoint and ledc_update_duty are not thread-safe, do not call these functions to
* control one LEDC channel in different tasks at the same time. * control one LEDC channel in different tasks at the same time.
* A thread-safe version of API is ledc_set_duty_and_update * A thread-safe version of API is ledc_set_duty_and_update
@ -178,6 +179,9 @@ esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t
/** /**
* @brief LEDC get duty * @brief LEDC get duty
* This function returns the duty at the present PWM cycle.
* You shouldn't expect the function to return the new duty in the same cycle of calling ledc_update_duty,
* because duty update doesn't take effect until the next cycle.
* *
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel (0-7), select from ledc_channel_t * @param channel LEDC channel (0-7), select from ledc_channel_t
@ -360,7 +364,8 @@ void ledc_fade_func_uninstall(void);
* Other duty operations will have to wait until the fade operation has finished. * Other duty operations will have to wait until the fade operation has finished.
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel number * @param channel LEDC channel number
* @param fade_mode Whether to block until fading done. * @param fade_mode Whether to block until fading done. See ledc_types.h ledc_fade_mode_t for more info.
* Note that this function will not return until fading to the target duty if LEDC_FADE_WAIT_DONE mode is selected.
* *
* @return * @return
* - ESP_OK Success * - ESP_OK Success

View File

@ -193,7 +193,7 @@ esp_err_t ledc_timer_set(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_
static IRAM_ATTR esp_err_t ledc_duty_config(ledc_mode_t speed_mode, ledc_channel_t channel, int hpoint_val, int duty_val, static IRAM_ATTR esp_err_t ledc_duty_config(ledc_mode_t speed_mode, ledc_channel_t channel, int hpoint_val, int duty_val,
ledc_duty_direction_t duty_direction, uint32_t duty_num, uint32_t duty_cycle, uint32_t duty_scale) ledc_duty_direction_t duty_direction, uint32_t duty_num, uint32_t duty_cycle, uint32_t duty_scale)
{ {
portENTER_CRITICAL(&ledc_spinlock); portENTER_CRITICAL_SAFE(&ledc_spinlock);
if (hpoint_val >= 0) { if (hpoint_val >= 0) {
ledc_hal_set_hpoint(&(p_ledc_obj[speed_mode]->ledc_hal), channel, hpoint_val); ledc_hal_set_hpoint(&(p_ledc_obj[speed_mode]->ledc_hal), channel, hpoint_val);
} }
@ -205,7 +205,7 @@ static IRAM_ATTR esp_err_t ledc_duty_config(ledc_mode_t speed_mode, ledc_channel
ledc_hal_set_duty_cycle(&(p_ledc_obj[speed_mode]->ledc_hal), channel, duty_cycle); ledc_hal_set_duty_cycle(&(p_ledc_obj[speed_mode]->ledc_hal), channel, duty_cycle);
ledc_hal_set_duty_scale(&(p_ledc_obj[speed_mode]->ledc_hal), channel, duty_scale); ledc_hal_set_duty_scale(&(p_ledc_obj[speed_mode]->ledc_hal), channel, duty_scale);
ledc_ls_channel_update(speed_mode, channel); ledc_ls_channel_update(speed_mode, channel);
portEXIT_CRITICAL(&ledc_spinlock); portEXIT_CRITICAL_SAFE(&ledc_spinlock);
return ESP_OK; return ESP_OK;
} }
@ -474,8 +474,8 @@ esp_err_t ledc_set_duty_with_hpoint(ledc_mode_t speed_mode, ledc_channel_t chann
hpoint, //uint32_t hpoint_val, hpoint, //uint32_t hpoint_val,
duty, //uint32_t duty_val, duty, //uint32_t duty_val,
1, //uint32_t increase, 1, //uint32_t increase,
1, //uint32_t duty_num, 0, //uint32_t duty_num,
1, //uint32_t duty_cycle, 0, //uint32_t duty_cycle,
0 //uint32_t duty_scale 0 //uint32_t duty_scale
); );
_ledc_fade_hw_release(speed_mode, channel); _ledc_fade_hw_release(speed_mode, channel);
@ -494,8 +494,8 @@ esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t
LEDC_VAL_NO_CHANGE, LEDC_VAL_NO_CHANGE,
duty, //uint32_t duty_val, duty, //uint32_t duty_val,
1, //uint32_t increase, 1, //uint32_t increase,
1, //uint32_t duty_num, 0, //uint32_t duty_num,
1, //uint32_t duty_cycle, 0, //uint32_t duty_cycle,
0 //uint32_t duty_scale 0 //uint32_t duty_scale
); );
_ledc_fade_hw_release(speed_mode, channel); _ledc_fade_hw_release(speed_mode, channel);
@ -575,9 +575,9 @@ void IRAM_ATTR ledc_fade_isr(void* arg)
ledc_calc_fade_end_channel(&intr_status, &channel); ledc_calc_fade_end_channel(&intr_status, &channel);
// clear interrupt // clear interrupt
portENTER_CRITICAL(&ledc_spinlock); portENTER_CRITICAL_ISR(&ledc_spinlock);
ledc_hal_clear_fade_end_intr_status(&(p_ledc_obj[speed_mode]->ledc_hal), channel); ledc_hal_clear_fade_end_intr_status(&(p_ledc_obj[speed_mode]->ledc_hal), channel);
portEXIT_CRITICAL(&ledc_spinlock); portEXIT_CRITICAL_ISR(&ledc_spinlock);
if (s_ledc_fade_rec[speed_mode][channel] == NULL) { if (s_ledc_fade_rec[speed_mode][channel] == NULL) {
//fade object not initialized yet. //fade object not initialized yet.
@ -623,9 +623,9 @@ void IRAM_ATTR ledc_fade_isr(void* arg)
1, 1,
0); 0);
} }
portENTER_CRITICAL(&ledc_spinlock); portENTER_CRITICAL_ISR(&ledc_spinlock);
ledc_hal_set_duty_start(&(p_ledc_obj[speed_mode]->ledc_hal), channel, true); ledc_hal_set_duty_start(&(p_ledc_obj[speed_mode]->ledc_hal), channel, true);
portEXIT_CRITICAL(&ledc_spinlock); portEXIT_CRITICAL_ISR(&ledc_spinlock);
} }
} }
} }
@ -765,7 +765,10 @@ static void _ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t channel, led
ledc_enable_intr_type(speed_mode, channel, LEDC_INTR_FADE_END); ledc_enable_intr_type(speed_mode, channel, LEDC_INTR_FADE_END);
ledc_update_duty(speed_mode, channel); ledc_update_duty(speed_mode, channel);
if (fade_mode == LEDC_FADE_WAIT_DONE) { if (fade_mode == LEDC_FADE_WAIT_DONE) {
xSemaphoreTake(s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem, portMAX_DELAY); // Waiting for fade done
_ledc_fade_hw_acquire(speed_mode, channel);
// Release hardware to support next time fade configure
_ledc_fade_hw_release(speed_mode, channel);
} }
} }
@ -807,7 +810,6 @@ esp_err_t ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_f
LEDC_CHECK(p_ledc_obj[speed_mode] != NULL, LEDC_NOT_INIT, ESP_ERR_INVALID_STATE); LEDC_CHECK(p_ledc_obj[speed_mode] != NULL, LEDC_NOT_INIT, ESP_ERR_INVALID_STATE);
_ledc_fade_hw_acquire(speed_mode, channel); _ledc_fade_hw_acquire(speed_mode, channel);
_ledc_fade_start(speed_mode, channel, fade_mode); _ledc_fade_start(speed_mode, channel, fade_mode);
_ledc_fade_hw_release(speed_mode, channel);
return ESP_OK; return ESP_OK;
} }
@ -844,14 +846,13 @@ esp_err_t ledc_set_duty_and_update(ledc_mode_t speed_mode, ledc_channel_t channe
LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode");
LEDC_ARG_CHECK(channel < LEDC_CHANNEL_MAX, "channel"); LEDC_ARG_CHECK(channel < LEDC_CHANNEL_MAX, "channel");
LEDC_ARG_CHECK(duty <= ledc_get_max_duty(speed_mode, channel), "target_duty"); LEDC_ARG_CHECK(duty <= ledc_get_max_duty(speed_mode, channel), "target_duty");
LEDC_ARG_CHECK(hpoint <= LEDC_HPOINT_VAL_MAX, "hpoint");
LEDC_CHECK(p_ledc_obj[speed_mode] != NULL, LEDC_NOT_INIT, ESP_ERR_INVALID_STATE); LEDC_CHECK(p_ledc_obj[speed_mode] != NULL, LEDC_NOT_INIT, ESP_ERR_INVALID_STATE);
LEDC_CHECK(ledc_fade_channel_init_check(speed_mode, channel) == ESP_OK , LEDC_FADE_INIT_ERROR_STR, ESP_FAIL); LEDC_CHECK(ledc_fade_channel_init_check(speed_mode, channel) == ESP_OK, LEDC_FADE_INIT_ERROR_STR, ESP_FAIL);
_ledc_op_lock_acquire(speed_mode, channel);
_ledc_fade_hw_acquire(speed_mode, channel); _ledc_fade_hw_acquire(speed_mode, channel);
_ledc_set_fade_with_step(speed_mode, channel, duty, 0, 1); ledc_duty_config(speed_mode, channel, hpoint, duty, 1, 0, 0, 0);
_ledc_fade_start(speed_mode, channel, LEDC_FADE_WAIT_DONE); ledc_update_duty(speed_mode, channel);
_ledc_fade_hw_release(speed_mode, channel); _ledc_fade_hw_release(speed_mode, channel);
_ledc_op_lock_release(speed_mode, channel);
return ESP_OK; return ESP_OK;
} }
@ -867,9 +868,6 @@ esp_err_t ledc_set_fade_time_and_start(ledc_mode_t speed_mode, ledc_channel_t ch
_ledc_fade_hw_acquire(speed_mode, channel); _ledc_fade_hw_acquire(speed_mode, channel);
_ledc_set_fade_with_time(speed_mode, channel, target_duty, max_fade_time_ms); _ledc_set_fade_with_time(speed_mode, channel, target_duty, max_fade_time_ms);
_ledc_fade_start(speed_mode, channel, fade_mode); _ledc_fade_start(speed_mode, channel, fade_mode);
if (fade_mode == LEDC_FADE_WAIT_DONE) {
_ledc_fade_hw_release(speed_mode, channel);
}
_ledc_op_lock_release(speed_mode, channel); _ledc_op_lock_release(speed_mode, channel);
return ESP_OK; return ESP_OK;
} }
@ -888,9 +886,6 @@ esp_err_t ledc_set_fade_step_and_start(ledc_mode_t speed_mode, ledc_channel_t ch
_ledc_fade_hw_acquire(speed_mode, channel); _ledc_fade_hw_acquire(speed_mode, channel);
_ledc_set_fade_with_step(speed_mode, channel, target_duty, scale, cycle_num); _ledc_set_fade_with_step(speed_mode, channel, target_duty, scale, cycle_num);
_ledc_fade_start(speed_mode, channel, fade_mode); _ledc_fade_start(speed_mode, channel, fade_mode);
if (fade_mode == LEDC_FADE_WAIT_DONE) {
_ledc_fade_hw_release(speed_mode, channel);
}
_ledc_op_lock_release(speed_mode, channel); _ledc_op_lock_release(speed_mode, channel);
return ESP_OK; return ESP_OK;
} }

View File

@ -63,12 +63,26 @@ static ledc_timer_config_t create_default_timer_config(void)
return ledc_time_config; return ledc_time_config;
} }
static void fade_setup(void)
{
ledc_channel_config_t ledc_ch_config = initialize_channel_config();
ledc_ch_config.duty = 0;
ledc_timer_config_t ledc_time_config = create_default_timer_config();
TEST_ESP_OK(ledc_channel_config(&ledc_ch_config));
TEST_ESP_OK(ledc_timer_config(&ledc_time_config));
vTaskDelay(5 / portTICK_PERIOD_MS);
//initialize fade service
TEST_ESP_OK(ledc_fade_func_install(0));
}
static void timer_duty_set_get(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty) static void timer_duty_set_get(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty)
{ {
TEST_ESP_OK(ledc_set_duty(speed_mode, channel, duty)); TEST_ESP_OK(ledc_set_duty(speed_mode, channel, duty));
TEST_ESP_OK(ledc_update_duty(speed_mode, channel)); TEST_ESP_OK(ledc_update_duty(speed_mode, channel));
vTaskDelay(1000 / portTICK_RATE_MS); vTaskDelay(100 / portTICK_RATE_MS);
TEST_ASSERT_EQUAL_INT32(ledc_get_duty(speed_mode, channel), duty); TEST_ASSERT_EQUAL_INT32(duty, ledc_get_duty(speed_mode, channel));
} }
// use logic analyzer to view // use logic analyzer to view
@ -297,9 +311,9 @@ TEST_CASE("LEDC memory leak test", "[ledc]")
TEST_ESP_OK(ledc_stop(ledc_time_config.speed_mode, LEDC_CHANNEL_0, 0)); TEST_ESP_OK(ledc_stop(ledc_time_config.speed_mode, LEDC_CHANNEL_0, 0));
} }
// the duty need to be detected by waveform given by the logic analyzer // duty should be manually checked from the waveform using a logic analyzer
// can't get it directly, so set it "ignore" // this test is enabled only for testting the settings
TEST_CASE("LEDC set and get dut(with logic analyzer)", "[ledc][ignore]") TEST_CASE("LEDC set and get duty", "[ledc]")
{ {
ledc_timer_t timer_list[4] = {LEDC_TIMER_0, LEDC_TIMER_1, LEDC_TIMER_2, LEDC_TIMER_3}; ledc_timer_t timer_list[4] = {LEDC_TIMER_0, LEDC_TIMER_1, LEDC_TIMER_2, LEDC_TIMER_3};
ledc_mode_t speed_mode_list[LEDC_SPEED_MODE_MAX] = SPEED_MODE_LIST; ledc_mode_t speed_mode_list[LEDC_SPEED_MODE_MAX] = SPEED_MODE_LIST;
@ -310,61 +324,111 @@ TEST_CASE("LEDC set and get dut(with logic analyzer)", "[ledc][ignore]")
} }
} }
TEST_CASE("LEDC fade with time(logic analyzer)", "[ledc][ignore]") TEST_CASE("LEDC fade with time", "[ledc]")
{ {
const ledc_mode_t test_speed_mode = TEST_SPEED_MODE; const ledc_mode_t test_speed_mode = TEST_SPEED_MODE;
ledc_channel_config_t ledc_ch_config = initialize_channel_config(); fade_setup();
ledc_ch_config.duty = 0;
ledc_timer_config_t ledc_time_config = create_default_timer_config();
TEST_ESP_OK(ledc_channel_config(&ledc_ch_config)); TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 4000, 200));
TEST_ESP_OK(ledc_timer_config(&ledc_time_config));
//initialize fade service
TEST_ESP_OK(ledc_fade_func_install(0));
TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 4000, 1000));
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_WAIT_DONE)); TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_WAIT_DONE));
// TODO: allows for 5% deviation here due to driver code (IDF-2099) TEST_ASSERT_EQUAL_INT32(4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
vTaskDelay(1050 / portTICK_RATE_MS);
TEST_ASSERT_EQUAL_INT32(ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0), 4000);
TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 0, 1000)); TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 0, 200));
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT)); TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT));
vTaskDelay(1050 / portTICK_RATE_MS); // duty should not be too far from initial value
TEST_ASSERT_EQUAL_INT32(ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0), 0); TEST_ASSERT_INT32_WITHIN(20, 4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
vTaskDelay(210 / portTICK_PERIOD_MS);
TEST_ASSERT_EQUAL_INT32(0, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
//deinitial fade service //deinitialize fade service
ledc_fade_func_uninstall(); ledc_fade_func_uninstall();
} }
TEST_CASE("LEDC fade with step(logic analyzer)", "[ledc][ignore]") TEST_CASE("LEDC fade with step", "[ledc]")
{ {
const ledc_mode_t test_speed_mode = TEST_SPEED_MODE; const ledc_mode_t test_speed_mode = TEST_SPEED_MODE;
ledc_channel_config_t ledc_ch_config = initialize_channel_config(); fade_setup();
ledc_ch_config.duty = 0;
ledc_timer_config_t ledc_time_config = create_default_timer_config();
TEST_ESP_OK(ledc_channel_config(&ledc_ch_config)); TEST_ESP_OK(ledc_set_fade_with_step(test_speed_mode, LEDC_CHANNEL_0, 4000, 4, 1));
TEST_ESP_OK(ledc_timer_config(&ledc_time_config));
//initialize fade service.
TEST_ESP_OK(ledc_fade_func_install(0));
TEST_ESP_OK(ledc_set_fade_with_step(test_speed_mode, LEDC_CHANNEL_0, 4000, 2, 1));
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_WAIT_DONE)); TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_WAIT_DONE));
vTaskDelay(1050 / portTICK_RATE_MS); TEST_ASSERT_EQUAL_INT32(4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
TEST_ASSERT_EQUAL_INT32(ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0), 4000);
TEST_ESP_OK(ledc_set_fade_with_step(test_speed_mode, LEDC_CHANNEL_0, 0, 4, 2)); TEST_ESP_OK(ledc_set_fade_with_step(test_speed_mode, LEDC_CHANNEL_0, 0, 4, 1));
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT)); TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT));
vTaskDelay(1050 / portTICK_RATE_MS); // duty should not be too far from initial value
TEST_ASSERT_EQUAL_INT32(ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0), 0); TEST_ASSERT_INT32_WITHIN(20, 4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
vTaskDelay(525 / portTICK_PERIOD_MS);
TEST_ASSERT_EQUAL_INT32(0, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
//scaler=0 check //scaler=0 check
TEST_ASSERT(ledc_set_fade_with_step(test_speed_mode, LEDC_CHANNEL_0, 4000, 0, 1) == ESP_ERR_INVALID_ARG); TEST_ASSERT(ledc_set_fade_with_step(test_speed_mode, LEDC_CHANNEL_0, 4000, 0, 1) == ESP_ERR_INVALID_ARG);
//deinitial fade service //deinitialize fade service
ledc_fade_func_uninstall();
}
TEST_CASE("LEDC fast switching duty with fade_wait_done", "[ledc]")
{
const ledc_mode_t test_speed_mode = TEST_SPEED_MODE;
fade_setup();
// fade function will block until fading to the target duty
int64_t fade_start, fade_stop;
fade_start = esp_timer_get_time();
TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 4000, 200));
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_WAIT_DONE));
TEST_ASSERT_EQUAL_INT32(4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 1000, 150));
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_WAIT_DONE));
TEST_ASSERT_EQUAL_INT32(1000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
fade_stop = esp_timer_get_time();
int time_ms = (fade_stop - fade_start) / 1000;
TEST_ASSERT_TRUE(fabs(time_ms - 350) < 20);
// next duty update will not take place until last fade reaches its target duty
TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 4000, 200));
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_WAIT_DONE));
TEST_ASSERT_EQUAL_INT32(4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
TEST_ESP_OK(ledc_set_duty(test_speed_mode, LEDC_CHANNEL_0, 500));
TEST_ESP_OK(ledc_update_duty(test_speed_mode, LEDC_CHANNEL_0));
vTaskDelay(5 / portTICK_PERIOD_MS);
TEST_ASSERT_EQUAL_INT32(500, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
//deinitialize fade service
ledc_fade_func_uninstall();
}
TEST_CASE("LEDC fast switching duty with fade_no_wait", "[ledc]")
{
const ledc_mode_t test_speed_mode = TEST_SPEED_MODE;
fade_setup();
// fade function returns immediately, but next fade still needs to wait for last fade ends
int64_t fade_start, first_fade_complete;
fade_start = esp_timer_get_time();
TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 4000, 200));
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT));
TEST_ASSERT_LESS_THAN(4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 1000, 150));
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT));
first_fade_complete = esp_timer_get_time();
// duty should not be too far from first fade target duty
TEST_ASSERT_INT32_WITHIN(20, 4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
int time_ms = (first_fade_complete - fade_start) / 1000;
TEST_ASSERT_TRUE(fabs(time_ms - 200) < 20);
vTaskDelay(158 / portTICK_PERIOD_MS);
TEST_ASSERT_EQUAL_INT32(1000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
// next duty update will not take place until last fade reaches its target duty
TEST_ESP_OK(ledc_set_fade_with_time(test_speed_mode, LEDC_CHANNEL_0, 4000, 200));
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT));
TEST_ASSERT_LESS_THAN(4000, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
TEST_ESP_OK(ledc_set_duty(test_speed_mode, LEDC_CHANNEL_0, 500));
TEST_ESP_OK(ledc_update_duty(test_speed_mode, LEDC_CHANNEL_0));
vTaskDelay(5 / portTICK_PERIOD_MS);
TEST_ASSERT_EQUAL_INT32(500, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
//deinitialize fade service
ledc_fade_func_uninstall(); ledc_fade_func_uninstall();
} }

View File

@ -579,14 +579,14 @@ UT_046:
UT_047: UT_047:
extends: .unit_test_s2_template extends: .unit_test_s2_template
parallel: 5 parallel: 6
tags: tags:
- ESP32S2_IDF - ESP32S2_IDF
- UT_T1_1 - UT_T1_1
UT_C3: UT_C3:
extends: .unit_test_c3_template extends: .unit_test_c3_template
parallel: 30 parallel: 31
tags: tags:
- ESP32C3_IDF - ESP32C3_IDF
- UT_T1_1 - UT_T1_1