Merge branch 'bugfix/ledc_max_duty_cycle' into 'master'

fix(ledc): fix ledc driver 100% duty cycle configuration

Closes IDFGH-10881 and IDFGH-10254

See merge request espressif/esp-idf!26067
This commit is contained in:
Song Ruo Jing
2023-10-07 16:38:16 +08:00
16 changed files with 166 additions and 85 deletions

View File

@@ -125,6 +125,8 @@ endif()
# LEDC related source files # LEDC related source files
if(CONFIG_SOC_LEDC_SUPPORTED) if(CONFIG_SOC_LEDC_SUPPORTED)
list(APPEND srcs "ledc/ledc.c") list(APPEND srcs "ledc/ledc.c")
list(APPEND ldfragments "ledc/linker.lf")
endif() endif()
# MCPWM related source files # MCPWM related source files

View File

@@ -409,15 +409,7 @@ menu "Driver Configurations"
endmenu # Parallel IO Configuration endmenu # Parallel IO Configuration
menu "LEDC Configuration" orsource "./ledc/Kconfig.ledc"
config LEDC_CTRL_FUNC_IN_IRAM
bool "Place LEDC control functions into IRAM"
default n
help
Place LEDC control functions (ledc_update_duty and ledc_stop) into IRAM,
so that these functions can be IRAM-safe and able to be called in an IRAM context.
Enabling this option can improve driver performance as well.
endmenu # LEDC Configuration
menu "I2C Configuration" menu "I2C Configuration"
config I2C_ISR_IRAM_SAFE config I2C_ISR_IRAM_SAFE

View File

@@ -0,0 +1,11 @@
menu "LEDC Configuration"
config LEDC_CTRL_FUNC_IN_IRAM
bool "Place LEDC control functions into IRAM"
default n
help
Place LEDC control functions (ledc_update_duty and ledc_stop) into IRAM,
so that these functions can be IRAM-safe and able to be called in an IRAM context.
Enabling this option can improve driver performance as well.
endmenu # LEDC Configuration

View File

@@ -38,12 +38,12 @@ extern "C" {
*/ */
typedef struct { typedef struct {
int gpio_num; /*!< the LEDC output gpio_num, if you want to use gpio16, gpio_num = 16 */ int gpio_num; /*!< the LEDC output gpio_num, if you want to use gpio16, gpio_num = 16 */
ledc_mode_t speed_mode; /*!< LEDC speed speed_mode, high-speed mode or low-speed mode */ ledc_mode_t speed_mode; /*!< LEDC speed speed_mode, high-speed mode (only exists on esp32) or low-speed mode */
ledc_channel_t channel; /*!< LEDC channel (0 - LEDC_CHANNEL_MAX-1) */ ledc_channel_t channel; /*!< LEDC channel (0 - LEDC_CHANNEL_MAX-1) */
ledc_intr_type_t intr_type; /*!< configure interrupt, Fade interrupt enable or Fade interrupt disable */ ledc_intr_type_t intr_type; /*!< configure interrupt, Fade interrupt enable or Fade interrupt disable */
ledc_timer_t timer_sel; /*!< Select the timer source of channel (0 - LEDC_TIMER_MAX-1) */ ledc_timer_t timer_sel; /*!< Select the timer source of channel (0 - LEDC_TIMER_MAX-1) */
uint32_t duty; /*!< LEDC channel duty, the range of duty setting is [0, (2**duty_resolution)] */ uint32_t duty; /*!< LEDC channel duty, the range of duty setting is [0, (2**duty_resolution)] */
int hpoint; /*!< LEDC channel hpoint value, the max value is 0xfffff */ int hpoint; /*!< LEDC channel hpoint value, the range is [0, (2**duty_resolution)-1] */
struct { struct {
unsigned int output_invert: 1;/*!< Enable (1) or disable (0) gpio output invert */ unsigned int output_invert: 1;/*!< Enable (1) or disable (0) gpio output invert */
} flags; /*!< LEDC flags */ } flags; /*!< LEDC flags */
@@ -54,7 +54,7 @@ typedef struct {
* @brief Configuration parameters of LEDC timer for ledc_timer_config function * @brief Configuration parameters of LEDC timer for ledc_timer_config function
*/ */
typedef struct { typedef struct {
ledc_mode_t speed_mode; /*!< LEDC speed speed_mode, high-speed mode or low-speed mode */ ledc_mode_t speed_mode; /*!< LEDC speed speed_mode, high-speed mode (only exists on esp32) or low-speed mode */
ledc_timer_bit_t duty_resolution; /*!< LEDC channel duty resolution */ ledc_timer_bit_t duty_resolution; /*!< LEDC channel duty resolution */
ledc_timer_t timer_num; /*!< The timer source of channel (0 - LEDC_TIMER_MAX-1) */ ledc_timer_t timer_num; /*!< The timer source of channel (0 - LEDC_TIMER_MAX-1) */
uint32_t freq_hz; /*!< LEDC timer frequency (Hz) */ uint32_t freq_hz; /*!< LEDC timer frequency (Hz) */
@@ -88,7 +88,7 @@ typedef struct {
ledc_cb_event_t event; /**< Event name */ ledc_cb_event_t event; /**< Event name */
uint32_t speed_mode; /**< Speed mode of the LEDC channel group */ uint32_t speed_mode; /**< Speed mode of the LEDC channel group */
uint32_t channel; /**< LEDC channel (0 - LEDC_CHANNEL_MAX-1) */ uint32_t channel; /**< LEDC channel (0 - LEDC_CHANNEL_MAX-1) */
uint32_t duty; /**< LEDC current duty of the channel, the range of duty is [0, (2**duty_resolution) - 1] */ uint32_t duty; /**< LEDC current duty of the channel, the range of duty is [0, (2**duty_resolution)] */
} ledc_cb_param_t; } ledc_cb_param_t;
/** /**
@@ -135,6 +135,7 @@ esp_err_t ledc_timer_config(const ledc_timer_config_t *timer_conf);
/** /**
* @brief LEDC update channel parameters * @brief LEDC update channel parameters
*
* @note Call this function to activate the LEDC updated parameters. * @note Call this function to activate the LEDC updated parameters.
* After ledc_set_duty, we need to call this function to update the settings. * After ledc_set_duty, we need to call this function to update the settings.
* And the new LEDC parameters don't take effect until the next PWM cycle. * And the new LEDC parameters don't take effect until the next PWM cycle.
@@ -144,13 +145,13 @@ esp_err_t ledc_timer_config(const ledc_timer_config_t *timer_conf);
* @note If `CONFIG_LEDC_CTRL_FUNC_IN_IRAM` is enabled, this function will be placed in the IRAM by linker, * @note If `CONFIG_LEDC_CTRL_FUNC_IN_IRAM` is enabled, this function will be placed in the IRAM by linker,
* makes it possible to execute even when the Cache is disabled. * makes it possible to execute even when the Cache is disabled.
* @note This function is allowed to run within ISR context. * @note This function is allowed to run within ISR context.
*
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t * @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* *
* @return * @return
* - ESP_OK Success * - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error * - ESP_ERR_INVALID_ARG Parameter error
*
*/ */
esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel); esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel);
@@ -177,6 +178,7 @@ esp_err_t ledc_set_pin(int gpio_num, ledc_mode_t speed_mode, ledc_channel_t ledc
* @note If `CONFIG_LEDC_CTRL_FUNC_IN_IRAM` is enabled, this function will be placed in the IRAM by linker, * @note If `CONFIG_LEDC_CTRL_FUNC_IN_IRAM` is enabled, this function will be placed in the IRAM by linker,
* makes it possible to execute even when the Cache is disabled. * makes it possible to execute even when the Cache is disabled.
* @note This function is allowed to run within ISR context. * @note This function is allowed to run within ISR context.
*
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t * @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param idle_level Set output idle level after LEDC stops. * @param idle_level Set output idle level after LEDC stops.
@@ -216,15 +218,17 @@ uint32_t ledc_get_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num);
/** /**
* @brief LEDC set duty and hpoint value * @brief LEDC set duty and hpoint value
* Only after calling ledc_update_duty will the duty update. * Only after calling ledc_update_duty will the duty update.
*
* @note ledc_set_duty, ledc_set_duty_with_hpoint and ledc_update_duty are not thread-safe, do not call these functions to * @note ledc_set_duty, ledc_set_duty_with_hpoint and ledc_update_duty are not thread-safe, do not call these functions to
* control one LEDC channel in different tasks at the same time. * control one LEDC channel in different tasks at the same time.
* A thread-safe version of API is ledc_set_duty_and_update * A thread-safe version of API is ledc_set_duty_and_update
* @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel. * @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel.
* Other duty operations will have to wait until the fade operation has finished. * Other duty operations will have to wait until the fade operation has finished.
*
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t * @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param duty Set the LEDC duty, the range of duty setting is [0, (2**duty_resolution) - 1] * @param duty Set the LEDC duty, the range of duty setting is [0, (2**duty_resolution)]
* @param hpoint Set the LEDC hpoint value(max: 0xfffff) * @param hpoint Set the LEDC hpoint value, the range is [0, (2**duty_resolution)-1]
* *
* @return * @return
* - ESP_OK Success * - ESP_OK Success
@@ -237,6 +241,7 @@ esp_err_t ledc_set_duty_with_hpoint(ledc_mode_t speed_mode, ledc_channel_t chann
* *
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t * @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
*
* @return * @return
* - LEDC_ERR_VAL if parameter error * - LEDC_ERR_VAL if parameter error
* - Others Current hpoint value of LEDC channel * - Others Current hpoint value of LEDC channel
@@ -247,14 +252,16 @@ int ledc_get_hpoint(ledc_mode_t speed_mode, ledc_channel_t channel);
* @brief LEDC set duty * @brief LEDC set duty
* This function do not change the hpoint value of this channel. if needed, please call ledc_set_duty_with_hpoint. * This function do not change the hpoint value of this channel. if needed, please call ledc_set_duty_with_hpoint.
* only after calling ledc_update_duty will the duty update. * only after calling ledc_update_duty will the duty update.
*
* @note ledc_set_duty, ledc_set_duty_with_hpoint and ledc_update_duty are not thread-safe, do not call these functions to * @note ledc_set_duty, ledc_set_duty_with_hpoint and ledc_update_duty are not thread-safe, do not call these functions to
* control one LEDC channel in different tasks at the same time. * control one LEDC channel in different tasks at the same time.
* A thread-safe version of API is ledc_set_duty_and_update. * A thread-safe version of API is ledc_set_duty_and_update.
* @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel. * @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel.
* Other duty operations will have to wait until the fade operation has finished. * Other duty operations will have to wait until the fade operation has finished.
*
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t * @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param duty Set the LEDC duty, the range of duty setting is [0, (2**duty_resolution) - 1] * @param duty Set the LEDC duty, the range of duty setting is [0, (2**duty_resolution)]
* *
* @return * @return
* - ESP_OK Success * - ESP_OK Success
@@ -280,11 +287,13 @@ uint32_t ledc_get_duty(ledc_mode_t speed_mode, ledc_channel_t channel);
/** /**
* @brief LEDC set gradient * @brief LEDC set gradient
* Set LEDC gradient, After the function calls the ledc_update_duty function, the function can take effect. * Set LEDC gradient, After the function calls the ledc_update_duty function, the function can take effect.
*
* @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel. * @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel.
* Other duty operations will have to wait until the fade operation has finished. * Other duty operations will have to wait until the fade operation has finished.
*
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t * @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param duty Set the start of the gradient duty, the range of duty setting is [0, (2**duty_resolution) - 1] * @param duty Set the start of the gradient duty, the range of duty setting is [0, (2**duty_resolution)]
* @param fade_direction Set the direction of the gradient * @param fade_direction Set the direction of the gradient
* @param step_num Set the number of the gradient * @param step_num Set the number of the gradient
* @param duty_cycle_num Set how many LEDC tick each time the gradient lasts * @param duty_cycle_num Set how many LEDC tick each time the gradient lasts
@@ -310,7 +319,8 @@ esp_err_t ledc_set_fade(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t
* *
* @return * @return
* - ESP_OK Success * - ESP_OK Success
* - ESP_ERR_INVALID_ARG Function pointer error. * - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_NOT_FOUND Failed to find available interrupt source
*/ */
esp_err_t ledc_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags, ledc_isr_handle_t *handle); esp_err_t ledc_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags, ledc_isr_handle_t *handle);
@@ -320,7 +330,7 @@ esp_err_t ledc_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags,
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param timer_sel Timer index (0-3), there are 4 timers in LEDC module * @param timer_sel Timer index (0-3), there are 4 timers in LEDC module
* @param clock_divider Timer clock divide value, the timer clock is divided from the selected clock source * @param clock_divider Timer clock divide value, the timer clock is divided from the selected clock source
* @param duty_resolution Resolution of duty setting in number of bits. The range of duty values is [0, (2**duty_resolution)] * @param duty_resolution Resolution of duty setting in number of bits. The range is [1, SOC_LEDC_TIMER_BIT_WIDTH]
* @param clk_src Select LEDC source clock. * @param clk_src Select LEDC source clock.
* *
* @return * @return
@@ -350,7 +360,6 @@ esp_err_t ledc_timer_rst(ledc_mode_t speed_mode, ledc_timer_t timer_sel);
* @return * @return
* - ESP_ERR_INVALID_ARG Parameter error * - ESP_ERR_INVALID_ARG Parameter error
* - ESP_OK Success * - ESP_OK Success
*
*/ */
esp_err_t ledc_timer_pause(ledc_mode_t speed_mode, ledc_timer_t timer_sel); esp_err_t ledc_timer_pause(ledc_mode_t speed_mode, ledc_timer_t timer_sel);
@@ -381,6 +390,7 @@ esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, ledc_channel_t channel
/** /**
* @brief Set LEDC fade function. * @brief Set LEDC fade function.
*
* @note Call ledc_fade_func_install() once before calling this function. * @note Call ledc_fade_func_install() once before calling this function.
* Call ledc_fade_start() after this to start fading. * Call ledc_fade_start() after this to start fading.
* @note ledc_set_fade_with_step, ledc_set_fade_with_time and ledc_fade_start are not thread-safe, do not call these functions to * @note ledc_set_fade_with_step, ledc_set_fade_with_time and ledc_fade_start are not thread-safe, do not call these functions to
@@ -388,22 +398,24 @@ esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, ledc_channel_t channel
* A thread-safe version of API is ledc_set_fade_step_and_start * A thread-safe version of API is ledc_set_fade_step_and_start
* @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel. * @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel.
* Other duty operations will have to wait until the fade operation has finished. * Other duty operations will have to wait until the fade operation has finished.
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. , *
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t * @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param target_duty Target duty of fading [0, (2**duty_resolution) - 1] * @param target_duty Target duty of fading [0, (2**duty_resolution)]
* @param scale Controls the increase or decrease step scale. * @param scale Controls the increase or decrease step scale.
* @param cycle_num increase or decrease the duty every cycle_num cycles * @param cycle_num increase or decrease the duty every cycle_num cycles
* *
* @return * @return
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_OK Success * - ESP_OK Success
* - ESP_ERR_INVALID_STATE Fade function not installed. * - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_INVALID_STATE Channel not initialized
* - ESP_FAIL Fade function init error * - ESP_FAIL Fade function init error
*/ */
esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, uint32_t scale, uint32_t cycle_num); esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, uint32_t scale, uint32_t cycle_num);
/** /**
* @brief Set LEDC fade function, with a limited time. * @brief Set LEDC fade function, with a limited time.
*
* @note Call ledc_fade_func_install() once before calling this function. * @note Call ledc_fade_func_install() once before calling this function.
* Call ledc_fade_start() after this to start fading. * Call ledc_fade_start() after this to start fading.
* @note ledc_set_fade_with_step, ledc_set_fade_with_time and ledc_fade_start are not thread-safe, do not call these functions to * @note ledc_set_fade_with_step, ledc_set_fade_with_time and ledc_fade_start are not thread-safe, do not call these functions to
@@ -411,43 +423,48 @@ esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel
* A thread-safe version of API is ledc_set_fade_step_and_start * A thread-safe version of API is ledc_set_fade_step_and_start
* @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel. * @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel.
* Other duty operations will have to wait until the fade operation has finished. * Other duty operations will have to wait until the fade operation has finished.
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. , *
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t * @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param target_duty Target duty of fading [0, (2**duty_resolution) - 1] * @param target_duty Target duty of fading [0, (2**duty_resolution)]
* @param max_fade_time_ms The maximum time of the fading ( ms ). * @param max_fade_time_ms The maximum time of the fading ( ms ).
* *
* @return * @return
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_OK Success * - ESP_OK Success
* - ESP_ERR_INVALID_STATE Fade function not installed. * - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_INVALID_STATE Channel not initialized
* - ESP_FAIL Fade function init error * - ESP_FAIL Fade function init error
*/ */
esp_err_t ledc_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, int max_fade_time_ms); esp_err_t ledc_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, int max_fade_time_ms);
/** /**
* @brief Install LEDC fade function. This function will occupy interrupt of LEDC module. * @brief Install LEDC fade function. This function will occupy interrupt of LEDC module.
*
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred) * @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info. * ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
* *
* @return * @return
* - ESP_OK Success * - ESP_OK Success
* - ESP_ERR_INVALID_STATE Fade function already installed. * - ESP_ERR_INVALID_ARG Intr flag error
* - ESP_ERR_NOT_FOUND Failed to find available interrupt source
* - ESP_ERR_INVALID_STATE Fade function already installed
*/ */
esp_err_t ledc_fade_func_install(int intr_alloc_flags); esp_err_t ledc_fade_func_install(int intr_alloc_flags);
/** /**
* @brief Uninstall LEDC fade function. * @brief Uninstall LEDC fade function.
*
*/ */
void ledc_fade_func_uninstall(void); void ledc_fade_func_uninstall(void);
/** /**
* @brief Start LEDC fading. * @brief Start LEDC fading.
*
* @note Call ledc_fade_func_install() once before calling this function. * @note Call ledc_fade_func_install() once before calling this function.
* Call this API right after ledc_set_fade_with_time or ledc_set_fade_with_step before to start fading. * Call this API right after ledc_set_fade_with_time or ledc_set_fade_with_step before to start fading.
* @note Starting fade operation with this API is not thread-safe, use with care. * @note Starting fade operation with this API is not thread-safe, use with care.
* @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel. * @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel.
* Other duty operations will have to wait until the fade operation has finished. * Other duty operations will have to wait until the fade operation has finished.
*
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel number * @param channel LEDC channel number
* @param fade_mode Whether to block until fading done. See ledc_types.h ledc_fade_mode_t for more info. * @param fade_mode Whether to block until fading done. See ledc_types.h ledc_fade_mode_t for more info.
@@ -455,7 +472,7 @@ void ledc_fade_func_uninstall(void);
* *
* @return * @return
* - ESP_OK Success * - ESP_OK Success
* - ESP_ERR_INVALID_STATE Fade function not installed. * - ESP_ERR_INVALID_STATE Channel not initialized or fade function not installed.
* - ESP_ERR_INVALID_ARG Parameter error. * - ESP_ERR_INVALID_ARG Parameter error.
*/ */
esp_err_t ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_fade_mode_t fade_mode); esp_err_t ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_fade_mode_t fade_mode);
@@ -463,81 +480,99 @@ esp_err_t ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_f
#if SOC_LEDC_SUPPORT_FADE_STOP #if SOC_LEDC_SUPPORT_FADE_STOP
/** /**
* @brief Stop LEDC fading. The duty of the channel is garanteed to be fixed at most one PWM cycle after the function returns. * @brief Stop LEDC fading. The duty of the channel is garanteed to be fixed at most one PWM cycle after the function returns.
*
* @note This API can be called if a new fixed duty or a new fade want to be set while the last fade operation is still running in progress. * @note This API can be called if a new fixed duty or a new fade want to be set while the last fade operation is still running in progress.
* @note Call this API will abort the fading operation only if it was started by calling ledc_fade_start with LEDC_FADE_NO_WAIT mode. * @note Call this API will abort the fading operation only if it was started by calling ledc_fade_start with LEDC_FADE_NO_WAIT mode.
* @note If a fade was started with LEDC_FADE_WAIT_DONE mode, calling this API afterwards has no use in stopping the fade. Fade will continue until it reachs the target duty. * @note If a fade was started with LEDC_FADE_WAIT_DONE mode, calling this API afterwards has no use in stopping the fade. Fade will continue until it reachs the target duty.
*
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel number * @param channel LEDC channel number
* *
* @return * @return
* - ESP_OK Success * - ESP_OK Success
* - ESP_ERR_INVALID_STATE Fade function not installed. * - ESP_ERR_INVALID_STATE Channel not initialized
* - ESP_ERR_INVALID_ARG Parameter error. * - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL Fade function init error
*/ */
esp_err_t ledc_fade_stop(ledc_mode_t speed_mode, ledc_channel_t channel); esp_err_t ledc_fade_stop(ledc_mode_t speed_mode, ledc_channel_t channel);
#endif //SOC_LEDC_SUPPORT_FADE_STOP #endif //SOC_LEDC_SUPPORT_FADE_STOP
/** /**
* @brief A thread-safe API to set duty for LEDC channel and return when duty updated. * @brief A thread-safe API to set duty for LEDC channel and return when duty updated.
*
* @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel. * @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel.
* Other duty operations will have to wait until the fade operation has finished. * Other duty operations will have to wait until the fade operation has finished.
* *
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t * @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param duty Set the LEDC duty, the range of duty setting is [0, (2**duty_resolution) - 1] * @param duty Set the LEDC duty, the range of duty setting is [0, (2**duty_resolution)]
* @param hpoint Set the LEDC hpoint value(max: 0xfffff) * @param hpoint Set the LEDC hpoint value, the range is [0, (2**duty_resolution)-1]
* *
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_STATE Channel not initialized
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL Fade function init error
*/ */
esp_err_t ledc_set_duty_and_update(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty, uint32_t hpoint); esp_err_t ledc_set_duty_and_update(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty, uint32_t hpoint);
/** /**
* @brief A thread-safe API to set and start LEDC fade function, with a limited time. * @brief A thread-safe API to set and start LEDC fade function, with a limited time.
*
* @note Call ledc_fade_func_install() once, before calling this function. * @note Call ledc_fade_func_install() once, before calling this function.
* @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel. * @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel.
* Other duty operations will have to wait until the fade operation has finished. * Other duty operations will have to wait until the fade operation has finished.
*
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t * @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param target_duty Target duty of fading [0, (2**duty_resolution) - 1] * @param target_duty Target duty of fading [0, (2**duty_resolution)]
* @param max_fade_time_ms The maximum time of the fading ( ms ). * @param max_fade_time_ms The maximum time of the fading ( ms ).
* @param fade_mode choose blocking or non-blocking mode * @param fade_mode choose blocking or non-blocking mode
*
* @return * @return
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_OK Success * - ESP_OK Success
* - ESP_ERR_INVALID_STATE Fade function not installed. * - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_INVALID_STATE Channel not initialized
* - ESP_FAIL Fade function init error * - ESP_FAIL Fade function init error
*/ */
esp_err_t ledc_set_fade_time_and_start(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, uint32_t max_fade_time_ms, ledc_fade_mode_t fade_mode); esp_err_t ledc_set_fade_time_and_start(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, uint32_t max_fade_time_ms, ledc_fade_mode_t fade_mode);
/** /**
* @brief A thread-safe API to set and start LEDC fade function. * @brief A thread-safe API to set and start LEDC fade function.
*
* @note Call ledc_fade_func_install() once before calling this function. * @note Call ledc_fade_func_install() once before calling this function.
* @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel. * @note For ESP32, hardware does not support any duty change while a fade operation is running in progress on that channel.
* Other duty operations will have to wait until the fade operation has finished. * Other duty operations will have to wait until the fade operation has finished.
*
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t * @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param target_duty Target duty of fading [0, (2**duty_resolution) - 1] * @param target_duty Target duty of fading [0, (2**duty_resolution)]
* @param scale Controls the increase or decrease step scale. * @param scale Controls the increase or decrease step scale.
* @param cycle_num increase or decrease the duty every cycle_num cycles * @param cycle_num increase or decrease the duty every cycle_num cycles
* @param fade_mode choose blocking or non-blocking mode * @param fade_mode choose blocking or non-blocking mode
*
* @return * @return
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_OK Success * - ESP_OK Success
* - ESP_ERR_INVALID_STATE Fade function not installed. * - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_INVALID_STATE Channel not initialized
* - ESP_FAIL Fade function init error * - ESP_FAIL Fade function init error
*/ */
esp_err_t ledc_set_fade_step_and_start(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, uint32_t scale, uint32_t cycle_num, ledc_fade_mode_t fade_mode); esp_err_t ledc_set_fade_step_and_start(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, uint32_t scale, uint32_t cycle_num, ledc_fade_mode_t fade_mode);
/** /**
* @brief LEDC callback registration function * @brief LEDC callback registration function
*
* @note The callback is called from an ISR, it must never attempt to block, and any FreeRTOS API called must be ISR capable. * @note The callback is called from an ISR, it must never attempt to block, and any FreeRTOS API called must be ISR capable.
*
* @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode. * @param speed_mode Select the LEDC channel group with specified speed mode. Note that not all targets support high speed mode.
* @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t * @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param cbs Group of LEDC callback functions * @param cbs Group of LEDC callback functions
* @param user_arg user registered data for the callback function * @param user_arg user registered data for the callback function
*
* @return * @return
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_OK Success * - ESP_OK Success
* - ESP_ERR_INVALID_STATE Fade function not installed. * - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_INVALID_STATE Channel not initialized
* - ESP_FAIL Fade function init error * - ESP_FAIL Fade function init error
*/ */
esp_err_t ledc_cb_register(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_cbs_t *cbs, void *user_arg); esp_err_t ledc_cb_register(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_cbs_t *cbs, void *user_arg);
@@ -608,10 +643,11 @@ typedef struct {
* @param start_duty Set the start of the gradient duty, the range of duty setting is [0, (2**duty_resolution)] * @param start_duty Set the start of the gradient duty, the range of duty setting is [0, (2**duty_resolution)]
* @param fade_params_list Pointer to the array of fade parameters for a multi-fade * @param fade_params_list Pointer to the array of fade parameters for a multi-fade
* @param list_len Length of the fade_params_list, i.e. number of fade ranges for a multi-fade (1 - SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX) * @param list_len Length of the fade_params_list, i.e. number of fade ranges for a multi-fade (1 - SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX)
*
* @return * @return
* - ESP_OK Success * - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error * - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_INVALID_STATE Fade function not installed * - ESP_ERR_INVALID_STATE Channel not initialized
* - ESP_FAIL Fade function init error * - ESP_FAIL Fade function init error
*/ */
esp_err_t ledc_set_multi_fade(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t start_duty, const ledc_fade_param_config_t *fade_params_list, uint32_t list_len); esp_err_t ledc_set_multi_fade(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t start_duty, const ledc_fade_param_config_t *fade_params_list, uint32_t list_len);
@@ -631,10 +667,11 @@ esp_err_t ledc_set_multi_fade(ledc_mode_t speed_mode, ledc_channel_t channel, ui
* @param fade_params_list Pointer to the array of fade parameters for a multi-fade * @param fade_params_list Pointer to the array of fade parameters for a multi-fade
* @param list_len Length of the fade_params_list, i.e. number of fade ranges for a multi-fade (1 - SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX) * @param list_len Length of the fade_params_list, i.e. number of fade ranges for a multi-fade (1 - SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX)
* @param fade_mode Choose blocking or non-blocking mode * @param fade_mode Choose blocking or non-blocking mode
*
* @return * @return
* - ESP_OK Success * - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error * - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_INVALID_STATE Fade function not installed * - ESP_ERR_INVALID_STATE Channel not initialized
* - ESP_FAIL Fade function init error * - ESP_FAIL Fade function init error
*/ */
esp_err_t ledc_set_multi_fade_and_start(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t start_duty, const ledc_fade_param_config_t *fade_params_list, uint32_t list_len, ledc_fade_mode_t fade_mode); esp_err_t ledc_set_multi_fade_and_start(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t start_duty, const ledc_fade_param_config_t *fade_params_list, uint32_t list_len, ledc_fade_mode_t fade_mode);
@@ -658,11 +695,11 @@ esp_err_t ledc_set_multi_fade_and_start(ledc_mode_t speed_mode, ledc_channel_t c
* @param[in] fade_params_list_size The size of the fade_params_list user allocated (1 - SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX) * @param[in] fade_params_list_size The size of the fade_params_list user allocated (1 - SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX)
* @param[out] fade_params_list Pointer to the array of ledc_fade_param_config_t structure * @param[out] fade_params_list Pointer to the array of ledc_fade_param_config_t structure
* @param[out] hw_fade_range_num Number of fade ranges for this multi-fade * @param[out] hw_fade_range_num Number of fade ranges for this multi-fade
*
* @return * @return
* - ESP_OK Success * - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error * - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_INVALID_STATE LEDC not initialized * - ESP_ERR_INVALID_STATE Channel not initialized
* - ESP_ERR_NO_MEM Out of memory
* - ESP_FAIL Required number of hardware ranges exceeds the size of the ledc_fade_param_config_t array user allocated * - ESP_FAIL Required number of hardware ranges exceeds the size of the ledc_fade_param_config_t array user allocated
*/ */
esp_err_t ledc_fill_multi_fade_param_list(ledc_mode_t speed_mode, ledc_channel_t channel, esp_err_t ledc_fill_multi_fade_param_list(ledc_mode_t speed_mode, ledc_channel_t channel,
@@ -685,10 +722,11 @@ esp_err_t ledc_fill_multi_fade_param_list(ledc_mode_t speed_mode, ledc_channel_t
* @param[out] cycle Pointer to accept fade cycle value * @param[out] cycle Pointer to accept fade cycle value
* @param[out] scale Pointer to accept fade scale value * @param[out] scale Pointer to accept fade scale value
* @param[out] step Pointer to accept fade step value * @param[out] step Pointer to accept fade step value
*
* @return * @return
* - ESP_OK Success * - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error * - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_INVALID_STATE LEDC not initialized * - ESP_ERR_INVALID_STATE Channel not initialized
*/ */
esp_err_t ledc_read_fade_param(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t range, uint32_t *dir, uint32_t *cycle, uint32_t *scale, uint32_t *step); esp_err_t ledc_read_fade_param(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t range, uint32_t *dir, uint32_t *cycle, uint32_t *scale, uint32_t *step);
#endif // SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED #endif // SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED

View File

@@ -7,6 +7,7 @@
#include "esp_types.h" #include "esp_types.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/semphr.h" #include "freertos/semphr.h"
#include "freertos/idf_additions.h"
#include "esp_log.h" #include "esp_log.h"
#include "esp_check.h" #include "esp_check.h"
#include "soc/gpio_periph.h" #include "soc/gpio_periph.h"
@@ -58,9 +59,6 @@ typedef struct {
ledc_fade_mode_t mode; ledc_fade_mode_t mode;
SemaphoreHandle_t ledc_fade_sem; SemaphoreHandle_t ledc_fade_sem;
SemaphoreHandle_t ledc_fade_mux; SemaphoreHandle_t ledc_fade_mux;
#if CONFIG_SPIRAM_USE_MALLOC
StaticQueue_t ledc_fade_sem_storage;
#endif
ledc_cb_t ledc_fade_callback; ledc_cb_t ledc_fade_callback;
void *cb_user_arg; void *cb_user_arg;
volatile ledc_fade_fsm_t fsm; volatile ledc_fade_fsm_t fsm;
@@ -673,7 +671,12 @@ esp_err_t ledc_channel_config(const ledc_channel_config_t *ledc_conf)
/*set channel parameters*/ /*set channel parameters*/
/* channel parameters decide how the waveform looks like in one period */ /* channel parameters decide how the waveform looks like in one period */
/* set channel duty and hpoint value, duty range is (0 ~ ((2 ** duty_resolution) - 1)), max hpoint value is 0xfffff*/ /* set channel duty and hpoint value, duty range is [0, (2**duty_res)], hpoint range is [0, (2**duty_res)-1] */
/* Note: On ESP32, ESP32S2, ESP32S3, ESP32C3, ESP32C2, ESP32C6, ESP32H2, ESP32P4, due to a hardware bug,
* 100% duty cycle (i.e. 2**duty_res) is not reachable when the binded timer selects the maximum duty
* resolution. For example, the max duty resolution on ESP32C3 is 14-bit width, then set duty to (2**14)
* will mess up the duty calculation in hardware.
*/
ledc_set_duty_with_hpoint(speed_mode, ledc_channel, duty, hpoint); ledc_set_duty_with_hpoint(speed_mode, ledc_channel, duty, hpoint);
/*update duty settings*/ /*update duty settings*/
ledc_update_duty(speed_mode, ledc_channel); ledc_update_duty(speed_mode, ledc_channel);
@@ -859,7 +862,7 @@ static inline void IRAM_ATTR ledc_calc_fade_end_channel(uint32_t *fade_end_statu
*channel = i; *channel = i;
} }
void IRAM_ATTR ledc_fade_isr(void *arg) static void IRAM_ATTR ledc_fade_isr(void *arg)
{ {
bool cb_yield = false; bool cb_yield = false;
BaseType_t HPTaskAwoken = pdFALSE; BaseType_t HPTaskAwoken = pdFALSE;
@@ -987,7 +990,7 @@ static esp_err_t ledc_fade_channel_deinit(ledc_mode_t speed_mode, ledc_channel_t
s_ledc_fade_rec[speed_mode][channel]->ledc_fade_mux = NULL; s_ledc_fade_rec[speed_mode][channel]->ledc_fade_mux = NULL;
} }
if (s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem) { if (s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem) {
vSemaphoreDelete(s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem); vSemaphoreDeleteWithCaps(s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem);
s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem = NULL; s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem = NULL;
} }
free(s_ledc_fade_rec[speed_mode][channel]); free(s_ledc_fade_rec[speed_mode][channel]);
@@ -1003,23 +1006,13 @@ static esp_err_t ledc_fade_channel_init_check(ledc_mode_t speed_mode, ledc_chann
return ESP_FAIL; return ESP_FAIL;
} }
if (s_ledc_fade_rec[speed_mode][channel] == NULL) { if (s_ledc_fade_rec[speed_mode][channel] == NULL) {
#if CONFIG_SPIRAM_USE_MALLOC // Always malloc internally since LEDC ISR is always placed in IRAM
s_ledc_fade_rec[speed_mode][channel] = (ledc_fade_t *) heap_caps_calloc(1, sizeof(ledc_fade_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); s_ledc_fade_rec[speed_mode][channel] = (ledc_fade_t *) heap_caps_calloc(1, sizeof(ledc_fade_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
if (s_ledc_fade_rec[speed_mode][channel] == NULL) { if (s_ledc_fade_rec[speed_mode][channel] == NULL) {
ledc_fade_channel_deinit(speed_mode, channel); ledc_fade_channel_deinit(speed_mode, channel);
return ESP_ERR_NO_MEM; return ESP_ERR_NO_MEM;
} }
s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem = xSemaphoreCreateBinaryWithCaps(MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
memset(&s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem_storage, 0, sizeof(StaticQueue_t));
s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem = xSemaphoreCreateBinaryStatic(&s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem_storage);
#else
s_ledc_fade_rec[speed_mode][channel] = (ledc_fade_t *) calloc(1, sizeof(ledc_fade_t));
if (s_ledc_fade_rec[speed_mode][channel] == NULL) {
ledc_fade_channel_deinit(speed_mode, channel);
return ESP_ERR_NO_MEM;
}
s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem = xSemaphoreCreateBinary();
#endif
s_ledc_fade_rec[speed_mode][channel]->ledc_fade_mux = xSemaphoreCreateMutex(); s_ledc_fade_rec[speed_mode][channel]->ledc_fade_mux = xSemaphoreCreateMutex();
xSemaphoreGive(s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem); xSemaphoreGive(s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem);
s_ledc_fade_rec[speed_mode][channel]->fsm = LEDC_FSM_IDLE; s_ledc_fade_rec[speed_mode][channel]->fsm = LEDC_FSM_IDLE;
@@ -1070,8 +1063,9 @@ static esp_err_t _ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t
ESP_LOGD(LEDC_TAG, "cur duty: %"PRIu32"; target: %"PRIu32", step: %d, cycle: %d; scale: %d; dir: %d", ESP_LOGD(LEDC_TAG, "cur duty: %"PRIu32"; target: %"PRIu32", step: %d, cycle: %d; scale: %d; dir: %d",
duty_cur, target_duty, step_num, cycle_num, scale, dir); duty_cur, target_duty, step_num, cycle_num, scale, dir);
} else { } else {
// Directly set duty to the target, does not care on the dir
portENTER_CRITICAL(&ledc_spinlock); portENTER_CRITICAL(&ledc_spinlock);
ledc_duty_config(speed_mode, channel, LEDC_VAL_NO_CHANGE, target_duty, dir, 1, 1, 0); ledc_duty_config(speed_mode, channel, LEDC_VAL_NO_CHANGE, target_duty, 1, 1, 1, 0);
portEXIT_CRITICAL(&ledc_spinlock); portEXIT_CRITICAL(&ledc_spinlock);
ESP_LOGD(LEDC_TAG, "Set to target duty: %"PRIu32, target_duty); ESP_LOGD(LEDC_TAG, "Set to target duty: %"PRIu32, target_duty);
} }
@@ -1231,6 +1225,7 @@ esp_err_t ledc_fade_stop(ledc_mode_t speed_mode, ledc_channel_t channel)
esp_err_t ledc_fade_func_install(int intr_alloc_flags) esp_err_t ledc_fade_func_install(int intr_alloc_flags)
{ {
LEDC_CHECK(s_ledc_fade_isr_handle == NULL, "fade function already installed", ESP_ERR_INVALID_STATE);
//OR intr_alloc_flags with ESP_INTR_FLAG_IRAM because the fade isr is in IRAM //OR intr_alloc_flags with ESP_INTR_FLAG_IRAM because the fade isr is in IRAM
return ledc_isr_register(ledc_fade_isr, NULL, intr_alloc_flags | ESP_INTR_FLAG_IRAM, &s_ledc_fade_isr_handle); return ledc_isr_register(ledc_fade_isr, NULL, intr_alloc_flags | ESP_INTR_FLAG_IRAM, &s_ledc_fade_isr_handle);
} }

View File

@@ -0,0 +1,12 @@
[mapping:ledc_driver]
archive: libdriver.a
entries:
if LEDC_CTRL_FUNC_IN_IRAM = y:
ledc: ledc_stop (noflash)
ledc: ledc_update_duty (noflash)
ledc: _ledc_update_duty (noflash)
[mapping:ledc_hal]
archive: libhal.a
entries:
ledc_hal_iram (noflash)

View File

@@ -15,7 +15,3 @@ entries:
if DAC_CTRL_FUNC_IN_IRAM = y: if DAC_CTRL_FUNC_IN_IRAM = y:
dac_oneshot: dac_oneshot_output_voltage (noflash) dac_oneshot: dac_oneshot_output_voltage (noflash)
dac_continuous: dac_continuous_write_asynchronously (noflash) dac_continuous: dac_continuous_write_asynchronously (noflash)
if LEDC_CTRL_FUNC_IN_IRAM = y:
ledc: ledc_stop (noflash)
ledc: ledc_update_duty (noflash)
ledc: _ledc_update_duty (noflash)

View File

@@ -4,5 +4,5 @@ set(srcs "test_app_main.c"
# In order for the cases defined by `TEST_CASE` to be linked into the final elf, # In order for the cases defined by `TEST_CASE` to be linked into the final elf,
# the component can be registered as WHOLE_ARCHIVE # the component can be registered as WHOLE_ARCHIVE
idf_component_register(SRCS ${srcs} idf_component_register(SRCS ${srcs}
PRIV_REQUIRES unity driver esp_timer PRIV_REQUIRES unity driver esp_timer esp_psram
WHOLE_ARCHIVE) WHOLE_ARCHIVE)

View File

@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD # SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0 # SPDX-License-Identifier: CC0-1.0
import pytest import pytest
@@ -6,6 +6,7 @@ from pytest_embedded_idf import IdfDut
@pytest.mark.supported_targets @pytest.mark.supported_targets
@pytest.mark.temp_skip_ci(targets=['esp32s3'], reason='skip due to duplication with test_ledc_psram')
@pytest.mark.generic @pytest.mark.generic
@pytest.mark.parametrize( @pytest.mark.parametrize(
'config', 'config',
@@ -17,3 +18,17 @@ from pytest_embedded_idf import IdfDut
) )
def test_ledc(dut: IdfDut) -> None: def test_ledc(dut: IdfDut) -> None:
dut.run_all_single_board_cases() dut.run_all_single_board_cases()
@pytest.mark.esp32s3
@pytest.mark.octal_psram
@pytest.mark.parametrize(
'config',
[
'iram_safe',
'release',
],
indirect=True,
)
def test_ledc_psram(dut: IdfDut) -> None:
dut.run_all_single_board_cases()

View File

@@ -1,4 +1,4 @@
CONFIG_FREERTOS_HZ=1000 CONFIG_FREERTOS_HZ=1000
CONFIG_ESP_TASK_WDT=n CONFIG_ESP_TASK_WDT_INIT=n
# Disable memory protection, because "LEDC continue work after software reset" test case requires a cpu reset # Disable memory protection, because "LEDC continue work after software reset" test case requires a cpu reset
CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=n CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=n

View File

@@ -0,0 +1,4 @@
CONFIG_SPIRAM=y
CONFIG_SPIRAM_MODE_OCT=y
CONFIG_SPIRAM_SPEED_80M=y
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=0

View File

@@ -14,8 +14,6 @@ entries:
spi_hal_iram (noflash) spi_hal_iram (noflash)
if HAL_SPI_SLAVE_FUNC_IN_IRAM = y: if HAL_SPI_SLAVE_FUNC_IN_IRAM = y:
spi_slave_hal_iram (noflash) spi_slave_hal_iram (noflash)
if SOC_LEDC_SUPPORTED = y:
ledc_hal_iram (noflash)
if SOC_I2C_SUPPORTED = y: if SOC_I2C_SUPPORTED = y:
i2c_hal_iram (noflash) i2c_hal_iram (noflash)
if HAL_WDT_USE_ROM_IMPL = n: if HAL_WDT_USE_ROM_IMPL = n:

View File

@@ -246,7 +246,13 @@ To set the duty cycle, use the dedicated function :cpp:func:`ledc_set_duty`. Aft
Another way to set the duty cycle, as well as some other channel parameters, is by calling :cpp:func:`ledc_channel_config` covered in Section :ref:`ledc-api-configure-channel`. Another way to set the duty cycle, as well as some other channel parameters, is by calling :cpp:func:`ledc_channel_config` covered in Section :ref:`ledc-api-configure-channel`.
The range of the duty cycle values passed to functions depends on selected ``duty_resolution`` and should be from ``0`` to ``(2 ** duty_resolution) - 1``. For example, if the selected duty resolution is 10, then the duty cycle values can range from 0 to 1023. This provides the resolution of ~ 0.1%. The range of the duty cycle values passed to functions depends on selected ``duty_resolution`` and should be from ``0`` to ``(2 ** duty_resolution)``. For example, if the selected duty resolution is 10, then the duty cycle values can range from 0 to 1024. This provides the resolution of ~ 0.1%.
.. only:: esp32 or esp32s2 or esp32s3 or esp32c3 or esp32c2 or esp32c6 or esp32h2 or esp32p4
.. warning::
On {IDF_TARGET_NAME}, when channel's binded timer selects its maximum duty resolution, the duty cycle value cannot be set to ``(2 ** duty_resolution)``. Otherwise, the internal duty counter in the hardware will overflow and be messed up.
Change PWM Duty Cycle Using Hardware Change PWM Duty Cycle Using Hardware

View File

@@ -246,7 +246,13 @@ LED PWM 控制器可在无需 CPU 干预的情况下自动改变占空比,实
另外一种设置占空比和其他通道参数的方式是调用 :ref:`ledc-api-configure-channel` 一节提到的函数 :cpp:func:`ledc_channel_config` 另外一种设置占空比和其他通道参数的方式是调用 :ref:`ledc-api-configure-channel` 一节提到的函数 :cpp:func:`ledc_channel_config`
传递给函数的占空比数值范围取决于选定的 ``duty_resolution``,应为 ``0````(2 ** duty_resolution) - 1``。例如,如选定的占空比分辨率为 10则占空比的数值范围为 0 至 1023。此时分辨率为 ~ 0.1%。 传递给函数的占空比数值范围取决于选定的 ``duty_resolution``,应为 ``0````(2 ** duty_resolution)``。例如,如选定的占空比分辨率为 10则占空比的数值范围为 0 至 1024。此时分辨率为 ~ 0.1%。
.. only:: esp32 or esp32s2 or esp32s3 or esp32c3 or esp32c2 or esp32c6 or esp32h2 or esp32p4
.. warning::
在 {IDF_TARGET_NAME} 上,当通道绑定的定时器配置了其最大 PWM 占空比分辨率( ``MAX_DUTY_RES`` ),通道的占空比不能被设置到 ``(2 ** MAX_DUTY_RES)`` 。否则,硬件内部占空比计数器会溢出,并导致占空比计算错误。
使用硬件改变 PWM 占空比 使用硬件改变 PWM 占空比

View File

@@ -27,7 +27,7 @@ The example uses fixed PWM frequency of 5 kHz, duty cycle in 50%, and output GPI
Depending on the selected `LEDC_FREQUENCY`, you will need to change the `LEDC_DUTY_RES`. Depending on the selected `LEDC_FREQUENCY`, you will need to change the `LEDC_DUTY_RES`.
To dinamicaly set the duty and frequency, you can use the following functions: To dynamically set the duty and frequency, you can use the following functions:
To set the frequency to 2.5 kHZ i.e: To set the frequency to 2.5 kHZ i.e:
@@ -35,10 +35,10 @@ To set the frequency to 2.5 kHZ i.e:
ledc_set_freq(LEDC_MODE, LEDC_TIMER, 2500); ledc_set_freq(LEDC_MODE, LEDC_TIMER, 2500);
``` ```
Now the duty to 100% i.e: Now set the duty to 100% i.e:
```c ```c
ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, 8191); ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, 8192);
ledc_update_duty(LEDC_MODE, LEDC_CHANNEL); ledc_update_duty(LEDC_MODE, LEDC_CHANNEL);
``` ```
@@ -46,7 +46,7 @@ To change the duty cycle you need to calculate the duty range according to the d
If duty resolution is 13 bits: If duty resolution is 13 bits:
Duty range: `0 to (2 ** 13) - 1 = 8191` where 0 is 0% and 8191 is 100%. Duty range: `0 to (2 ** 13) = 8191` where 0 is 0% and 8192 is 100%.
### Build and Flash ### Build and Flash

View File

@@ -15,9 +15,15 @@
#define LEDC_OUTPUT_IO (5) // Define the output GPIO #define LEDC_OUTPUT_IO (5) // Define the output GPIO
#define LEDC_CHANNEL LEDC_CHANNEL_0 #define LEDC_CHANNEL LEDC_CHANNEL_0
#define LEDC_DUTY_RES LEDC_TIMER_13_BIT // Set duty resolution to 13 bits #define LEDC_DUTY_RES LEDC_TIMER_13_BIT // Set duty resolution to 13 bits
#define LEDC_DUTY (4095) // Set duty to 50%. ((2 ** 13) - 1) * 50% = 4095 #define LEDC_DUTY (4096) // Set duty to 50%. (2 ** 13) * 50% = 4096
#define LEDC_FREQUENCY (5000) // Frequency in Hertz. Set frequency at 5 kHz #define LEDC_FREQUENCY (5000) // Frequency in Hertz. Set frequency at 5 kHz
/* Warning:
* For ESP32, ESP32S2, ESP32S3, ESP32C3, ESP32C2, ESP32C6, ESP32H2, ESP32P4 targets,
* when LEDC_DUTY_RES selects the maximum duty resolution (i.e. value equal to SOC_LEDC_TIMER_BIT_WIDTH),
* 100% duty cycle is not reachable (duty cannot be set to (2 ** SOC_LEDC_TIMER_BIT_WIDTH)).
*/
static void example_ledc_init(void) static void example_ledc_init(void)
{ {
// Prepare and then apply the LEDC PWM timer configuration // Prepare and then apply the LEDC PWM timer configuration