ledc: Fix two bugs inside LEDC driver

1. Regression introduced when refactoring on clock sources selection (0d07f859).
   If channel configuration is called before timer configuration on C6, PWM signal may not be able to output.
2. Missing the improper fade parameter fix inside ledc_set_duty_and_update() function.
This commit is contained in:
Song Ruo Jing 2023-04-04 16:28:58 +08:00
parent b932b8eb94
commit 5070e51dde
9 changed files with 22 additions and 6 deletions

View File

@ -450,10 +450,10 @@ esp_err_t ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_f
#if SOC_LEDC_SUPPORT_FADE_STOP
/**
* @brief Stop LEDC fading. Duty of the channel will stay at its present vlaue.
* @brief Stop LEDC fading. The duty of the channel is garanteed to be fixed at most one PWM cycle after the function returns.
* @note This API can be called if a new fixed duty or a new fade want to be set while the last fade operation is still running in progress.
* @note Call this API will abort the fading operation only if it was started by calling ledc_fade_start with LEDC_FADE_NO_WAIT mode.
* @note If a fade was started with LEDC_FADE_WAIT_DONE mode, calling this API afterwards is no use in stopping the fade. Fade will continue until it reachs the target duty.
* @note If a fade was started with LEDC_FADE_WAIT_DONE mode, calling this API afterwards HAS no use in stopping the fade. Fade will continue until it reachs the target duty.
* @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
*

View File

@ -599,7 +599,7 @@ esp_err_t ledc_channel_config(const ledc_channel_config_t *ledc_conf)
// Set channel configurations and update bits before core clock is on could lead to error
// Therefore, we should connect the core clock to a real clock source to make it on before any ledc register operation
// It can be switched to the other desired clock sources to meet the output pwm freq requirement later at timer configuration
ledc_hal_set_slow_clk_sel(&(p_ledc_obj[speed_mode]->ledc_hal), 1);
ledc_hal_set_slow_clk_sel(&(p_ledc_obj[speed_mode]->ledc_hal), LEDC_LL_GLOBAL_CLK_DEFAULT);
#endif
}
@ -1214,7 +1214,7 @@ esp_err_t ledc_set_duty_and_update(ledc_mode_t speed_mode, ledc_channel_t channe
LEDC_CHECK(ledc_fade_channel_init_check(speed_mode, channel) == ESP_OK, LEDC_FADE_INIT_ERROR_STR, ESP_FAIL);
_ledc_fade_hw_acquire(speed_mode, channel);
portENTER_CRITICAL(&ledc_spinlock);
ledc_duty_config(speed_mode, channel, hpoint, duty, 1, 0, 0, 0);
ledc_duty_config(speed_mode, channel, hpoint, duty, 1, 1, 1, 0);
_ledc_update_duty(speed_mode, channel);
portEXIT_CRITICAL(&ledc_spinlock);
_ledc_fade_hw_release(speed_mode, channel);

View File

@ -375,11 +375,13 @@ TEST_CASE("LEDC fade stop test", "[ledc]")
// Get duty value right before stopping the fade
uint32_t duty_before_stop = ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0);
TEST_ESP_OK(ledc_fade_stop(test_speed_mode, LEDC_CHANNEL_0));
// PWM signal is 2000 Hz. It may take one cycle (500 us) at maximum to stablize the duty.
esp_rom_delay_us(500);
// Get duty value now, which is at least one cycle after the ledc_fade_stop function returns
uint32_t duty_after_stop = ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0);
fade_stop = esp_timer_get_time();
time_ms = (fade_stop - fade_start) / 1000;
TEST_ASSERT_TRUE(llabs(time_ms - 127) < 20);
// Get duty value after fade_stop returns (give at least one cycle for the duty set in fade_stop to take effective)
uint32_t duty_after_stop = ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0);
TEST_ASSERT_INT32_WITHIN(4, duty_before_stop, duty_after_stop); // 4 is the scale for one step in the last fade
vTaskDelay(300 / portTICK_PERIOD_MS);
// Duty should not change any more after ledc_fade_stop returns

View File

@ -32,6 +32,8 @@ extern "C" {
LEDC_SLOW_CLK_RC_FAST, \
}
#define LEDC_LL_GLOBAL_CLK_DEFAULT LEDC_SLOW_CLK_RC_FAST
/**
* @brief Set LEDC low speed timer clock

View File

@ -33,6 +33,8 @@ extern "C" {
LEDC_SLOW_CLK_RC_FAST, \
}
#define LEDC_LL_GLOBAL_CLK_DEFAULT LEDC_SLOW_CLK_RC_FAST
/**
* @brief Set LEDC low speed timer clock
*

View File

@ -34,6 +34,8 @@ extern "C" {
LEDC_SLOW_CLK_RC_FAST, \
}
#define LEDC_LL_GLOBAL_CLK_DEFAULT LEDC_SLOW_CLK_RC_FAST
/**
* @brief Enable LEDC function clock

View File

@ -33,6 +33,8 @@ extern "C" {
LEDC_SLOW_CLK_RC_FAST, \
}
#define LEDC_LL_GLOBAL_CLK_DEFAULT LEDC_SLOW_CLK_RC_FAST
/**
* @brief Set LEDC low speed timer clock
*

View File

@ -38,6 +38,9 @@ extern "C" {
#define LEDC_LL_IS_TIMER_SPECIFIC_CLOCK(SPEED, CLK) ((CLK) == LEDC_USE_REF_TICK)
#define LEDC_LL_GLOBAL_CLK_DEFAULT LEDC_SLOW_CLK_RC_FAST
/**
* @brief Set LEDC low speed timer clock
*

View File

@ -33,6 +33,9 @@ extern "C" {
LEDC_SLOW_CLK_RC_FAST, \
}
#define LEDC_LL_GLOBAL_CLK_DEFAULT LEDC_SLOW_CLK_RC_FAST
/**
* @brief Set LEDC low speed timer clock
*