mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
rmt: simplify rmt source clock configure with clk_tree API
Also decrease the payload size for testing the multi-channel behaviour.
This commit is contained in:
parent
648b1a41c6
commit
1626766abf
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 --------------------------------------*/
|
||||
|
Loading…
Reference in New Issue
Block a user