mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-09 07:34:32 +02:00
Merge branch 'bugfix/fix_rmt_tx_multi_channel_test' into 'master'
rmt: simplify the clock configuration with clk_tree API Closes IDF-6717, IDF-6810, and IDFCI-1606 See merge request espressif/esp-idf!22275
This commit is contained in:
@@ -21,7 +21,7 @@
|
|||||||
#include "soc/soc_memory_layout.h"
|
#include "soc/soc_memory_layout.h"
|
||||||
#include "soc/rmt_periph.h"
|
#include "soc/rmt_periph.h"
|
||||||
#include "soc/rmt_struct.h"
|
#include "soc/rmt_struct.h"
|
||||||
#include "esp_private/esp_clk.h"
|
#include "clk_tree.h"
|
||||||
#include "hal/rmt_hal.h"
|
#include "hal/rmt_hal.h"
|
||||||
#include "hal/rmt_ll.h"
|
#include "hal/rmt_ll.h"
|
||||||
#include "hal/gpio_hal.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_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))
|
#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 {
|
typedef struct {
|
||||||
rmt_hal_context_t hal;
|
rmt_hal_context_t hal;
|
||||||
_lock_t rmt_driver_isr_lock;
|
_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);
|
rmt_ll_enable_mem_access_nonfifo(dev, true);
|
||||||
|
|
||||||
if (rmt_param->flags & RMT_CHANNEL_FLAGS_AWARE_DFS) {
|
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
|
#if SOC_RMT_SUPPORT_XTAL
|
||||||
// clock src: XTAL_CLK
|
// 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);
|
rmt_ll_set_group_clock_src(dev, channel, (rmt_clock_source_t)RMT_BASECLK_XTAL, 1, 0, 0);
|
||||||
#elif SOC_RMT_SUPPORT_REF_TICK
|
#elif SOC_RMT_SUPPORT_REF_TICK
|
||||||
// clock src: REF_CLK
|
// 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);
|
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
|
#endif
|
||||||
} else {
|
} else {
|
||||||
// fallback to use default clock source
|
// 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_ll_set_group_clock_src(dev, channel, (rmt_clock_source_t)RMT_BASECLK_DEFAULT, 1, 0, 0);
|
||||||
}
|
}
|
||||||
RMT_EXIT_CRITICAL();
|
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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
#include "soc/rmt_periph.h"
|
#include "soc/rmt_periph.h"
|
||||||
#include "hal/rmt_ll.h"
|
#include "hal/rmt_ll.h"
|
||||||
#include "driver/gpio.h"
|
#include "driver/gpio.h"
|
||||||
#include "esp_private/esp_clk.h"
|
#include "clk_tree.h"
|
||||||
#include "esp_private/periph_ctrl.h"
|
#include "esp_private/periph_ctrl.h"
|
||||||
|
|
||||||
static const char *TAG = "rmt";
|
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,
|
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);
|
"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
|
// TODO: [clk_tree] to use a generic clock enable/disable or acquire/release function for all clock source
|
||||||
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
|
|
||||||
#if SOC_RMT_SUPPORT_RC_FAST
|
#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_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
|
// 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);
|
rmt_ll_set_group_clock_src(group->hal.regs, channel_id, clk_src, 1, 1, 0);
|
||||||
group->resolution_hz = periph_src_clk_hz;
|
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));
|
TEST_ESP_OK(gptimer_get_raw_count(timers[i], &value));
|
||||||
// convert the raw count to us
|
// convert the raw count to us
|
||||||
value = value * 1000000 / timer_resolution_hz[i];
|
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");
|
printf("stop timers\r\n");
|
||||||
for (int i = 0; i < SOC_TIMER_GROUP_TOTAL_TIMERS; i++) {
|
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.
|
* between the alarm triggering and the execution of the callback that actually stops the gptimer.
|
||||||
*/
|
*/
|
||||||
#if CONFIG_PM_ENABLE
|
#if CONFIG_PM_ENABLE
|
||||||
#define GPTIMER_STOP_ON_ALARM_COUNT_DELTA 100
|
#define GPTIMER_STOP_ON_ALARM_COUNT_DELTA 150
|
||||||
#else
|
#else
|
||||||
#define GPTIMER_STOP_ON_ALARM_COUNT_DELTA 50
|
#define GPTIMER_STOP_ON_ALARM_COUNT_DELTA 50
|
||||||
#endif // CONFIG_PM_ENABLE
|
#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_FREERTOS_HZ=1000
|
||||||
CONFIG_ESP_TASK_WDT=n
|
|
||||||
# Disable nano printf, because we need to print the timer count in %llu format
|
# Disable nano printf, because we need to print the timer count in %llu format
|
||||||
CONFIG_NEWLIB_NANO_FORMAT=n
|
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)
|
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_RMT_CHANS 2
|
||||||
#define TEST_LED_NUM 24
|
#define TEST_LED_NUM 1
|
||||||
#define TEST_STOP_TIME_NO_SYNCHRO_DELTA 150
|
#define TEST_STOP_TIME_NO_SYNCHRO_DELTA 250
|
||||||
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6
|
#define TEST_STOP_TIME_SYNCHRO_DELTA 60
|
||||||
#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
|
|
||||||
rmt_tx_channel_config_t tx_channel_cfg = {
|
rmt_tx_channel_config_t tx_channel_cfg = {
|
||||||
.clk_src = RMT_CLK_SRC_DEFAULT,
|
.clk_src = RMT_CLK_SRC_DEFAULT,
|
||||||
.resolution_hz = 10000000, // 10MHz, 1 tick = 0.1us (led strip needs a high resolution)
|
.resolution_hz = 10000000, // 10MHz, 1 tick = 0.1us (led strip needs a high resolution)
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
CONFIG_PM_ENABLE=y
|
CONFIG_PM_ENABLE=y
|
||||||
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
|
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
|
||||||
|
CONFIG_PM_DFS_INIT_AUTO=y
|
||||||
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
||||||
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
|
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
|
||||||
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=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_FREERTOS_HZ=1000
|
||||||
CONFIG_ESP_TASK_WDT=n
|
|
||||||
CONFIG_UNITY_ENABLE_64BIT=y
|
CONFIG_UNITY_ENABLE_64BIT=y
|
||||||
CONFIG_ESP_MAIN_TASK_STACK_SIZE=4096
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=4096
|
||||||
|
@@ -615,10 +615,6 @@ config SOC_RMT_SUPPORT_XTAL
|
|||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
|
||||||
config SOC_RMT_SUPPORT_PLL_F80M
|
|
||||||
bool
|
|
||||||
default y
|
|
||||||
|
|
||||||
config SOC_RMT_SUPPORT_RC_FAST
|
config SOC_RMT_SUPPORT_RC_FAST
|
||||||
bool
|
bool
|
||||||
default y
|
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_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_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_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 */
|
#define SOC_RMT_SUPPORT_RC_FAST 1 /*!< Support set RC_FAST as the RMT clock source */
|
||||||
|
|
||||||
/*-------------------------- MCPWM CAPS --------------------------------------*/
|
/*-------------------------- MCPWM CAPS --------------------------------------*/
|
||||||
|
Reference in New Issue
Block a user