espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
12.91k stars 7.09k forks source link

ledc: ledc_set_timer_div(556): timer clock conflict, already is 4 but attempt to 11. (IDFGH-12791) #13769

Open MR-VENOM opened 1 month ago

MR-VENOM commented 1 month ago

Answers checklist.

IDF version.

v5.2.1

Espressif SoC revision.

ESP32-S3 (QFN56) (revision v0.1)

Operating System used.

Linux

How did you build your project?

Command line with idf.py

If you are using Windows, please specify command line type.

None

Development Kit.

Custom board

Power Supply used.

USB

What is the expected behavior?

Trying to create 2 LEDC channel with diffrent frequency 50hz and 4khz. On timer 0 and timer 1.

static void example_ledc_init(void)
{
    // Prepare and then apply the LEDC PWM timer configuration
    ledc_timer_config_t ledc_timer = {.speed_mode = LEDC_LOW_SPEED_MODE,
                                      .timer_num = LEDC_TIMER_0,
                                      .duty_resolution = LEDC_TIMER_10_BIT,
                                      .freq_hz =
                                          4000, // Set output frequency at 4 kHz
                                      .clk_cfg = LEDC_AUTO_CLK};
    ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));

    ledc_timer_config_t ledc_timer2 = {.speed_mode = LEDC_LOW_SPEED_MODE,
                                      .timer_num = LEDC_TIMER_1,
                                      .duty_resolution = LEDC_TIMER_10_BIT,
                                      .freq_hz =
                                          50, // Set output frequency at 4 kHz
                                      .clk_cfg = LEDC_AUTO_CLK};
    ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer2));

    // Prepare and then apply the LEDC PWM channel configuration
    ledc_channel_config_t ledc_channel = {.speed_mode = LEDC_LOW_SPEED_MODE,
                                          .channel = LEDC_CHANNEL_0,
                                          .timer_sel = LEDC_TIMER_0,
                                          .intr_type = LEDC_INTR_DISABLE,
                                          .gpio_num = 1,
                                          .duty = 0, // Set duty to 0%
                                          .hpoint = 0};
    ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel));

    ledc_channel_config_t ledc_channel2 = {.speed_mode = LEDC_LOW_SPEED_MODE,
                                          .channel = LEDC_CHANNEL_1,
                                          .timer_sel = LEDC_TIMER_1,
                                          .intr_type = LEDC_INTR_DISABLE,
                                          .gpio_num = 2,
                                          .duty = 0, // Set duty to 0%
                                          .hpoint = 0};
    ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel2));
}

void app_main(void)
{
    // Set the LEDC peripheral configuration
    example_ledc_init();
    // Set duty to 50%

    while (true)
    {
        ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 4096));
        ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0));

        ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_1, 0));
        ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_1));
        vTaskDelay(1);
        ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 0));
        ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0));

        ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_1, 4096));
        ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_1));
        vTaskDelay(1);
    }
}

What is the actual behavior?

ESP crashes with the bellow backtrace.

Steps to reproduce.

  1. Create an LEDC example from IDF
  2. Create one more set off timer and channel with frequency 50hz and 4kHZ
  3. Build flash monitor.
  4. Watch the esp cry for help.

Debug Logs.

E (300) ledc: ledc_set_timer_div(556): timer clock conflict, already is 4 but attempt to 11
ESP_ERROR_CHECK failed: esp_err_t 0xffffffff (ESP_FAIL) at 0x420081fb
0x420081fb: example_ledc_init at 
examples/ledc_basic/main/ledc_basic_example_main.c:49 (discriminator 1)

file: "./main/ledc_basic_example_main.c" line 49
func: example_ledc_init
expression: ledc_timer_config(&ledc_timer2)

abort() was called at PC 0x40379b8b on core 0
0x40379b8b: _esp_error_check_failed at esp/v5.2.1/esp-idf/components/esp_system/esp_err.c:50

Backtrace: 0x403758d2:0x3fc98d60 0x40379b95:0x3fc98d80 0x4037feb9:0x3fc98da0 0x40379b8b:0x3fc98e10 0x420081fb:0x3fc98e40 0x42008263:0x3fc98ed0 0x420193db:0x3fc98ef0 0x4037a3f9:0x3fc98f20

More Information.

No response

suda-morris commented 1 month ago

one workaround is, .clk_cfg = LEDC_AUTO_CLK -> .clk_cfg = LEDC_USE_XTAL_CLK

songruo commented 1 month ago

Hi @MR-VENOM, the key problem is that all timers are sharing one clock source. While timer 0 wants a 4kHz signal, this can be achieved with either APB or XTAL clock sources, timer 1 wants a 50Hz signal, this can only be achieved with XTAL clock. When you first configured for timer 0 with LEDC_AUTO_CLK, the driver selected the clock source to be APB, and that's the reason why later you configure for timer 1, the driver notices the conflict between APB and XTAL.

In your situation, I think the users should be very clear on the clock source choice, and avoid using LEDC_AUTO_CLK.

We will consider provide a helper API, by giving the timer configuration, returns all the feasible clock sources for such a timer.

MR-VENOM commented 1 month ago

Hi @MR-VENOM, the key problem is that all timers are sharing one clock source. While timer 0 wants a 4kHz signal, this can be achieved with either APB or XTAL clock sources, timer 1 wants a 50Hz signal, this can only be achieved with XTAL clock. When you first configured for timer 0 with LEDC_AUTO_CLK, the driver selected the clock source to be APB, and that's the reason why later you configure for timer 1, the driver notices the conflict between APB and XTAL.

In your situation, I think the users should be very clear on the clock source choice, and avoid using LEDC_AUTO_CLK.

We will consider provide a helper API, by giving the timer configuration, returns all the feasible clock sources for such a timer.

But the documentation says the LEDC AUTO CLOCK will select the clk automatically with the given frequency and resolution. And one thing I notices is when I give 13bit the error does not happen.

https://github.com/espressif/esp-idf/blob/d4cd437ede613fffacc06ac6d6c93a083829022f/components/soc/esp32c5/mp/include/soc/clk_tree_defs.h#L472

songruo commented 1 month ago

Yes, LEDC_AUTO_CLK works fine if you are only configuring one timer. As I explained in the previous thread, the problem is two timers are configured one after another. The first one has no way to know the next timer being configured can only use XTAL as the clock source.

With 13-bit resolution, the error does not happen is because, in such case, even 50Hz timer can also use APB as the clock source.