diff --git a/components/esp_driver_ledc/src/ledc.c b/components/esp_driver_ledc/src/ledc.c index 8d826fbae2..276732afc0 100644 --- a/components/esp_driver_ledc/src/ledc.c +++ b/components/esp_driver_ledc/src/ledc.c @@ -723,7 +723,7 @@ esp_err_t ledc_channel_config(const ledc_channel_config_t *ledc_conf) static void _ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel) { ledc_hal_set_sig_out_en(&(p_ledc_obj[speed_mode]->ledc_hal), channel, true); - 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); ledc_ls_channel_update(speed_mode, channel); } @@ -746,7 +746,6 @@ esp_err_t ledc_stop(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t idl portENTER_CRITICAL_SAFE(&ledc_spinlock); ledc_hal_set_idle_level(&(p_ledc_obj[speed_mode]->ledc_hal), channel, idle_level); ledc_hal_set_sig_out_en(&(p_ledc_obj[speed_mode]->ledc_hal), channel, false); - ledc_hal_set_duty_start(&(p_ledc_obj[speed_mode]->ledc_hal), channel, false); ledc_ls_channel_update(speed_mode, channel); portEXIT_CRITICAL_SAFE(&ledc_spinlock); return ESP_OK; @@ -1009,7 +1008,7 @@ static void IRAM_ATTR ledc_fade_isr(void *arg) cycle, scale); s_ledc_fade_rec[speed_mode][channel]->fsm = LEDC_FSM_HW_FADE; - 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); ledc_ls_channel_update(speed_mode, channel); } portEXIT_CRITICAL_ISR(&ledc_spinlock); diff --git a/components/hal/esp32/include/hal/ledc_ll.h b/components/hal/esp32/include/hal/ledc_ll.h index e460ebe98b..0f59bb1ff6 100644 --- a/components/hal/esp32/include/hal/ledc_ll.h +++ b/components/hal/esp32/include/hal/ledc_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -464,13 +464,15 @@ static inline void ledc_ll_set_sig_out_en(ledc_dev_t *hw, ledc_mode_t speed_mode * @param hw Beginning address of the peripheral registers * @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode * @param channel_num LEDC channel index (0-7), select from ledc_channel_t - * @param duty_start The duty start * * @return None */ -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) +static inline void ledc_ll_set_duty_start(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num) { - hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start = duty_start; + // wait until the last duty change took effect (duty_start bit will be self-cleared when duty update or fade is done) + // 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) + while (hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start); + hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start = 1; } /** diff --git a/components/hal/esp32c2/include/hal/ledc_ll.h b/components/hal/esp32c2/include/hal/ledc_ll.h index e70282c9b7..55b393e61f 100644 --- a/components/hal/esp32c2/include/hal/ledc_ll.h +++ b/components/hal/esp32c2/include/hal/ledc_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -441,13 +441,12 @@ static inline void ledc_ll_set_sig_out_en(ledc_dev_t *hw, ledc_mode_t speed_mode * @param hw Beginning address of the peripheral registers * @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode * @param channel_num LEDC channel index (0-7), select from ledc_channel_t - * @param duty_start The duty start * * @return None */ -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) +static inline void ledc_ll_set_duty_start(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num) { - hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start = duty_start; + hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start = 1; } /** diff --git a/components/hal/esp32c3/include/hal/ledc_ll.h b/components/hal/esp32c3/include/hal/ledc_ll.h index 373a3c679e..8671b4f1c0 100644 --- a/components/hal/esp32c3/include/hal/ledc_ll.h +++ b/components/hal/esp32c3/include/hal/ledc_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -442,13 +442,12 @@ static inline void ledc_ll_set_sig_out_en(ledc_dev_t *hw, ledc_mode_t speed_mode * @param hw Beginning address of the peripheral registers * @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode * @param channel_num LEDC channel index (0-7), select from ledc_channel_t - * @param duty_start The duty start * * @return None */ -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) +static inline void ledc_ll_set_duty_start(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num) { - hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start = duty_start; + hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start = 1; } /** diff --git a/components/hal/esp32c6/include/hal/ledc_ll.h b/components/hal/esp32c6/include/hal/ledc_ll.h index 7f6e4d319f..ad2008cc7b 100644 --- a/components/hal/esp32c6/include/hal/ledc_ll.h +++ b/components/hal/esp32c6/include/hal/ledc_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -569,13 +569,12 @@ static inline void ledc_ll_set_sig_out_en(ledc_dev_t *hw, ledc_mode_t speed_mode * @param hw Beginning address of the peripheral registers * @param speed_mode LEDC speed_mode, low-speed mode only * @param channel_num LEDC channel index (0-5), select from ledc_channel_t - * @param duty_start The duty start * * @return None */ -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) +static inline void ledc_ll_set_duty_start(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num) { - hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start = duty_start; + hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start = 1; } /** diff --git a/components/hal/esp32h2/include/hal/ledc_ll.h b/components/hal/esp32h2/include/hal/ledc_ll.h index 7d6e3313d7..fe3c46d1c3 100644 --- a/components/hal/esp32h2/include/hal/ledc_ll.h +++ b/components/hal/esp32h2/include/hal/ledc_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -567,13 +567,12 @@ static inline void ledc_ll_set_sig_out_en(ledc_dev_t *hw, ledc_mode_t speed_mode * @param hw Beginning address of the peripheral registers * @param speed_mode LEDC speed_mode, low-speed mode only * @param channel_num LEDC channel index (0-5), select from ledc_channel_t - * @param duty_start The duty start * * @return None */ -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) +static inline void ledc_ll_set_duty_start(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num) { - hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start = duty_start; + hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start = 1; } /** diff --git a/components/hal/esp32p4/include/hal/ledc_ll.h b/components/hal/esp32p4/include/hal/ledc_ll.h index f7b759e12b..3ed1b7015b 100644 --- a/components/hal/esp32p4/include/hal/ledc_ll.h +++ b/components/hal/esp32p4/include/hal/ledc_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -461,13 +461,12 @@ static inline void ledc_ll_set_sig_out_en(ledc_dev_t *hw, ledc_mode_t speed_mode * @param hw Beginning address of the peripheral registers * @param speed_mode LEDC speed_mode, low-speed mode only * @param channel_num LEDC channel index (0-5), select from ledc_channel_t - * @param duty_start The duty start * * @return None */ -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) +static inline void ledc_ll_set_duty_start(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num) { - hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start = duty_start; + hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start = 1; } /** diff --git a/components/hal/esp32s2/include/hal/ledc_ll.h b/components/hal/esp32s2/include/hal/ledc_ll.h index a9ed6babcd..a3ce0b4feb 100644 --- a/components/hal/esp32s2/include/hal/ledc_ll.h +++ b/components/hal/esp32s2/include/hal/ledc_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -481,13 +481,12 @@ static inline void ledc_ll_set_sig_out_en(ledc_dev_t *hw, ledc_mode_t speed_mode * @param hw Beginning address of the peripheral registers * @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode * @param channel_num LEDC channel index (0-7), select from ledc_channel_t - * @param duty_start The duty start * * @return None */ -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) +static inline void ledc_ll_set_duty_start(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num) { - hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start = duty_start; + hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start = 1; } /** diff --git a/components/hal/esp32s3/include/hal/ledc_ll.h b/components/hal/esp32s3/include/hal/ledc_ll.h index 35c374c10b..7fd9a6b06f 100644 --- a/components/hal/esp32s3/include/hal/ledc_ll.h +++ b/components/hal/esp32s3/include/hal/ledc_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -442,13 +442,12 @@ static inline void ledc_ll_set_sig_out_en(ledc_dev_t *hw, ledc_mode_t speed_mode * @param hw Beginning address of the peripheral registers * @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode * @param channel_num LEDC channel index (0-7), select from ledc_channel_t - * @param duty_start The duty start * * @return None */ -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) +static inline void ledc_ll_set_duty_start(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num) { - hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start = duty_start; + hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start = 1; } /** diff --git a/components/hal/include/hal/ledc_hal.h b/components/hal/include/hal/ledc_hal.h index fe9275ee9b..18ac920a2d 100644 --- a/components/hal/include/hal/ledc_hal.h +++ b/components/hal/include/hal/ledc_hal.h @@ -263,11 +263,10 @@ void ledc_hal_ls_channel_update(ledc_hal_context_t *hal, ledc_channel_t channel_ * * @param hal Context of the HAL layer * @param channel_num LEDC channel index (0-7), select from ledc_channel_t - * @param duty_start The duty start * * @return None */ -void ledc_hal_set_duty_start(ledc_hal_context_t *hal, ledc_channel_t channel_num, bool duty_start); +void ledc_hal_set_duty_start(ledc_hal_context_t *hal, ledc_channel_t channel_num); /** * @brief Set LEDC the integer part of duty value diff --git a/components/hal/ledc_hal_iram.c b/components/hal/ledc_hal_iram.c index ac3112caa8..34884c78e7 100644 --- a/components/hal/ledc_hal_iram.c +++ b/components/hal/ledc_hal_iram.c @@ -16,9 +16,9 @@ void ledc_hal_ls_channel_update(ledc_hal_context_t *hal, ledc_channel_t channel_ ledc_ll_ls_channel_update(hal->dev, hal->speed_mode, channel_num); } -void ledc_hal_set_duty_start(ledc_hal_context_t *hal, ledc_channel_t channel_num, bool duty_start) +void ledc_hal_set_duty_start(ledc_hal_context_t *hal, ledc_channel_t channel_num) { - ledc_ll_set_duty_start(hal->dev, hal->speed_mode, channel_num, duty_start); + ledc_ll_set_duty_start(hal->dev, hal->speed_mode, channel_num); } void ledc_hal_set_duty_int_part(ledc_hal_context_t *hal, ledc_channel_t channel_num, uint32_t duty_val)