From 662df0da3b9afd29e8e003c7c9b3b5790f5963a3 Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Thu, 15 Dec 2022 16:32:12 +0800 Subject: [PATCH] ledc: Channel configuration requires the ledc core clock on to be effective. Therefore, a clock source is selected for the core clock since the peripheral initialization. Additionally, correct the usage of channel para_up and duty_start bits. --- components/driver/ledc.c | 9 ++++++++- components/hal/esp32c6/include/hal/ledc_ll.h | 2 +- components/hal/ledc_hal.c | 1 + docs/en/api-reference/peripherals/ledc.rst | 4 ++++ docs/zh_CN/api-reference/peripherals/ledc.rst | 4 ++++ 5 files changed, 18 insertions(+), 2 deletions(-) diff --git a/components/driver/ledc.c b/components/driver/ledc.c index 1db5044220..1991983701 100644 --- a/components/driver/ledc.c +++ b/components/driver/ledc.c @@ -258,7 +258,6 @@ int duty_val, ledc_duty_direction_t duty_direction, uint32_t duty_num, uint32_t ledc_hal_set_duty_range(&(p_ledc_obj[speed_mode]->ledc_hal), channel, 0); ledc_hal_set_range_number(&(p_ledc_obj[speed_mode]->ledc_hal), channel, 1); #endif - ledc_ls_channel_update(speed_mode, channel); return ESP_OK; } @@ -662,6 +661,13 @@ esp_err_t ledc_channel_config(const ledc_channel_config_t *ledc_conf) return ESP_ERR_NO_MEM; } ledc_hal_init(&(p_ledc_obj[speed_mode]->ledc_hal), speed_mode); +#if !CONFIG_IDF_TARGET_ESP32 + // On targets other than esp32, the default ledc core(global) clock does not connect to any clock source + // 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); +#endif } /*set channel parameters*/ @@ -940,6 +946,7 @@ void IRAM_ATTR ledc_fade_isr(void *arg) 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_ls_channel_update(speed_mode, channel); } portEXIT_CRITICAL_ISR(&ledc_spinlock); if (finished) { diff --git a/components/hal/esp32c6/include/hal/ledc_ll.h b/components/hal/esp32c6/include/hal/ledc_ll.h index c984d730f6..525c07186a 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 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/components/hal/ledc_hal.c b/components/hal/ledc_hal.c index 1fda28f24d..aac0af090e 100644 --- a/components/hal/ledc_hal.c +++ b/components/hal/ledc_hal.c @@ -9,6 +9,7 @@ #include "esp_attr.h" #include "hal/ledc_hal.h" #include "soc/soc_caps.h" +#include "sdkconfig.h" #include "hal/assert.h" void ledc_hal_init(ledc_hal_context_t *hal, ledc_mode_t speed_mode) diff --git a/docs/en/api-reference/peripherals/ledc.rst b/docs/en/api-reference/peripherals/ledc.rst index 6c8af9192f..9ffe4dee4e 100644 --- a/docs/en/api-reference/peripherals/ledc.rst +++ b/docs/en/api-reference/peripherals/ledc.rst @@ -42,6 +42,10 @@ As an optional step, it is also possible to set up an interrupt on fade end. Key Settings of LED PWM Controller's API +.. note:: + + For an initial setup, it is recommended to configure for the timers first (by calling :cpp:func:`ledc_timer_config`), and then for the channels (by calling :cpp:func:`ledc_channel_config`). This ensures the PWM frequency is at the desired value since the appearance of the PWM signal from the IO pad. + .. _ledc-api-configure-timer: diff --git a/docs/zh_CN/api-reference/peripherals/ledc.rst b/docs/zh_CN/api-reference/peripherals/ledc.rst index 9c68514a2d..c369a88d1c 100644 --- a/docs/zh_CN/api-reference/peripherals/ledc.rst +++ b/docs/zh_CN/api-reference/peripherals/ledc.rst @@ -42,6 +42,10 @@ LED PWM 控制器可在无需 CPU 干预的情况下自动改变占空比,实 LED PWM 控制器 API 的关键配置 +.. note:: + + 首次 LEDC 配置时,建议先配置定时器(调用函数 :cpp:func:`ledc_timer_config`),再配置通道(调用函数 :cpp:func:`ledc_channel_config`)。这样可以确保 IO 脚上的 PWM 信号自有输出开始其频率就是正确的。 + .. _ledc-api-configure-timer: