ledc: Fix FADE_NO_WAIT mode concurrency problem.

Add test cases for fade concurrency issue and fade timing check.

Closes https://github.com/espressif/esp-idf/issues/6710
This commit is contained in:
songruojing
2021-07-29 13:54:17 +08:00
parent e175086226
commit be2ab09832
3 changed files with 121 additions and 60 deletions

View File

@@ -216,7 +216,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,
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) {
ledc_hal_set_hpoint(&(p_ledc_obj[speed_mode]->ledc_hal), channel, hpoint_val);
}
@@ -228,7 +228,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_scale(&(p_ledc_obj[speed_mode]->ledc_hal), channel, duty_scale);
ledc_ls_channel_update(speed_mode, channel);
portEXIT_CRITICAL(&ledc_spinlock);
portEXIT_CRITICAL_SAFE(&ledc_spinlock);
return ESP_OK;
}
@@ -802,9 +802,9 @@ void IRAM_ATTR ledc_fade_isr(void *arg)
ledc_calc_fade_end_channel(&intr_status, &channel);
// 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);
portEXIT_CRITICAL(&ledc_spinlock);
portEXIT_CRITICAL_ISR(&ledc_spinlock);
if (s_ledc_fade_rec[speed_mode][channel] == NULL) {
//fade object not initialized yet.
@@ -854,9 +854,9 @@ void IRAM_ATTR ledc_fade_isr(void *arg)
1,
0);
}
portENTER_CRITICAL(&ledc_spinlock);
portENTER_CRITICAL_ISR(&ledc_spinlock);
ledc_hal_set_duty_start(&(p_ledc_obj[speed_mode]->ledc_hal), channel, true);
portEXIT_CRITICAL(&ledc_spinlock);
portEXIT_CRITICAL_ISR(&ledc_spinlock);
}
}
if (HPTaskAwoken == pdTRUE || cb_yield) {
@@ -999,7 +999,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_update_duty(speed_mode, channel);
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);
}
}
@@ -1041,7 +1044,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_fade_hw_acquire(speed_mode, channel);
_ledc_fade_start(speed_mode, channel, fade_mode);
_ledc_fade_hw_release(speed_mode, channel);
return ESP_OK;
}
@@ -1089,12 +1091,10 @@ esp_err_t ledc_set_duty_and_update(ledc_mode_t speed_mode, ledc_channel_t channe
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(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_duty_config(speed_mode, channel, hpoint, duty, 1, 0, 0, 0);
ledc_update_duty(speed_mode, channel);
_ledc_fade_hw_release(speed_mode, channel);
_ledc_op_lock_release(speed_mode, channel);
return ESP_OK;
}
@@ -1110,9 +1110,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_set_fade_with_time(speed_mode, channel, target_duty, max_fade_time_ms);
_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);
return ESP_OK;
}
@@ -1131,9 +1128,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_set_fade_with_step(speed_mode, channel, target_duty, scale, cycle_num);
_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);
return ESP_OK;
}