From 00eb97725ba97702dc7c851d66e41d2314592816 Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Wed, 31 Jul 2024 09:39:22 +0800 Subject: [PATCH] feat(system): support choosing xtal as rtc-fast clock src on P4 and C5 With xtal as rtc-fast clock source the LP-Core can run at twice the default clock frequency. 40 MHz as opposed to 20 MHz. --- .../esp_hw_support/port/esp32c5/Kconfig.rtc | 21 +++++++++++++++++++ .../esp_hw_support/port/esp32p4/Kconfig.rtc | 21 +++++++++++++++++++ .../esp_hw_support/port/esp_clk_tree_common.c | 2 +- components/esp_system/port/soc/esp32c5/clk.c | 6 ++++++ components/esp_system/port/soc/esp32p4/clk.c | 6 ++++++ .../esp32p4/include/soc/Kconfig.soc_caps.in | 4 ++++ components/soc/esp32p4/include/soc/soc_caps.h | 2 ++ .../ulp/lp_core/lp_core/lp_core_utils.c | 10 +++++++++ .../ulp/test_apps/.build-test-rules.yml | 7 ++++++- .../lp_core_basic_tests/main/test_lp_core.c | 5 +++-- .../pytest_lp_core_basic.py | 21 +++++++++++++++++++ .../lp_core_basic_tests/sdkconfig.ci.xtal | 1 + docs/en/api-reference/system/ulp-lp-core.rst | 13 ++++++++++++ 13 files changed, 115 insertions(+), 4 deletions(-) create mode 100644 components/ulp/test_apps/lp_core/lp_core_basic_tests/sdkconfig.ci.xtal diff --git a/components/esp_hw_support/port/esp32c5/Kconfig.rtc b/components/esp_hw_support/port/esp32c5/Kconfig.rtc index ce8a3ebe90..7a897a9504 100644 --- a/components/esp_hw_support/port/esp32c5/Kconfig.rtc +++ b/components/esp_hw_support/port/esp32c5/Kconfig.rtc @@ -35,3 +35,24 @@ config RTC_CLK_CAL_CYCLES - 32768 Hz if the 32k crystal oscillator is used. For this use value 3000 or more. In case more value will help improve the definition of the launch of the crystal. If the crystal could not start, it will be switched to internal RC. + +choice RTC_FAST_CLK_SRC + depends on SOC_CLK_LP_FAST_SUPPORT_XTAL + prompt "RTC fast clock source" + default RTC_FAST_CLK_SRC_RC_FAST + help + Choose which clock is used as RTC fast clock source. + + Choosing the faster 48 MHz external crystal clock (XTAL) can allow modules which depend on RTC_FAST + to work at a higher clock frequency. With this the ULP LP-Core will run with a + CPU frequency of 48 Mhz instead of the default 20 Mhz. + + The drawback is that the XTAL is usually powered down during sleep, as + it draw a lot of power. Choosing this option will cause the XTAL to stay + powered on, increasing sleep power consumption. + + config RTC_FAST_CLK_SRC_RC_FAST + bool "20 Mhz RC Fast Clock" + config RTC_FAST_CLK_SRC_XTAL + bool "48 Mhz crystal (increased power consumption during sleep)" +endchoice diff --git a/components/esp_hw_support/port/esp32p4/Kconfig.rtc b/components/esp_hw_support/port/esp32p4/Kconfig.rtc index 19541352ab..3c5c409f62 100644 --- a/components/esp_hw_support/port/esp32p4/Kconfig.rtc +++ b/components/esp_hw_support/port/esp32p4/Kconfig.rtc @@ -34,3 +34,24 @@ config RTC_CLK_CAL_CYCLES - 32768 Hz if the 32k crystal oscillator is used. For this use value 3000 or more. In case more value will help improve the definition of the launch of the crystal. If the crystal could not start, it will be switched to internal RC. + +choice RTC_FAST_CLK_SRC + depends on SOC_CLK_LP_FAST_SUPPORT_XTAL + prompt "RTC fast clock source" + default RTC_FAST_CLK_SRC_RC_FAST + help + Choose which clock is used as RTC fast clock source. + + Choosing the faster 40 MHz XTAL can allow modules which depend on RTC_FAST + to work at a higher clock frequency. With this the ULP LP-Core will run with a + CPU frequency of 40 Mhz instead of the default 20 Mhz. + + The drawback is that the XTAL is usually powered down during sleep, as + it draw a lot of power. Choosing this option will cause the XTAL to stay + powered on, increasing sleep power consumption. + + config RTC_FAST_CLK_SRC_RC_FAST + bool "20 Mhz RC Fast Clock" + config RTC_FAST_CLK_SRC_XTAL + bool "40 Mhz crystal (increased power consumption during sleep)" +endchoice diff --git a/components/esp_hw_support/port/esp_clk_tree_common.c b/components/esp_hw_support/port/esp_clk_tree_common.c index cf5a2eece1..6a971e2468 100644 --- a/components/esp_hw_support/port/esp_clk_tree_common.c +++ b/components/esp_hw_support/port/esp_clk_tree_common.c @@ -191,7 +191,7 @@ uint32_t esp_clk_tree_lp_fast_get_freq_hz(esp_clk_tree_src_freq_precision_t prec case SOC_RTC_FAST_CLK_SRC_LP_PLL: return clk_ll_lp_pll_get_freq_mhz() * MHZ; #endif -#if SOC_CLK_LP_FAST_SUPPORT_XTAL +#if SOC_CLK_LP_FAST_SUPPORT_XTAL && !CONFIG_IDF_TARGET_ESP32P4 // On P4 SOC_RTC_FAST_CLK_SRC_XTAL is an alias for SOC_RTC_FAST_CLK_SRC_XTAL_DIV case SOC_RTC_FAST_CLK_SRC_XTAL: return clk_hal_xtal_get_freq_mhz() * MHZ; #endif diff --git a/components/esp_system/port/soc/esp32c5/clk.c b/components/esp_system/port/soc/esp32c5/clk.c index c8f0bd1bf8..bf9e58487f 100644 --- a/components/esp_system/port/soc/esp32c5/clk.c +++ b/components/esp_system/port/soc/esp32c5/clk.c @@ -56,8 +56,14 @@ __attribute__((weak)) void esp_clk_init(void) assert((rtc_clk_xtal_freq_get() == SOC_XTAL_FREQ_48M) || (rtc_clk_xtal_freq_get() == SOC_XTAL_FREQ_40M)); rtc_clk_8m_enable(true); +#if CONFIG_RTC_FAST_CLK_SRC_RC_FAST rtc_clk_fast_src_set(SOC_RTC_FAST_CLK_SRC_RC_FAST); +#elif CONFIG_RTC_FAST_CLK_SRC_XTAL + rtc_clk_fast_src_set(SOC_RTC_FAST_CLK_SRC_XTAL); +#else +#error "No RTC fast clock source configured" #endif +#endif //!CONFIG_IDF_ENV_FPGA #ifdef CONFIG_BOOTLOADER_WDT_ENABLE // WDT uses a SLOW_CLK clock source. After a function select_rtc_slow_clk a frequency of this source can changed. diff --git a/components/esp_system/port/soc/esp32p4/clk.c b/components/esp_system/port/soc/esp32p4/clk.c index 49f9737e8e..2a2c67dda0 100644 --- a/components/esp_system/port/soc/esp32p4/clk.c +++ b/components/esp_system/port/soc/esp32p4/clk.c @@ -53,7 +53,13 @@ __attribute__((weak)) void esp_clk_init(void) assert(rtc_clk_xtal_freq_get() == SOC_XTAL_FREQ_40M); rtc_clk_8m_enable(true); +#if CONFIG_RTC_FAST_CLK_SRC_RC_FAST rtc_clk_fast_src_set(SOC_RTC_FAST_CLK_SRC_RC_FAST); +#elif CONFIG_RTC_FAST_CLK_SRC_XTAL + rtc_clk_fast_src_set(SOC_RTC_FAST_CLK_SRC_XTAL); +#else +#error "No RTC fast clock source configured" +#endif #ifdef CONFIG_BOOTLOADER_WDT_ENABLE // WDT uses a SLOW_CLK clock source. After a function select_rtc_slow_clk a frequency of this source can changed. diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index fd4fb65c29..2fade1d44b 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1751,6 +1751,10 @@ config SOC_CLK_LP_FAST_SUPPORT_LP_PLL bool default y +config SOC_CLK_LP_FAST_SUPPORT_XTAL + bool + default y + config SOC_PERIPH_CLK_CTRL_SHARED bool default y diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 0dce165cf3..0a50c51b3c 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -682,6 +682,8 @@ #define SOC_CLK_RC32K_SUPPORTED (1) /*!< Support an internal 32kHz RC oscillator */ #define SOC_CLK_LP_FAST_SUPPORT_LP_PLL (1) /*!< Support LP_PLL clock as the LP_FAST clock source */ +#define SOC_CLK_LP_FAST_SUPPORT_XTAL (1) /*!< Support XTAL clock as the LP_FAST clock source */ + #define SOC_PERIPH_CLK_CTRL_SHARED (1) /*!< Peripheral clock control (e.g. set clock source) is shared between various peripherals */ diff --git a/components/ulp/lp_core/lp_core/lp_core_utils.c b/components/ulp/lp_core/lp_core/lp_core_utils.c index 0eecf4006d..07e63200f0 100644 --- a/components/ulp/lp_core/lp_core/lp_core_utils.c +++ b/components/ulp/lp_core/lp_core/lp_core_utils.c @@ -28,7 +28,17 @@ #endif /* LP_FAST_CLK is not very accurate, for now use a rough estimate */ +#if CONFIG_RTC_FAST_CLK_SRC_RC_FAST #define LP_CORE_CPU_FREQUENCY_HZ 16000000 // For P4 TRM says 20 MHz by default, but we tune it closer to 16 MHz +#elif CONFIG_RTC_FAST_CLK_SRC_XTAL +#if SOC_XTAL_SUPPORT_48M +#define LP_CORE_CPU_FREQUENCY_HZ 48000000 +#else +#define LP_CORE_CPU_FREQUENCY_HZ 40000000 +#endif +#else // Default value in chip without rtc fast clock sel option +#define LP_CORE_CPU_FREQUENCY_HZ 16000000 +#endif static uint32_t lp_wakeup_cause = 0; diff --git a/components/ulp/test_apps/.build-test-rules.yml b/components/ulp/test_apps/.build-test-rules.yml index 0f1c3e5be9..b3c0386d56 100644 --- a/components/ulp/test_apps/.build-test-rules.yml +++ b/components/ulp/test_apps/.build-test-rules.yml @@ -1,6 +1,11 @@ # Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps -components/ulp/test_apps/lp_core: +components/ulp/test_apps/lp_core/lp_core_basic_tests: + disable: + - if: SOC_LP_CORE_SUPPORTED != 1 + - if: CONFIG_NAME == "xtal" and SOC_CLK_LP_FAST_SUPPORT_XTAL != 1 + +components/ulp/test_apps/lp_core/lp_core_hp_uart: disable: - if: SOC_LP_CORE_SUPPORTED != 1 diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/test_lp_core.c b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/test_lp_core.c index bc1102c75f..62ead4122d 100644 --- a/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/test_lp_core.c +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/main/test_lp_core.c @@ -132,6 +132,7 @@ TEST_CASE("Test LP core delay", "[lp_core]") #define LP_TIMER_TEST_SLEEP_DURATION_US (20000) #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C5) +#if SOC_DEEP_SLEEP_SUPPORTED && CONFIG_RTC_FAST_CLK_SRC_RC_FAST static void do_ulp_wakeup_deepsleep(lp_core_test_commands_t ulp_cmd) { @@ -228,7 +229,8 @@ TEST_CASE_MULTIPLE_STAGES("LP Timer can wakeup lp core periodically during deep do_ulp_wakeup_with_lp_timer_deepsleep, check_reset_reason_and_sleep_duration); -#endif //#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C5) +#endif //#if SOC_DEEP_SLEEP_SUPPORTED && CONFIG_RTC_FAST_CLK_SRC_RC_FAST +#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32C5) TEST_CASE("LP Timer can wakeup lp core periodically", "[lp_core]") { @@ -382,5 +384,4 @@ TEST_CASE("LP core ISR tests", "[ulp]") printf("ULP LP IO ISR triggered %"PRIu32" times\n", ulp_io_isr_counter); TEST_ASSERT_EQUAL(ISR_TEST_ITERATIONS, ulp_io_isr_counter); #endif //SOC_RTCIO_PIN_COUNT > 0 - } diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/pytest_lp_core_basic.py b/components/ulp/test_apps/lp_core/lp_core_basic_tests/pytest_lp_core_basic.py index 325bd2ca59..53178dca4e 100644 --- a/components/ulp/test_apps/lp_core/lp_core_basic_tests/pytest_lp_core_basic.py +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/pytest_lp_core_basic.py @@ -8,10 +8,31 @@ from pytest_embedded import Dut @pytest.mark.esp32c6 @pytest.mark.esp32p4 @pytest.mark.generic +@pytest.mark.parametrize( + 'config', + [ + 'default', + ], + indirect=True, +) def test_lp_core(dut: Dut) -> None: dut.run_all_single_board_cases() +@pytest.mark.esp32c5 +@pytest.mark.esp32p4 +@pytest.mark.generic +@pytest.mark.parametrize( + 'config', + [ + 'xtal', + ], + indirect=True, +) +def test_lp_core_xtal(dut: Dut) -> None: + dut.run_all_single_board_cases() + + @pytest.mark.esp32c6 # TODO: Enable LP I2C test for esp32p4 (IDF-9407) @pytest.mark.generic_multi_device diff --git a/components/ulp/test_apps/lp_core/lp_core_basic_tests/sdkconfig.ci.xtal b/components/ulp/test_apps/lp_core/lp_core_basic_tests/sdkconfig.ci.xtal new file mode 100644 index 0000000000..340667e4bd --- /dev/null +++ b/components/ulp/test_apps/lp_core/lp_core_basic_tests/sdkconfig.ci.xtal @@ -0,0 +1 @@ +CONFIG_RTC_FAST_CLK_SRC_XTAL=y diff --git a/docs/en/api-reference/system/ulp-lp-core.rst b/docs/en/api-reference/system/ulp-lp-core.rst index fa4005e14a..13753476e1 100644 --- a/docs/en/api-reference/system/ulp-lp-core.rst +++ b/docs/en/api-reference/system/ulp-lp-core.rst @@ -262,6 +262,19 @@ For example, to override the handler for the LP IO interrupt, you can define the In addition to configuring the interrupt related registers for the interrupt source you want to handle, you also need to enable the interrupts globally in the LP-Core interrupt controller. This can be done using the :cpp:func:`ulp_lp_core_intr_enable` function. +ULP LP-Core Clock Configuration +------------------------------- +{IDF_TARGET_XTAL_FREQ:default="Not updated", esp32c5="48 MHz", esp32p4="40 MHz"} + +The ULP LP-Core clock source is based on the system clock ``LP_FAST_CLK``, see `TRM <{IDF_TARGET_TRM_EN_URL}>`__ > ``Reset and Clock`` for more details. + +.. only:: SOC_CLK_LP_FAST_SUPPORT_XTAL + + On {IDF_TARGET_NAME} ``LP_FAST_CLK`` supports using the external {IDF_TARGET_XTAL_FREQ} crystal (XTAL) as the source for ``LP_FAST_CLK``, which allows the ULP LP-Core to run at a higher frequency than with the default ``RTC_FAST_CLOCK`` which runs at around 20 MHz. The drawback is that this clock is normally powered down during sleep to reduce power consumption, with it selected XTAL will also stay powered on during sleep, increasing power consumption. If you only plan to use the LP-Core as a co-processor while the HP-Core is active, then this option can be used to increase both the performance and the frequency stability of the LP-Core. + + To enable this feature set :ref:`CONFIG_RTC_FAST_CLK_SRC` to ``CONFIG_RTC_FAST_CLK_SRC_XTAL``. + + Debugging ULP LP-Core Applications ----------------------------------