mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
LEDC: divisor calculation will now be rounded up when necessary
Closes https://github.com/espressif/esp-idf/issues/7722
This commit is contained in:
parent
aa2ca7dd94
commit
1e8a0909f6
@ -118,6 +118,29 @@ static uint32_t ledc_get_src_clk_freq(ledc_clk_cfg_t clk_cfg)
|
||||
return src_clk_freq;
|
||||
}
|
||||
|
||||
/* Retrieve the clock frequency for global clocks only */
|
||||
static uint32_t ledc_get_glb_clk_freq(ledc_slow_clk_sel_t clk_cfg)
|
||||
{
|
||||
uint32_t src_clk_freq = 0;
|
||||
|
||||
switch (clk_cfg) {
|
||||
case LEDC_SLOW_CLK_APB:
|
||||
src_clk_freq = LEDC_APB_CLK_HZ;
|
||||
break;
|
||||
case LEDC_SLOW_CLK_RTC8M:
|
||||
src_clk_freq = s_ledc_slow_clk_8M;
|
||||
break;
|
||||
#if SOC_LEDC_SUPPORT_XTAL_CLOCK
|
||||
case LEDC_SLOW_CLK_XTAL:
|
||||
src_clk_freq = rtc_clk_xtal_freq_get() * 1000000;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
return src_clk_freq;
|
||||
}
|
||||
|
||||
|
||||
static esp_err_t ledc_enable_intr_type(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_intr_type_t type)
|
||||
{
|
||||
portENTER_CRITICAL(&ledc_spinlock);
|
||||
@ -283,24 +306,29 @@ static inline uint32_t ledc_calculate_divisor(uint32_t src_clk_freq, int freq_hz
|
||||
* a 80MHz clock (APB).
|
||||
* If the precision is 1024 (10 bits), the resulted multiplier is:
|
||||
* (80000000 << 8) / (5000 * 1024) = 4000 (0xfa0)
|
||||
* Let's ignore the fractional part to simplify the exaplanation, so we get
|
||||
* Let's ignore the fractional part to simplify the explanation, so we get
|
||||
* a result of 15 (0xf).
|
||||
* This can be interpreted as: every 15 "precision" ticks, the resulted
|
||||
* clock will go high, where one precision tick is made out of 1024 source
|
||||
* clock ticks.
|
||||
* Thus, every `15 * 1024` source clock ticks, the resulted clock will go
|
||||
* high. */
|
||||
return ( (uint64_t) src_clk_freq << LEDC_LL_FRACTIONAL_BITS ) / (freq_hz * precision);
|
||||
* high.
|
||||
*
|
||||
* NOTE: We are also going to round up the value when necessary, thanks to:
|
||||
* (freq_hz * precision) / 2
|
||||
*/
|
||||
return ( ( (uint64_t) src_clk_freq << LEDC_LL_FRACTIONAL_BITS ) + ((freq_hz * precision) / 2 ) )
|
||||
/ (freq_hz * precision);
|
||||
}
|
||||
|
||||
static inline uint32_t ledc_auto_global_clk_divisor(int freq_hz, uint32_t precision, ledc_clk_cfg_t* clk_target)
|
||||
static inline uint32_t ledc_auto_global_clk_divisor(int freq_hz, uint32_t precision, ledc_slow_clk_sel_t* clk_target)
|
||||
{
|
||||
uint32_t div_param = 0;
|
||||
uint32_t i = 0;
|
||||
uint32_t clk_freq = 0;
|
||||
/* This function will go through all the following clock sources to look
|
||||
* for a valid divisor which generates the requested frequency. */
|
||||
const ledc_clk_cfg_t glb_clks[] = LEDC_LL_GLOBAL_CLOCKS;
|
||||
const ledc_slow_clk_sel_t glb_clks[] = LEDC_LL_GLOBAL_CLOCKS;
|
||||
|
||||
for (i = 0; i < DIM(glb_clks); i++) {
|
||||
/* Before calculating the divisor, we need to have the RTC frequency.
|
||||
@ -310,7 +338,7 @@ static inline uint32_t ledc_auto_global_clk_divisor(int freq_hz, uint32_t precis
|
||||
continue;
|
||||
}
|
||||
|
||||
clk_freq = ledc_get_src_clk_freq(glb_clks[i]);
|
||||
clk_freq = ledc_get_glb_clk_freq(glb_clks[i]);
|
||||
div_param = ledc_calculate_divisor(clk_freq, freq_hz, precision);
|
||||
|
||||
/* If the divisor is valid, we can return this value. */
|
||||
@ -368,7 +396,7 @@ static inline uint32_t ledc_auto_timer_specific_clk_divisor(ledc_mode_t speed_mo
|
||||
* by the caller.
|
||||
*/
|
||||
static uint32_t ledc_auto_clk_divisor(ledc_mode_t speed_mode, int freq_hz, uint32_t precision,
|
||||
ledc_clk_src_t* clk_source, ledc_clk_cfg_t* clk_target)
|
||||
ledc_clk_src_t* clk_source, ledc_slow_clk_sel_t* clk_target)
|
||||
{
|
||||
uint32_t div_param = 0;
|
||||
|
||||
@ -393,6 +421,35 @@ static uint32_t ledc_auto_clk_divisor(ledc_mode_t speed_mode, int freq_hz, uint3
|
||||
return div_param;
|
||||
}
|
||||
|
||||
static ledc_slow_clk_sel_t ledc_clk_cfg_to_global_clk(const ledc_clk_cfg_t clk_cfg)
|
||||
{
|
||||
/* Initialization required for preventing a compiler warning */
|
||||
ledc_slow_clk_sel_t glb_clk = LEDC_SLOW_CLK_APB;
|
||||
|
||||
switch (clk_cfg) {
|
||||
case LEDC_USE_APB_CLK:
|
||||
glb_clk = LEDC_SLOW_CLK_APB;
|
||||
break;
|
||||
case LEDC_USE_RTC8M_CLK:
|
||||
glb_clk = LEDC_SLOW_CLK_RTC8M;
|
||||
break;
|
||||
#if SOC_LEDC_SUPPORT_XTAL_CLOCK
|
||||
case LEDC_USE_XTAL_CLK:
|
||||
glb_clk = LEDC_SLOW_CLK_XTAL;
|
||||
break;
|
||||
#endif
|
||||
#if SOC_LEDC_SUPPORT_REF_TICK
|
||||
case LEDC_USE_REF_TICK:
|
||||
#endif
|
||||
default:
|
||||
/* We should not get here, REF_TICK is NOT a global clock,
|
||||
* it is a timer-specific clock. */
|
||||
assert(false);
|
||||
}
|
||||
|
||||
return glb_clk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function setting the LEDC timer divisor with the given source clock,
|
||||
* frequency and resolution. If the clock configuration passed is
|
||||
@ -405,11 +462,13 @@ static esp_err_t ledc_set_timer_div(ledc_mode_t speed_mode, ledc_timer_t timer_n
|
||||
/* This variable represents the timer's mux value. It will be overwritten
|
||||
* if a timer-specific clock is used. */
|
||||
ledc_clk_src_t timer_clk_src = LEDC_SCLK;
|
||||
/* Store the global clock. */
|
||||
ledc_slow_clk_sel_t glb_clk = LEDC_SLOW_CLK_APB;
|
||||
uint32_t src_clk_freq = 0;
|
||||
|
||||
if (clk_cfg == LEDC_AUTO_CLK) {
|
||||
/* User hasn't specified the speed, we should try to guess it. */
|
||||
div_param = ledc_auto_clk_divisor(speed_mode, freq_hz, precision, &timer_clk_src, &clk_cfg);
|
||||
div_param = ledc_auto_clk_divisor(speed_mode, freq_hz, precision, &timer_clk_src, &glb_clk);
|
||||
|
||||
} else if (clk_cfg == LEDC_USE_RTC8M_CLK) {
|
||||
/* User specified source clock(RTC8M_CLK) for low speed channel.
|
||||
@ -425,17 +484,24 @@ static esp_err_t ledc_set_timer_div(ledc_mode_t speed_mode, ledc_timer_t timer_n
|
||||
/* We have the RTC clock frequency now. */
|
||||
div_param = ledc_calculate_divisor(s_ledc_slow_clk_8M, freq_hz, precision);
|
||||
|
||||
/* Set the global clock source */
|
||||
glb_clk = LEDC_SLOW_CLK_RTC8M;
|
||||
|
||||
} else {
|
||||
|
||||
#if SOC_LEDC_HAS_TIMER_SPECIFIC_MUX
|
||||
if (LEDC_LL_IS_TIMER_SPECIFIC_CLOCK(speed_mode, clk_cfg)) {
|
||||
/* Currently we can convert a timer specific clock to a source clock that
|
||||
/* Currently we can convert a timer-specific clock to a source clock that
|
||||
* easily because their values are identical in the enumerations (on purpose)
|
||||
* If we decide to change the values in the future, we should consider defining
|
||||
* a macro/function to convert timer-specific clock to clock source .*/
|
||||
timer_clk_src = (ledc_clk_src_t) clk_cfg;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
glb_clk = ledc_clk_cfg_to_global_clk(clk_cfg);
|
||||
}
|
||||
|
||||
src_clk_freq = ledc_get_src_clk_freq(clk_cfg);
|
||||
div_param = ledc_calculate_divisor(src_clk_freq, freq_hz, precision);
|
||||
}
|
||||
@ -462,9 +528,9 @@ static esp_err_t ledc_set_timer_div(ledc_mode_t speed_mode, ledc_timer_t timer_n
|
||||
#else
|
||||
if (timer_clk_src == LEDC_SCLK) {
|
||||
#endif
|
||||
ESP_LOGD(LEDC_TAG, "In slow speed mode, using clock %d", clk_cfg);
|
||||
ESP_LOGD(LEDC_TAG, "In slow speed mode, using clock %d", glb_clk);
|
||||
portENTER_CRITICAL(&ledc_spinlock);
|
||||
ledc_hal_set_slow_clk(&(p_ledc_obj[speed_mode]->ledc_hal), clk_cfg);
|
||||
ledc_hal_set_slow_clk_sel(&(p_ledc_obj[speed_mode]->ledc_hal), glb_clk);
|
||||
portEXIT_CRITICAL(&ledc_spinlock);
|
||||
}
|
||||
|
||||
|
@ -1,16 +1,8 @@
|
||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// The LL layer for LEDC register operations.
|
||||
// Note that most of the register operations in this layer are non-atomic operations.
|
||||
@ -26,8 +18,8 @@
|
||||
#define LEDC_LL_FRACTIONAL_MAX ((1 << LEDC_LL_FRACTIONAL_BITS) - 1)
|
||||
|
||||
#define LEDC_LL_GLOBAL_CLOCKS { \
|
||||
LEDC_USE_APB_CLK, \
|
||||
LEDC_USE_RTC8M_CLK, \
|
||||
LEDC_SLOW_CLK_APB, \
|
||||
LEDC_SLOW_CLK_RTC8M, \
|
||||
}
|
||||
#define LEDC_LL_TIMER_SPECIFIC_CLOCKS \
|
||||
{\
|
||||
|
@ -1,16 +1,8 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// The LL layer for LEDC register operations.
|
||||
// Note that most of the register operations in this layer are non-atomic operations.
|
||||
@ -29,10 +21,10 @@ extern "C" {
|
||||
#define LEDC_LL_FRACTIONAL_BITS (8)
|
||||
#define LEDC_LL_FRACTIONAL_MAX ((1 << LEDC_LL_FRACTIONAL_BITS) - 1)
|
||||
#define LEDC_LL_GLOBAL_CLOCKS { \
|
||||
LEDC_USE_APB_CLK, \
|
||||
LEDC_USE_XTAL_CLK, \
|
||||
LEDC_USE_RTC8M_CLK, \
|
||||
}
|
||||
LEDC_SLOW_CLK_APB, \
|
||||
LEDC_SLOW_CLK_XTAL, \
|
||||
LEDC_SLOW_CLK_RTC8M, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set LEDC low speed timer clock
|
||||
|
@ -1,16 +1,8 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// The LL layer for LEDC register operations.
|
||||
// Note that most of the register operations in this layer are non-atomic operations.
|
||||
@ -29,9 +21,9 @@ extern "C" {
|
||||
#define LEDC_LL_FRACTIONAL_BITS (8)
|
||||
#define LEDC_LL_FRACTIONAL_MAX ((1 << LEDC_LL_FRACTIONAL_BITS) - 1)
|
||||
#define LEDC_LL_GLOBAL_CLOCKS { \
|
||||
LEDC_USE_APB_CLK, \
|
||||
LEDC_USE_XTAL_CLK, \
|
||||
LEDC_USE_RTC8M_CLK, \
|
||||
LEDC_SLOW_CLK_APB, \
|
||||
LEDC_SLOW_CLK_XTAL, \
|
||||
LEDC_SLOW_CLK_RTC8M, \
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,16 +1,8 @@
|
||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// The LL layer for LEDC register operations.
|
||||
// Note that most of the register operations in this layer are non-atomic operations.
|
||||
@ -29,9 +21,9 @@ extern "C" {
|
||||
#define LEDC_LL_FRACTIONAL_BITS (8)
|
||||
#define LEDC_LL_FRACTIONAL_MAX ((1 << LEDC_LL_FRACTIONAL_BITS) - 1)
|
||||
#define LEDC_LL_GLOBAL_CLOCKS { \
|
||||
LEDC_USE_APB_CLK, \
|
||||
LEDC_USE_XTAL_CLK, \
|
||||
LEDC_USE_RTC8M_CLK, \
|
||||
LEDC_SLOW_CLK_APB, \
|
||||
LEDC_SLOW_CLK_XTAL, \
|
||||
LEDC_SLOW_CLK_RTC8M, \
|
||||
}
|
||||
#define LEDC_LL_TIMER_SPECIFIC_CLOCKS \
|
||||
{\
|
||||
|
@ -1,16 +1,8 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// The LL layer for LEDC register operations.
|
||||
// Note that most of the register operations in this layer are non-atomic operations.
|
||||
@ -29,9 +21,9 @@ extern "C" {
|
||||
#define LEDC_LL_FRACTIONAL_BITS (8)
|
||||
#define LEDC_LL_FRACTIONAL_MAX ((1 << LEDC_LL_FRACTIONAL_BITS) - 1)
|
||||
#define LEDC_LL_GLOBAL_CLOCKS { \
|
||||
LEDC_USE_APB_CLK, \
|
||||
LEDC_USE_XTAL_CLK, \
|
||||
LEDC_USE_RTC8M_CLK, \
|
||||
LEDC_SLOW_CLK_APB, \
|
||||
LEDC_SLOW_CLK_XTAL, \
|
||||
LEDC_SLOW_CLK_RTC8M, \
|
||||
}
|
||||
#define LEDC_LL_TIMER_SPECIFIC_CLOCKS \
|
||||
{\
|
||||
|
@ -1153,7 +1153,6 @@ components/hal/esp32/include/hal/emac_ll.h
|
||||
components/hal/esp32/include/hal/i2c_ll.h
|
||||
components/hal/esp32/include/hal/i2s_ll.h
|
||||
components/hal/esp32/include/hal/interrupt_controller_ll.h
|
||||
components/hal/esp32/include/hal/ledc_ll.h
|
||||
components/hal/esp32/include/hal/mcpwm_ll.h
|
||||
components/hal/esp32/include/hal/mpu_ll.h
|
||||
components/hal/esp32/include/hal/pcnt_ll.h
|
||||
@ -1188,7 +1187,6 @@ components/hal/esp32c3/include/hal/hmac_hal.h
|
||||
components/hal/esp32c3/include/hal/hmac_ll.h
|
||||
components/hal/esp32c3/include/hal/i2c_ll.h
|
||||
components/hal/esp32c3/include/hal/interrupt_controller_ll.h
|
||||
components/hal/esp32c3/include/hal/ledc_ll.h
|
||||
components/hal/esp32c3/include/hal/memprot_ll.h
|
||||
components/hal/esp32c3/include/hal/mpu_ll.h
|
||||
components/hal/esp32c3/include/hal/rtc_cntl_ll.h
|
||||
@ -1220,7 +1218,6 @@ components/hal/esp32h2/include/hal/hmac_hal.h
|
||||
components/hal/esp32h2/include/hal/hmac_ll.h
|
||||
components/hal/esp32h2/include/hal/i2c_ll.h
|
||||
components/hal/esp32h2/include/hal/interrupt_controller_ll.h
|
||||
components/hal/esp32h2/include/hal/ledc_ll.h
|
||||
components/hal/esp32h2/include/hal/memprot_ll.h
|
||||
components/hal/esp32h2/include/hal/mpu_ll.h
|
||||
components/hal/esp32h2/include/hal/rtc_cntl_ll.h
|
||||
@ -1259,7 +1256,6 @@ components/hal/esp32s2/include/hal/gpspi_flash_ll.h
|
||||
components/hal/esp32s2/include/hal/i2c_ll.h
|
||||
components/hal/esp32s2/include/hal/i2s_ll.h
|
||||
components/hal/esp32s2/include/hal/interrupt_controller_ll.h
|
||||
components/hal/esp32s2/include/hal/ledc_ll.h
|
||||
components/hal/esp32s2/include/hal/memprot_ll.h
|
||||
components/hal/esp32s2/include/hal/memprot_peri_ll.h
|
||||
components/hal/esp32s2/include/hal/mpu_ll.h
|
||||
@ -1291,7 +1287,6 @@ components/hal/esp32s3/include/hal/cpu_ll.h
|
||||
components/hal/esp32s3/include/hal/gpspi_flash_ll.h
|
||||
components/hal/esp32s3/include/hal/i2c_ll.h
|
||||
components/hal/esp32s3/include/hal/interrupt_controller_ll.h
|
||||
components/hal/esp32s3/include/hal/ledc_ll.h
|
||||
components/hal/esp32s3/include/hal/mcpwm_ll.h
|
||||
components/hal/esp32s3/include/hal/memprot_ll.h
|
||||
components/hal/esp32s3/include/hal/mpu_ll.h
|
||||
|
Loading…
Reference in New Issue
Block a user