DIV by zero in ledc.c -> ledc_set_fade_with_step() fnc in case of scale =0

zilizii
Posts: 15
Joined: Sun Oct 29, 2017 2:19 pm

DIV by zero in ledc.c -> ledc_set_fade_with_step() fnc in case of scale =0

Postby zilizii » Tue Oct 31, 2017 7:59 pm

Hello,

I started to investigate about a strange behaviour. In case of decrease of the duty the scale used for division without to check scale is not 0. Please update.
The problematic part
step_num = (duty_cur - target_duty) / scale;

Code: Select all

esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel, int target_duty, int scale, int cycle_num)
{
    LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
    LEDC_CHECK(channel < LEDC_CHANNEL_MAX, LEDC_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG);
    LEDC_CHECK(ledc_fade_channel_init_check(speed_mode, channel) == ESP_OK , LEDC_FADE_INIT_ERROR_STR, ESP_FAIL);

    int timer_sel = LEDC.channel_group[speed_mode].channel[channel].conf0.timer_sel;
    int max_duty = (1 << (LEDC.timer_group[speed_mode].timer[timer_sel].conf.bit_num)) - 1;
    LEDC_CHECK(target_duty <= max_duty, LEDC_FADE_TARGET_ERR_STR, ESP_ERR_INVALID_ARG);
    //disable the interrupt, so the operation will not mess up
    ledc_enable_intr_type(speed_mode, channel, LEDC_INTR_DISABLE);

    portENTER_CRITICAL(&ledc_spinlock);
    int duty_cur = LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> LEDC_DUTY_DECIMAL_BIT_NUM;
    int duty_delta = target_duty > duty_cur ? target_duty - duty_cur : duty_cur - target_duty;
    if (duty_delta == 0) {
        portEXIT_CRITICAL(&ledc_spinlock);
        return ESP_OK;
    }
    s_ledc_fade_rec[speed_mode][channel]->speed_mode = speed_mode;
    s_ledc_fade_rec[speed_mode][channel]->target_duty = target_duty;
    s_ledc_fade_rec[speed_mode][channel]->cycle_num = cycle_num;
    s_ledc_fade_rec[speed_mode][channel]->scale = scale;
    int step_num;
    if (duty_cur > target_duty) {
        s_ledc_fade_rec[speed_mode][channel]->direction = LEDC_DUTY_DIR_DECREASE;
        [color=#FF0000]step_num = (duty_cur - target_duty) / scale;[/color]
        step_num = step_num > LEDC_STEP_NUM_MAX ? LEDC_STEP_NUM_MAX : step_num;
    } else {
        s_ledc_fade_rec[speed_mode][channel]->direction = LEDC_DUTY_DIR_INCREASE;
        step_num = (target_duty - duty_cur) / scale;
        step_num = step_num > LEDC_STEP_NUM_MAX ? LEDC_STEP_NUM_MAX : step_num;
    }
    portEXIT_CRITICAL(&ledc_spinlock);

    ledc_set_fade(
        speed_mode,
        channel,
        duty_cur,
        s_ledc_fade_rec[speed_mode][channel]->direction,
        step_num,
        s_ledc_fade_rec[speed_mode][channel]->cycle_num,
        s_ledc_fade_rec[speed_mode][channel]->scale
        );
    ESP_LOGD(LEDC_TAG, "cur duty: %d; target: %d, step: %d, cycle: %d; scale: %d\n",
        LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> LEDC_DUTY_DECIMAL_BIT_NUM,
        target_duty,
        step_num,
        s_ledc_fade_rec[speed_mode][channel]->cycle_num,
        s_ledc_fade_rec[speed_mode][channel]->scale
        );
    int bit_num_ch0 = (speed_mode == LEDC_HIGH_SPEED_MODE) ? LEDC_DUTY_CHNG_END_HSCH0_INT_ENA_S : LEDC_DUTY_CHNG_END_LSCH0_INT_ENA_S;
    LEDC.int_clr.val |= BIT(bit_num_ch0 + channel);
    ledc_enable_intr_type(speed_mode, channel, LEDC_INTR_FADE_END);
    return ESP_OK;
}
Trial - Error scenario for learning ESP32 :D

ESP_Sprite
Posts: 9739
Joined: Thu Nov 26, 2015 4:08 am

Re: DIV by zero in ledc.c -> ledc_set_fade_with_step() fnc in case of scale =0

Postby ESP_Sprite » Wed Nov 01, 2017 6:10 pm

Seems a bug indeed, thanks for catching. Can you perhaps make an issue for this on https://github.com/espressif/esp-idf/issues ? That makes it easier for us to track the bug and inform you when we have fixed it.

Who is online

Users browsing this forum: No registered users and 21 guests