feat(ledc): add ETM support for LEDC peripheral

Closes https://github.com/espressif/esp-idf/issues/11855
This commit is contained in:
Song Ruo Jing
2025-08-26 20:11:16 +08:00
parent 21237012e6
commit cc3577e31a
49 changed files with 2070 additions and 21 deletions
@@ -5,6 +5,10 @@ set(public_include "include")
if(CONFIG_SOC_LEDC_SUPPORTED)
list(APPEND srcs "src/ledc.c")
if(CONFIG_SOC_ETM_SUPPORTED AND CONFIG_SOC_LEDC_SUPPORT_ETM)
list(APPEND srcs "src/ledc_etm.c")
endif()
endif()
if(${target} STREQUAL "linux")
@@ -8,6 +8,7 @@
#include "esp_err.h"
#include "esp_intr_alloc.h"
#include "driver/ledc_etm.h"
#include "hal/ledc_types.h"
#ifdef __cplusplus
@@ -385,6 +386,25 @@ esp_err_t ledc_timer_resume(ledc_mode_t speed_mode, ledc_timer_t timer_sel);
*/
esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_timer_t timer_sel);
#if SOC_LEDC_SUPPORT_ETM
/**
* @brief Configure the maximum timer overflow times for the LEDC channel to be used to trigger `LEDC_ETM_EVENT_CHANNEL_REACH_MAX_OVF_CNT` ETM event
*
* When the overflow counter maximum value is re-configured, the counter will also be reset.
* Timer can be paused before calling this API by calling `ledc_timer_pause()`, and resumed afterwards by calling `ledc_timer_resume()`.
*
* @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 max_ovf_cnt The timer overflow counter maximum value. To disable the timer overflow count, set this parameter to 0.
*
* @return
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_ERR_INVALID_STATE Channel not initialized
* - ESP_OK Success
*/
esp_err_t ledc_channel_configure_maximum_timer_ovf_cnt(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t max_ovf_cnt);
#endif
/**
* @brief Set LEDC fade function.
*
@@ -0,0 +1,115 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_err.h"
#include "esp_etm.h"
#include "hal/ledc_types.h"
#include "soc/soc_caps.h"
#ifdef __cplusplus
extern "C" {
#endif
#if SOC_LEDC_SUPPORT_ETM
/**
* @brief LEDC timer ETM event configuration
*/
typedef struct {
ledc_timer_etm_event_type_t event_type; /*!< LEDC timer ETM event type */
} ledc_timer_etm_event_config_t;
/**
* @brief LEDC channel ETM event configuration
*/
typedef struct {
ledc_channel_etm_event_type_t event_type; /*!< LEDC channel ETM event type */
} ledc_channel_etm_event_config_t;
/**
* @brief Get the ETM timer event for LEDC
*
* @note The created ETM event object can be deleted later by calling `esp_etm_del_event`
*
* @param[in] speed_mode Select the LEDC channel group with specified speed mode
* @param[in] timer_sel LEDC timer index, select from ledc_timer_t
* @param[in] config LEDC timer ETM event configuration
* @param[out] out_event Returned ETM event handle
* @return
* - ESP_OK: Get ETM event successfully
* - ESP_ERR_INVALID_ARG: Get ETM event failed because of invalid argument
* - ESP_ERR_NO_MEM: Get ETM event failed because of no memory
*/
esp_err_t ledc_timer_new_etm_event(ledc_mode_t speed_mode, ledc_timer_t timer_sel, const ledc_timer_etm_event_config_t *config, esp_etm_event_handle_t *out_event);
/**
* @brief Get the ETM channel event for LEDC
*
* @note The created ETM event object can be deleted later by calling `esp_etm_del_event`
*
* @param[in] speed_mode Select the LEDC channel group with specified speed mode
* @param[in] channel LEDC channel index, select from ledc_channel_t
* @param[in] config LEDC channel ETM event configuration
* @param[out] out_event Returned ETM event handle
* @return
* - ESP_OK: Get ETM event successfully
* - ESP_ERR_INVALID_ARG: Get ETM event failed because of invalid argument
* - ESP_ERR_NO_MEM: Get ETM event failed because of no memory
*/
esp_err_t ledc_channel_new_etm_event(ledc_mode_t speed_mode, ledc_channel_t channel, const ledc_channel_etm_event_config_t *config, esp_etm_event_handle_t *out_event);
/**
* @brief LEDC timer ETM task configuration
*/
typedef struct {
ledc_timer_etm_task_type_t task_type; /*!< LEDC timer ETM task type */
} ledc_timer_etm_task_config_t;
/**
* @brief LEDC channel ETM task configuration
*/
typedef struct {
ledc_channel_etm_task_type_t task_type; /*!< LEDC channel ETM task type */
} ledc_channel_etm_task_config_t;
/**
* @brief Get the ETM timer task for LEDC
*
* @note The created ETM task object can be deleted later by calling `esp_etm_del_task`
*
* @param[in] speed_mode Select the LEDC channel group with specified speed mode
* @param[in] timer_sel LEDC timer index, select from ledc_timer_t
* @param[in] config LEDC timer ETM task configuration
* @param[out] out_task Returned ETM task handle
* @return
* - ESP_OK: Get ETM task successfully
* - ESP_ERR_INVALID_ARG: Get ETM task failed because of invalid argument
* - ESP_ERR_NO_MEM: Get ETM task failed because of no memory
*/
esp_err_t ledc_timer_new_etm_task(ledc_mode_t speed_mode, ledc_timer_t timer_sel, const ledc_timer_etm_task_config_t *config, esp_etm_task_handle_t *out_task);
/**
* @brief Get the ETM channel task for LEDC
*
* @note The created ETM task object can be deleted later by calling `esp_etm_del_task`
*
* @param[in] speed_mode Select the LEDC channel group with specified speed mode
* @param[in] channel LEDC channel index, select from ledc_channel_t
* @param[in] config LEDC channel ETM task configuration
* @param[out] out_task Returned ETM task handle
* @return
* - ESP_OK: Get ETM task successfully
* - ESP_ERR_INVALID_ARG: Get ETM task failed because of invalid argument
* - ESP_ERR_NO_MEM: Get ETM task failed because of no memory
*/
esp_err_t ledc_channel_new_etm_task(ledc_mode_t speed_mode, ledc_channel_t channel, const ledc_channel_etm_task_config_t *config, esp_etm_task_handle_t *out_task);
#endif // SOC_LEDC_SUPPORT_ETM
#ifdef __cplusplus
}
#endif
+16
View File
@@ -277,6 +277,7 @@ static IRAM_ATTR esp_err_t ledc_duty_config(ledc_mode_t speed_mode, ledc_channel
// Clear left-off LEDC gamma ram registers, random data in ram could cause output waveform error
ledc_hal_clear_left_off_fade_param(&(p_ledc_obj[speed_mode]->ledc_hal), channel, 1);
#endif
ESP_EARLY_LOGD(LEDC_TAG, "duty_config: duty-%d, dir-%d, cycle-%d, scale-%d, step-%d", duty_val, duty_direction, duty_cycle, duty_scale, duty_num);
return ESP_OK;
}
@@ -392,6 +393,21 @@ esp_err_t ledc_timer_resume(ledc_mode_t speed_mode, ledc_timer_t timer_sel)
return ESP_OK;
}
#if SOC_LEDC_SUPPORT_ETM
esp_err_t ledc_channel_configure_maximum_timer_ovf_cnt(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t max_ovf_cnt)
{
LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode");
LEDC_ARG_CHECK(channel < LEDC_CHANNEL_MAX, "channel");
LEDC_ARG_CHECK(max_ovf_cnt <= LEDC_LL_OVF_CNT_MAX, "max_ovf_cnt");
LEDC_CHECK(p_ledc_obj[speed_mode] != NULL, LEDC_NOT_INIT, ESP_ERR_INVALID_STATE);
ledc_hal_channel_configure_maximum_timer_ovf_cnt(&(p_ledc_obj[speed_mode]->ledc_hal), channel, max_ovf_cnt);
ledc_ls_channel_update(speed_mode, channel);
return ESP_OK;
}
#endif
esp_err_t ledc_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags, ledc_isr_handle_t *handle)
{
esp_err_t ret;
+154
View File
@@ -0,0 +1,154 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "freertos/FreeRTOS.h"
#include "esp_check.h"
#include "driver/ledc.h"
#include "esp_private/etm_interface.h"
#include "esp_heap_caps.h"
#include "hal/ledc_ll.h"
#define TAG "ledc_etm"
typedef struct {
union {
esp_etm_event_t evt_base;
esp_etm_task_t task_base;
};
ledc_mode_t speed_mode;
volatile uint32_t *en_reg_addr;
uint32_t en_bit;
} ledc_etm_event_task_t;
static portMUX_TYPE s_ledc_etm_spinlock = portMUX_INITIALIZER_UNLOCKED;
static esp_err_t ledc_del_etm_event(esp_etm_event_t *event)
{
ledc_etm_event_task_t *etm_event = __containerof(event, ledc_etm_event_task_t, evt_base);
if (etm_event->en_reg_addr != 0) {
portENTER_CRITICAL(&s_ledc_etm_spinlock);
ledc_ll_etm_enable_evt_task(LEDC_LL_GET_HW(), etm_event->speed_mode, etm_event->en_reg_addr, etm_event->en_bit, false);
portEXIT_CRITICAL(&s_ledc_etm_spinlock);
}
free(etm_event);
return ESP_OK;
}
static esp_err_t ledc_del_etm_task(esp_etm_task_t *task)
{
ledc_etm_event_task_t *etm_task = __containerof(task, ledc_etm_event_task_t, task_base);
if (etm_task->en_reg_addr != 0) {
portENTER_CRITICAL(&s_ledc_etm_spinlock);
ledc_ll_etm_enable_evt_task(LEDC_LL_GET_HW(), etm_task->speed_mode, etm_task->en_reg_addr, etm_task->en_bit, false);
portEXIT_CRITICAL(&s_ledc_etm_spinlock);
}
free(etm_task);
return ESP_OK;
}
esp_err_t ledc_timer_new_etm_event(ledc_mode_t speed_mode, ledc_timer_t timer_sel, const ledc_timer_etm_event_config_t *config, esp_etm_event_handle_t *out_event)
{
ESP_RETURN_ON_FALSE(speed_mode < LEDC_SPEED_MODE_MAX && timer_sel < LEDC_TIMER_MAX && config && config->event_type < LEDC_TIMER_ETM_EVENT_MAX && out_event, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
ledc_etm_event_task_t *event = heap_caps_calloc(1, sizeof(ledc_etm_event_task_t), MALLOC_CAP_DEFAULT);
ESP_RETURN_ON_FALSE(event, ESP_ERR_NO_MEM, TAG, "no memory for ETM event");
uint32_t evt_id = LEDC_LL_ETM_TIMER_EVENT_ID(speed_mode, timer_sel, config->event_type);
volatile uint32_t *en_reg = LEDC_LL_ETM_TIMER_EVENT_EN_REG(speed_mode, config->event_type);
uint32_t en_bit = LEDC_LL_ETM_TIMER_EVENT_EN_BIT(speed_mode, timer_sel, config->event_type);
portENTER_CRITICAL(&s_ledc_etm_spinlock);
ledc_ll_etm_enable_evt_task(LEDC_LL_GET_HW(), speed_mode, en_reg, en_bit, true);
portEXIT_CRITICAL(&s_ledc_etm_spinlock);
event->speed_mode = speed_mode;
event->en_reg_addr = en_reg;
event->en_bit = en_bit;
event->evt_base.event_id = evt_id;
event->evt_base.trig_periph = ETM_TRIG_PERIPH_LEDC;
event->evt_base.del = ledc_del_etm_event;
*out_event = &event->evt_base;
return ESP_OK;
}
esp_err_t ledc_channel_new_etm_event(ledc_mode_t speed_mode, ledc_channel_t channel, const ledc_channel_etm_event_config_t *config, esp_etm_event_handle_t *out_event)
{
ESP_RETURN_ON_FALSE(speed_mode < LEDC_SPEED_MODE_MAX && channel < LEDC_CHANNEL_MAX && config && config->event_type < LEDC_CHANNEL_ETM_EVENT_MAX && out_event, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
ledc_etm_event_task_t *event = heap_caps_calloc(1, sizeof(ledc_etm_event_task_t), MALLOC_CAP_DEFAULT);
ESP_RETURN_ON_FALSE(event, ESP_ERR_NO_MEM, TAG, "no memory for ETM event");
uint32_t evt_id = LEDC_LL_ETM_CHANNEL_EVENT_ID(speed_mode, channel, config->event_type);
volatile uint32_t *en_reg = LEDC_LL_ETM_CHANNEL_EVENT_EN_REG(speed_mode, config->event_type);
uint32_t en_bit = LEDC_LL_ETM_CHANNEL_EVENT_EN_BIT(speed_mode, channel, config->event_type);
portENTER_CRITICAL(&s_ledc_etm_spinlock);
ledc_ll_etm_enable_evt_task(LEDC_LL_GET_HW(), speed_mode, en_reg, en_bit, true);
portEXIT_CRITICAL(&s_ledc_etm_spinlock);
event->speed_mode = speed_mode;
event->en_reg_addr = en_reg;
event->en_bit = en_bit;
event->evt_base.event_id = evt_id;
event->evt_base.trig_periph = ETM_TRIG_PERIPH_LEDC;
event->evt_base.del = ledc_del_etm_event;
*out_event = &event->evt_base;
return ESP_OK;
}
esp_err_t ledc_timer_new_etm_task(ledc_mode_t speed_mode, ledc_timer_t timer_sel, const ledc_timer_etm_task_config_t *config, esp_etm_task_handle_t *out_task)
{
ESP_RETURN_ON_FALSE(speed_mode < LEDC_SPEED_MODE_MAX && timer_sel < LEDC_TIMER_MAX && config && config->task_type < LEDC_TIMER_ETM_TASK_MAX && out_task, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
ledc_etm_event_task_t *task = heap_caps_calloc(1, sizeof(ledc_etm_event_task_t), MALLOC_CAP_DEFAULT);
ESP_RETURN_ON_FALSE(task, ESP_ERR_NO_MEM, TAG, "no memory for ETM task");
uint32_t task_id = LEDC_LL_ETM_TIMER_TASK_ID(speed_mode, timer_sel, config->task_type);
volatile uint32_t *en_reg = LEDC_LL_ETM_TIMER_TASK_EN_REG(speed_mode, config->task_type);
uint32_t en_bit = LEDC_LL_ETM_TIMER_TASK_EN_BIT(speed_mode, timer_sel, config->task_type);
portENTER_CRITICAL(&s_ledc_etm_spinlock);
ledc_ll_etm_enable_evt_task(LEDC_LL_GET_HW(), speed_mode, en_reg, en_bit, true);
portEXIT_CRITICAL(&s_ledc_etm_spinlock);
task->speed_mode = speed_mode;
task->en_reg_addr = en_reg;
task->en_bit = en_bit;
task->task_base.task_id = task_id;
task->task_base.trig_periph = ETM_TRIG_PERIPH_LEDC;
task->task_base.del = ledc_del_etm_task;
*out_task = &task->task_base;
return ESP_OK;
}
esp_err_t ledc_channel_new_etm_task(ledc_mode_t speed_mode, ledc_channel_t channel, const ledc_channel_etm_task_config_t *config, esp_etm_task_handle_t *out_task)
{
ESP_RETURN_ON_FALSE(speed_mode < LEDC_SPEED_MODE_MAX && channel < LEDC_CHANNEL_MAX && config && config->task_type < LEDC_CHANNEL_ETM_TASK_MAX && out_task, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
ledc_etm_event_task_t *task = heap_caps_calloc(1, sizeof(ledc_etm_event_task_t), MALLOC_CAP_DEFAULT);
ESP_RETURN_ON_FALSE(task, ESP_ERR_NO_MEM, TAG, "no memory for ETM task");
uint32_t task_id = LEDC_LL_ETM_CHANNEL_TASK_ID(speed_mode, channel, config->task_type);
volatile uint32_t *en_reg = LEDC_LL_ETM_CHANNEL_TASK_EN_REG(speed_mode, config->task_type);
uint32_t en_bit = LEDC_LL_ETM_CHANNEL_TASK_EN_BIT(speed_mode, channel, config->task_type);
portENTER_CRITICAL(&s_ledc_etm_spinlock);
ledc_ll_etm_enable_evt_task(LEDC_LL_GET_HW(), speed_mode, en_reg, en_bit, true);
portEXIT_CRITICAL(&s_ledc_etm_spinlock);
task->speed_mode = speed_mode;
task->en_reg_addr = en_reg;
task->en_bit = en_bit;
task->task_base.task_id = task_id;
task->task_base.trig_periph = ETM_TRIG_PERIPH_LEDC;
task->task_base.del = ledc_del_etm_task;
*out_task = &task->task_base;
return ESP_OK;
}
@@ -6,6 +6,10 @@ if(CONFIG_SOC_LIGHT_SLEEP_SUPPORTED)
list(APPEND srcs "test_ledc_sleep.cpp")
endif()
if(CONFIG_SOC_ETM_SUPPORTED AND CONFIG_SOC_LEDC_SUPPORT_ETM)
list(APPEND srcs "test_ledc_etm.cpp")
endif()
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
# the component can be registered as WHOLE_ARCHIVE
idf_component_register(
@@ -0,0 +1,72 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "unity.h"
#include "test_utils.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/ledc.h"
#include "test_ledc_utils.h"
#include "esp_etm.h"
#include "esp_attr.h"
#include "driver/uart.h"
TEST_CASE("ledc etm event and task", "[ledc]")
{
// Generate a PWM signal with certain number of pulses
ledc_timer_config_t ledc_time_config = create_default_timer_config();
TEST_ESP_OK(ledc_timer_config(&ledc_time_config));
ledc_channel_config_t ledc_ch_config = initialize_channel_config();
TEST_ESP_OK(ledc_channel_config(&ledc_ch_config));
vTaskDelay(pdMS_TO_TICKS(50));
ledc_timer_pause(TEST_SPEED_MODE, LEDC_TIMER_0);
TEST_ESP_OK(ledc_channel_configure_maximum_timer_ovf_cnt(TEST_SPEED_MODE, LEDC_CHANNEL_0, 500));
esp_etm_channel_config_t etm_config = {};
esp_etm_channel_handle_t etm_channel_a = NULL;
TEST_ESP_OK(esp_etm_new_channel(&etm_config, &etm_channel_a));
esp_etm_event_handle_t event_handle = NULL;
ledc_channel_etm_event_config_t event_config = {
.event_type = LEDC_CHANNEL_ETM_EVENT_REACH_MAX_OVF_CNT,
};
TEST_ESP_OK(ledc_channel_new_etm_event(TEST_SPEED_MODE, LEDC_CHANNEL_0, &event_config, &event_handle));
esp_etm_task_handle_t task_handle_a = NULL;
ledc_timer_etm_task_config_t task_config_a = {
.task_type = LEDC_TIMER_ETM_TASK_PAUSE,
};
TEST_ESP_OK(ledc_timer_new_etm_task(TEST_SPEED_MODE, LEDC_TIMER_0, &task_config_a, &task_handle_a));
TEST_ESP_OK(esp_etm_channel_connect(etm_channel_a, event_handle, task_handle_a));
TEST_ESP_OK(esp_etm_channel_enable(etm_channel_a));
// use UART auto baud rate detection feature to count the PWM pulse count
uart_bitrate_detect_config_t conf = {
.rx_io_num = PULSE_IO,
.source_clk = UART_SCLK_DEFAULT,
};
uart_bitrate_res_t res = {};
uart_detect_bitrate_start(UART_NUM_1, &conf);
TEST_ESP_OK(ledc_timer_rst(TEST_SPEED_MODE, LEDC_TIMER_0));
TEST_ESP_OK(ledc_timer_resume(TEST_SPEED_MODE, LEDC_TIMER_0));
vTaskDelay(pdMS_TO_TICKS(500));
uart_detect_bitrate_stop(UART_NUM_1, true, &res);
uint32_t pulse_count = (res.edge_cnt + 1) / 2;
TEST_ASSERT_INT32_WITHIN(1, 500, pulse_count);
TEST_ESP_OK(esp_etm_channel_disable(etm_channel_a));
TEST_ESP_OK(esp_etm_del_event(event_handle));
TEST_ESP_OK(esp_etm_del_task(task_handle_a));
TEST_ESP_OK(esp_etm_del_channel(etm_channel_a));
}
@@ -30,6 +30,7 @@ typedef enum {
ETM_TRIG_PERIPH_I2S, /*!< ETM trigger source: I2S */
ETM_TRIG_PERIPH_LP_CORE, /*!< ETM trigger source: Low-Power Core */
ETM_TRIG_PERIPH_MODEM, /*!< ETM trigger source: Modem */
ETM_TRIG_PERIPH_LEDC, /*!< ETM trigger source: LEDC */
} etm_trigger_peripheral_t;
/**
@@ -20,10 +20,13 @@ extern "C" {
#define LEDC_LL_GET_HW() &LEDC
#define LEDC_LL_CHANNEL_SUPPORT_OVF_CNT 1
#define LEDC_LL_DUTY_NUM_MAX (LEDC_DUTY_NUM_CH0_V)
#define LEDC_LL_DUTY_CYCLE_MAX (LEDC_DUTY_CYCLE_CH0_V)
#define LEDC_LL_DUTY_SCALE_MAX (LEDC_DUTY_SCALE_CH0_V)
#define LEDC_LL_HPOINT_VAL_MAX (LEDC_HPOINT_CH0_V)
#define LEDC_LL_OVF_CNT_MAX (LEDC_OVF_NUM_CH0_V + 1)
#define LEDC_LL_FRACTIONAL_BITS (8)
#define LEDC_LL_FRACTIONAL_MAX ((1 << LEDC_LL_FRACTIONAL_BITS) - 1)
@@ -587,6 +590,51 @@ static inline void ledc_ll_get_channel_timer(ledc_dev_t *hw, ledc_mode_t speed_m
*timer_sel = (ledc_timer_t)(hw->channel_group[speed_mode].channel[channel_num].conf0.timer_sel);
}
/**
* @brief Enable or disable the timer overflow counter for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-5), select from ledc_channel_t
* @param enable True to enable; false to disable
*
* @return None
*/
static inline void ledc_ll_channel_enable_timer_ovt_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel, bool enable)
{
hw->channel_group[speed_mode].channel[channel].conf0.ovf_cnt_en = enable;
}
/**
* @brief Set the maximum timer overflow count for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-5), select from ledc_channel_t
* @param max_ovf_cnt The maximum timer overflow count
*
* @return None
*/
static inline void ledc_ll_channel_set_maximum_timer_ovf_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t max_ovf_cnt)
{
HAL_ASSERT(max_ovf_cnt > 0 && max_ovf_cnt <= LEDC_LL_OVF_CNT_MAX);
hw->channel_group[speed_mode].channel[channel].conf0.ovf_num = max_ovf_cnt - 1;
}
/**
* @brief Reset the timer overflow counter for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-5), select from ledc_channel_t
*
* @return None
*/
static inline void ledc_ll_channel_reset_timer_ovf_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel)
{
hw->channel_group[speed_mode].channel[channel].conf0.ovf_cnt_reset = 1;
}
#ifdef __cplusplus
}
#endif
@@ -21,10 +21,13 @@ extern "C" {
#define LEDC_LL_GET_HW() &LEDC
#define LEDC_LL_CHANNEL_SUPPORT_OVF_CNT 1
#define LEDC_LL_DUTY_NUM_MAX (LEDC_DUTY_NUM_LSCH0_V)
#define LEDC_LL_DUTY_CYCLE_MAX (LEDC_DUTY_CYCLE_LSCH0_V)
#define LEDC_LL_DUTY_SCALE_MAX (LEDC_DUTY_SCALE_LSCH0_V)
#define LEDC_LL_HPOINT_VAL_MAX (LEDC_HPOINT_LSCH0_V)
#define LEDC_LL_OVF_CNT_MAX (LEDC_OVF_NUM_LSCH0_V + 1)
#define LEDC_LL_FRACTIONAL_BITS (8)
#define LEDC_LL_FRACTIONAL_MAX ((1 << LEDC_LL_FRACTIONAL_BITS) - 1)
@@ -589,6 +592,51 @@ static inline void ledc_ll_get_channel_timer(ledc_dev_t *hw, ledc_mode_t speed_m
*timer_sel = (ledc_timer_t)(hw->channel_group[speed_mode].channel[channel_num].conf0.timer_sel);
}
/**
* @brief Enable or disable the timer overflow counter for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-5), select from ledc_channel_t
* @param enable True to enable; false to disable
*
* @return None
*/
static inline void ledc_ll_channel_enable_timer_ovt_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel, bool enable)
{
hw->channel_group[speed_mode].channel[channel].conf0.ovf_cnt_en = enable;
}
/**
* @brief Set the maximum timer overflow count for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-5), select from ledc_channel_t
* @param max_ovf_cnt The maximum timer overflow count
*
* @return None
*/
static inline void ledc_ll_channel_set_maximum_timer_ovf_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t max_ovf_cnt)
{
HAL_ASSERT(max_ovf_cnt > 0 && max_ovf_cnt <= LEDC_LL_OVF_CNT_MAX);
hw->channel_group[speed_mode].channel[channel].conf0.ovf_num = max_ovf_cnt - 1;
}
/**
* @brief Reset the timer overflow counter for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-5), select from ledc_channel_t
*
* @return None
*/
static inline void ledc_ll_channel_reset_timer_ovf_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel)
{
hw->channel_group[speed_mode].channel[channel].conf0.ovf_cnt_rst = 1;
}
#ifdef __cplusplus
}
#endif
@@ -16,6 +16,7 @@
#include "soc/clk_tree_defs.h"
#include "soc/pcr_struct.h"
#include "soc/soc_caps.h"
#include "soc/soc_etm_source.h"
#ifdef __cplusplus
extern "C" {
@@ -23,14 +24,105 @@ extern "C" {
#define LEDC_LL_GET_HW() &LEDC
#define LEDC_LL_CHANNEL_SUPPORT_OVF_CNT 1
#define LEDC_LL_DUTY_NUM_MAX (LEDC_CH0_GAMMA_RANGE0_DUTY_NUM_V)
#define LEDC_LL_DUTY_CYCLE_MAX (LEDC_CH0_GAMMA_RANGE0_DUTY_CYCLE_V)
#define LEDC_LL_DUTY_SCALE_MAX (LEDC_CH0_GAMMA_RANGE0_SCALE_V)
#define LEDC_LL_HPOINT_VAL_MAX (LEDC_HPOINT_CH0_V)
#define LEDC_LL_OVF_CNT_MAX (LEDC_OVF_NUM_CH0_V + 1)
#define LEDC_LL_FRACTIONAL_BITS (8)
#define LEDC_LL_FRACTIONAL_MAX ((1 << LEDC_LL_FRACTIONAL_BITS) - 1)
#define LEDC_LL_GLOBAL_CLOCKS SOC_LEDC_CLKS
// Channel tasks: ID, enable register and bit
#define LEDC_LL_ETM_CHANNEL_TASK_ID(group, channel, task) \
((uint32_t [1][LEDC_CHANNEL_ETM_TASK_MAX]){{ \
[LEDC_CHANNEL_ETM_TASK_FADE_SCALE_UPDATE] = LEDC_TASK_DUTY_SCALE_UPDATE_CH0, \
[LEDC_CHANNEL_ETM_TASK_SIG_OUT_DIS] = LEDC_TASK_SIG_OUT_DIS_CH0, \
[LEDC_CHANNEL_ETM_TASK_OVF_CNT_RST] = LEDC_TASK_OVF_CNT_RST_CH0, \
[LEDC_CHANNEL_ETM_TASK_FADE_RESTART] = LEDC_TASK_GAMMA_RESTART_CH0, \
[LEDC_CHANNEL_ETM_TASK_FADE_PAUSE] = LEDC_TASK_GAMMA_PAUSE_CH0, \
[LEDC_CHANNEL_ETM_TASK_FADE_RESUME] = LEDC_TASK_GAMMA_RESUME_CH0, \
}}[(group)][(task)] + (channel))
#define LEDC_LL_ETM_CHANNEL_TASK_EN_REG(group, task) \
((volatile uint32_t *[1][LEDC_CHANNEL_ETM_TASK_MAX]){{ \
[LEDC_CHANNEL_ETM_TASK_FADE_SCALE_UPDATE] = (volatile uint32_t *)LEDC_EVT_TASK_EN0_REG, \
[LEDC_CHANNEL_ETM_TASK_SIG_OUT_DIS] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
[LEDC_CHANNEL_ETM_TASK_OVF_CNT_RST] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
[LEDC_CHANNEL_ETM_TASK_FADE_RESTART] = (volatile uint32_t *)LEDC_EVT_TASK_EN2_REG, \
[LEDC_CHANNEL_ETM_TASK_FADE_PAUSE] = (volatile uint32_t *)LEDC_EVT_TASK_EN2_REG, \
[LEDC_CHANNEL_ETM_TASK_FADE_RESUME] = (volatile uint32_t *)LEDC_EVT_TASK_EN2_REG, \
}}[(group)][(task)])
#define LEDC_LL_ETM_CHANNEL_TASK_EN_BIT(group, channel, task) \
((uint32_t [1][LEDC_CHANNEL_ETM_TASK_MAX]){{ \
[LEDC_CHANNEL_ETM_TASK_FADE_SCALE_UPDATE] = BIT(LEDC_TASK_DUTY_SCALE_UPDATE_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_SIG_OUT_DIS] = BIT(LEDC_TASK_SIG_OUT_DIS_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_OVF_CNT_RST] = BIT(LEDC_TASK_OVF_CNT_RST_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_FADE_RESTART] = BIT(LEDC_TASK_GAMMA_RESTART_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_FADE_PAUSE] = BIT(LEDC_TASK_GAMMA_PAUSE_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_FADE_RESUME] = BIT(LEDC_TASK_GAMMA_RESUME_CH0_EN_S), \
}}[(group)][(task)] << (channel))
// Channel events: ID, enable register and bit
#define LEDC_LL_ETM_CHANNEL_EVENT_ID(group, channel, event) \
((uint32_t [1][LEDC_CHANNEL_ETM_EVENT_MAX]){{ \
[LEDC_CHANNEL_ETM_EVENT_FADE_END] = LEDC_EVT_DUTY_CHNG_END_CH0, \
[LEDC_CHANNEL_ETM_EVENT_REACH_MAX_OVF_CNT] = LEDC_EVT_OVF_CNT_PLS_CH0, \
}}[(group)][(event)] + (channel))
#define LEDC_LL_ETM_CHANNEL_EVENT_EN_REG(group, event) \
((volatile uint32_t *[1][LEDC_CHANNEL_ETM_EVENT_MAX]){{ \
[LEDC_CHANNEL_ETM_EVENT_FADE_END] = (volatile uint32_t *)LEDC_EVT_TASK_EN0_REG, \
[LEDC_CHANNEL_ETM_EVENT_REACH_MAX_OVF_CNT] = (volatile uint32_t *)LEDC_EVT_TASK_EN0_REG, \
}}[(group)][(event)])
#define LEDC_LL_ETM_CHANNEL_EVENT_EN_BIT(group, channel, event) \
((uint32_t [1][LEDC_CHANNEL_ETM_EVENT_MAX]){{ \
[LEDC_CHANNEL_ETM_EVENT_FADE_END] = BIT(LEDC_EVT_DUTY_CHNG_END_CH0_EN_S), \
[LEDC_CHANNEL_ETM_EVENT_REACH_MAX_OVF_CNT] = BIT(LEDC_EVT_OVF_CNT_PLS_CH0_EN_S), \
}}[(group)][(event)] << (channel))
// Timer tasks: ID, enable register and bit
#define LEDC_LL_ETM_TIMER_TASK_ID(group, timer, task) \
((uint32_t [1][LEDC_TIMER_ETM_TASK_MAX]){{ \
[LEDC_TIMER_ETM_TASK_RST] = LEDC_TASK_TIMER0_RST, \
[LEDC_TIMER_ETM_TASK_RESUME] = LEDC_TASK_TIMER0_RESUME, \
[LEDC_TIMER_ETM_TASK_PAUSE] = LEDC_TASK_TIMER0_PAUSE, \
}}[(group)][(task)] + (timer))
#define LEDC_LL_ETM_TIMER_TASK_EN_REG(group, task) \
((volatile uint32_t *[1][LEDC_TIMER_ETM_TASK_MAX]){{ \
[LEDC_TIMER_ETM_TASK_RST] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
[LEDC_TIMER_ETM_TASK_RESUME] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
[LEDC_TIMER_ETM_TASK_PAUSE] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
}}[(group)][(task)])
#define LEDC_LL_ETM_TIMER_TASK_EN_BIT(group, timer, task) \
((uint32_t [1][LEDC_TIMER_ETM_TASK_MAX]){{ \
[LEDC_TIMER_ETM_TASK_RST] = BIT(LEDC_TASK_TIMER0_RST_EN_S), \
[LEDC_TIMER_ETM_TASK_RESUME] = BIT(LEDC_TASK_TIMER0_PAUSE_RESUME_EN_S), \
[LEDC_TIMER_ETM_TASK_PAUSE] = BIT(LEDC_TASK_TIMER0_PAUSE_RESUME_EN_S), \
}}[(group)][(task)] << (timer))
// Timer events: ID, enable register and bit
#define LEDC_LL_ETM_TIMER_EVENT_ID(group, timer, event) \
((uint32_t [1][LEDC_TIMER_ETM_EVENT_MAX]){{ \
[LEDC_TIMER_ETM_EVENT_OVF] = LEDC_EVT_TIME_OVF_TIMER0, \
}}[(group)][(event)] + (timer))
#define LEDC_LL_ETM_TIMER_EVENT_EN_REG(group, event) \
((volatile uint32_t *[1][LEDC_TIMER_ETM_EVENT_MAX]){{ \
[LEDC_TIMER_ETM_EVENT_OVF] = (volatile uint32_t *)LEDC_EVT_TASK_EN0_REG, \
}}[(group)][(event)])
#define LEDC_LL_ETM_TIMER_EVENT_EN_BIT(group, timer, event) \
((uint32_t [1][LEDC_TIMER_ETM_EVENT_MAX]){{ \
[LEDC_TIMER_ETM_EVENT_OVF] = BIT(LEDC_EVT_TIME_OVF_TIMER0_EN_S), \
}}[(group)][(event)] << (timer))
/**
* @brief Enable peripheral register clock
*
@@ -587,6 +679,69 @@ static inline void ledc_ll_get_channel_timer(ledc_dev_t *hw, ledc_mode_t speed_m
*timer_sel = (ledc_timer_t)(hw->channel_group[speed_mode].channel[channel_num].conf0.timer_sel);
}
/**
* @brief Enable or disable ETM event/task
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param reg_addr Register address to control the ETM event/task
* @param bit Bit position in the register
* @param enable Enable or disable the ETM event/task
*/
static inline void ledc_ll_etm_enable_evt_task(ledc_dev_t *hw, ledc_mode_t speed_mode, volatile uint32_t *reg_addr, uint32_t bit, bool enable)
{
if (enable) {
REG_SET_BIT(reg_addr, bit);
} else {
REG_CLR_BIT(reg_addr, bit);
}
}
/**
* @brief Enable or disable the timer overflow counter for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-5), select from ledc_channel_t
* @param enable True to enable; false to disable
*
* @return None
*/
static inline void ledc_ll_channel_enable_timer_ovt_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel, bool enable)
{
hw->channel_group[speed_mode].channel[channel].conf0.ovf_cnt_en = enable;
}
/**
* @brief Set the maximum timer overflow count for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-5), select from ledc_channel_t
* @param max_ovf_cnt The maximum timer overflow count
*
* @return None
*/
static inline void ledc_ll_channel_set_maximum_timer_ovf_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t max_ovf_cnt)
{
HAL_ASSERT(max_ovf_cnt > 0 && max_ovf_cnt <= LEDC_LL_OVF_CNT_MAX);
hw->channel_group[speed_mode].channel[channel].conf0.ovf_num = max_ovf_cnt - 1;
}
/**
* @brief Reset the timer overflow counter for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-5), select from ledc_channel_t
*
* @return None
*/
static inline void ledc_ll_channel_reset_timer_ovf_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel)
{
hw->channel_group[speed_mode].channel[channel].conf0.ovf_cnt_reset = 1;
}
#ifdef __cplusplus
}
#endif
@@ -17,6 +17,7 @@
#include "hal/assert.h"
#include "esp_rom_sys.h" //for sync issue workaround
#include "soc/soc_caps.h"
#include "soc/soc_etm_source.h"
#ifdef __cplusplus
extern "C" {
@@ -24,10 +25,13 @@ extern "C" {
#define LEDC_LL_GET_HW() &LEDC
#define LEDC_LL_CHANNEL_SUPPORT_OVF_CNT 1
#define LEDC_LL_DUTY_NUM_MAX (LEDC_CH0_GAMMA_DUTY_NUM_V)
#define LEDC_LL_DUTY_CYCLE_MAX (LEDC_CH0_GAMMA_DUTY_CYCLE_V)
#define LEDC_LL_DUTY_SCALE_MAX (LEDC_CH0_GAMMA_SCALE_V)
#define LEDC_LL_HPOINT_VAL_MAX (LEDC_HPOINT_CH0_V)
#define LEDC_LL_OVF_CNT_MAX (LEDC_OVF_NUM_CH0_V + 1)
#define LEDC_LL_FRACTIONAL_BITS (8)
#define LEDC_LL_FRACTIONAL_MAX ((1 << LEDC_LL_FRACTIONAL_BITS) - 1)
#define LEDC_LL_GLOBAL_CLOCKS SOC_LEDC_CLKS
@@ -35,6 +39,94 @@ extern "C" {
#define LEDC_LL_GLOBAL_CLK_NC_BY_DEFAULT 1
#define LEDC_LL_GLOBAL_CLK_DEFAULT LEDC_SLOW_CLK_RC_FAST // The temporal global clock source to set to at least make the LEDC core clock on
// Channel tasks: ID, enable register and bit
#define LEDC_LL_ETM_CHANNEL_TASK_ID(group, channel, task) \
((uint32_t [1][LEDC_CHANNEL_ETM_TASK_MAX]){{ \
[LEDC_CHANNEL_ETM_TASK_FADE_SCALE_UPDATE] = LEDC_TASK_DUTY_SCALE_UPDATE_CH0, \
[LEDC_CHANNEL_ETM_TASK_SIG_OUT_DIS] = LEDC_TASK_SIG_OUT_DIS_CH0, \
[LEDC_CHANNEL_ETM_TASK_OVF_CNT_RST] = LEDC_TASK_OVF_CNT_RST_CH0, \
[LEDC_CHANNEL_ETM_TASK_FADE_RESTART] = LEDC_TASK_GAMMA_RESTART_CH0, \
[LEDC_CHANNEL_ETM_TASK_FADE_PAUSE] = LEDC_TASK_GAMMA_PAUSE_CH0, \
[LEDC_CHANNEL_ETM_TASK_FADE_RESUME] = LEDC_TASK_GAMMA_RESUME_CH0, \
}}[(group)][(task)] + (channel))
#define LEDC_LL_ETM_CHANNEL_TASK_EN_REG(group, task) \
((volatile uint32_t *[1][LEDC_CHANNEL_ETM_TASK_MAX]){{ \
[LEDC_CHANNEL_ETM_TASK_FADE_SCALE_UPDATE] = (volatile uint32_t *)LEDC_EVT_TASK_EN0_REG, \
[LEDC_CHANNEL_ETM_TASK_SIG_OUT_DIS] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
[LEDC_CHANNEL_ETM_TASK_OVF_CNT_RST] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
[LEDC_CHANNEL_ETM_TASK_FADE_RESTART] = (volatile uint32_t *)LEDC_EVT_TASK_EN2_REG, \
[LEDC_CHANNEL_ETM_TASK_FADE_PAUSE] = (volatile uint32_t *)LEDC_EVT_TASK_EN2_REG, \
[LEDC_CHANNEL_ETM_TASK_FADE_RESUME] = (volatile uint32_t *)LEDC_EVT_TASK_EN2_REG, \
}}[(group)][(task)])
#define LEDC_LL_ETM_CHANNEL_TASK_EN_BIT(group, channel, task) \
((uint32_t [1][LEDC_CHANNEL_ETM_TASK_MAX]){{ \
[LEDC_CHANNEL_ETM_TASK_FADE_SCALE_UPDATE] = BIT(LEDC_TASK_DUTY_SCALE_UPDATE_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_SIG_OUT_DIS] = BIT(LEDC_TASK_SIG_OUT_DIS_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_OVF_CNT_RST] = BIT(LEDC_TASK_OVF_CNT_RST_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_FADE_RESTART] = BIT(LEDC_TASK_GAMMA_RESTART_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_FADE_PAUSE] = BIT(LEDC_TASK_GAMMA_PAUSE_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_FADE_RESUME] = BIT(LEDC_TASK_GAMMA_RESUME_CH0_EN_S), \
}}[(group)][(task)] << (channel))
// Channel events: ID, enable register and bit
#define LEDC_LL_ETM_CHANNEL_EVENT_ID(group, channel, event) \
((uint32_t [1][LEDC_CHANNEL_ETM_EVENT_MAX]){{ \
[LEDC_CHANNEL_ETM_EVENT_FADE_END] = LEDC_EVT_DUTY_CHNG_END_CH0, \
[LEDC_CHANNEL_ETM_EVENT_REACH_MAX_OVF_CNT] = LEDC_EVT_OVF_CNT_PLS_CH0, \
}}[(group)][(event)] + (channel))
#define LEDC_LL_ETM_CHANNEL_EVENT_EN_REG(group, event) \
((volatile uint32_t *[1][LEDC_CHANNEL_ETM_EVENT_MAX]){{ \
[LEDC_CHANNEL_ETM_EVENT_FADE_END] = (volatile uint32_t *)LEDC_EVT_TASK_EN0_REG, \
[LEDC_CHANNEL_ETM_EVENT_REACH_MAX_OVF_CNT] = (volatile uint32_t *)LEDC_EVT_TASK_EN0_REG, \
}}[(group)][(event)])
#define LEDC_LL_ETM_CHANNEL_EVENT_EN_BIT(group, channel, event) \
((uint32_t [1][LEDC_CHANNEL_ETM_EVENT_MAX]){{ \
[LEDC_CHANNEL_ETM_EVENT_FADE_END] = BIT(LEDC_EVT_DUTY_CHNG_END_CH0_EN_S), \
[LEDC_CHANNEL_ETM_EVENT_REACH_MAX_OVF_CNT] = BIT(LEDC_EVT_OVF_CNT_PLS_CH0_EN_S), \
}}[(group)][(event)] << (channel))
// Timer tasks: ID, enable register and bit
#define LEDC_LL_ETM_TIMER_TASK_ID(group, timer, task) \
((uint32_t [1][LEDC_TIMER_ETM_TASK_MAX]){{ \
[LEDC_TIMER_ETM_TASK_RST] = LEDC_TASK_TIMER0_RST, \
[LEDC_TIMER_ETM_TASK_RESUME] = LEDC_TASK_TIMER0_RESUME, \
[LEDC_TIMER_ETM_TASK_PAUSE] = LEDC_TASK_TIMER0_PAUSE, \
}}[(group)][(task)] + (timer))
#define LEDC_LL_ETM_TIMER_TASK_EN_REG(group, task) \
((volatile uint32_t *[1][LEDC_TIMER_ETM_TASK_MAX]){{ \
[LEDC_TIMER_ETM_TASK_RST] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
[LEDC_TIMER_ETM_TASK_RESUME] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
[LEDC_TIMER_ETM_TASK_PAUSE] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
}}[(group)][(task)])
#define LEDC_LL_ETM_TIMER_TASK_EN_BIT(group, timer, task) \
((uint32_t [1][LEDC_TIMER_ETM_TASK_MAX]){{ \
[LEDC_TIMER_ETM_TASK_RST] = BIT(LEDC_TASK_TIMER0_RST_EN_S), \
[LEDC_TIMER_ETM_TASK_RESUME] = BIT(LEDC_TASK_TIMER0_PAUSE_RESUME_EN_S), \
[LEDC_TIMER_ETM_TASK_PAUSE] = BIT(LEDC_TASK_TIMER0_PAUSE_RESUME_EN_S), \
}}[(group)][(task)] << (timer))
// Timer events: ID, enable register and bit
#define LEDC_LL_ETM_TIMER_EVENT_ID(group, timer, event) \
((uint32_t [1][LEDC_TIMER_ETM_EVENT_MAX]){{ \
[LEDC_TIMER_ETM_EVENT_OVF] = LEDC_EVT_TIME_OVF_TIMER0, \
}}[(group)][(event)] + (timer))
#define LEDC_LL_ETM_TIMER_EVENT_EN_REG(group, event) \
((volatile uint32_t *[1][LEDC_TIMER_ETM_EVENT_MAX]){{ \
[LEDC_TIMER_ETM_EVENT_OVF] = (volatile uint32_t *)LEDC_EVT_TASK_EN0_REG, \
}}[(group)][(event)])
#define LEDC_LL_ETM_TIMER_EVENT_EN_BIT(group, timer, event) \
((uint32_t [1][LEDC_TIMER_ETM_EVENT_MAX]){{ \
[LEDC_TIMER_ETM_EVENT_OVF] = BIT(LEDC_EVT_TIME_OVF_TIMER0_EN_S), \
}}[(group)][(event)] << (timer))
/**
* @brief Enable peripheral register clock
*
@@ -709,6 +801,69 @@ static inline void ledc_ll_get_channel_timer(ledc_dev_t *hw, ledc_mode_t speed_m
*timer_sel = (ledc_timer_t)(hw->channel_group[speed_mode].channel[channel_num].conf0.timer_sel);
}
/**
* @brief Enable or disable ETM event/task
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param reg_addr Register address to control the ETM event/task
* @param bit Bit position in the register
* @param enable Enable or disable the ETM event/task
*/
static inline void ledc_ll_etm_enable_evt_task(ledc_dev_t *hw, ledc_mode_t speed_mode, volatile uint32_t *reg_addr, uint32_t bit, bool enable)
{
if (enable) {
REG_SET_BIT(reg_addr, bit);
} else {
REG_CLR_BIT(reg_addr, bit);
}
}
/**
* @brief Enable or disable the timer overflow counter for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-5), select from ledc_channel_t
* @param enable True to enable; false to disable
*
* @return None
*/
static inline void ledc_ll_channel_enable_timer_ovt_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel, bool enable)
{
hw->channel_group[speed_mode].channel[channel].conf0.ovf_cnt_en = enable;
}
/**
* @brief Set the maximum timer overflow count for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-5), select from ledc_channel_t
* @param max_ovf_cnt The maximum timer overflow count
*
* @return None
*/
static inline void ledc_ll_channel_set_maximum_timer_ovf_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t max_ovf_cnt)
{
HAL_ASSERT(max_ovf_cnt > 0 && max_ovf_cnt <= LEDC_LL_OVF_CNT_MAX);
hw->channel_group[speed_mode].channel[channel].conf0.ovf_num = max_ovf_cnt - 1;
}
/**
* @brief Reset the timer overflow counter for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-5), select from ledc_channel_t
*
* @return None
*/
static inline void ledc_ll_channel_reset_timer_ovf_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel)
{
hw->channel_group[speed_mode].channel[channel].conf0.ovf_cnt_reset = 1;
}
#ifdef __cplusplus
}
#endif
@@ -16,6 +16,7 @@
#include "soc/clk_tree_defs.h"
#include "soc/pcr_struct.h"
#include "soc/soc_caps.h"
#include "soc/soc_etm_source.h"
#ifdef __cplusplus
extern "C" {
@@ -23,14 +24,105 @@ extern "C" {
#define LEDC_LL_GET_HW() &LEDC
#define LEDC_LL_CHANNEL_SUPPORT_OVF_CNT 1
#define LEDC_LL_DUTY_NUM_MAX (LEDC_CH0_GAMMA_RANGE0_DUTY_NUM_V)
#define LEDC_LL_DUTY_CYCLE_MAX (LEDC_CH0_GAMMA_RANGE0_DUTY_CYCLE_V)
#define LEDC_LL_DUTY_SCALE_MAX (LEDC_CH0_GAMMA_RANGE0_SCALE_V)
#define LEDC_LL_HPOINT_VAL_MAX (LEDC_HPOINT_CH0_V)
#define LEDC_LL_OVF_CNT_MAX (LEDC_OVF_NUM_CH0_V + 1)
#define LEDC_LL_FRACTIONAL_BITS (8)
#define LEDC_LL_FRACTIONAL_MAX ((1 << LEDC_LL_FRACTIONAL_BITS) - 1)
#define LEDC_LL_GLOBAL_CLOCKS SOC_LEDC_CLKS
// Channel tasks: ID, enable register and bit
#define LEDC_LL_ETM_CHANNEL_TASK_ID(group, channel, task) \
((uint32_t [1][LEDC_CHANNEL_ETM_TASK_MAX]){{ \
[LEDC_CHANNEL_ETM_TASK_FADE_SCALE_UPDATE] = LEDC_TASK_DUTY_SCALE_UPDATE_CH0, \
[LEDC_CHANNEL_ETM_TASK_SIG_OUT_DIS] = LEDC_TASK_SIG_OUT_DIS_CH0, \
[LEDC_CHANNEL_ETM_TASK_OVF_CNT_RST] = LEDC_TASK_OVF_CNT_RST_CH0, \
[LEDC_CHANNEL_ETM_TASK_FADE_RESTART] = LEDC_TASK_GAMMA_RESTART_CH0, \
[LEDC_CHANNEL_ETM_TASK_FADE_PAUSE] = LEDC_TASK_GAMMA_PAUSE_CH0, \
[LEDC_CHANNEL_ETM_TASK_FADE_RESUME] = LEDC_TASK_GAMMA_RESUME_CH0, \
}}[(group)][(task)] + (channel))
#define LEDC_LL_ETM_CHANNEL_TASK_EN_REG(group, task) \
((volatile uint32_t *[1][LEDC_CHANNEL_ETM_TASK_MAX]){{ \
[LEDC_CHANNEL_ETM_TASK_FADE_SCALE_UPDATE] = (volatile uint32_t *)LEDC_EVT_TASK_EN0_REG, \
[LEDC_CHANNEL_ETM_TASK_SIG_OUT_DIS] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
[LEDC_CHANNEL_ETM_TASK_OVF_CNT_RST] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
[LEDC_CHANNEL_ETM_TASK_FADE_RESTART] = (volatile uint32_t *)LEDC_EVT_TASK_EN2_REG, \
[LEDC_CHANNEL_ETM_TASK_FADE_PAUSE] = (volatile uint32_t *)LEDC_EVT_TASK_EN2_REG, \
[LEDC_CHANNEL_ETM_TASK_FADE_RESUME] = (volatile uint32_t *)LEDC_EVT_TASK_EN2_REG, \
}}[(group)][(task)])
#define LEDC_LL_ETM_CHANNEL_TASK_EN_BIT(group, channel, task) \
((uint32_t [1][LEDC_CHANNEL_ETM_TASK_MAX]){{ \
[LEDC_CHANNEL_ETM_TASK_FADE_SCALE_UPDATE] = BIT(LEDC_TASK_DUTY_SCALE_UPDATE_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_SIG_OUT_DIS] = BIT(LEDC_TASK_SIG_OUT_DIS_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_OVF_CNT_RST] = BIT(LEDC_TASK_OVF_CNT_RST_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_FADE_RESTART] = BIT(LEDC_TASK_GAMMA_RESTART_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_FADE_PAUSE] = BIT(LEDC_TASK_GAMMA_PAUSE_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_FADE_RESUME] = BIT(LEDC_TASK_GAMMA_RESUME_CH0_EN_S), \
}}[(group)][(task)] << (channel))
// Channel events: ID, enable register and bit
#define LEDC_LL_ETM_CHANNEL_EVENT_ID(group, channel, event) \
((uint32_t [1][LEDC_CHANNEL_ETM_EVENT_MAX]){{ \
[LEDC_CHANNEL_ETM_EVENT_FADE_END] = LEDC_EVT_DUTY_CHNG_END_CH0, \
[LEDC_CHANNEL_ETM_EVENT_REACH_MAX_OVF_CNT] = LEDC_EVT_OVF_CNT_PLS_CH0, \
}}[(group)][(event)] + (channel))
#define LEDC_LL_ETM_CHANNEL_EVENT_EN_REG(group, event) \
((volatile uint32_t *[1][LEDC_CHANNEL_ETM_EVENT_MAX]){{ \
[LEDC_CHANNEL_ETM_EVENT_FADE_END] = (volatile uint32_t *)LEDC_EVT_TASK_EN0_REG, \
[LEDC_CHANNEL_ETM_EVENT_REACH_MAX_OVF_CNT] = (volatile uint32_t *)LEDC_EVT_TASK_EN0_REG, \
}}[(group)][(event)])
#define LEDC_LL_ETM_CHANNEL_EVENT_EN_BIT(group, channel, event) \
((uint32_t [1][LEDC_CHANNEL_ETM_EVENT_MAX]){{ \
[LEDC_CHANNEL_ETM_EVENT_FADE_END] = BIT(LEDC_EVT_DUTY_CHNG_END_CH0_EN_S), \
[LEDC_CHANNEL_ETM_EVENT_REACH_MAX_OVF_CNT] = BIT(LEDC_EVT_OVF_CNT_PLS_CH0_EN_S), \
}}[(group)][(event)] << (channel))
// Timer tasks: ID, enable register and bit
#define LEDC_LL_ETM_TIMER_TASK_ID(group, timer, task) \
((uint32_t [1][LEDC_TIMER_ETM_TASK_MAX]){{ \
[LEDC_TIMER_ETM_TASK_RST] = LEDC_TASK_TIMER0_RST, \
[LEDC_TIMER_ETM_TASK_RESUME] = LEDC_TASK_TIMER0_RESUME, \
[LEDC_TIMER_ETM_TASK_PAUSE] = LEDC_TASK_TIMER0_PAUSE, \
}}[(group)][(task)] + (timer))
#define LEDC_LL_ETM_TIMER_TASK_EN_REG(group, task) \
((volatile uint32_t *[1][LEDC_TIMER_ETM_TASK_MAX]){{ \
[LEDC_TIMER_ETM_TASK_RST] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
[LEDC_TIMER_ETM_TASK_RESUME] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
[LEDC_TIMER_ETM_TASK_PAUSE] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
}}[(group)][(task)])
#define LEDC_LL_ETM_TIMER_TASK_EN_BIT(group, timer, task) \
((uint32_t [1][LEDC_TIMER_ETM_TASK_MAX]){{ \
[LEDC_TIMER_ETM_TASK_RST] = BIT(LEDC_TASK_TIMER0_RST_EN_S), \
[LEDC_TIMER_ETM_TASK_RESUME] = BIT(LEDC_TASK_TIMER0_PAUSE_RESUME_EN_S), \
[LEDC_TIMER_ETM_TASK_PAUSE] = BIT(LEDC_TASK_TIMER0_PAUSE_RESUME_EN_S), \
}}[(group)][(task)] << (timer))
// Timer events: ID, enable register and bit
#define LEDC_LL_ETM_TIMER_EVENT_ID(group, timer, event) \
((uint32_t [1][LEDC_TIMER_ETM_EVENT_MAX]){{ \
[LEDC_TIMER_ETM_EVENT_OVF] = LEDC_EVT_TIME_OVF_TIMER0, \
}}[(group)][(event)] + (timer))
#define LEDC_LL_ETM_TIMER_EVENT_EN_REG(group, event) \
((volatile uint32_t *[1][LEDC_TIMER_ETM_EVENT_MAX]){{ \
[LEDC_TIMER_ETM_EVENT_OVF] = (volatile uint32_t *)LEDC_EVT_TASK_EN0_REG, \
}}[(group)][(event)])
#define LEDC_LL_ETM_TIMER_EVENT_EN_BIT(group, timer, event) \
((uint32_t [1][LEDC_TIMER_ETM_EVENT_MAX]){{ \
[LEDC_TIMER_ETM_EVENT_OVF] = BIT(LEDC_EVT_TIME_OVF_TIMER0_EN_S), \
}}[(group)][(event)] << (timer))
/**
* @brief Enable peripheral register clock
*
@@ -587,6 +679,71 @@ static inline void ledc_ll_get_channel_timer(ledc_dev_t *hw, ledc_mode_t speed_m
*timer_sel = (ledc_timer_t)(hw->channel_group[speed_mode].channel[channel_num].conf0.timer_sel);
}
/**
* @brief Enable or disable ETM event/task
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param reg_addr Register address to control the ETM event/task
* @param bit Bit position in the register
* @param enable Enable or disable the ETM event/task
*
* @return None
*/
static inline void ledc_ll_etm_enable_evt_task(ledc_dev_t *hw, ledc_mode_t speed_mode, volatile uint32_t *reg_addr, uint32_t bit, bool enable)
{
if (enable) {
REG_SET_BIT(reg_addr, bit);
} else {
REG_CLR_BIT(reg_addr, bit);
}
}
/**
* @brief Enable or disable the timer overflow counter for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-5), select from ledc_channel_t
* @param enable True to enable; false to disable
*
* @return None
*/
static inline void ledc_ll_channel_enable_timer_ovt_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel, bool enable)
{
hw->channel_group[speed_mode].channel[channel].conf0.ovf_cnt_en = enable;
}
/**
* @brief Set the maximum timer overflow count for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-5), select from ledc_channel_t
* @param max_ovf_cnt The maximum timer overflow count
*
* @return None
*/
static inline void ledc_ll_channel_set_maximum_timer_ovf_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t max_ovf_cnt)
{
HAL_ASSERT(max_ovf_cnt > 0 && max_ovf_cnt <= LEDC_LL_OVF_CNT_MAX);
hw->channel_group[speed_mode].channel[channel].conf0.ovf_num = max_ovf_cnt - 1;
}
/**
* @brief Reset the timer overflow counter for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-5), select from ledc_channel_t
*
* @return None
*/
static inline void ledc_ll_channel_reset_timer_ovf_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel)
{
hw->channel_group[speed_mode].channel[channel].conf0.ovf_cnt_reset = 1;
}
#ifdef __cplusplus
}
#endif
@@ -17,6 +17,7 @@
#include "hal/assert.h"
#include "esp_rom_sys.h" //for sync issue workaround
#include "soc/soc_caps.h"
#include "soc/soc_etm_source.h"
#ifdef __cplusplus
extern "C" {
@@ -24,14 +25,105 @@ extern "C" {
#define LEDC_LL_GET_HW() &LEDC
#define LEDC_LL_CHANNEL_SUPPORT_OVF_CNT 1
#define LEDC_LL_DUTY_NUM_MAX (LEDC_CH0_GAMMA_DUTY_NUM_V)
#define LEDC_LL_DUTY_CYCLE_MAX (LEDC_CH0_GAMMA_DUTY_CYCLE_V)
#define LEDC_LL_DUTY_SCALE_MAX (LEDC_CH0_GAMMA_SCALE_V)
#define LEDC_LL_HPOINT_VAL_MAX (LEDC_HPOINT_CH0_V)
#define LEDC_LL_OVF_CNT_MAX (LEDC_OVF_NUM_CH0_V + 1)
#define LEDC_LL_FRACTIONAL_BITS (8)
#define LEDC_LL_FRACTIONAL_MAX ((1 << LEDC_LL_FRACTIONAL_BITS) - 1)
#define LEDC_LL_GLOBAL_CLOCKS SOC_LEDC_CLKS
// Channel tasks: ID, enable register and bit
#define LEDC_LL_ETM_CHANNEL_TASK_ID(group, channel, task) \
((uint32_t [1][LEDC_CHANNEL_ETM_TASK_MAX]){{ \
[LEDC_CHANNEL_ETM_TASK_FADE_SCALE_UPDATE] = LEDC_TASK_DUTY_SCALE_UPDATE_CH0, \
[LEDC_CHANNEL_ETM_TASK_SIG_OUT_DIS] = LEDC_TASK_SIG_OUT_DIS_CH0, \
[LEDC_CHANNEL_ETM_TASK_OVF_CNT_RST] = LEDC_TASK_OVF_CNT_RST_CH0, \
[LEDC_CHANNEL_ETM_TASK_FADE_RESTART] = LEDC_TASK_GAMMA_RESTART_CH0, \
[LEDC_CHANNEL_ETM_TASK_FADE_PAUSE] = LEDC_TASK_GAMMA_PAUSE_CH0, \
[LEDC_CHANNEL_ETM_TASK_FADE_RESUME] = LEDC_TASK_GAMMA_RESUME_CH0, \
}}[(group)][(task)] + (channel))
#define LEDC_LL_ETM_CHANNEL_TASK_EN_REG(group, task) \
((volatile uint32_t *[1][LEDC_CHANNEL_ETM_TASK_MAX]){{ \
[LEDC_CHANNEL_ETM_TASK_FADE_SCALE_UPDATE] = (volatile uint32_t *)LEDC_EVT_TASK_EN0_REG, \
[LEDC_CHANNEL_ETM_TASK_SIG_OUT_DIS] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
[LEDC_CHANNEL_ETM_TASK_OVF_CNT_RST] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
[LEDC_CHANNEL_ETM_TASK_FADE_RESTART] = (volatile uint32_t *)LEDC_EVT_TASK_EN2_REG, \
[LEDC_CHANNEL_ETM_TASK_FADE_PAUSE] = (volatile uint32_t *)LEDC_EVT_TASK_EN2_REG, \
[LEDC_CHANNEL_ETM_TASK_FADE_RESUME] = (volatile uint32_t *)LEDC_EVT_TASK_EN2_REG, \
}}[(group)][(task)])
#define LEDC_LL_ETM_CHANNEL_TASK_EN_BIT(group, channel, task) \
((uint32_t [1][LEDC_CHANNEL_ETM_TASK_MAX]){{ \
[LEDC_CHANNEL_ETM_TASK_FADE_SCALE_UPDATE] = BIT(LEDC_TASK_DUTY_SCALE_UPDATE_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_SIG_OUT_DIS] = BIT(LEDC_TASK_SIG_OUT_DIS_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_OVF_CNT_RST] = BIT(LEDC_TASK_OVF_CNT_RST_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_FADE_RESTART] = BIT(LEDC_TASK_GAMMA_RESTART_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_FADE_PAUSE] = BIT(LEDC_TASK_GAMMA_PAUSE_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_FADE_RESUME] = BIT(LEDC_TASK_GAMMA_RESUME_CH0_EN_S), \
}}[(group)][(task)] << (channel))
// Channel events: ID, enable register and bit
#define LEDC_LL_ETM_CHANNEL_EVENT_ID(group, channel, event) \
((uint32_t [1][LEDC_CHANNEL_ETM_EVENT_MAX]){{ \
[LEDC_CHANNEL_ETM_EVENT_FADE_END] = LEDC_EVT_DUTY_CHNG_END_CH0, \
[LEDC_CHANNEL_ETM_EVENT_REACH_MAX_OVF_CNT] = LEDC_EVT_OVF_CNT_PLS_CH0, \
}}[(group)][(event)] + (channel))
#define LEDC_LL_ETM_CHANNEL_EVENT_EN_REG(group, event) \
((volatile uint32_t *[1][LEDC_CHANNEL_ETM_EVENT_MAX]){{ \
[LEDC_CHANNEL_ETM_EVENT_FADE_END] = (volatile uint32_t *)LEDC_EVT_TASK_EN0_REG, \
[LEDC_CHANNEL_ETM_EVENT_REACH_MAX_OVF_CNT] = (volatile uint32_t *)LEDC_EVT_TASK_EN0_REG, \
}}[(group)][(event)])
#define LEDC_LL_ETM_CHANNEL_EVENT_EN_BIT(group, channel, event) \
((uint32_t [1][LEDC_CHANNEL_ETM_EVENT_MAX]){{ \
[LEDC_CHANNEL_ETM_EVENT_FADE_END] = BIT(LEDC_EVT_DUTY_CHNG_END_CH0_EN_S), \
[LEDC_CHANNEL_ETM_EVENT_REACH_MAX_OVF_CNT] = BIT(LEDC_EVT_OVF_CNT_PLS_CH0_EN_S), \
}}[(group)][(event)] << (channel))
// Timer tasks: ID, enable register and bit
#define LEDC_LL_ETM_TIMER_TASK_ID(group, timer, task) \
((uint32_t [1][LEDC_TIMER_ETM_TASK_MAX]){{ \
[LEDC_TIMER_ETM_TASK_RST] = LEDC_TASK_TIMER0_RST, \
[LEDC_TIMER_ETM_TASK_RESUME] = LEDC_TASK_TIMER0_RESUME, \
[LEDC_TIMER_ETM_TASK_PAUSE] = LEDC_TASK_TIMER0_PAUSE, \
}}[(group)][(task)] + (timer))
#define LEDC_LL_ETM_TIMER_TASK_EN_REG(group, task) \
((volatile uint32_t *[1][LEDC_TIMER_ETM_TASK_MAX]){{ \
[LEDC_TIMER_ETM_TASK_RST] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
[LEDC_TIMER_ETM_TASK_RESUME] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
[LEDC_TIMER_ETM_TASK_PAUSE] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
}}[(group)][(task)])
#define LEDC_LL_ETM_TIMER_TASK_EN_BIT(group, timer, task) \
((uint32_t [1][LEDC_TIMER_ETM_TASK_MAX]){{ \
[LEDC_TIMER_ETM_TASK_RST] = BIT(LEDC_TASK_TIMER0_RST_EN_S), \
[LEDC_TIMER_ETM_TASK_RESUME] = BIT(LEDC_TASK_TIMER0_PAUSE_RESUME_EN_S), \
[LEDC_TIMER_ETM_TASK_PAUSE] = BIT(LEDC_TASK_TIMER0_PAUSE_RESUME_EN_S), \
}}[(group)][(task)] << (timer))
// Timer events: ID, enable register and bit
#define LEDC_LL_ETM_TIMER_EVENT_ID(group, timer, event) \
((uint32_t [1][LEDC_TIMER_ETM_EVENT_MAX]){{ \
[LEDC_TIMER_ETM_EVENT_OVF] = LEDC_EVT_TIME_OVF_TIMER0, \
}}[(group)][(event)] + (timer))
#define LEDC_LL_ETM_TIMER_EVENT_EN_REG(group, event) \
((volatile uint32_t *[1][LEDC_TIMER_ETM_EVENT_MAX]){{ \
[LEDC_TIMER_ETM_EVENT_OVF] = (volatile uint32_t *)LEDC_EVT_TASK_EN0_REG, \
}}[(group)][(event)])
#define LEDC_LL_ETM_TIMER_EVENT_EN_BIT(group, timer, event) \
((uint32_t [1][LEDC_TIMER_ETM_EVENT_MAX]){{ \
[LEDC_TIMER_ETM_EVENT_OVF] = BIT(LEDC_EVT_TIME_OVF_TIMER0_EN_S), \
}}[(group)][(event)] << (timer))
/**
* @brief Enable peripheral register clock
*
@@ -706,6 +798,69 @@ static inline void ledc_ll_get_channel_timer(ledc_dev_t *hw, ledc_mode_t speed_m
*timer_sel = (ledc_timer_t)(hw->channel_group[speed_mode].channel[channel_num].conf0.timer_sel);
}
/**
* @brief Enable or disable ETM event/task
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param reg_addr Register address to control the ETM event/task
* @param bit Bit position in the register
* @param enable Enable or disable the ETM event/task
*/
static inline void ledc_ll_etm_enable_evt_task(ledc_dev_t *hw, ledc_mode_t speed_mode, volatile uint32_t *reg_addr, uint32_t bit, bool enable)
{
if (enable) {
REG_SET_BIT(reg_addr, bit);
} else {
REG_CLR_BIT(reg_addr, bit);
}
}
/**
* @brief Enable or disable the timer overflow counter for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-5), select from ledc_channel_t
* @param enable True to enable; false to disable
*
* @return None
*/
static inline void ledc_ll_channel_enable_timer_ovt_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel, bool enable)
{
hw->channel_group[speed_mode].channel[channel].conf0.ovf_cnt_en = enable;
}
/**
* @brief Set the maximum timer overflow count for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-5), select from ledc_channel_t
* @param max_ovf_cnt The maximum timer overflow count
*
* @return None
*/
static inline void ledc_ll_channel_set_maximum_timer_ovf_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t max_ovf_cnt)
{
HAL_ASSERT(max_ovf_cnt > 0 && max_ovf_cnt <= LEDC_LL_OVF_CNT_MAX);
hw->channel_group[speed_mode].channel[channel].conf0.ovf_num = max_ovf_cnt - 1;
}
/**
* @brief Reset the timer overflow counter for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-5), select from ledc_channel_t
*
* @return None
*/
static inline void ledc_ll_channel_reset_timer_ovf_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel)
{
hw->channel_group[speed_mode].channel[channel].conf0.ovf_cnt_reset = 1;
}
#ifdef __cplusplus
}
#endif
@@ -17,6 +17,7 @@
#include "hal/assert.h"
#include "esp_rom_sys.h" //for sync issue workaround
#include "soc/soc_caps.h"
#include "soc/soc_etm_source.h"
#ifdef __cplusplus
extern "C" {
@@ -24,14 +25,105 @@ extern "C" {
#define LEDC_LL_GET_HW() &LEDC
#define LEDC_LL_CHANNEL_SUPPORT_OVF_CNT 1
#define LEDC_LL_DUTY_NUM_MAX (LEDC_CH0_GAMMA_DUTY_NUM_V)
#define LEDC_LL_DUTY_CYCLE_MAX (LEDC_CH0_GAMMA_DUTY_CYCLE_V)
#define LEDC_LL_DUTY_SCALE_MAX (LEDC_CH0_GAMMA_SCALE_V)
#define LEDC_LL_HPOINT_VAL_MAX (LEDC_HPOINT_CH0_V)
#define LEDC_LL_OVF_CNT_MAX (LEDC_OVF_NUM_CH0_V + 1)
#define LEDC_LL_FRACTIONAL_BITS (8)
#define LEDC_LL_FRACTIONAL_MAX ((1 << LEDC_LL_FRACTIONAL_BITS) - 1)
#define LEDC_LL_GLOBAL_CLOCKS SOC_LEDC_CLKS
// Channel tasks: ID, enable register and bit
#define LEDC_LL_ETM_CHANNEL_TASK_ID(group, channel, task) \
((uint32_t [1][LEDC_CHANNEL_ETM_TASK_MAX]){{ \
[LEDC_CHANNEL_ETM_TASK_FADE_SCALE_UPDATE] = LEDC_TASK_DUTY_SCALE_UPDATE_CH0, \
[LEDC_CHANNEL_ETM_TASK_SIG_OUT_DIS] = LEDC_TASK_SIG_OUT_DIS_CH0, \
[LEDC_CHANNEL_ETM_TASK_OVF_CNT_RST] = LEDC_TASK_OVF_CNT_RST_CH0, \
[LEDC_CHANNEL_ETM_TASK_FADE_RESTART] = LEDC_TASK_GAMMA_RESTART_CH0, \
[LEDC_CHANNEL_ETM_TASK_FADE_PAUSE] = LEDC_TASK_GAMMA_PAUSE_CH0, \
[LEDC_CHANNEL_ETM_TASK_FADE_RESUME] = LEDC_TASK_GAMMA_RESUME_CH0, \
}}[(group)][(task)] + (channel))
#define LEDC_LL_ETM_CHANNEL_TASK_EN_REG(group, task) \
((volatile uint32_t *[1][LEDC_CHANNEL_ETM_TASK_MAX]){{ \
[LEDC_CHANNEL_ETM_TASK_FADE_SCALE_UPDATE] = (volatile uint32_t *)LEDC_EVT_TASK_EN0_REG, \
[LEDC_CHANNEL_ETM_TASK_SIG_OUT_DIS] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
[LEDC_CHANNEL_ETM_TASK_OVF_CNT_RST] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
[LEDC_CHANNEL_ETM_TASK_FADE_RESTART] = (volatile uint32_t *)LEDC_EVT_TASK_EN2_REG, \
[LEDC_CHANNEL_ETM_TASK_FADE_PAUSE] = (volatile uint32_t *)LEDC_EVT_TASK_EN2_REG, \
[LEDC_CHANNEL_ETM_TASK_FADE_RESUME] = (volatile uint32_t *)LEDC_EVT_TASK_EN2_REG, \
}}[(group)][(task)])
#define LEDC_LL_ETM_CHANNEL_TASK_EN_BIT(group, channel, task) \
((uint32_t [1][LEDC_CHANNEL_ETM_TASK_MAX]){{ \
[LEDC_CHANNEL_ETM_TASK_FADE_SCALE_UPDATE] = BIT(LEDC_TASK_DUTY_SCALE_UPDATE_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_SIG_OUT_DIS] = BIT(LEDC_TASK_SIG_OUT_DIS_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_OVF_CNT_RST] = BIT(LEDC_TASK_OVF_CNT_RST_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_FADE_RESTART] = BIT(LEDC_TASK_GAMMA_RESTART_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_FADE_PAUSE] = BIT(LEDC_TASK_GAMMA_PAUSE_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_FADE_RESUME] = BIT(LEDC_TASK_GAMMA_RESUME_CH0_EN_S), \
}}[(group)][(task)] << (channel))
// Channel events: ID, enable register and bit
#define LEDC_LL_ETM_CHANNEL_EVENT_ID(group, channel, event) \
((uint32_t [1][LEDC_CHANNEL_ETM_EVENT_MAX]){{ \
[LEDC_CHANNEL_ETM_EVENT_FADE_END] = LEDC_EVT_DUTY_CHNG_END_CH0, \
[LEDC_CHANNEL_ETM_EVENT_REACH_MAX_OVF_CNT] = LEDC_EVT_OVF_CNT_PLS_CH0, \
}}[(group)][(event)] + (channel))
#define LEDC_LL_ETM_CHANNEL_EVENT_EN_REG(group, event) \
((volatile uint32_t *[1][LEDC_CHANNEL_ETM_EVENT_MAX]){{ \
[LEDC_CHANNEL_ETM_EVENT_FADE_END] = (volatile uint32_t *)LEDC_EVT_TASK_EN0_REG, \
[LEDC_CHANNEL_ETM_EVENT_REACH_MAX_OVF_CNT] = (volatile uint32_t *)LEDC_EVT_TASK_EN0_REG, \
}}[(group)][(event)])
#define LEDC_LL_ETM_CHANNEL_EVENT_EN_BIT(group, channel, event) \
((uint32_t [1][LEDC_CHANNEL_ETM_EVENT_MAX]){{ \
[LEDC_CHANNEL_ETM_EVENT_FADE_END] = BIT(LEDC_EVT_DUTY_CHNG_END_CH0_EN_S), \
[LEDC_CHANNEL_ETM_EVENT_REACH_MAX_OVF_CNT] = BIT(LEDC_EVT_OVF_CNT_PLS_CH0_EN_S), \
}}[(group)][(event)] << (channel))
// Timer tasks: ID, enable register and bit
#define LEDC_LL_ETM_TIMER_TASK_ID(group, timer, task) \
((uint32_t [1][LEDC_TIMER_ETM_TASK_MAX]){{ \
[LEDC_TIMER_ETM_TASK_RST] = LEDC_TASK_TIMER0_RST, \
[LEDC_TIMER_ETM_TASK_RESUME] = LEDC_TASK_TIMER0_RESUME, \
[LEDC_TIMER_ETM_TASK_PAUSE] = LEDC_TASK_TIMER0_PAUSE, \
}}[(group)][(task)] + (timer))
#define LEDC_LL_ETM_TIMER_TASK_EN_REG(group, task) \
((volatile uint32_t *[1][LEDC_TIMER_ETM_TASK_MAX]){{ \
[LEDC_TIMER_ETM_TASK_RST] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
[LEDC_TIMER_ETM_TASK_RESUME] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
[LEDC_TIMER_ETM_TASK_PAUSE] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
}}[(group)][(task)])
#define LEDC_LL_ETM_TIMER_TASK_EN_BIT(group, timer, task) \
((uint32_t [1][LEDC_TIMER_ETM_TASK_MAX]){{ \
[LEDC_TIMER_ETM_TASK_RST] = BIT(LEDC_TASK_TIMER0_RST_EN_S), \
[LEDC_TIMER_ETM_TASK_RESUME] = BIT(LEDC_TASK_TIMER0_PAUSE_RESUME_EN_S), \
[LEDC_TIMER_ETM_TASK_PAUSE] = BIT(LEDC_TASK_TIMER0_PAUSE_RESUME_EN_S), \
}}[(group)][(task)] << (timer))
// Timer events: ID, enable register and bit
#define LEDC_LL_ETM_TIMER_EVENT_ID(group, timer, event) \
((uint32_t [1][LEDC_TIMER_ETM_EVENT_MAX]){{ \
[LEDC_TIMER_ETM_EVENT_OVF] = LEDC_EVT_TIME_OVF_TIMER0, \
}}[(group)][(event)] + (timer))
#define LEDC_LL_ETM_TIMER_EVENT_EN_REG(group, event) \
((volatile uint32_t *[1][LEDC_TIMER_ETM_EVENT_MAX]){{ \
[LEDC_TIMER_ETM_EVENT_OVF] = (volatile uint32_t *)LEDC_EVT_TASK_EN0_REG, \
}}[(group)][(event)])
#define LEDC_LL_ETM_TIMER_EVENT_EN_BIT(group, timer, event) \
((uint32_t [1][LEDC_TIMER_ETM_EVENT_MAX]){{ \
[LEDC_TIMER_ETM_EVENT_OVF] = BIT(LEDC_EVT_TIME_OVF_TIMER0_EN_S), \
}}[(group)][(event)] << (timer))
/**
* @brief Enable peripheral register clock
*
@@ -705,6 +797,71 @@ static inline void ledc_ll_get_channel_timer(ledc_dev_t *hw, ledc_mode_t speed_m
*timer_sel = (ledc_timer_t)(hw->channel_group[speed_mode].channel[channel_num].conf0.timer_sel);
}
/**
* @brief Enable or disable ETM event/task
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param reg_addr Register address to control the ETM event/task
* @param bit Bit position in the register
* @param enable Enable or disable the ETM event/task
*
* @return None
*/
static inline void ledc_ll_etm_enable_evt_task(ledc_dev_t *hw, ledc_mode_t speed_mode, volatile uint32_t *reg_addr, uint32_t bit, bool enable)
{
if (enable) {
REG_SET_BIT(reg_addr, bit);
} else {
REG_CLR_BIT(reg_addr, bit);
}
}
/**
* @brief Enable or disable the timer overflow counter for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-5), select from ledc_channel_t
* @param enable True to enable; false to disable
*
* @return None
*/
static inline void ledc_ll_channel_enable_timer_ovt_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel, bool enable)
{
hw->channel_group[speed_mode].channel[channel].conf0.ovf_cnt_en = enable;
}
/**
* @brief Set the maximum timer overflow count for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-5), select from ledc_channel_t
* @param max_ovf_cnt The maximum timer overflow count
*
* @return None
*/
static inline void ledc_ll_channel_set_maximum_timer_ovf_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t max_ovf_cnt)
{
HAL_ASSERT(max_ovf_cnt > 0 && max_ovf_cnt <= LEDC_LL_OVF_CNT_MAX);
hw->channel_group[speed_mode].channel[channel].conf0.ovf_num = max_ovf_cnt - 1;
}
/**
* @brief Reset the timer overflow counter for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-5), select from ledc_channel_t
*
* @return None
*/
static inline void ledc_ll_channel_reset_timer_ovf_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel)
{
hw->channel_group[speed_mode].channel[channel].conf0.ovf_cnt_reset = 1;
}
#ifdef __cplusplus
}
#endif
@@ -16,6 +16,7 @@
#include "soc/clk_tree_defs.h"
#include "soc/pcr_struct.h"
#include "soc/soc_caps.h"
#include "soc/soc_etm_source.h"
#ifdef __cplusplus
extern "C" {
@@ -23,14 +24,105 @@ extern "C" {
#define LEDC_LL_GET_HW() &LEDC
#define LEDC_LL_CHANNEL_SUPPORT_OVF_CNT 1
#define LEDC_LL_DUTY_NUM_MAX (LEDC_CH0_FADE_PARAM_DUTY_NUM_V)
#define LEDC_LL_DUTY_CYCLE_MAX (LEDC_CH0_FADE_PARAM_DUTY_CYCLE_V)
#define LEDC_LL_DUTY_SCALE_MAX (LEDC_CH0_FADE_PARAM_SCALE_V)
#define LEDC_LL_HPOINT_VAL_MAX (LEDC_HPOINT_CH0_V)
#define LEDC_LL_OVF_CNT_MAX (LEDC_OVF_NUM_CH0_V + 1)
#define LEDC_LL_FRACTIONAL_BITS (8)
#define LEDC_LL_FRACTIONAL_MAX ((1 << LEDC_LL_FRACTIONAL_BITS) - 1)
#define LEDC_LL_GLOBAL_CLOCKS SOC_LEDC_CLKS
// Channel tasks: ID, enable register and bit
#define LEDC_LL_ETM_CHANNEL_TASK_ID(group, channel, task) \
((uint32_t [1][LEDC_CHANNEL_ETM_TASK_MAX]){{ \
[LEDC_CHANNEL_ETM_TASK_FADE_SCALE_UPDATE] = LEDC_TASK_DUTY_SCALE_UPDATE_CH0, \
[LEDC_CHANNEL_ETM_TASK_SIG_OUT_DIS] = LEDC_TASK_SIG_OUT_DIS_CH0, \
[LEDC_CHANNEL_ETM_TASK_OVF_CNT_RST] = LEDC_TASK_OVF_CNT_RST_CH0, \
[LEDC_CHANNEL_ETM_TASK_FADE_RESTART] = LEDC_TASK_FADE_RESTART_CH0, \
[LEDC_CHANNEL_ETM_TASK_FADE_PAUSE] = LEDC_TASK_FADE_PAUSE_CH0, \
[LEDC_CHANNEL_ETM_TASK_FADE_RESUME] = LEDC_TASK_FADE_RESUME_CH0, \
}}[(group)][(task)] + (channel))
#define LEDC_LL_ETM_CHANNEL_TASK_EN_REG(group, task) \
((volatile uint32_t *[1][LEDC_CHANNEL_ETM_TASK_MAX]){{ \
[LEDC_CHANNEL_ETM_TASK_FADE_SCALE_UPDATE] = (volatile uint32_t *)LEDC_EVT_TASK_EN0_REG, \
[LEDC_CHANNEL_ETM_TASK_SIG_OUT_DIS] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
[LEDC_CHANNEL_ETM_TASK_OVF_CNT_RST] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
[LEDC_CHANNEL_ETM_TASK_FADE_RESTART] = (volatile uint32_t *)LEDC_EVT_TASK_EN2_REG, \
[LEDC_CHANNEL_ETM_TASK_FADE_PAUSE] = (volatile uint32_t *)LEDC_EVT_TASK_EN2_REG, \
[LEDC_CHANNEL_ETM_TASK_FADE_RESUME] = (volatile uint32_t *)LEDC_EVT_TASK_EN2_REG, \
}}[(group)][(task)])
#define LEDC_LL_ETM_CHANNEL_TASK_EN_BIT(group, channel, task) \
((uint32_t [1][LEDC_CHANNEL_ETM_TASK_MAX]){{ \
[LEDC_CHANNEL_ETM_TASK_FADE_SCALE_UPDATE] = BIT(LEDC_TASK_DUTY_SCALE_UPDATE_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_SIG_OUT_DIS] = BIT(LEDC_TASK_SIG_OUT_DIS_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_OVF_CNT_RST] = BIT(LEDC_TASK_OVF_CNT_RST_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_FADE_RESTART] = BIT(LEDC_TASK_FADE_RESTART_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_FADE_PAUSE] = BIT(LEDC_TASK_FADE_PAUSE_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_FADE_RESUME] = BIT(LEDC_TASK_FADE_RESUME_CH0_EN_S), \
}}[(group)][(task)] << (channel))
// Channel events: ID, enable register and bit
#define LEDC_LL_ETM_CHANNEL_EVENT_ID(group, channel, event) \
((uint32_t [1][LEDC_CHANNEL_ETM_EVENT_MAX]){{ \
[LEDC_CHANNEL_ETM_EVENT_FADE_END] = LEDC_EVT_DUTY_CHNG_END_CH0, \
[LEDC_CHANNEL_ETM_EVENT_REACH_MAX_OVF_CNT] = LEDC_EVT_OVF_CNT_PLS_CH0, \
}}[(group)][(event)] + (channel))
#define LEDC_LL_ETM_CHANNEL_EVENT_EN_REG(group, event) \
((volatile uint32_t *[1][LEDC_CHANNEL_ETM_EVENT_MAX]){{ \
[LEDC_CHANNEL_ETM_EVENT_FADE_END] = (volatile uint32_t *)LEDC_EVT_TASK_EN0_REG, \
[LEDC_CHANNEL_ETM_EVENT_REACH_MAX_OVF_CNT] = (volatile uint32_t *)LEDC_EVT_TASK_EN0_REG, \
}}[(group)][(event)])
#define LEDC_LL_ETM_CHANNEL_EVENT_EN_BIT(group, channel, event) \
((uint32_t [1][LEDC_CHANNEL_ETM_EVENT_MAX]){{ \
[LEDC_CHANNEL_ETM_EVENT_FADE_END] = BIT(LEDC_EVT_DUTY_CHNG_END_CH0_EN_S), \
[LEDC_CHANNEL_ETM_EVENT_REACH_MAX_OVF_CNT] = BIT(LEDC_EVT_OVF_CNT_PLS_CH0_EN_S), \
}}[(group)][(event)] << (channel))
// Timer tasks: ID, enable register and bit
#define LEDC_LL_ETM_TIMER_TASK_ID(group, timer, task) \
((uint32_t [1][LEDC_TIMER_ETM_TASK_MAX]){{ \
[LEDC_TIMER_ETM_TASK_RST] = LEDC_TASK_TIMER0_RST, \
[LEDC_TIMER_ETM_TASK_RESUME] = LEDC_TASK_TIMER0_RESUME, \
[LEDC_TIMER_ETM_TASK_PAUSE] = LEDC_TASK_TIMER0_PAUSE, \
}}[(group)][(task)] + (timer))
#define LEDC_LL_ETM_TIMER_TASK_EN_REG(group, task) \
((volatile uint32_t *[1][LEDC_TIMER_ETM_TASK_MAX]){{ \
[LEDC_TIMER_ETM_TASK_RST] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
[LEDC_TIMER_ETM_TASK_RESUME] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
[LEDC_TIMER_ETM_TASK_PAUSE] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
}}[(group)][(task)])
#define LEDC_LL_ETM_TIMER_TASK_EN_BIT(group, timer, task) \
((uint32_t [1][LEDC_TIMER_ETM_TASK_MAX]){{ \
[LEDC_TIMER_ETM_TASK_RST] = BIT(LEDC_TASK_TIMER0_RST_EN_S), \
[LEDC_TIMER_ETM_TASK_RESUME] = BIT(LEDC_TASK_TIMER0_PAUSE_RESUME_EN_S), \
[LEDC_TIMER_ETM_TASK_PAUSE] = BIT(LEDC_TASK_TIMER0_PAUSE_RESUME_EN_S), \
}}[(group)][(task)] << (timer))
// Timer events: ID, enable register and bit
#define LEDC_LL_ETM_TIMER_EVENT_ID(group, timer, event) \
((uint32_t [1][LEDC_TIMER_ETM_EVENT_MAX]){{ \
[LEDC_TIMER_ETM_EVENT_OVF] = LEDC_EVT_TIME_OVF_TIMER0, \
}}[(group)][(event)] + (timer))
#define LEDC_LL_ETM_TIMER_EVENT_EN_REG(group, event) \
((volatile uint32_t *[1][LEDC_TIMER_ETM_EVENT_MAX]){{ \
[LEDC_TIMER_ETM_EVENT_OVF] = (volatile uint32_t *)LEDC_EVT_TASK_EN0_REG, \
}}[(group)][(event)])
#define LEDC_LL_ETM_TIMER_EVENT_EN_BIT(group, timer, event) \
((uint32_t [1][LEDC_TIMER_ETM_EVENT_MAX]){{ \
[LEDC_TIMER_ETM_EVENT_OVF] = BIT(LEDC_EVT_TIME_OVF_TIMER0_EN_S), \
}}[(group)][(event)] << (timer))
/**
* @brief Enable peripheral register clock
*
@@ -534,6 +626,71 @@ static inline void ledc_ll_get_channel_timer(ledc_dev_t *hw, ledc_mode_t speed_m
*timer_sel = (ledc_timer_t)(hw->channel_group[speed_mode].channel[channel_num].conf0.timer_sel);
}
/**
* @brief Enable or disable ETM event/task
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param reg_addr Register address to control the ETM event/task
* @param bit Bit position in the register
* @param enable Enable or disable the ETM event/task
*
* @return None
*/
static inline void ledc_ll_etm_enable_evt_task(ledc_dev_t *hw, ledc_mode_t speed_mode, volatile uint32_t *reg_addr, uint32_t bit, bool enable)
{
if (enable) {
REG_SET_BIT(reg_addr, bit);
} else {
REG_CLR_BIT(reg_addr, bit);
}
}
/**
* @brief Enable or disable the timer overflow counter for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-5), select from ledc_channel_t
* @param enable True to enable; false to disable
*
* @return None
*/
static inline void ledc_ll_channel_enable_timer_ovt_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel, bool enable)
{
hw->channel_group[speed_mode].channel[channel].conf0.ovf_cnt_en = enable;
}
/**
* @brief Set the maximum timer overflow count for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-5), select from ledc_channel_t
* @param max_ovf_cnt The maximum timer overflow count
*
* @return None
*/
static inline void ledc_ll_channel_set_maximum_timer_ovf_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t max_ovf_cnt)
{
HAL_ASSERT(max_ovf_cnt > 0 && max_ovf_cnt <= LEDC_LL_OVF_CNT_MAX);
hw->channel_group[speed_mode].channel[channel].conf0.ovf_num = max_ovf_cnt - 1;
}
/**
* @brief Reset the timer overflow counter for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-5), select from ledc_channel_t
*
* @return None
*/
static inline void ledc_ll_channel_reset_timer_ovf_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel)
{
hw->channel_group[speed_mode].channel[channel].conf0.ovf_cnt_reset = 1;
}
#ifdef __cplusplus
}
#endif
+172 -17
View File
@@ -16,6 +16,7 @@
#include "soc/clk_tree_defs.h"
#include "soc/hp_sys_clkrst_struct.h"
#include "soc/soc_caps.h"
#include "soc/soc_etm_source.h"
#ifdef __cplusplus
extern "C" {
@@ -23,14 +24,105 @@ extern "C" {
#define LEDC_LL_GET_HW() &LEDC
#define LEDC_LL_CHANNEL_SUPPORT_OVF_CNT 1
#define LEDC_LL_DUTY_NUM_MAX (LEDC_CH0_GAMMA_RANGE0_DUTY_NUM_V)
#define LEDC_LL_DUTY_CYCLE_MAX (LEDC_CH0_GAMMA_RANGE0_DUTY_CYCLE_V)
#define LEDC_LL_DUTY_SCALE_MAX (LEDC_CH0_GAMMA_RANGE0_SCALE_V)
#define LEDC_LL_HPOINT_VAL_MAX (LEDC_HPOINT_CH0_V)
#define LEDC_LL_OVF_CNT_MAX (LEDC_OVF_NUM_CH0_V + 1)
#define LEDC_LL_FRACTIONAL_BITS (8)
#define LEDC_LL_FRACTIONAL_MAX ((1 << LEDC_LL_FRACTIONAL_BITS) - 1)
#define LEDC_LL_GLOBAL_CLOCKS SOC_LEDC_CLKS
// Channel tasks: ID, enable register and bit
#define LEDC_LL_ETM_CHANNEL_TASK_ID(group, channel, task) \
((uint32_t [1][LEDC_CHANNEL_ETM_TASK_MAX]){{ \
[LEDC_CHANNEL_ETM_TASK_FADE_SCALE_UPDATE] = LEDC_TASK_DUTY_SCALE_UPDATE_CH0, \
[LEDC_CHANNEL_ETM_TASK_SIG_OUT_DIS] = LEDC_TASK_SIG_OUT_DIS_CH0, \
[LEDC_CHANNEL_ETM_TASK_OVF_CNT_RST] = LEDC_TASK_OVF_CNT_RST_CH0, \
[LEDC_CHANNEL_ETM_TASK_FADE_RESTART] = LEDC_TASK_GAMMA_RESTART_CH0, \
[LEDC_CHANNEL_ETM_TASK_FADE_PAUSE] = LEDC_TASK_GAMMA_PAUSE_CH0, \
[LEDC_CHANNEL_ETM_TASK_FADE_RESUME] = LEDC_TASK_GAMMA_RESUME_CH0, \
}}[(group)][(task)] + (channel))
#define LEDC_LL_ETM_CHANNEL_TASK_EN_REG(group, task) \
((volatile uint32_t *[1][LEDC_CHANNEL_ETM_TASK_MAX]){{ \
[LEDC_CHANNEL_ETM_TASK_FADE_SCALE_UPDATE] = (volatile uint32_t *)LEDC_EVT_TASK_EN0_REG, \
[LEDC_CHANNEL_ETM_TASK_SIG_OUT_DIS] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
[LEDC_CHANNEL_ETM_TASK_OVF_CNT_RST] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
[LEDC_CHANNEL_ETM_TASK_FADE_RESTART] = (volatile uint32_t *)LEDC_EVT_TASK_EN2_REG, \
[LEDC_CHANNEL_ETM_TASK_FADE_PAUSE] = (volatile uint32_t *)LEDC_EVT_TASK_EN2_REG, \
[LEDC_CHANNEL_ETM_TASK_FADE_RESUME] = (volatile uint32_t *)LEDC_EVT_TASK_EN2_REG, \
}}[(group)][(task)])
#define LEDC_LL_ETM_CHANNEL_TASK_EN_BIT(group, channel, task) \
((uint32_t [1][LEDC_CHANNEL_ETM_TASK_MAX]){{ \
[LEDC_CHANNEL_ETM_TASK_FADE_SCALE_UPDATE] = BIT(LEDC_TASK_DUTY_SCALE_UPDATE_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_SIG_OUT_DIS] = BIT(LEDC_TASK_SIG_OUT_DIS_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_OVF_CNT_RST] = BIT(LEDC_TASK_OVF_CNT_RST_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_FADE_RESTART] = BIT(LEDC_TASK_GAMMA_RESTART_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_FADE_PAUSE] = BIT(LEDC_TASK_GAMMA_PAUSE_CH0_EN_S), \
[LEDC_CHANNEL_ETM_TASK_FADE_RESUME] = BIT(LEDC_TASK_GAMMA_RESUME_CH0_EN_S), \
}}[(group)][(task)] << (channel))
// Channel events: ID, enable register and bit
#define LEDC_LL_ETM_CHANNEL_EVENT_ID(group, channel, event) \
((uint32_t [1][LEDC_CHANNEL_ETM_EVENT_MAX]){{ \
[LEDC_CHANNEL_ETM_EVENT_FADE_END] = LEDC_EVT_DUTY_CHNG_END_CH0, \
[LEDC_CHANNEL_ETM_EVENT_REACH_MAX_OVF_CNT] = LEDC_EVT_OVF_CNT_PLS_CH0, \
}}[(group)][(event)] + (channel))
#define LEDC_LL_ETM_CHANNEL_EVENT_EN_REG(group, event) \
((volatile uint32_t *[1][LEDC_CHANNEL_ETM_EVENT_MAX]){{ \
[LEDC_CHANNEL_ETM_EVENT_FADE_END] = (volatile uint32_t *)LEDC_EVT_TASK_EN0_REG, \
[LEDC_CHANNEL_ETM_EVENT_REACH_MAX_OVF_CNT] = (volatile uint32_t *)LEDC_EVT_TASK_EN0_REG, \
}}[(group)][(event)])
#define LEDC_LL_ETM_CHANNEL_EVENT_EN_BIT(group, channel, event) \
((uint32_t [1][LEDC_CHANNEL_ETM_EVENT_MAX]){{ \
[LEDC_CHANNEL_ETM_EVENT_FADE_END] = BIT(LEDC_EVT_DUTY_CHNG_END_CH0_EN_S), \
[LEDC_CHANNEL_ETM_EVENT_REACH_MAX_OVF_CNT] = BIT(LEDC_EVT_OVF_CNT_PLS_CH0_EN_S), \
}}[(group)][(event)] << (channel))
// Timer tasks: ID, enable register and bit
#define LEDC_LL_ETM_TIMER_TASK_ID(group, timer, task) \
((uint32_t [1][LEDC_TIMER_ETM_TASK_MAX]){{ \
[LEDC_TIMER_ETM_TASK_RST] = LEDC_TASK_TIMER0_RST, \
[LEDC_TIMER_ETM_TASK_RESUME] = LEDC_TASK_TIMER0_RESUME, \
[LEDC_TIMER_ETM_TASK_PAUSE] = LEDC_TASK_TIMER0_PAUSE, \
}}[(group)][(task)] + (timer))
#define LEDC_LL_ETM_TIMER_TASK_EN_REG(group, task) \
((volatile uint32_t *[1][LEDC_TIMER_ETM_TASK_MAX]){{ \
[LEDC_TIMER_ETM_TASK_RST] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
[LEDC_TIMER_ETM_TASK_RESUME] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
[LEDC_TIMER_ETM_TASK_PAUSE] = (volatile uint32_t *)LEDC_EVT_TASK_EN1_REG, \
}}[(group)][(task)])
#define LEDC_LL_ETM_TIMER_TASK_EN_BIT(group, timer, task) \
((uint32_t [1][LEDC_TIMER_ETM_TASK_MAX]){{ \
[LEDC_TIMER_ETM_TASK_RST] = BIT(LEDC_TASK_TIMER0_RST_EN_S), \
[LEDC_TIMER_ETM_TASK_RESUME] = BIT(LEDC_TASK_TIMER0_PAUSE_RESUME_EN_S), \
[LEDC_TIMER_ETM_TASK_PAUSE] = BIT(LEDC_TASK_TIMER0_PAUSE_RESUME_EN_S), \
}}[(group)][(task)] << (timer))
// Timer events: ID, enable register and bit
#define LEDC_LL_ETM_TIMER_EVENT_ID(group, timer, event) \
((uint32_t [1][LEDC_TIMER_ETM_EVENT_MAX]){{ \
[LEDC_TIMER_ETM_EVENT_OVF] = LEDC_EVT_TIME_OVF_TIMER0, \
}}[(group)][(event)] + (timer))
#define LEDC_LL_ETM_TIMER_EVENT_EN_REG(group, event) \
((volatile uint32_t *[1][LEDC_TIMER_ETM_EVENT_MAX]){{ \
[LEDC_TIMER_ETM_EVENT_OVF] = (volatile uint32_t *)LEDC_EVT_TASK_EN0_REG, \
}}[(group)][(event)])
#define LEDC_LL_ETM_TIMER_EVENT_EN_BIT(group, timer, event) \
((uint32_t [1][LEDC_TIMER_ETM_EVENT_MAX]){{ \
[LEDC_TIMER_ETM_EVENT_OVF] = BIT(LEDC_EVT_TIME_OVF_TIMER0_EN_S), \
}}[(group)][(event)] << (timer))
/**
* @brief Enable peripheral register clock
*
@@ -336,7 +428,7 @@ static inline void ledc_ll_get_max_duty(ledc_dev_t *hw, ledc_mode_t speed_mode,
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel_num LEDC channel index (0-5), select from ledc_channel_t
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
*
* @return None
*/
@@ -350,7 +442,7 @@ static inline void ledc_ll_ls_channel_update(ledc_dev_t *hw, ledc_mode_t speed_m
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel_num LEDC channel index (0-5), select from ledc_channel_t
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
* @param hpoint_val LEDC hpoint value(max: 0xfffff)
*
* @return None
@@ -365,7 +457,7 @@ static inline void ledc_ll_set_hpoint(ledc_dev_t *hw, ledc_mode_t speed_mode, le
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel_num LEDC channel index (0-5), select from ledc_channel_t
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
* @param hpoint_val Pointer to accept the LEDC hpoint value(max: 0xfffff)
*
* @return None
@@ -380,7 +472,7 @@ static inline void ledc_ll_get_hpoint(ledc_dev_t *hw, ledc_mode_t speed_mode, le
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel_num LEDC channel index (0-5), select from ledc_channel_t
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
* @param duty_val LEDC duty value, the range of duty setting is [0, (2**duty_resolution)]
*
* @return None
@@ -395,7 +487,7 @@ static inline void ledc_ll_set_duty_int_part(ledc_dev_t *hw, ledc_mode_t speed_m
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel_num LEDC channel index (0-5), select from ledc_channel_t
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
* @param duty_val Pointer to accept the LEDC duty value
*
* @return None
@@ -410,7 +502,7 @@ static inline void ledc_ll_get_duty(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel_num LEDC channel index (0-5), select from ledc_channel_t
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
* @param range Gamma fade range index, 0 ~ SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX
* @param dir LEDC duty change direction, increase or decrease
* @param cycle The duty cycles
@@ -436,7 +528,7 @@ static inline void ledc_ll_set_fade_param_range(ledc_dev_t *hw, ledc_mode_t spee
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel_num LEDC channel index (0-5), select from ledc_channel_t
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
* @param range_num Total number of ranges (1 - SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX) of the fading configured
*
* @return None
@@ -451,7 +543,7 @@ static inline void ledc_ll_set_range_number(ledc_dev_t *hw, ledc_mode_t speed_mo
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel_num LEDC channel index (0-5), select from ledc_channel_t
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
* @param range_num Pointer to accept fade range number
*
* @return None
@@ -466,7 +558,7 @@ static inline void ledc_ll_get_range_number(ledc_dev_t *hw, ledc_mode_t speed_mo
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel_num LEDC channel index (0-5), select from ledc_channel_t
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
* @param range Gamma fade range index to get, 0 ~ SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX
* @param dir Pointer to accept fade direction value
* @param cycle Pointer to accept fade cycle value
@@ -492,7 +584,7 @@ static inline void ledc_ll_get_fade_param_range(ledc_dev_t *hw, ledc_mode_t spee
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel_num LEDC channel index (0-5), select from ledc_channel_t
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
* @param sig_out_en The output enable status
*
* @return None
@@ -508,7 +600,7 @@ static inline void ledc_ll_set_sig_out_en(ledc_dev_t *hw, ledc_mode_t speed_mode
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel_num LEDC channel index (0-5), select from ledc_channel_t
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
*
* @return None
*/
@@ -522,7 +614,7 @@ static inline void ledc_ll_set_duty_start(ledc_dev_t *hw, ledc_mode_t speed_mode
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel_num LEDC channel index (0-5), select from ledc_channel_t
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
* @param idle_level The output idle level
*
* @return None
@@ -538,7 +630,7 @@ static inline void ledc_ll_set_idle_level(ledc_dev_t *hw, ledc_mode_t speed_mode
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel_num LEDC channel index (0-5), select from ledc_channel_t
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
* @param fade_end_intr_en The fade end interrupt enable status
*
* @return None
@@ -555,7 +647,7 @@ static inline void ledc_ll_set_fade_end_intr(ledc_dev_t *hw, ledc_mode_t speed_m
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel_num LEDC channel index (0-5), select from ledc_channel_t
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
* @param intr_status The fade end interrupt status
*
* @return None
@@ -572,7 +664,7 @@ static inline void ledc_ll_get_fade_end_intr_status(ledc_dev_t *hw, ledc_mode_t
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel_num LEDC channel index (0-5), select from ledc_channel_t
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
*
* @return None
*/
@@ -587,7 +679,7 @@ static inline void ledc_ll_clear_fade_end_intr_status(ledc_dev_t *hw, ledc_mode_
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel_num LEDC channel index (0-5), select from ledc_channel_t
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
* @param timer_sel LEDC timer index (0-3), select from ledc_timer_t
*
* @return None
@@ -602,7 +694,7 @@ static inline void ledc_ll_bind_channel_timer(ledc_dev_t *hw, ledc_mode_t speed_
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel_num LEDC channel index (0-5), select from ledc_channel_t
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
* @param timer_sel Pointer to accept the LEDC timer index
*
* @return None
@@ -612,6 +704,69 @@ static inline void ledc_ll_get_channel_timer(ledc_dev_t *hw, ledc_mode_t speed_m
*timer_sel = (ledc_timer_t)(hw->channel_group[speed_mode].channel[channel_num].conf0.timer_sel);
}
/**
* @brief Enable or disable ETM event/task
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param reg_addr Register address to control the ETM event/task
* @param bit Bit position in the register
* @param enable Enable or disable the ETM event/task
*/
static inline void ledc_ll_etm_enable_evt_task(ledc_dev_t *hw, ledc_mode_t speed_mode, volatile uint32_t *reg_addr, uint32_t bit, bool enable)
{
if (enable) {
REG_SET_BIT(reg_addr, bit);
} else {
REG_CLR_BIT(reg_addr, bit);
}
}
/**
* @brief Enable or disable the timer overflow counter for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-7), select from ledc_channel_t
* @param enable True to enable; false to disable
*
* @return None
*/
static inline void ledc_ll_channel_enable_timer_ovt_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel, bool enable)
{
hw->channel_group[speed_mode].channel[channel].conf0.ovf_cnt_en = enable;
}
/**
* @brief Set the maximum timer overflow count for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-7), select from ledc_channel_t
* @param max_ovf_cnt The maximum timer overflow count
*
* @return None
*/
static inline void ledc_ll_channel_set_maximum_timer_ovf_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t max_ovf_cnt)
{
HAL_ASSERT(max_ovf_cnt > 0 && max_ovf_cnt <= LEDC_LL_OVF_CNT_MAX);
hw->channel_group[speed_mode].channel[channel].conf0.ovf_num = max_ovf_cnt - 1;
}
/**
* @brief Reset the timer overflow counter for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-7), select from ledc_channel_t
*
* @return None
*/
static inline void ledc_ll_channel_reset_timer_ovf_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel)
{
hw->channel_group[speed_mode].channel[channel].conf0.ovf_cnt_reset = 1;
}
#ifdef __cplusplus
}
#endif
@@ -21,10 +21,13 @@ extern "C" {
#define LEDC_LL_GET_HW() &LEDC
#define LEDC_LL_CHANNEL_SUPPORT_OVF_CNT 1
#define LEDC_LL_DUTY_NUM_MAX (LEDC_DUTY_NUM_LSCH0_V)
#define LEDC_LL_DUTY_CYCLE_MAX (LEDC_DUTY_CYCLE_LSCH0_V)
#define LEDC_LL_DUTY_SCALE_MAX (LEDC_DUTY_SCALE_LSCH0_V)
#define LEDC_LL_HPOINT_VAL_MAX (LEDC_HPOINT_LSCH0_V)
#define LEDC_LL_OVF_CNT_MAX (LEDC_OVF_NUM_LSCH0_V + 1)
#define LEDC_LL_FRACTIONAL_BITS (8)
#define LEDC_LL_FRACTIONAL_MAX ((1 << LEDC_LL_FRACTIONAL_BITS) - 1)
@@ -628,6 +631,51 @@ static inline void ledc_ll_get_channel_timer(ledc_dev_t *hw, ledc_mode_t speed_m
*timer_sel = (ledc_timer_t)(hw->channel_group[speed_mode].channel[channel_num].conf0.timer_sel);
}
/**
* @brief Enable or disable the timer overflow counter for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-7), select from ledc_channel_t
* @param enable True to enable; false to disable
*
* @return None
*/
static inline void ledc_ll_channel_enable_timer_ovt_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel, bool enable)
{
hw->channel_group[speed_mode].channel[channel].conf0.ovf_cnt_en = enable;
}
/**
* @brief Set the maximum timer overflow count for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-7), select from ledc_channel_t
* @param max_ovf_cnt The maximum timer overflow count
*
* @return None
*/
static inline void ledc_ll_channel_set_maximum_timer_ovf_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t max_ovf_cnt)
{
HAL_ASSERT(max_ovf_cnt > 0 && max_ovf_cnt <= LEDC_LL_OVF_CNT_MAX);
hw->channel_group[speed_mode].channel[channel].conf0.ovf_num = max_ovf_cnt - 1;
}
/**
* @brief Reset the timer overflow counter for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-7), select from ledc_channel_t
*
* @return None
*/
static inline void ledc_ll_channel_reset_timer_ovf_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel)
{
hw->channel_group[speed_mode].channel[channel].conf0.ovf_cnt_rst = 1;
}
#ifdef __cplusplus
}
#endif
@@ -21,10 +21,13 @@ extern "C" {
#define LEDC_LL_GET_HW() &LEDC
#define LEDC_LL_CHANNEL_SUPPORT_OVF_CNT 1
#define LEDC_LL_DUTY_NUM_MAX (LEDC_DUTY_NUM_LSCH0_V)
#define LEDC_LL_DUTY_CYCLE_MAX (LEDC_DUTY_CYCLE_LSCH0_V)
#define LEDC_LL_DUTY_SCALE_MAX (LEDC_DUTY_SCALE_LSCH0_V)
#define LEDC_LL_HPOINT_VAL_MAX (LEDC_HPOINT_LSCH0_V)
#define LEDC_LL_OVF_CNT_MAX (LEDC_OVF_NUM_LSCH0_V + 1)
#define LEDC_LL_FRACTIONAL_BITS (8)
#define LEDC_LL_FRACTIONAL_MAX ((1 << LEDC_LL_FRACTIONAL_BITS) - 1)
@@ -589,6 +592,51 @@ static inline void ledc_ll_get_channel_timer(ledc_dev_t *hw, ledc_mode_t speed_m
*timer_sel = (ledc_timer_t)(hw->channel_group[speed_mode].channel[channel_num].conf0.timer_sel);
}
/**
* @brief Enable or disable the timer overflow counter for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-7), select from ledc_channel_t
* @param enable True to enable; false to disable
*
* @return None
*/
static inline void ledc_ll_channel_enable_timer_ovt_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel, bool enable)
{
hw->channel_group[speed_mode].channel[channel].conf0.ovf_cnt_en = enable;
}
/**
* @brief Set the maximum timer overflow count for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-7), select from ledc_channel_t
* @param max_ovf_cnt The maximum timer overflow count
*
* @return None
*/
static inline void ledc_ll_channel_set_maximum_timer_ovf_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t max_ovf_cnt)
{
HAL_ASSERT(max_ovf_cnt > 0 && max_ovf_cnt <= LEDC_LL_OVF_CNT_MAX);
hw->channel_group[speed_mode].channel[channel].conf0.ovf_num = max_ovf_cnt - 1;
}
/**
* @brief Reset the timer overflow counter for the specified channel
*
* @param hw Beginning address of the peripheral registers
* @param speed_mode LEDC speed_mode, low-speed mode only
* @param channel LEDC channel index (0-7), select from ledc_channel_t
*
* @return None
*/
static inline void ledc_ll_channel_reset_timer_ovf_cnt(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel)
{
hw->channel_group[speed_mode].channel[channel].conf0.ovf_cnt_rst = 1;
}
#ifdef __cplusplus
}
#endif
+14 -1
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -248,6 +248,19 @@ typedef struct {
*/
void ledc_hal_init(ledc_hal_context_t *hal, ledc_mode_t speed_mode);
#if LEDC_LL_CHANNEL_SUPPORT_OVF_CNT
/**
* @brief Configure the maximum timer overflow times for the LEDC channel
*
* @param hal Context of the HAL layer
* @param channel LEDC channel index, select from ledc_channel_t
* @param max_ovf_cnt The maximum timer overflow times. To disable the timer overflow count, set this parameter to 0.
*
* @return None
*/
void ledc_hal_channel_configure_maximum_timer_ovf_cnt(ledc_hal_context_t *hal, ledc_channel_t channel, uint32_t max_ovf_cnt);
#endif
/**
* @brief Update channel configure when select low speed mode
*
+51 -1
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -139,6 +139,56 @@ typedef enum {
LEDC_FADE_MAX,
} ledc_fade_mode_t;
#if SOC_LEDC_SUPPORT_ETM
/**
* @brief LEDC channel related specific tasks that supported by the ETM module
*/
typedef enum {
LEDC_CHANNEL_ETM_TASK_FADE_SCALE_UPDATE, /*!< Update newly configured scale for the fade on the channel */
LEDC_CHANNEL_ETM_TASK_SIG_OUT_DIS, /*!< Disable signal output on the channel */
LEDC_CHANNEL_ETM_TASK_OVF_CNT_RST, /*!< Reset channel's timer overflow counter */
LEDC_CHANNEL_ETM_TASK_FADE_RESTART, /* Restart the last fade on the channel, the replay will start from last configured duty
(note that, for a single fade, the duty may be configured to a new value in ISR,
so it may not be the initial value you configured before fade) */
LEDC_CHANNEL_ETM_TASK_FADE_PAUSE, /*!< Pause fading on the channel */
LEDC_CHANNEL_ETM_TASK_FADE_RESUME, /*!< Resume fading on the channel */
LEDC_CHANNEL_ETM_TASK_MAX,
} ledc_channel_etm_task_type_t;
/**
* @brief LEDC timer related specific tasks that supported by the ETM module
*/
typedef enum {
LEDC_TIMER_ETM_TASK_RST, /*!< Reset the timer
When timer is reset, a timer overflow equivalent signal is sent to the channel, so any newly configured parameter is able to get updated
This is not the case on C6/H2/P4/C5/H4/H21, on such targets, no timer overflow equivalent signal is sent to the channel, i.e. newly configured parameter is not able to get updated when this ETM task is triggered */
LEDC_TIMER_ETM_TASK_RESUME, /*!< Resume the timer
Note that the ETM timer pause/resume task must be used in pair
Pause by ETM task and resume by calling `ledc_timer_resume` is not allowed, vice versa */
LEDC_TIMER_ETM_TASK_PAUSE, /*!< Pause the timer */
LEDC_TIMER_ETM_TASK_MAX,
} ledc_timer_etm_task_type_t;
/**
* @brief LEDC channel related specific events that supported by the ETM module
*/
typedef enum {
LEDC_CHANNEL_ETM_EVENT_FADE_END, /*!< Channel fading ended */
LEDC_CHANNEL_ETM_EVENT_REACH_MAX_OVF_CNT, /*!< Channel has reached the maximum timer overflow count
The maximum overflow count value can be set with `ledc_channel_configure_maximum_timer_ovf_cnt` */
LEDC_CHANNEL_ETM_EVENT_MAX,
} ledc_channel_etm_event_type_t;
/**
* @brief LEDC timer related specific events that supported by the ETM module
*/
typedef enum {
LEDC_TIMER_ETM_EVENT_OVF, /*!< Timer overflow happened */
LEDC_TIMER_ETM_EVENT_MAX,
} ledc_timer_etm_event_type_t;
#endif
#ifdef __cplusplus
}
#endif
+14 -1
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -63,3 +63,16 @@ void ledc_hal_get_fade_param(ledc_hal_context_t *hal, ledc_channel_t channel_num
ledc_ll_get_fade_param_range(hal->dev, hal->speed_mode, channel_num, range, dir, cycle, scale, step);
}
#endif
#if LEDC_LL_CHANNEL_SUPPORT_OVF_CNT
void ledc_hal_channel_configure_maximum_timer_ovf_cnt(ledc_hal_context_t *hal, ledc_channel_t channel, uint32_t max_ovf_cnt)
{
if (max_ovf_cnt == 0) {
ledc_ll_channel_enable_timer_ovt_cnt(hal->dev, hal->speed_mode, channel, false);
} else {
ledc_ll_channel_enable_timer_ovt_cnt(hal->dev, hal->speed_mode, channel, true);
ledc_ll_channel_set_maximum_timer_ovf_cnt(hal->dev, hal->speed_mode, channel, max_ovf_cnt);
ledc_ll_channel_reset_timer_ovf_cnt(hal->dev, hal->speed_mode, channel);
}
}
#endif
@@ -783,6 +783,10 @@ config SOC_LEDC_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_LEDC_SUPPORT_ETM
bool
default y
config SOC_MMU_PERIPH_NUM
int
default 1
@@ -315,6 +315,7 @@
#define SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX (16)
#define SOC_LEDC_FADE_PARAMS_BIT_WIDTH (10)
#define SOC_LEDC_SUPPORT_SLEEP_RETENTION (1)
#define SOC_LEDC_SUPPORT_ETM (1)
/*-------------------------- MMU CAPS ----------------------------------------*/
#define SOC_MMU_PERIPH_NUM (1U)
@@ -707,6 +707,10 @@ config SOC_LEDC_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_LEDC_SUPPORT_ETM
bool
default y
config SOC_MMU_PAGE_SIZE_CONFIGURABLE
bool
default y
@@ -291,6 +291,7 @@
#define SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX (16)
#define SOC_LEDC_FADE_PARAMS_BIT_WIDTH (10)
#define SOC_LEDC_SUPPORT_SLEEP_RETENTION (1)
#define SOC_LEDC_SUPPORT_ETM (1)
/*-------------------------- MMU CAPS ----------------------------------------*/
#define SOC_MMU_PAGE_SIZE_CONFIGURABLE (1)
@@ -643,6 +643,10 @@ config SOC_LEDC_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_LEDC_SUPPORT_ETM
bool
default y
config SOC_MMU_PAGE_SIZE_CONFIGURABLE
bool
default y
@@ -262,6 +262,7 @@
#define SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX (16)
#define SOC_LEDC_FADE_PARAMS_BIT_WIDTH (10)
#define SOC_LEDC_SUPPORT_SLEEP_RETENTION (1)
#define SOC_LEDC_SUPPORT_ETM (1)
/*-------------------------- MMU CAPS ----------------------------------------*/
#define SOC_MMU_PAGE_SIZE_CONFIGURABLE (1)
@@ -715,6 +715,10 @@ config SOC_LEDC_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_LEDC_SUPPORT_ETM
bool
default y
config SOC_MPU_CONFIGURABLE_REGIONS_SUPPORTED
bool
default n
@@ -310,6 +310,7 @@
#define SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX (16)
#define SOC_LEDC_FADE_PARAMS_BIT_WIDTH (10)
#define SOC_LEDC_SUPPORT_SLEEP_RETENTION (1)
#define SOC_LEDC_SUPPORT_ETM (1)
/*-------------------------- MPU CAPS ----------------------------------------*/
#define SOC_MPU_CONFIGURABLE_REGIONS_SUPPORTED 0
@@ -511,6 +511,10 @@ config SOC_LEDC_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_LEDC_SUPPORT_ETM
bool
default y
config SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE
bool
default y
@@ -287,6 +287,7 @@
#define SOC_LEDC_GAMMA_CURVE_FADE_RANGE_MAX (16)
#define SOC_LEDC_FADE_PARAMS_BIT_WIDTH (10)
#define SOC_LEDC_SUPPORT_SLEEP_RETENTION (1)
#define SOC_LEDC_SUPPORT_ETM (1)
/*-------------------------- MPU CAPS ----------------------------------------*/
// #define SOC_MPU_CONFIGURABLE_REGIONS_SUPPORTED 0
@@ -491,6 +491,10 @@ config SOC_LEDC_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_LEDC_SUPPORT_ETM
bool
default y
config SOC_MMU_PAGE_SIZE_CONFIGURABLE
bool
default y
@@ -288,6 +288,7 @@
#define SOC_LEDC_SUPPORT_FADE_STOP (1)
#define SOC_LEDC_FADE_PARAMS_BIT_WIDTH (10)
#define SOC_LEDC_SUPPORT_SLEEP_RETENTION (1)
#define SOC_LEDC_SUPPORT_ETM (1)
/*-------------------------- MMU CAPS ----------------------------------------*/
#define SOC_MMU_PAGE_SIZE_CONFIGURABLE (1)
@@ -1091,6 +1091,10 @@ config SOC_LEDC_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_LEDC_SUPPORT_ETM
bool
default y
config SOC_MMU_PERIPH_NUM
int
default 2
@@ -399,6 +399,7 @@
#define SOC_LEDC_SUPPORT_FADE_STOP (1)
#define SOC_LEDC_FADE_PARAMS_BIT_WIDTH (10)
#define SOC_LEDC_SUPPORT_SLEEP_RETENTION (1)
#define SOC_LEDC_SUPPORT_ETM (1)
/*-------------------------- MMU CAPS ----------------------------------------*/
#define SOC_MMU_PERIPH_NUM (2U)
+1
View File
@@ -107,6 +107,7 @@ INPUT = \
$(PROJECT_PATH)/components/esp_driver_gptimer/include/driver/gptimer_etm.h \
$(PROJECT_PATH)/components/esp_driver_gptimer/include/driver/gptimer_types.h \
$(PROJECT_PATH)/components/esp_driver_ledc/include/driver/ledc.h \
$(PROJECT_PATH)/components/esp_driver_ledc/include/driver/ledc_etm.h \
$(PROJECT_PATH)/components/esp_driver_mcpwm/include/driver/mcpwm_cap.h \
$(PROJECT_PATH)/components/esp_driver_mcpwm/include/driver/mcpwm_cmpr.h \
$(PROJECT_PATH)/components/esp_driver_mcpwm/include/driver/mcpwm_etm.h \
@@ -74,6 +74,7 @@ Other Peripheral Events
:SOC_ANA_CMPR_SUPPORT_ETM: - Refer to :doc:`/api-reference/peripherals/ana_cmpr` for how to get the ETM event handle from analog comparator.
:SOC_TEMPERATURE_SENSOR_SUPPORT_ETM: - Refer to :doc:`/api-reference/peripherals/temp_sensor` for how to get the ETM event handle from temperature sensor.
:SOC_I2S_SUPPORTS_ETM: - Refer to :doc:`/api-reference/peripherals/i2s` for how to get the ETM event handle from I2S.
:SOC_LEDC_SUPPORT_ETM: - Refer to :doc:`/api-reference/peripherals/ledc` for how to get the ETM event handle from LEDC.
.. _etm-task:
@@ -101,6 +102,7 @@ Other Peripheral Tasks
:SOC_TIMER_SUPPORT_ETM: - Refer to :ref:`gptimer-etm-event-and-task` for how to get the ETM task handle from GPTimer.
:SOC_TEMPERATURE_SENSOR_SUPPORT_ETM: - Refer to :doc:`/api-reference/peripherals/temp_sensor` for how to get the ETM task handle from temperature sensor.
:SOC_I2S_SUPPORTS_ETM: - Refer to :doc:`/api-reference/peripherals/i2s` for how to get the ETM task handle from I2S.
:SOC_LEDC_SUPPORT_ETM: - Refer to :doc:`/api-reference/peripherals/ledc` for how to get the ETM task handle from LEDC.
.. _etm-channel-control:
@@ -354,6 +354,21 @@ There are several individual timer-specific functions that can be used to change
The first function is called "behind the scenes" by :cpp:func:`ledc_timer_config` to provide a startup of a timer after it is configured.
.. only:: SOC_LEDC_SUPPORT_ETM and SOC_ETM_SUPPORTED
LEDC's ETM Events and Tasks
---------------------------
LEDC can generate various events that can be connected to the :doc:`ETM </api-reference/peripherals/etm>` module. Timer's supported events are listed in :cpp:type:`ledc_timer_etm_event_type_t`, and channel's supported events are listed in :cpp:type:`ledc_channel_etm_event_type_t`. Users can create an ``ETM event`` handle by calling :cpp:func:`ledc_timer_new_etm_event` or :cpp:func:`ledc_channel_new_etm_event` respectively.
LEDC also supports some tasks that can be triggered by other events and executed automatically. Timer's supported tasks are listed in :cpp:type:`ledc_timer_etm_task_type_t`, and channel's supported tasks are listed in :cpp:type:`ledc_channel_etm_task_type_t`. Users can create an ``ETM task`` handle by calling :cpp:func:`ledc_timer_new_etm_task` or :cpp:func:`ledc_channel_new_etm_task` respectively.
Some useful applications of ETM with LEDC are:
* To generate a PWM signal with certain number of pulses
* To synchronize the PWM period with an external signal
* To start / stop the PWM signal output or a fading without CPU intervention
For how to connect the LEDC events and tasks to the ETM channel, please refer to the :doc:`ETM </api-reference/peripherals/etm>` documentation.
Power Management
----------------
@@ -418,6 +433,7 @@ Application Example
* :example:`peripherals/ledc/ledc_basic` demonstrates how to use the LEDC to generate a PWM signal in LOW SPEED mode.
* :example:`peripherals/ledc/ledc_fade` demonstrates how to control the intensity of LEDs using the LEDC fade functionality.
:SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED: * :example:`peripherals/ledc/ledc_gamma_curve_fade` demonstrates how to use the LEDC for color control of RGB LEDs with gamma correction.
:SOC_LEDC_SUPPORT_ETM and SOC_ETM_SUPPORTED: * :example:`peripherals/ledc/ledc_dimmer` demonstrates how to use the LEDC and ETM to generate TRIAC gate trigger pulses that are synchronized to the mains zerocross.
API Reference
@@ -425,3 +441,7 @@ API Reference
.. include-build-file:: inc/ledc.inc
.. include-build-file:: inc/ledc_types.inc
.. only:: SOC_LEDC_SUPPORT_ETM and SOC_ETM_SUPPORTED
.. include-build-file:: inc/ledc_etm.inc
@@ -74,6 +74,7 @@ GPIO **边沿** 事件是最常见的事件类型,任何 GPIO 管脚均可触
:SOC_ANA_CMPR_SUPPORT_ETM: - 要了解如何从模拟比较器获取 ETM 事件句柄,请参阅 :doc:`/api-reference/peripherals/ana_cmpr`。
:SOC_TEMPERATURE_SENSOR_SUPPORT_ETM: - 要了解如何从温度传感器获取 ETM 事件句柄,请参阅 :doc:`/api-reference/peripherals/temp_sensor`。
:SOC_I2S_SUPPORTS_ETM: - 要了解如何从 I2S 获取 ETM 事件句柄,请参阅 :doc:`/api-reference/peripherals/i2s`。
:SOC_LEDC_SUPPORT_ETM: - 要了解如何从 LEDC 获取 ETM 事件句柄,请参阅 :doc:`/api-reference/peripherals/ledc`。
.. _etm-task:
@@ -101,6 +102,7 @@ GPIO 任务是最常见的任务类型。一个 GPIO 可以采取一个或多个
:SOC_TIMER_SUPPORT_ETM: - 要了解如何从 GPTimer 获取 ETM 任务句柄,请参阅 :ref:`gptimer-etm-event-and-task`。
:SOC_TEMPERATURE_SENSOR_SUPPORT_ETM: - 要了解如何从温度传感器获取 ETM 任务句柄,请参阅 :doc:`/api-reference/peripherals/temp_sensor`。
:SOC_I2S_SUPPORTS_ETM: - 要了解如何从 I2S 获取 ETM 任务句柄,请参阅 :doc:`/api-reference/peripherals/i2s`。
:SOC_LEDC_SUPPORT_ETM: - 要了解如何从 LEDC 获取 ETM 任务句柄,请参阅 :doc:`/api-reference/peripherals/ledc`。
.. _etm-channel-control:
@@ -354,6 +354,21 @@ LED PWM 控制器 API 有多种方式即时改变 PWM 频率:
第一个定时器复位函数在函数 :cpp:func:`ledc_timer_config` 内部完成所有定时器配置后会被调用一次。
.. only:: SOC_LEDC_SUPPORT_ETM and SOC_ETM_SUPPORTED
LEDC 的 ETM 事件和任务
----------------------
LEDC 可以生成多种事件,这些事件可以连接到 :doc:`ETM </api-reference/peripherals/etm>` 模块。定时器支持的事件列在 :cpp:type:`ledc_timer_etm_event_type_t` 中,通道支持的事件列在 :cpp:type:`ledc_channel_etm_event_type_t` 中。用户可以分别通过调用 :cpp:func:`ledc_timer_new_etm_event`:cpp:func:`ledc_channel_new_etm_event` 来创建 ``ETM event`` 句柄。
LEDC 还支持一些可由其他事件触发并自动执行的任务。定时器支持的任务列在 :cpp:type:`ledc_timer_etm_task_type_t` 中,通道支持的任务列在 :cpp:type:`ledc_channel_etm_task_type_t` 中。用户可以分别通过调用 :cpp:func:`ledc_timer_new_etm_task`:cpp:func:`ledc_channel_new_etm_task` 来创建 ``ETM task`` 句柄。
一些使用 ETM 与 LEDC 结合的实用应用包括:
* 生成一段特定脉冲数的 PWM 信号
* 同步 PWM 周期与外部信号
* 无需 CPU 干预即可开始 / 停止 PWM 信号输出或一次渐变
关于如何将 LEDC 事件和任务连接到 ETM 通道,请参考 :doc:`ETM </api-reference/peripherals/etm>` 文档。
电源管理
--------
@@ -418,6 +433,7 @@ LED PWM 控制器 API 会在设定的频率和占空比分辨率超过 LED PWM
* :example:`peripherals/ledc/ledc_basic` 演示了如何使用 LEDC 生成低速模式的 PWM 信号。
* :example:`peripherals/ledc/ledc_fade` 演示了如何使用 LEDC 实现 LED 亮度的渐变控制。
:SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED: * :example:`peripherals/ledc/ledc_gamma_curve_fade` 演示了如何使用 LEDC 对 RGB LED 实现带伽马校正的颜色控制。
:SOC_LEDC_SUPPORT_ETM and SOC_ETM_SUPPORTED: * :example:`peripherals/ledc/ledc_dimmer` 演示了如何使用 LEDC 和 ETM 生成与交流电零交叉同步的 TRIAC 门触发脉冲。
API 参考
@@ -425,3 +441,7 @@ API 参考
.. include-build-file:: inc/ledc.inc
.. include-build-file:: inc/ledc_types.inc
.. only:: SOC_LEDC_SUPPORT_ETM and SOC_ETM_SUPPORTED
.. include-build-file:: inc/ledc_etm.inc
@@ -272,6 +272,12 @@ examples/peripherals/ledc:
depends_components:
- esp_driver_ledc
examples/peripherals/ledc/ledc_dimmer:
disable:
- if: SOC_ETM_SUPPORTED != 1 or SOC_LEDC_SUPPORT_ETM != 1
depends_components:
- esp_driver_ledc
examples/peripherals/ledc/ledc_gamma_curve_fade:
disable:
- if: SOC_LEDC_SUPPORTED != 1 or SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED != 1
@@ -49,7 +49,6 @@ static void example_ledc_init(void)
.speed_mode = LEDC_MODE,
.channel = LEDC_CHANNEL,
.timer_sel = LEDC_TIMER,
.intr_type = LEDC_INTR_DISABLE,
.gpio_num = LEDC_OUTPUT_IO,
.duty = 0, // Set duty to 0%
.hpoint = 0,
@@ -0,0 +1,8 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.22)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
# "Trim" the build. Include the minimal set of components, main, and anything it depends on.
idf_build_set_property(MINIMAL_BUILD ON)
project(ledc_dimmer)
@@ -0,0 +1,63 @@
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H4 | ESP32-P4 |
| ----------------- | -------- | -------- | --------- | -------- | -------- | -------- |
# LEDC Dimmer Example
This example demonstrates how to generate TRIAC gate trigger pulses that are synchronized to the mains zerocross using LEDC and ETM. As a simplified demonstration, it simulates the 50 Hz zerocross AC mains detector input using a GPIO that toggles at 50 Hz, and uses ETM to reset the LEDC timer on each edge (every half-cycle) for synchronization. By shifting the LEDC `hpoint` (phase angle) after each reset, the gate pulse moves within the halfcycle, achieving dimming.
## How to use example
### Hardware Required
* A development board with any Espressif SoC that has ETM functionality (e.g., ESP32C61-DevKitC etc.)
* A USB cable for power supply and programming
## Signals and pins
| Signal | GPIO |
| --------------------------------------------------------------- | --------------------------------------------------------------------------- |
| Reference wave (50 Hz square from a AC mains detection circuit) | GPIO3 (configured as input/output in this demo to simulate the square wave) |
| Gate trigger pulse (LEDC output) | GPIO2 |
Expected observation if connect an oscilloscope or logic analyzer:
- A 50 Hz square wave on `GPIO3`.
- Short pulses on `GPIO2` that occur once each halfcycle, moving left/right (earlier/later) every 2 seconds as the brightness ramps down and up.
## Build and flash
Build the project and flash it to the board, then run monitor tool to view serial output:
```bash
idf.py build
idf.py -p PORT flash monitor
```
(Replace PORT with the name of the serial port to use.)
(To exit the serial monitor, type ``Ctrl-]``.)
See the [ESPIDF Getting Started Guide](https://idf.espressif.com/) for full steps to configure and use ESP-IDF to build projects.
## Adapting to real mains dimming (advanced)
If you want to control a real TRIAC load (lamp):
1. Replace the simulated reference wave with a proper zerocross detector feeding an isolated input GPIO.
- Configure `REFERENCE_WAVE_IO` as input only, remove the toggling task, and ensure ETM still triggers on both edges. Or to normalize the AC mains to some analog signal, and use analog comparator to trigger a ETM event.
2. Drive the TRIAC gate through an optotriac from the LEDC output GPIO with proper currentlimit resistor.
Here shows a simplified schematic for reference:
![AC Lamp Dimmer with ESP32 and TRIAC](image/ac_lamp_dimmer_triac.png)
And here is an actual timing diagrams (AC mains + dimmer output waveforms with phase angle):
![Timing Diagram](image/timing_diagram.png)
## Troubleshooting
- Pulse timing not updating on C6/C5/H2/P4/H4/H21 → Check the notes in the example source file. For such targets, LEDC timer period should be shorter than the half-cycle of the mains, so that timer overflow could happen to update the duty parameters.
- Please make sure (hpoint + duty) is always less than (2 ** timer_resolution), otherwise, behavior is unexpected.
For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon.
Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

@@ -0,0 +1,3 @@
idf_component_register(SRCS "ledc_dimmer_example_main.c"
PRIV_REQUIRES esp_driver_ledc esp_driver_gpio
INCLUDE_DIRS ".")
@@ -0,0 +1,145 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_check.h"
#include "driver/ledc.h"
#include "driver/gpio.h"
#include "esp_etm.h"
#include "sdkconfig.h"
#define REFERENCE_WAVE_IO (3) // Reference wave GPIO
#define GATE_TRIGGER_PULSE_IO (2) // Gate trigger pulse GPIO
#define LEDC_TIMER LEDC_TIMER_0
#define LEDC_MODE LEDC_LOW_SPEED_MODE
#define LEDC_CHANNEL LEDC_CHANNEL_0
#define LEDC_DUTY_RES LEDC_TIMER_13_BIT // Set duty resolution to 13 bits
#define LEDC_DUTY (400) // Set duty to 400 out of 8192 (13-bit)
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32H4 || CONFIG_IDF_TARGET_ESP32H21
// On such targets. due to hardware limitation, LEDC timer reset ETM task won't sync newly configured duty parameters.
// Therefore, the LEDC timer frequency should be higher than 100 Hz (2 * 50 Hz) to ensure a timer overflow happens before the timer reset to update the duty parameters.
#define LEDC_FREQUENCY (120) // Frequency in Hertz. Set frequency at 120 Hz
#define LEDC_HPOINT_INITIAL (1640) // Initial hpoint value (to ensure no pulse between timer overflow and timer reset)
#else
#define LEDC_FREQUENCY (80) // Frequency in Hertz. Set frequency at 80 Hz
#define LEDC_HPOINT_INITIAL (0) // Initial hpoint value
#endif
// For C6/C5/H2/P4/H4/H21:
// 120Hz 8192-step PWM cycle in 100Hz -> (1640, 8192 - LEDC_DUTY) steps for a 84% ~ 21% dimming (this is the limitation due to the hardware)
// For other targets:
// 100Hz in a 80Hz 8192-step PWM cycle -> (0, 6554) steps for a 100% ~ 0% dimming
// Overall, we want to increase and decrease the brightness in 10 steps, so each step is:
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32H4 || CONFIG_IDF_TARGET_ESP32H21
#define LEDC_HPOINT_STEP (615)
#else
#define LEDC_HPOINT_STEP (655)
#endif
// Simulate a signal comes from the 50Hz mains AC supply
// Use GPIO + vTaskDelay to output a 50Hz square wave as the reference signal
static void reference_wave_init(void)
{
gpio_config_t io_conf = {};
io_conf.mode = GPIO_MODE_INPUT_OUTPUT;
io_conf.pin_bit_mask = (1ULL << REFERENCE_WAVE_IO);
ESP_ERROR_CHECK(gpio_config(&io_conf));
}
static void reference_wave_task(void *arg)
{
while (1) {
// Set the reference wave high
ESP_ERROR_CHECK(gpio_set_level(REFERENCE_WAVE_IO, 1));
vTaskDelay(pdMS_TO_TICKS(10)); // High for 10ms
// Set the reference wave low
ESP_ERROR_CHECK(gpio_set_level(REFERENCE_WAVE_IO, 0));
vTaskDelay(pdMS_TO_TICKS(10)); // Low for 10ms
}
}
// Initialize the gate trigger pulse signal using LEDC
static void gate_trigger_pulse_signal_init(void)
{
ledc_timer_config_t ledc_timer = {
.speed_mode = LEDC_MODE,
.duty_resolution = LEDC_DUTY_RES,
.timer_num = LEDC_TIMER,
.freq_hz = LEDC_FREQUENCY,
.clk_cfg = LEDC_AUTO_CLK
};
ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));
ledc_channel_config_t ledc_channel = {
.speed_mode = LEDC_MODE,
.channel = LEDC_CHANNEL,
.timer_sel = LEDC_TIMER,
.gpio_num = GATE_TRIGGER_PULSE_IO,
.duty = LEDC_DUTY,
.hpoint = LEDC_HPOINT_INITIAL
};
ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel));
}
void app_main(void)
{
gate_trigger_pulse_signal_init();
vTaskDelay(pdMS_TO_TICKS(50)); // Wait for the LEDC to run for at least one cycle
reference_wave_init();
xTaskCreate(reference_wave_task, "reference_wave_task", 2048, NULL, 5, NULL);
// Connect reference wave GPIO toggle event to LEDC timer reset task, so that the timing frame of the gate trigger pulse
// can be synchronized to the reference wave signal
esp_etm_channel_config_t etm_config = {};
esp_etm_channel_handle_t etm_channel = NULL;
ESP_ERROR_CHECK(esp_etm_new_channel(&etm_config, &etm_channel));
esp_etm_event_handle_t gpio_event = NULL;
gpio_etm_event_config_t gpio_event_config = {
.edge = GPIO_ETM_EVENT_EDGE_ANY,
};
ESP_ERROR_CHECK(gpio_new_etm_event(&gpio_event_config, &gpio_event));
ESP_ERROR_CHECK(gpio_etm_event_bind_gpio(gpio_event, REFERENCE_WAVE_IO));
esp_etm_task_handle_t ledc_task = NULL;
ledc_timer_etm_task_config_t ledc_task_config = {
.task_type = LEDC_TIMER_ETM_TASK_RST,
};
ESP_ERROR_CHECK(ledc_timer_new_etm_task(LEDC_MODE, LEDC_TIMER, &ledc_task_config, &ledc_task));
ESP_ERROR_CHECK(esp_etm_channel_connect(etm_channel, gpio_event, ledc_task));
ESP_ERROR_CHECK(esp_etm_channel_enable(etm_channel));
int cnt = 0;
bool dimming = true; // controls the dimming direction
uint32_t hpoint = LEDC_HPOINT_INITIAL;
while (1) {
vTaskDelay(pdMS_TO_TICKS(2000));
if (dimming) {
// Decrease brightness
if (cnt < 10) {
hpoint += LEDC_HPOINT_STEP;
cnt++;
} else if (cnt == 10) {
dimming = false;
}
} else {
// Increase brightness
if (cnt > 0) {
hpoint -= LEDC_HPOINT_STEP;
cnt--;
} else if (cnt == 0) {
dimming = true;
}
}
ESP_ERROR_CHECK(ledc_set_duty_with_hpoint(LEDC_MODE, LEDC_CHANNEL, LEDC_DUTY, hpoint));
ESP_ERROR_CHECK(ledc_update_duty(LEDC_MODE, LEDC_CHANNEL));
}
}