diff --git a/components/driver/deprecated/rmt_legacy.c b/components/driver/deprecated/rmt_legacy.c index 54e4035986..14a059df87 100644 --- a/components/driver/deprecated/rmt_legacy.c +++ b/components/driver/deprecated/rmt_legacy.c @@ -21,7 +21,7 @@ #include "soc/soc_memory_layout.h" #include "soc/rmt_periph.h" #include "soc/rmt_struct.h" -#include "esp_private/esp_clk.h" +#include "clk_tree.h" #include "hal/rmt_hal.h" #include "hal/rmt_ll.h" #include "hal/gpio_hal.h" @@ -58,16 +58,6 @@ static const char *TAG = "rmt(legacy)"; #define RMT_DECODE_RX_CHANNEL(encode_chan) ((encode_chan - RMT_RX_CHANNEL_ENCODING_START)) #define RMT_ENCODE_RX_CHANNEL(decode_chan) ((decode_chan + RMT_RX_CHANNEL_ENCODING_START)) -#if SOC_RMT_SUPPORT_APB -#define RMT_DEFAULT_CLOCK_FREQ esp_clk_apb_freq() -#elif SOC_RMT_SUPPORT_PLL_F80M -#define RMT_DEFAULT_CLOCK_FREQ (80*1000*1000) -#elif SOC_RMT_SUPPORT_XTAL -#define RMT_DEFAULT_CLOCK_FREQ esp_clk_xtal_freq() -#else -#error "RMT unknow default clock" -#endif - typedef struct { rmt_hal_context_t hal; _lock_t rmt_driver_isr_lock; @@ -575,19 +565,20 @@ static esp_err_t rmt_internal_config(rmt_dev_t *dev, const rmt_config_t *rmt_par rmt_ll_enable_mem_access_nonfifo(dev, true); if (rmt_param->flags & RMT_CHANNEL_FLAGS_AWARE_DFS) { - // [clk_tree] TODO: refactor the following code by clk_tree API #if SOC_RMT_SUPPORT_XTAL // clock src: XTAL_CLK - rmt_source_clk_hz = esp_clk_xtal_freq(); + clk_tree_src_get_freq_hz((soc_module_clk_t)RMT_BASECLK_XTAL, CLK_TREE_SRC_FREQ_PRECISION_CACHED, &rmt_source_clk_hz); rmt_ll_set_group_clock_src(dev, channel, (rmt_clock_source_t)RMT_BASECLK_XTAL, 1, 0, 0); #elif SOC_RMT_SUPPORT_REF_TICK // clock src: REF_CLK - rmt_source_clk_hz = REF_CLK_FREQ; + clk_tree_src_get_freq_hz((soc_module_clk_t)RMT_BASECLK_REF, CLK_TREE_SRC_FREQ_PRECISION_CACHED, &rmt_source_clk_hz); rmt_ll_set_group_clock_src(dev, channel, (rmt_clock_source_t)RMT_BASECLK_REF, 1, 0, 0); +#else +#error "No clock source is aware of DFS" #endif } else { // fallback to use default clock source - rmt_source_clk_hz = RMT_DEFAULT_CLOCK_FREQ; + clk_tree_src_get_freq_hz((soc_module_clk_t)RMT_BASECLK_DEFAULT, CLK_TREE_SRC_FREQ_PRECISION_CACHED, &rmt_source_clk_hz); rmt_ll_set_group_clock_src(dev, channel, (rmt_clock_source_t)RMT_BASECLK_DEFAULT, 1, 0, 0); } RMT_EXIT_CRITICAL(); diff --git a/components/driver/rmt/rmt_common.c b/components/driver/rmt/rmt_common.c index 24da4b6f02..5fcd75c67f 100644 --- a/components/driver/rmt/rmt_common.c +++ b/components/driver/rmt/rmt_common.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -19,7 +19,7 @@ #include "soc/rmt_periph.h" #include "hal/rmt_ll.h" #include "driver/gpio.h" -#include "esp_private/esp_clk.h" +#include "clk_tree.h" #include "esp_private/periph_ctrl.h" static const char *TAG = "rmt"; @@ -122,65 +122,46 @@ esp_err_t rmt_select_periph_clock(rmt_channel_handle_t chan, rmt_clock_source_t ESP_RETURN_ON_FALSE(!clock_selection_conflict, ESP_ERR_INVALID_STATE, TAG, "group clock conflict, already is %d but attempt to %d", group->clk_src, clk_src); - // [clk_tree] TODO: replace the following switch table by clk_tree API - switch (clk_src) { -#if SOC_RMT_SUPPORT_APB - case RMT_CLK_SRC_APB: - periph_src_clk_hz = esp_clk_apb_freq(); -#if CONFIG_PM_ENABLE - sprintf(chan->pm_lock_name, "rmt_%d_%d", group->group_id, channel_id); // e.g. rmt_0_0 - ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, chan->pm_lock_name, &chan->pm_lock); - ESP_RETURN_ON_ERROR(ret, TAG, "create APB_FREQ_MAX lock failed"); - ESP_LOGD(TAG, "install APB_FREQ_MAX lock for RMT channel (%d,%d)", group->group_id, channel_id); -#endif // CONFIG_PM_ENABLE - break; -#endif // SOC_RMT_SUPPORT_APB -#if SOC_RMT_SUPPORT_PLL_F80M - case RMT_CLK_SRC_PLL_F80M: - periph_src_clk_hz = 80000000; -#if CONFIG_PM_ENABLE - sprintf(chan->pm_lock_name, "rmt_%d_%d", group->group_id, channel_id); // e.g. rmt_0_0 - // ESP32C6 PLL_F80M is available even when SOC_ROOT_CLK switches from PLL to XTAL, so using NO_LIGHT_SLEEP lock here is sufficient - ret = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, chan->pm_lock_name, &chan->pm_lock); - ESP_RETURN_ON_ERROR(ret, TAG, "create NO_LIGHT_SLEEP lock failed"); - ESP_LOGD(TAG, "install NO_LIGHT_SLEEP lock for RMT channel (%d,%d)", group->group_id, channel_id); -#endif // CONFIG_PM_ENABLE - break; -#endif // SOC_RMT_SUPPORT_PLL_F80M -#if SOC_RMT_SUPPORT_AHB - case RMT_CLK_SRC_AHB: - // TODO: decide which kind of PM lock we should use for such clock - periph_src_clk_hz = 48 * 1000 * 1000; - break; -#endif // SOC_RMT_SUPPORT_AHB -#if SOC_RMT_SUPPORT_XTAL - case RMT_CLK_SRC_XTAL: - periph_src_clk_hz = esp_clk_xtal_freq(); -#if CONFIG_PM_ENABLE - sprintf(chan->pm_lock_name, "rmt_%d_%d", group->group_id, channel_id); // e.g. rmt_0_0 - // XTAL will be power down in the light sleep (predefined low power modes) - // acquire a NO_LIGHT_SLEEP lock here to prevent the system go into light sleep automatically - ret = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, chan->pm_lock_name, &chan->pm_lock); - ESP_RETURN_ON_ERROR(ret, TAG, "create NO_LIGHT_SLEEP lock failed"); - ESP_LOGD(TAG, "install NO_LIGHT_SLEEP lock for RMT channel (%d,%d)", group->group_id, channel_id); -#endif // CONFIG_PM_ENABLE - break; -#endif // SOC_RMT_SUPPORT_XTAL -#if SOC_RMT_SUPPORT_REF_TICK - case RMT_CLK_SRC_REF_TICK: - periph_src_clk_hz = REF_CLK_FREQ; - break; -#endif // SOC_RMT_SUPPORT_REF_TICK + // TODO: [clk_tree] to use a generic clock enable/disable or acquire/release function for all clock source #if SOC_RMT_SUPPORT_RC_FAST - case RMT_CLK_SRC_RC_FAST: + if (clk_src == RMT_CLK_SRC_RC_FAST) { + // RC_FAST clock is not enabled automatically on start up, we enable it here manually. + // Note there's a ref count in the enable/disable function, we must call them in pair in the driver. periph_rtc_dig_clk8m_enable(); - periph_src_clk_hz = periph_rtc_dig_clk8m_get_freq(); - break; -#endif // SOC_RMT_SUPPORT_RC_FAST - default: - ESP_RETURN_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, TAG, "clock source %d is not supported", clk_src); - break; } +#endif // SOC_RMT_SUPPORT_RC_FAST + + // get clock source frequency + ESP_RETURN_ON_ERROR(clk_tree_src_get_freq_hz((soc_module_clk_t)clk_src, CLK_TREE_SRC_FREQ_PRECISION_CACHED, &periph_src_clk_hz), + TAG, "get clock source frequency failed"); + +#if CONFIG_PM_ENABLE + bool need_pm_lock = true; + // to make the RMT work reliable, the source clock must stay alive and unchanged + // driver will create different pm lock for that purpose, according to different clock source + esp_pm_lock_type_t pm_lock_type = ESP_PM_NO_LIGHT_SLEEP; + +#if SOC_RMT_SUPPORT_RC_FAST + if (clk_src == RMT_CLK_SRC_RC_FAST) { + // RC_FAST won't be turn off in sleep and won't change its frequency during DFS + need_pm_lock = false; + } +#endif // SOC_RMT_SUPPORT_RC_FAST + +#if SOC_RMT_SUPPORT_APB + if (clk_src == RMT_CLK_SRC_APB) { + // APB clock frequency can be changed during DFS + pm_lock_type = ESP_PM_APB_FREQ_MAX; + } +#endif // SOC_RMT_SUPPORT_APB + + if (need_pm_lock) { + sprintf(chan->pm_lock_name, "rmt_%d_%d", group->group_id, channel_id); // e.g. rmt_0_0 + ret = esp_pm_lock_create(pm_lock_type, 0, chan->pm_lock_name, &chan->pm_lock); + ESP_RETURN_ON_ERROR(ret, TAG, "create pm lock failed"); + } +#endif // CONFIG_PM_ENABLE + // no division for group clock source, to achieve highest resolution rmt_ll_set_group_clock_src(group->hal.regs, channel_id, clk_src, 1, 1, 0); group->resolution_hz = periph_src_clk_hz; diff --git a/components/driver/test_apps/gptimer/main/test_gptimer.c b/components/driver/test_apps/gptimer/main/test_gptimer.c index 5eb20caf8e..ccb48ef3e3 100644 --- a/components/driver/test_apps/gptimer/main/test_gptimer.c +++ b/components/driver/test_apps/gptimer/main/test_gptimer.c @@ -90,7 +90,7 @@ TEST_CASE("gptimer_wallclock_with_various_clock_sources", "[gptimer]") TEST_ESP_OK(gptimer_get_raw_count(timers[i], &value)); // convert the raw count to us value = value * 1000000 / timer_resolution_hz[i]; - TEST_ASSERT_UINT_WITHIN(1000, 20000, value); + TEST_ASSERT_UINT_WITHIN(1100, 20000, value); } printf("stop timers\r\n"); for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) { @@ -139,7 +139,7 @@ TEST_CASE("gptimer_wallclock_with_various_clock_sources", "[gptimer]") * between the alarm triggering and the execution of the callback that actually stops the gptimer. */ #if CONFIG_PM_ENABLE -#define GPTIMER_STOP_ON_ALARM_COUNT_DELTA 100 +#define GPTIMER_STOP_ON_ALARM_COUNT_DELTA 150 #else #define GPTIMER_STOP_ON_ALARM_COUNT_DELTA 50 #endif // CONFIG_PM_ENABLE diff --git a/components/driver/test_apps/gptimer/sdkconfig.defaults b/components/driver/test_apps/gptimer/sdkconfig.defaults index 3de1470382..1d96fcebe1 100644 --- a/components/driver/test_apps/gptimer/sdkconfig.defaults +++ b/components/driver/test_apps/gptimer/sdkconfig.defaults @@ -1,4 +1,7 @@ +# This file was generated using idf.py save-defconfig. It can be edited manually. +# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration +# +# CONFIG_ESP_TASK_WDT_INIT is not set CONFIG_FREERTOS_HZ=1000 -CONFIG_ESP_TASK_WDT=n # Disable nano printf, because we need to print the timer count in %llu format CONFIG_NEWLIB_NANO_FORMAT=n diff --git a/components/driver/test_apps/rmt/main/test_rmt_tx.c b/components/driver/test_apps/rmt/main/test_rmt_tx.c index 5ef13e8349..eb4df6bf5e 100644 --- a/components/driver/test_apps/rmt/main/test_rmt_tx.c +++ b/components/driver/test_apps/rmt/main/test_rmt_tx.c @@ -464,13 +464,9 @@ static bool test_rmt_tx_done_cb_record_time(rmt_channel_handle_t channel, const static void test_rmt_multi_channels_trans(size_t channel0_mem_block_symbols, size_t channel1_mem_block_symbols, bool channel0_with_dma, bool channel1_with_dma) { #define TEST_RMT_CHANS 2 -#define TEST_LED_NUM 24 -#define TEST_STOP_TIME_NO_SYNCHRO_DELTA 150 -#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 -#define TEST_STOP_TIME_SYNCHRO_DELTA 400 -#else -#define TEST_STOP_TIME_SYNCHRO_DELTA 10 -#endif // #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 +#define TEST_LED_NUM 1 +#define TEST_STOP_TIME_NO_SYNCHRO_DELTA 250 +#define TEST_STOP_TIME_SYNCHRO_DELTA 60 rmt_tx_channel_config_t tx_channel_cfg = { .clk_src = RMT_CLK_SRC_DEFAULT, .resolution_hz = 10000000, // 10MHz, 1 tick = 0.1us (led strip needs a high resolution) diff --git a/components/driver/test_apps/rmt/sdkconfig.ci.release b/components/driver/test_apps/rmt/sdkconfig.ci.release index 91d93f163e..199b0cf97c 100644 --- a/components/driver/test_apps/rmt/sdkconfig.ci.release +++ b/components/driver/test_apps/rmt/sdkconfig.ci.release @@ -1,5 +1,6 @@ CONFIG_PM_ENABLE=y CONFIG_FREERTOS_USE_TICKLESS_IDLE=y +CONFIG_PM_DFS_INIT_AUTO=y CONFIG_COMPILER_OPTIMIZATION_SIZE=y CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y diff --git a/components/driver/test_apps/rmt/sdkconfig.defaults b/components/driver/test_apps/rmt/sdkconfig.defaults index 00add4c150..f67db9e921 100644 --- a/components/driver/test_apps/rmt/sdkconfig.defaults +++ b/components/driver/test_apps/rmt/sdkconfig.defaults @@ -1,4 +1,7 @@ +# This file was generated using idf.py save-defconfig. It can be edited manually. +# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration +# +# CONFIG_ESP_TASK_WDT_INIT is not set CONFIG_FREERTOS_HZ=1000 -CONFIG_ESP_TASK_WDT=n CONFIG_UNITY_ENABLE_64BIT=y CONFIG_ESP_MAIN_TASK_STACK_SIZE=4096 diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 0fcab8d132..35469a9b52 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -615,10 +615,6 @@ config SOC_RMT_SUPPORT_XTAL bool default y -config SOC_RMT_SUPPORT_PLL_F80M - bool - default y - config SOC_RMT_SUPPORT_RC_FAST bool default y diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 5fa75a7b51..211c0d3720 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -262,7 +262,6 @@ #define SOC_RMT_SUPPORT_TX_SYNCHRO 1 /*!< Support coordinate a group of TX channels to start simultaneously */ #define SOC_RMT_SUPPORT_TX_CARRIER_DATA_ONLY 1 /*!< TX carrier can be modulated to data phase only */ #define SOC_RMT_SUPPORT_XTAL 1 /*!< Support set XTAL clock as the RMT clock source */ -#define SOC_RMT_SUPPORT_PLL_F80M 1 /*!< Support set PLL_F80M as the RMT clock source */ #define SOC_RMT_SUPPORT_RC_FAST 1 /*!< Support set RC_FAST as the RMT clock source */ /*-------------------------- MCPWM CAPS --------------------------------------*/