Skip to content

Commit 3fdb473

Browse files
committed
Merge branch 'bugfix/ledc_update_duty_wait' into 'master'
fix(ledc): duty_start update bit should wait for its self-clear before next set Closes IDF-11989 See merge request espressif/esp-idf!39949
2 parents 22adc7e + 63e2d68 commit 3fdb473

File tree

31 files changed

+111
-167
lines changed

31 files changed

+111
-167
lines changed

components/esp_driver_ledc/CMakeLists.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,12 @@ endif()
1010
if(${target} STREQUAL "linux")
1111
set(priv_requires "")
1212
else()
13-
set(priv_requires esp_pm)
13+
set(priv_requires esp_pm esp_driver_gpio)
1414
endif()
1515

1616
idf_component_register(
1717
SRCS ${srcs}
1818
INCLUDE_DIRS ${public_include}
1919
PRIV_REQUIRES "${priv_requires}"
20-
REQUIRES esp_driver_gpio # IDF-11989: Remove this in IDF v6.0
2120
LDFRAGMENTS "linker.lf"
2221
)

components/esp_driver_ledc/include/driver/ledc.h

Lines changed: 2 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,11 @@
99
#include "esp_err.h"
1010
#include "esp_intr_alloc.h"
1111
#include "hal/ledc_types.h"
12-
#include "driver/gpio.h"
1312

1413
#ifdef __cplusplus
1514
extern "C" {
1615
#endif
1716

18-
#if SOC_LEDC_SUPPORT_APB_CLOCK
19-
/**
20-
* @brief Frequency of one of the LEDC peripheral clock sources, APB_CLK
21-
* @note This macro should have no use in your application, we keep it here only for backward compatible
22-
*/
23-
#define LEDC_APB_CLK_HZ _Pragma ("GCC warning \"'LEDC_APB_CLK_HZ' macro is deprecated\"") (APB_CLK_FREQ)
24-
#endif
25-
#if SOC_LEDC_SUPPORT_REF_TICK
26-
/**
27-
* @brief Frequency of one of the LEDC peripheral clock sources, REF_TICK
28-
* @note This macro should have no use in your application, we keep it here only for backward compatible
29-
*/
30-
#define LEDC_REF_CLK_HZ _Pragma ("GCC warning \"'LEDC_REF_CLK_HZ' macro is deprecated\"") (REF_CLK_FREQ)
31-
#endif
32-
3317
#define LEDC_ERR_DUTY (0xFFFFFFFF)
3418
#define LEDC_ERR_VAL (-1)
3519

@@ -52,7 +36,7 @@ typedef struct {
5236
int gpio_num; /*!< the LEDC output gpio_num, if you want to use gpio16, gpio_num = 16 */
5337
ledc_mode_t speed_mode; /*!< LEDC speed speed_mode, high-speed mode (only exists on esp32) or low-speed mode */
5438
ledc_channel_t channel; /*!< LEDC channel (0 - LEDC_CHANNEL_MAX-1) */
55-
ledc_intr_type_t intr_type; /*!< configure interrupt, Fade interrupt enable or Fade interrupt disable */
39+
ledc_intr_type_t intr_type __attribute__((deprecated)); /*!< @deprecated, no need to explicitly configure interrupt, handled in the driver */
5640
ledc_timer_t timer_sel; /*!< Select the timer source of channel (0 - LEDC_TIMER_MAX-1) */
5741
uint32_t duty; /*!< LEDC channel duty, the range of duty setting is [0, (2**duty_resolution)] */
5842
int hpoint; /*!< LEDC channel hpoint value, the range is [0, (2**duty_resolution)-1] */
@@ -347,28 +331,7 @@ esp_err_t ledc_set_fade(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t
347331
* - ESP_ERR_INVALID_ARG Parameter error
348332
* - ESP_ERR_NOT_FOUND Failed to find available interrupt source
349333
*/
350-
esp_err_t ledc_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags, ledc_isr_handle_t *handle);
351-
352-
/**
353-
* @brief Configure LEDC timer settings
354-
*
355-
* This function does not take care of whether the chosen clock source is enabled or not, also does not handle the clock source
356-
* to meet channel sleep mode choice.
357-
*
358-
* If the chosen clock source is a new clock source to the LEDC timer, please use `ledc_timer_config`;
359-
* If the clock source is kept to be the same, but frequency needs to be updated, please use `ledc_set_freq`.
360-
*
361-
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
362-
* @param timer_sel Timer index (0-3), there are 4 timers in LEDC module
363-
* @param clock_divider Timer clock divide value, the timer clock is divided from the selected clock source
364-
* @param duty_resolution Resolution of duty setting in number of bits. The range is [1, SOC_LEDC_TIMER_BIT_WIDTH]
365-
* @param clk_src Select LEDC source clock.
366-
*
367-
* @return
368-
* - (-1) Parameter error
369-
* - Other Current LEDC duty
370-
*/
371-
esp_err_t ledc_timer_set(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t clock_divider, uint32_t duty_resolution, ledc_clk_src_t clk_src) __attribute__((deprecated("Please use ledc_timer_config() or ledc_set_freq()")));
334+
esp_err_t ledc_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags, ledc_isr_handle_t *handle) __attribute__((deprecated("LEDC interrupt handling is implemented by driver itself, please only register event callbacks if necessary")));
372335

373336
/**
374337
* @brief Reset LEDC timer

components/esp_driver_ledc/src/ledc.c

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "clk_ctrl_os.h"
2121
#include "esp_private/esp_sleep_internal.h"
2222
#include "esp_private/periph_ctrl.h"
23+
#include "driver/gpio.h"
2324
#include "esp_private/gpio.h"
2425
#include "esp_private/esp_clk_tree_common.h"
2526
#include "esp_private/esp_gpio_reserve.h"
@@ -260,13 +261,6 @@ static esp_err_t ledc_set_timer_params(ledc_mode_t speed_mode, ledc_timer_t time
260261
return ESP_OK;
261262
}
262263

263-
// Deprecated public API
264-
esp_err_t ledc_timer_set(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t clock_divider, uint32_t duty_resolution,
265-
ledc_clk_src_t clk_src)
266-
{
267-
return ledc_set_timer_params(speed_mode, timer_sel, clock_divider, duty_resolution, clk_src);
268-
}
269-
270264
static IRAM_ATTR esp_err_t ledc_duty_config(ledc_mode_t speed_mode, ledc_channel_t channel, int hpoint_val,
271265
int duty_val, ledc_duty_direction_t duty_direction, uint32_t duty_num, uint32_t duty_cycle, uint32_t duty_scale)
272266
{
@@ -832,15 +826,13 @@ esp_err_t ledc_channel_config(const ledc_channel_config_t *ledc_conf)
832826
int gpio_num = ledc_conf->gpio_num;
833827
uint32_t ledc_channel = ledc_conf->channel;
834828
uint32_t timer_select = ledc_conf->timer_sel;
835-
uint32_t intr_type = ledc_conf->intr_type;
836829
uint32_t duty = ledc_conf->duty;
837830
uint32_t hpoint = ledc_conf->hpoint;
838831
bool output_invert = ledc_conf->flags.output_invert;
839832
LEDC_ARG_CHECK(ledc_channel < LEDC_CHANNEL_MAX, "ledc_channel");
840833
LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode");
841834
LEDC_ARG_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "gpio_num");
842835
LEDC_ARG_CHECK(timer_select < LEDC_TIMER_MAX, "timer_select");
843-
LEDC_ARG_CHECK(intr_type < LEDC_INTR_MAX, "intr_type");
844836
LEDC_ARG_CHECK(ledc_conf->sleep_mode < LEDC_SLEEP_MODE_INVALID, "sleep_mode");
845837
#if !SOC_LEDC_SUPPORT_SLEEP_RETENTION
846838
ESP_RETURN_ON_FALSE(ledc_conf->sleep_mode != LEDC_SLEEP_MODE_NO_ALIVE_ALLOW_PD, ESP_ERR_NOT_SUPPORTED, LEDC_TAG, "register back up is not supported");
@@ -881,10 +873,6 @@ esp_err_t ledc_channel_config(const ledc_channel_config_t *ledc_conf)
881873
ledc_update_duty(speed_mode, ledc_channel);
882874
/*bind the channel with the timer*/
883875
ledc_bind_channel_timer(speed_mode, ledc_channel, timer_select);
884-
/*set interrupt type*/
885-
portENTER_CRITICAL(&ledc_spinlock);
886-
ledc_enable_intr_type(speed_mode, ledc_channel, intr_type);
887-
portEXIT_CRITICAL(&ledc_spinlock);
888876
ESP_LOGD(LEDC_TAG, "LEDC_PWM CHANNEL %"PRIu32"|GPIO %02u|Duty %04"PRIu32"|Time %"PRIu32,
889877
ledc_channel, gpio_num, duty, timer_select);
890878
/*set LEDC signal in gpio matrix*/
@@ -975,7 +963,7 @@ esp_err_t ledc_channel_config(const ledc_channel_config_t *ledc_conf)
975963
static void _ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel)
976964
{
977965
ledc_hal_set_sig_out_en(&(p_ledc_obj[speed_mode]->ledc_hal), channel, true);
978-
ledc_hal_set_duty_start(&(p_ledc_obj[speed_mode]->ledc_hal), channel, true);
966+
ledc_hal_set_duty_start(&(p_ledc_obj[speed_mode]->ledc_hal), channel);
979967
ledc_ls_channel_update(speed_mode, channel);
980968
}
981969

@@ -998,7 +986,6 @@ esp_err_t ledc_stop(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t idl
998986
portENTER_CRITICAL_SAFE(&ledc_spinlock);
999987
ledc_hal_set_idle_level(&(p_ledc_obj[speed_mode]->ledc_hal), channel, idle_level);
1000988
ledc_hal_set_sig_out_en(&(p_ledc_obj[speed_mode]->ledc_hal), channel, false);
1001-
ledc_hal_set_duty_start(&(p_ledc_obj[speed_mode]->ledc_hal), channel, false);
1002989
ledc_ls_channel_update(speed_mode, channel);
1003990
portEXIT_CRITICAL_SAFE(&ledc_spinlock);
1004991
return ESP_OK;
@@ -1261,7 +1248,7 @@ static void IRAM_ATTR ledc_fade_isr(void *arg)
12611248
cycle,
12621249
scale);
12631250
s_ledc_fade_rec[speed_mode][channel]->fsm = LEDC_FSM_HW_FADE;
1264-
ledc_hal_set_duty_start(&(p_ledc_obj[speed_mode]->ledc_hal), channel, true);
1251+
ledc_hal_set_duty_start(&(p_ledc_obj[speed_mode]->ledc_hal), channel);
12651252
ledc_ls_channel_update(speed_mode, channel);
12661253
}
12671254
portEXIT_CRITICAL_ISR(&ledc_spinlock);
@@ -1534,7 +1521,7 @@ esp_err_t ledc_fade_func_install(int intr_alloc_flags)
15341521
{
15351522
LEDC_CHECK(s_ledc_fade_isr_handle == NULL, "fade function already installed", ESP_ERR_INVALID_STATE);
15361523
//OR intr_alloc_flags with ESP_INTR_FLAG_IRAM because the fade isr is in IRAM
1537-
return ledc_isr_register(ledc_fade_isr, NULL, intr_alloc_flags | ESP_INTR_FLAG_IRAM, &s_ledc_fade_isr_handle);
1524+
return esp_intr_alloc(ETS_LEDC_INTR_SOURCE, intr_alloc_flags | ESP_INTR_FLAG_IRAM, ledc_fade_isr, NULL, &s_ledc_fade_isr_handle);
15381525
}
15391526

15401527
void ledc_fade_func_uninstall(void)

components/esp_driver_ledc/test_apps/ledc/main/test_ledc.c

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,13 @@
1414
#include "freertos/FreeRTOS.h"
1515
#include "freertos/task.h"
1616
#include "unity.h"
17-
#include "soc/gpio_periph.h"
18-
#include "soc/io_mux_reg.h"
1917
#include "esp_system.h"
2018
#include "esp_timer.h"
2119
#include "driver/ledc.h"
2220
#include "soc/ledc_struct.h"
2321
#include "esp_clk_tree.h"
2422
#include "test_ledc_utils.h"
23+
#include "driver/gpio.h"
2524

2625
static void fade_setup(void)
2726
{
@@ -91,13 +90,6 @@ TEST_CASE("LEDC channel config wrong channel", "[ledc]")
9190
TEST_ASSERT(ledc_channel_config(&ledc_ch_config) == ESP_ERR_INVALID_ARG);
9291
}
9392

94-
TEST_CASE("LEDC channel config wrong interrupt type", "[ledc]")
95-
{
96-
ledc_channel_config_t ledc_ch_config = initialize_channel_config();
97-
ledc_ch_config.intr_type = 2;
98-
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, ledc_channel_config(&ledc_ch_config));
99-
}
100-
10193
TEST_CASE("LEDC wrong timer", "[ledc]")
10294
{
10395
ledc_channel_config_t ledc_ch_config = initialize_channel_config();
@@ -150,6 +142,12 @@ TEST_CASE("LEDC output idle level test", "[ledc]")
150142
TEST_ESP_OK(ledc_stop(test_speed_mode, LEDC_CHANNEL_0, !current_level));
151143
vTaskDelay(1000 / portTICK_PERIOD_MS);
152144
TEST_ASSERT_EQUAL_INT32(!current_level, LEDC.channel_group[test_speed_mode].channel[LEDC_CHANNEL_0].conf0.idle_lv);
145+
// check real output level over some period
146+
gpio_input_enable(PULSE_IO);
147+
for (int i = 0; i < 40; i++) {
148+
TEST_ASSERT_EQUAL_INT32(!current_level, gpio_get_level(PULSE_IO));
149+
esp_rom_delay_us(50);
150+
}
153151
}
154152

155153
TEST_CASE("LEDC iterate over all channel and timer configs", "[ledc]")

components/esp_driver_ledc/test_apps/ledc/main/test_ledc_utils.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ ledc_channel_config_t initialize_channel_config(void)
1818
config.gpio_num = PULSE_IO;
1919
config.speed_mode = TEST_SPEED_MODE;
2020
config.channel = LEDC_CHANNEL_0;
21-
config.intr_type = LEDC_INTR_DISABLE;
2221
config.timer_sel = LEDC_TIMER_0;
2322
config.duty = 4000;
2423
config.hpoint = 0;

components/hal/esp32/include/hal/ledc_ll.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -481,13 +481,15 @@ static inline void ledc_ll_set_sig_out_en(ledc_dev_t *hw, ledc_mode_t speed_mode
481481
* @param hw Beginning address of the peripheral registers
482482
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
483483
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
484-
* @param duty_start The duty start
485484
*
486485
* @return None
487486
*/
488-
static inline void ledc_ll_set_duty_start(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, bool duty_start)
487+
static inline void ledc_ll_set_duty_start(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num)
489488
{
490-
hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start = duty_start;
489+
// wait until the last duty change took effect (duty_start bit will be self-cleared when duty update or fade is done)
490+
// this is necessary on ESP32 only, otherwise, internal logic might mess up (later targets with SOC_LEDC_SUPPORT_FADE_STOP allow to re-configure parameters while last update is still in progress)
491+
while (hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start);
492+
hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start = 1;
491493
}
492494

493495
/**

components/hal/esp32c2/include/hal/ledc_ll.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -458,13 +458,12 @@ static inline void ledc_ll_set_sig_out_en(ledc_dev_t *hw, ledc_mode_t speed_mode
458458
* @param hw Beginning address of the peripheral registers
459459
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
460460
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
461-
* @param duty_start The duty start
462461
*
463462
* @return None
464463
*/
465-
static inline void ledc_ll_set_duty_start(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, bool duty_start)
464+
static inline void ledc_ll_set_duty_start(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num)
466465
{
467-
hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start = duty_start;
466+
hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start = 1;
468467
}
469468

470469
/**

components/hal/esp32c3/include/hal/ledc_ll.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -459,13 +459,12 @@ static inline void ledc_ll_set_sig_out_en(ledc_dev_t *hw, ledc_mode_t speed_mode
459459
* @param hw Beginning address of the peripheral registers
460460
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
461461
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
462-
* @param duty_start The duty start
463462
*
464463
* @return None
465464
*/
466-
static inline void ledc_ll_set_duty_start(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, bool duty_start)
465+
static inline void ledc_ll_set_duty_start(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num)
467466
{
468-
hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start = duty_start;
467+
hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start = 1;
469468
}
470469

471470
/**

components/hal/esp32c5/include/hal/ledc_ll.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -458,13 +458,12 @@ static inline void ledc_ll_set_sig_out_en(ledc_dev_t *hw, ledc_mode_t speed_mode
458458
* @param hw Beginning address of the peripheral registers
459459
* @param speed_mode LEDC speed_mode, low-speed mode only
460460
* @param channel_num LEDC channel index (0-5), select from ledc_channel_t
461-
* @param duty_start The duty start
462461
*
463462
* @return None
464463
*/
465-
static inline void ledc_ll_set_duty_start(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, bool duty_start)
464+
static inline void ledc_ll_set_duty_start(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num)
466465
{
467-
hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start = duty_start;
466+
hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start = 1;
468467
}
469468

470469
/**

components/hal/esp32c6/include/hal/ledc_ll.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -579,13 +579,12 @@ static inline void ledc_ll_set_sig_out_en(ledc_dev_t *hw, ledc_mode_t speed_mode
579579
* @param hw Beginning address of the peripheral registers
580580
* @param speed_mode LEDC speed_mode, low-speed mode only
581581
* @param channel_num LEDC channel index (0-5), select from ledc_channel_t
582-
* @param duty_start The duty start
583582
*
584583
* @return None
585584
*/
586-
static inline void ledc_ll_set_duty_start(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, bool duty_start)
585+
static inline void ledc_ll_set_duty_start(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num)
587586
{
588-
hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start = duty_start;
587+
hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start = 1;
589588
}
590589

591590
/**

0 commit comments

Comments
 (0)