From 32cd193ddf9ce93bba0e9ff349fb0e20dd42eb37 Mon Sep 17 00:00:00 2001 From: morris Date: Wed, 14 Dec 2022 19:00:58 +0800 Subject: [PATCH] rmt: support pll clock source on esp32c6 --- components/driver/.build-test-rules.yml | 4 ---- components/driver/rmt/rmt_common.c | 14 +++++++++++++- .../legacy_rmt_driver/main/test_legacy_rmt.c | 2 +- components/driver/test_apps/rmt/pytest_rmt.py | 1 + components/hal/esp32c6/include/hal/rmt_ll.h | 12 +++++++++--- .../soc/esp32c6/include/soc/Kconfig.soc_caps.in | 6 +++++- .../soc/esp32c6/include/soc/clk_tree_defs.h | 15 ++++++++------- components/soc/esp32c6/include/soc/soc_caps.h | 3 ++- examples/peripherals/.build-test-rules.yml | 4 ---- .../main/stepper_motor_example_main.c | 4 ++-- .../rmt/stepper_motor/pytest_stepper_motor.py | 1 + 11 files changed, 42 insertions(+), 24 deletions(-) diff --git a/components/driver/.build-test-rules.yml b/components/driver/.build-test-rules.yml index 82493a7a79..d6c37bc11c 100644 --- a/components/driver/.build-test-rules.yml +++ b/components/driver/.build-test-rules.yml @@ -73,10 +73,6 @@ components/driver/test_apps/pulse_cnt: components/driver/test_apps/rmt: disable: - if: SOC_RMT_SUPPORTED != 1 - disable_test: - - if: IDF_TARGET == "esp32c6" - temporary: true - reason: target esp32c6 is not supported yet components/driver/test_apps/rs485: disable_test: diff --git a/components/driver/rmt/rmt_common.c b/components/driver/rmt/rmt_common.c index e3dc6ed448..33af3fc8fa 100644 --- a/components/driver/rmt/rmt_common.c +++ b/components/driver/rmt/rmt_common.c @@ -133,8 +133,20 @@ esp_err_t rmt_select_periph_clock(rmt_channel_handle_t chan, rmt_clock_source_t 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 -#endif // SOC_RMT_SUPPORT_APB 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 diff --git a/components/driver/test_apps/legacy_rmt_driver/main/test_legacy_rmt.c b/components/driver/test_apps/legacy_rmt_driver/main/test_legacy_rmt.c index 9ad9c3ae2a..b73d40ec64 100644 --- a/components/driver/test_apps/legacy_rmt_driver/main/test_legacy_rmt.c +++ b/components/driver/test_apps/legacy_rmt_driver/main/test_legacy_rmt.c @@ -618,7 +618,7 @@ TEST_CASE("RMT Interrupt IRAM Safe", "[rmt]") .rmt_mode = RMT_MODE_TX, }; TEST_ESP_OK(rmt_config(&tx)); - TEST_ESP_OK(rmt_set_source_clk(tx.channel, RMT_BASECLK_APB)); + TEST_ESP_OK(rmt_set_source_clk(tx.channel, RMT_BASECLK_DEFAULT)); // install interrupt with IRAM safe TEST_ESP_OK(rmt_driver_install(tx.channel, 0, ESP_INTR_FLAG_IRAM)); diff --git a/components/driver/test_apps/rmt/pytest_rmt.py b/components/driver/test_apps/rmt/pytest_rmt.py index 441f669120..61ac424f66 100644 --- a/components/driver/test_apps/rmt/pytest_rmt.py +++ b/components/driver/test_apps/rmt/pytest_rmt.py @@ -9,6 +9,7 @@ from pytest_embedded import Dut @pytest.mark.esp32s2 @pytest.mark.esp32s3 @pytest.mark.esp32c3 +@pytest.mark.esp32c6 @pytest.mark.generic @pytest.mark.parametrize( 'config', diff --git a/components/hal/esp32c6/include/hal/rmt_ll.h b/components/hal/esp32c6/include/hal/rmt_ll.h index 35beca2c9c..497e5d1aca 100644 --- a/components/hal/esp32c6/include/hal/rmt_ll.h +++ b/components/hal/esp32c6/include/hal/rmt_ll.h @@ -95,9 +95,12 @@ static inline void rmt_ll_set_group_clock_src(rmt_dev_t *dev, uint32_t channel, PCR.rmt_sclk_conf.rmt_sclk_div_a = divider_numerator; PCR.rmt_sclk_conf.rmt_sclk_div_b = divider_denominator; switch (src) { - case RMT_CLK_SRC_APB: + case RMT_CLK_SRC_PLL_F80M: PCR.rmt_sclk_conf.rmt_sclk_sel = 1; break; + case RMT_CLK_SRC_RC_FAST: + PCR.rmt_sclk_conf.rmt_sclk_sel = 2; + break; case RMT_CLK_SRC_XTAL: PCR.rmt_sclk_conf.rmt_sclk_sel = 3; break; @@ -758,10 +761,13 @@ static inline bool rmt_ll_tx_is_loop_enabled(rmt_dev_t *dev, uint32_t channel) __attribute__((always_inline)) static inline rmt_clock_source_t rmt_ll_get_group_clock_src(rmt_dev_t *dev, uint32_t channel) { - rmt_clock_source_t clk_src = RMT_CLK_SRC_APB; + rmt_clock_source_t clk_src = RMT_CLK_SRC_PLL_F80M; switch (PCR.rmt_sclk_conf.rmt_sclk_sel) { case 1: - clk_src = RMT_CLK_SRC_APB; + clk_src = RMT_CLK_SRC_PLL_F80M; + break; + case 2: + clk_src = RMT_CLK_SRC_RC_FAST; break; case 3: clk_src = RMT_CLK_SRC_XTAL; diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index ee3f246389..01190a4321 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -515,7 +515,11 @@ config SOC_RMT_SUPPORT_XTAL bool default y -config SOC_RMT_SUPPORT_APB +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/clk_tree_defs.h b/components/soc/esp32c6/include/soc/clk_tree_defs.h index 8fa92582e9..b062d22310 100644 --- a/components/soc/esp32c6/include/soc/clk_tree_defs.h +++ b/components/soc/esp32c6/include/soc/clk_tree_defs.h @@ -174,24 +174,25 @@ typedef enum { /** * @brief Array initializer for all supported clock sources of RMT */ -#define SOC_RMT_CLKS {SOC_MOD_CLK_APB, SOC_MOD_CLK_XTAL} +#define SOC_RMT_CLKS {SOC_MOD_CLK_PLL_F80M, SOC_MOD_CLK_RC_FAST, SOC_MOD_CLK_XTAL} /** * @brief Type of RMT clock source */ typedef enum { - RMT_CLK_SRC_APB = SOC_MOD_CLK_APB, /*!< Select APB as the source clock */ - RMT_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ - RMT_CLK_SRC_DEFAULT = SOC_MOD_CLK_APB, /*!< Select APB as the default choice */ + RMT_CLK_SRC_PLL_F80M = SOC_MOD_CLK_PLL_F80M, /*!< Select PLL_F80M as the source clock */ + RMT_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */ + RMT_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ + RMT_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F80M, /*!< Select PLL_F80M as the default choice */ } soc_periph_rmt_clk_src_t; /** * @brief Type of RMT clock source, reserved for the legacy RMT driver */ typedef enum { - RMT_BASECLK_APB = SOC_MOD_CLK_APB, /*!< RMT source clock is APB */ - RMT_BASECLK_XTAL = SOC_MOD_CLK_XTAL, /*!< RMT source clock is XTAL */ - RMT_BASECLK_DEFAULT = SOC_MOD_CLK_APB, /*!< RMT source clock default choice is APB */ + RMT_BASECLK_PLL_F80M = SOC_MOD_CLK_PLL_F80M, /*!< RMT source clock is PLL_F80M */ + RMT_BASECLK_XTAL = SOC_MOD_CLK_XTAL, /*!< RMT source clock is XTAL */ + RMT_BASECLK_DEFAULT = SOC_MOD_CLK_PLL_F80M, /*!< RMT source clock default choice is PLL_F80M */ } soc_periph_rmt_clk_src_legacy_t; //////////////////////////////////////////////////Temp Sensor/////////////////////////////////////////////////////////// diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 190f74a4ef..93339c3e52 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -252,7 +252,8 @@ #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_APB 1 /*!< Support set APB 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 --------------------------------------*/ #define SOC_MCPWM_GROUPS (1U) ///< 1 MCPWM groups on the chip (i.e., the number of independent MCPWM peripherals) diff --git a/examples/peripherals/.build-test-rules.yml b/examples/peripherals/.build-test-rules.yml index 6ccf051edc..3320f9228c 100644 --- a/examples/peripherals/.build-test-rules.yml +++ b/examples/peripherals/.build-test-rules.yml @@ -131,10 +131,6 @@ examples/peripherals/rmt/onewire_ds18b20: examples/peripherals/rmt/stepper_motor: disable: - if: SOC_RMT_SUPPORT_TX_LOOP_AUTO_STOP != 1 - disable_test: - - if: IDF_TARGET == "esp32c6" - temporary: true - reason: target esp32c6 is not supported yet examples/peripherals/sdio/host: enable: diff --git a/examples/peripherals/rmt/stepper_motor/main/stepper_motor_example_main.c b/examples/peripherals/rmt/stepper_motor/main/stepper_motor_example_main.c index f25051ba2e..0db125df37 100644 --- a/examples/peripherals/rmt/stepper_motor/main/stepper_motor_example_main.c +++ b/examples/peripherals/rmt/stepper_motor/main/stepper_motor_example_main.c @@ -12,8 +12,8 @@ #include "stepper_motor_encoder.h" ///////////////////////////////Change the following configurations according to your board////////////////////////////// -#define STEP_MOTOR_GPIO_EN 16 -#define STEP_MOTOR_GPIO_DIR 17 +#define STEP_MOTOR_GPIO_EN 19 +#define STEP_MOTOR_GPIO_DIR 20 #define STEP_MOTOR_GPIO_STEP 18 #define STEP_MOTOR_ENABLE_LEVEL 0 // DRV8825 is enabled on low level #define STEP_MOTOR_SPIN_DIR_CLOCKWISE 0 diff --git a/examples/peripherals/rmt/stepper_motor/pytest_stepper_motor.py b/examples/peripherals/rmt/stepper_motor/pytest_stepper_motor.py index 1fceeb0cf2..2449c0d776 100644 --- a/examples/peripherals/rmt/stepper_motor/pytest_stepper_motor.py +++ b/examples/peripherals/rmt/stepper_motor/pytest_stepper_motor.py @@ -6,6 +6,7 @@ from pytest_embedded import Dut @pytest.mark.esp32s3 +@pytest.mark.esp32c6 @pytest.mark.generic def test_stepper_motor_example(dut: Dut) -> None: dut.expect_exact('example: Initialize EN + DIR GPIO')