diff --git a/components/driver/CMakeLists.txt b/components/driver/CMakeLists.txt index abaa4315da1e..f1e499a27856 100644 --- a/components/driver/CMakeLists.txt +++ b/components/driver/CMakeLists.txt @@ -183,7 +183,8 @@ endif() # USB Serial JTAG related source files if(CONFIG_SOC_USB_SERIAL_JTAG_SUPPORTED) - list(APPEND srcs "usb_serial_jtag/usb_serial_jtag.c") + list(APPEND srcs "usb_serial_jtag/usb_serial_jtag.c" + "usb_serial_jtag/usb_serial_jtag_connection_monitor.c") endif() # Other source files @@ -204,3 +205,10 @@ else() REQUIRES esp_pm esp_ringbuf freertos soc hal esp_hw_support LDFRAGMENTS linker.lf) endif() + +# If system needs to monitor USJ connection status, then usb_serial_jtag_connection_monitor object file has to be linked +# to the binary, to allow tick hook to be registered +if(CONFIG_USJ_NO_AUTO_LS_ON_CONNECTION OR + (CONFIG_SOC_USB_SERIAL_JTAG_SUPPORT_LIGHT_SLEEP AND CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED)) + target_link_libraries(${COMPONENT_LIB} INTERFACE "-u usb_serial_jtag_connection_monitor_include") +endif() diff --git a/components/driver/Kconfig b/components/driver/Kconfig index b60bf8cef368..b3985314f6ce 100644 --- a/components/driver/Kconfig +++ b/components/driver/Kconfig @@ -461,4 +461,21 @@ menu "Driver Configurations" endmenu # DAC Configuration + menu "USB Serial/JTAG Configuration" + depends on SOC_USB_SERIAL_JTAG_SUPPORTED + config USJ_NO_AUTO_LS_ON_CONNECTION + bool "Don't enter the automatic light sleep when USB Serial/JTAG port is connected" + depends on PM_ENABLE && ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED && !SOC_USB_SERIAL_JTAG_SUPPORT_LIGHT_SLEEP + default n + help + If enabled, the chip will constantly monitor the connection status of the USB Serial/JTAG port. As long + as the USB Serial/JTAG is connected, a ESP_PM_NO_LIGHT_SLEEP power management lock will be acquired to + prevent the system from entering light sleep. + This option can be useful if serial monitoring is needed via USB Serial/JTAG while power management is + enabled, as the USB Serial/JTAG cannot work under light sleep and after waking up from light sleep. + Note. This option can only control the automatic Light-Sleep behavior. If esp_light_sleep_start() is + called manually from the program, enabling this option will not prevent light sleep entry even if the + USB Serial/JTAG is in use. + endmenu # USB Serial/JTAG Configuration + endmenu # Driver configurations diff --git a/components/driver/usb_serial_jtag/include/driver/usb_serial_jtag.h b/components/driver/usb_serial_jtag/include/driver/usb_serial_jtag.h index c1e97bb4d801..fec968a5bfce 100644 --- a/components/driver/usb_serial_jtag/include/driver/usb_serial_jtag.h +++ b/components/driver/usb_serial_jtag/include/driver/usb_serial_jtag.h @@ -82,6 +82,20 @@ int usb_serial_jtag_write_bytes(const void* src, size_t size, TickType_t ticks_t */ esp_err_t usb_serial_jtag_driver_uninstall(void); +/** + * @brief Check if the USB Serial/JTAG port is connected to the host + * + * This function checks whether the USB Serial/JTAG (USJ) port is currently connected. USJ is considered "connected" + * so long as it is receiving SOF packets from the host, even if there is no serial commuincation occuring (i.e., the + * USJ is connected to the PC, but the serial port is not opened). Having the USB port connected to a power bank will + * never be considered as connected (due to the lack of SOF packets). + * + * @note If your application needs this function, it will add some extra overhead time to every freertos tick. + * + * @return True if USJ is connected, false otherwise + */ +bool usb_serial_jtag_is_connected(void); + #ifdef __cplusplus } #endif diff --git a/components/driver/usb_serial_jtag/usb_serial_jtag_connection_monitor.c b/components/driver/usb_serial_jtag/usb_serial_jtag_connection_monitor.c new file mode 100644 index 000000000000..238069e20a2a --- /dev/null +++ b/components/driver/usb_serial_jtag/usb_serial_jtag_connection_monitor.c @@ -0,0 +1,89 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "driver/usb_serial_jtag.h" +#include "hal/usb_serial_jtag_ll.h" +#include "esp_private/startup_internal.h" +#include "esp_freertos_hooks.h" +#include "esp_pm.h" +#include "esp_private/rtc_clk.h" +#include "esp_check.h" +#include "sdkconfig.h" + +static volatile bool s_usb_serial_jtag_conn_status; +#if CONFIG_USJ_NO_AUTO_LS_ON_CONNECTION +static esp_pm_lock_handle_t s_usb_serial_jtag_pm_lock; +#endif + +// FreeRTOS tick interrupt may get delayed in handling, which could lead to no SOF coming in within the period from +// a delayed tick to the following tick. Therefore, when FREERTOS_HZ is comparable to SOF packet frequency, a NO_SOF +// tolerance needs to be given to avoid a false disconnection detection. +#define USJ_DISCONNECT_CONFIRM_PERIOD_MS 3 +#define ALLOWED_NO_SOF_TICKS pdMS_TO_TICKS(USJ_DISCONNECT_CONFIRM_PERIOD_MS) + +static uint32_t remaining_allowed_no_sof_ticks; + +static __attribute__((unused)) const char *USB_SERIAL_JTAG_CONN_MONITOR_TAG = "usb_serial_jtag"; + + +bool usb_serial_jtag_is_connected(void) +{ + return s_usb_serial_jtag_conn_status; +} + +static void IRAM_ATTR usb_serial_jtag_sof_tick_hook(void) +{ + // SOF packet is sent by the HOST every 1ms on a full speed bus + // Between two consecutive tick hooks, there will be at least 1ms (selectable tick rate range is 1 - 1000Hz) + // Therefore, SOF intr bit must have be raised at every tick hook if it is connected to a HOST + // Here, the strategy is: Always assume USB Serial/JTAG is connected until we are sure it is not connected + // Consider it is disconnected only if SOF intr bit is not raised within (ALLOWED_NO_SOF_TICKS + 1) tick periods + bool sof_received = (usb_serial_jtag_ll_get_intraw_mask() & USB_SERIAL_JTAG_INTR_SOF); + usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SOF); + if (s_usb_serial_jtag_conn_status != sof_received) { + if (!sof_received) { + if (remaining_allowed_no_sof_ticks > 0) { + remaining_allowed_no_sof_ticks--; + } else { + // Tolerance credit used up, considered as USJ disconnected +#if CONFIG_USJ_NO_AUTO_LS_ON_CONNECTION + esp_pm_lock_release(s_usb_serial_jtag_pm_lock); +#endif + rtc_clk_bbpll_remove_consumer(); + s_usb_serial_jtag_conn_status = false; + } + } else { + // USJ re-connected +#if CONFIG_USJ_NO_AUTO_LS_ON_CONNECTION + esp_pm_lock_acquire(s_usb_serial_jtag_pm_lock); +#endif + rtc_clk_bbpll_add_consumer(); + s_usb_serial_jtag_conn_status = true; + remaining_allowed_no_sof_ticks = ALLOWED_NO_SOF_TICKS; + } + } +} + +ESP_SYSTEM_INIT_FN(usb_serial_jtag_conn_status_init, BIT(0), 230) +{ +#if CONFIG_USJ_NO_AUTO_LS_ON_CONNECTION + ESP_RETURN_ON_ERROR(esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "usb_serial_jtag", &s_usb_serial_jtag_pm_lock), + USB_SERIAL_JTAG_CONN_MONITOR_TAG, "create NO_LIGHT_SLEEP lock failed"); + // We always assume it is connected at first, so acquires the lock to avoid auto light sleep + esp_pm_lock_acquire(s_usb_serial_jtag_pm_lock); +#endif + rtc_clk_bbpll_add_consumer(); + s_usb_serial_jtag_conn_status = true; + remaining_allowed_no_sof_ticks = ALLOWED_NO_SOF_TICKS; + + return esp_register_freertos_tick_hook(usb_serial_jtag_sof_tick_hook); +} + +void usb_serial_jtag_connection_monitor_include(void) +{ + // Linker hook function, exists to make the linker examine this file +} diff --git a/components/esp_hw_support/Kconfig b/components/esp_hw_support/Kconfig index b15cf931e617..97bafe7bc0f2 100644 --- a/components/esp_hw_support/Kconfig +++ b/components/esp_hw_support/Kconfig @@ -135,31 +135,6 @@ menu "Hardware Settings" menu "RTC Clock Config" orsource "./port/$IDF_TARGET/Kconfig.rtc" - - config RTC_CLOCK_BBPLL_POWER_ON_WITH_USB - # This is used for configure the RTC clock. - bool "Keep BBPLL clock always work" - depends on ESP_CONSOLE_USB_SERIAL_JTAG || ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG - default y - help - When software switches the CPU clock source from BBPLL clock to XTAL, usually the BBPLL will be - switched off. This helps to save some power consumption in sleep modes. However this may also happen - during the software reset, resulting in the inactive (disconnected from host) of the USB_SERIAL_JTAG - device during software reset. - - When USB_SERIAL_JTAG is being used, whether to turn off the clock source during software reset and in - sleep modes is determined by RTC_CLOCK_BBPLL_POWER_ON_WITH_USB. - - - When RTC_CLOCK_BBPLL_POWER_ON_WITH_USB is enabled, the clock will be kept, so that the - USB_SERIAL_JTAG will keep alive during software reset. The side-effect is the increasing of power - consumption during sleep modes, even though USB_SERIAL_JTAG will not work in sleep modes. - - - When RTC_CLOCK_BBPLL_POWER_ON_WITH_USB is disabled, the clock will be turned off. USB_SERIAL_JTAG - will be inactive during software reset and in sleep modes. This saves some power consumption in - sleep modes. - - When USB_SERIAL_JTAG is not being used, software will always turn off BBPLL regardless of - RTC_CLOCK_BBPLL_POWER_ON_WITH_USB is set or not. endmenu menu "Peripheral Control" diff --git a/components/esp_hw_support/include/esp_private/rtc_clk.h b/components/esp_hw_support/include/esp_private/rtc_clk.h new file mode 100644 index 000000000000..7edf69be069b --- /dev/null +++ b/components/esp_hw_support/include/esp_private/rtc_clk.h @@ -0,0 +1,49 @@ +/* + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Switch CPU clock source to XTAL, and let cpu frequency equal to main XTAL frequency. + * + * This function does not disable BBPLL. If BBPLL requires to be disabled to save power, please call + * `rtc_clk_cpu_freq_set_xtal` instead. It does one extra check to see whether can disable the BBPLL after switching the + * CPU clock source to XTAL. + * + * Currently, this function should only be called in `esp_restart_noos` and `esp_restart_noos_dig` to switch the CPU + * clock source back to XTAL (by default) before reset. + */ +void rtc_clk_cpu_set_to_default_config(void); + +/** + * @brief Notify that the BBPLL has a new in-use consumer + * + * Currently, this function is only used for tracking whether USB Serial/JTAG is using the 48MHz PHY clock + * + * Note: Calling this function only helps to not disable the BBPLL clock in `rtc_clk_cpu_freq_set_config`. + * For light and deep sleep, whether to disable the BBPLL in the interal call to `rtc_clk_cpu_freq_set_xtal` + * varies for targets. + * On ESP32C3/S3, USB CDC device can not function properly during sleep due to the lack of APB clock. Therefore. + * `rtc_clk_cpu_freq_set_xtal` will always disable BBPLL, no matter whether BBPLL has any consumer. + * On ESP32C6/H2, USB CDC device can maintain the minimum connection with the host during sleep, so + * `rtc_clk_cpu_freq_set_xtal` will check for BBPLL consumers, and keep BBPLL if USB Serial/JTAG is in use. + */ +void rtc_clk_bbpll_add_consumer(void); + +/** + * @brief Notify that the BBPLL has lost a consumer + */ +void rtc_clk_bbpll_remove_consumer(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/port/esp32/rtc_clk.c b/components/esp_hw_support/port/esp32/rtc_clk.c index acdde51d6880..3f3a08666745 100644 --- a/components/esp_hw_support/port/esp32/rtc_clk.c +++ b/components/esp_hw_support/port/esp32/rtc_clk.c @@ -9,6 +9,7 @@ #include #include #include "soc/rtc.h" +#include "esp_private/rtc_clk.h" #include "soc/rtc_periph.h" #include "soc/sens_periph.h" #include "soc/soc_caps.h" @@ -347,20 +348,22 @@ static void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq) } /** - * Switch to XTAL frequency. Does not disable the PLL. + * Switch to use XTAL as the CPU clock source. + * Must satisfy: cpu_freq = XTAL_FREQ / div. + * Does not disable the PLL. */ -void rtc_clk_cpu_freq_to_xtal(int freq, int div) +void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div) { - ets_update_cpu_frequency(freq); + ets_update_cpu_frequency(cpu_freq); /* set divider from XTAL to APB clock */ clk_ll_cpu_set_divider(div); /* adjust ref_tick */ - clk_ll_ref_tick_set_divider(SOC_CPU_CLK_SRC_XTAL, freq); + clk_ll_ref_tick_set_divider(SOC_CPU_CLK_SRC_XTAL, cpu_freq); /* switch clock source */ clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL); - rtc_clk_apb_freq_update(freq * MHZ); + rtc_clk_apb_freq_update(cpu_freq * MHZ); /* lower the voltage */ - int dbias = (freq <= 2) ? DIG_DBIAS_2M : DIG_DBIAS_XTAL; + int dbias = (cpu_freq <= 2) ? DIG_DBIAS_2M : DIG_DBIAS_XTAL; REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, dbias); } @@ -396,12 +399,17 @@ static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz) } void rtc_clk_cpu_freq_set_xtal(void) +{ + rtc_clk_cpu_set_to_default_config(); + rtc_clk_bbpll_disable(); +} + +void rtc_clk_cpu_set_to_default_config(void) { int freq_mhz = (int)rtc_clk_xtal_freq_get(); rtc_clk_cpu_freq_to_xtal(freq_mhz, 1); rtc_clk_wait_for_slow_cycle(); - rtc_clk_bbpll_disable(); } bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t* out_config) diff --git a/components/esp_hw_support/port/esp32c2/rtc_clk.c b/components/esp_hw_support/port/esp32c2/rtc_clk.c index a0d88be36feb..425552b25fb6 100644 --- a/components/esp_hw_support/port/esp32c2/rtc_clk.c +++ b/components/esp_hw_support/port/esp32c2/rtc_clk.c @@ -15,6 +15,7 @@ #include "esp32c2/rom/uart.h" #include "esp32c2/rom/gpio.h" #include "soc/rtc.h" +#include "esp_private/rtc_clk.h" #include "hal/gpio_ll.h" #include "soc/io_mux_reg.h" #include "soc/soc.h" @@ -269,25 +270,32 @@ void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config) } void rtc_clk_cpu_freq_set_xtal(void) +{ + rtc_clk_cpu_set_to_default_config(); + rtc_clk_bbpll_disable(); +} + +void rtc_clk_cpu_set_to_default_config(void) { int freq_mhz = (int)rtc_clk_xtal_freq_get(); rtc_clk_cpu_freq_to_xtal(freq_mhz, 1); - rtc_clk_bbpll_disable(); } /** - * Switch to XTAL frequency. Does not disable the PLL. + * Switch to use XTAL as the CPU clock source. + * Must satisfy: cpu_freq = XTAL_FREQ / div. + * Does not disable the PLL. */ -void rtc_clk_cpu_freq_to_xtal(int freq, int div) +void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div) { - ets_update_cpu_frequency(freq); + ets_update_cpu_frequency(cpu_freq); /* Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0) first. */ clk_ll_cpu_set_divider(1); clk_ll_cpu_set_divider(div); /* switch clock source */ clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL); - rtc_clk_apb_freq_update(freq * MHZ); + rtc_clk_apb_freq_update(cpu_freq * MHZ); } static void rtc_clk_cpu_freq_to_8m(void) diff --git a/components/esp_hw_support/port/esp32c3/rtc_clk.c b/components/esp_hw_support/port/esp32c3/rtc_clk.c index 7e307aaa171f..89bf37e28a66 100644 --- a/components/esp_hw_support/port/esp32c3/rtc_clk.c +++ b/components/esp_hw_support/port/esp32c3/rtc_clk.c @@ -13,9 +13,9 @@ #include "esp32c3/rom/ets_sys.h" #include "esp32c3/rom/rtc.h" #include "soc/rtc.h" +#include "esp_private/rtc_clk.h" #include "esp_hw_log.h" #include "esp_rom_sys.h" -#include "hal/usb_serial_jtag_ll.h" #include "hal/clk_tree_ll.h" #include "hal/regi2c_ctrl_ll.h" @@ -26,7 +26,18 @@ static int s_cur_pll_freq; static void rtc_clk_cpu_freq_to_xtal(int freq, int div); static void rtc_clk_cpu_freq_to_8m(void); -static bool rtc_clk_set_bbpll_always_on(void); + +static uint32_t s_bbpll_digi_consumers_ref_count = 0; // Currently, it only tracks whether the 48MHz PHY clock is in-use by USB Serial/JTAG + +void rtc_clk_bbpll_add_consumer(void) +{ + s_bbpll_digi_consumers_ref_count += 1; +} + +void rtc_clk_bbpll_remove_consumer(void) +{ + s_bbpll_digi_consumers_ref_count -= 1; +} void rtc_clk_32k_enable(bool enable) { @@ -208,8 +219,8 @@ void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config) soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src(); if (config->source == SOC_CPU_CLK_SRC_XTAL) { rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div); - if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) && !rtc_clk_set_bbpll_always_on()) { - // We don't turn off the bbpll if some consumers only depends on bbpll + if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) && !s_bbpll_digi_consumers_ref_count) { + // We don't turn off the bbpll if some consumers depend on bbpll rtc_clk_bbpll_disable(); } } else if (config->source == SOC_CPU_CLK_SRC_PLL) { @@ -220,8 +231,8 @@ void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config) rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz); } else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) { rtc_clk_cpu_freq_to_8m(); - if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) && !rtc_clk_set_bbpll_always_on()) { - // We don't turn off the bbpll if some consumers only depends on bbpll + if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) && !s_bbpll_digi_consumers_ref_count) { + // We don't turn off the bbpll if some consumers depend on bbpll rtc_clk_bbpll_disable(); } } @@ -284,28 +295,32 @@ void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config) } void rtc_clk_cpu_freq_set_xtal(void) +{ + rtc_clk_cpu_set_to_default_config(); + rtc_clk_bbpll_disable(); +} + +void rtc_clk_cpu_set_to_default_config(void) { int freq_mhz = (int)rtc_clk_xtal_freq_get(); rtc_clk_cpu_freq_to_xtal(freq_mhz, 1); - // We don't turn off the bbpll if some consumers only depends on bbpll - if (!rtc_clk_set_bbpll_always_on()) { - rtc_clk_bbpll_disable(); - } } /** - * Switch to XTAL frequency. Does not disable the PLL. + * Switch to use XTAL as the CPU clock source. + * Must satisfy: cpu_freq = XTAL_FREQ / div. + * Does not disable the PLL. */ -static void rtc_clk_cpu_freq_to_xtal(int freq, int div) +static void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div) { - ets_update_cpu_frequency(freq); + ets_update_cpu_frequency(cpu_freq); /* Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0) first. */ clk_ll_cpu_set_divider(1); clk_ll_cpu_set_divider(div); /* switch clock source */ clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL); - rtc_clk_apb_freq_update(freq * MHZ); + rtc_clk_apb_freq_update(cpu_freq * MHZ); } static void rtc_clk_cpu_freq_to_8m(void) @@ -368,21 +383,6 @@ bool rtc_dig_8m_enabled(void) return clk_ll_rc_fast_digi_is_enabled(); } -static bool rtc_clk_set_bbpll_always_on(void) -{ - /* We just keep the rtc bbpll clock on just under the case that - user selects the `RTC_CLOCK_BBPLL_POWER_ON_WITH_USB` as well as - the USB_SERIAL_JTAG is connected with PC. - */ - bool is_bbpll_on = false; -#if CONFIG_RTC_CLOCK_BBPLL_POWER_ON_WITH_USB - if (usb_serial_jtag_ll_txfifo_writable() == 1) { - is_bbpll_on = true; - } -#endif - return is_bbpll_on; -} - /* Name used in libphy.a:phy_chip_v7.o * TODO: update the library to use rtc_clk_xtal_freq_get */ diff --git a/components/esp_hw_support/port/esp32c6/rtc_clk.c b/components/esp_hw_support/port/esp32c6/rtc_clk.c index 091c9fbdc712..72986907b425 100644 --- a/components/esp_hw_support/port/esp32c6/rtc_clk.c +++ b/components/esp_hw_support/port/esp32c6/rtc_clk.c @@ -13,20 +13,30 @@ #include "esp32c6/rom/ets_sys.h" #include "esp32c6/rom/rtc.h" #include "soc/rtc.h" +#include "esp_private/rtc_clk.h" #include "esp_hw_log.h" #include "esp_rom_sys.h" #include "hal/clk_tree_ll.h" #include "hal/regi2c_ctrl_ll.h" #include "soc/io_mux_reg.h" #include "soc/lp_aon_reg.h" -#include "hal/usb_serial_jtag_ll.h" static const char *TAG = "rtc_clk"; // Current PLL frequency, in 480MHz. Zero if PLL is not enabled. static int s_cur_pll_freq; -static bool rtc_clk_set_bbpll_always_on(void); +static uint32_t s_bbpll_digi_consumers_ref_count = 0; // Currently, it only tracks whether the 48MHz PHY clock is in-use by USB Serial/JTAG + +void rtc_clk_bbpll_add_consumer(void) +{ + s_bbpll_digi_consumers_ref_count += 1; +} + +void rtc_clk_bbpll_remove_consumer(void) +{ + s_bbpll_digi_consumers_ref_count -= 1; +} void rtc_clk_32k_enable(bool enable) { @@ -145,14 +155,16 @@ static void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq) } /** - * Switch to XTAL frequency. Does not disable the PLL. + * Switch to use XTAL as the CPU clock source. + * Must satisfy: cpu_freq = XTAL_FREQ / div. + * Does not disable the PLL. */ -static void rtc_clk_cpu_freq_to_xtal(int freq, int div) +static void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div) { clk_ll_ahb_set_ls_divider(div); clk_ll_cpu_set_ls_divider(div); clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL); - ets_update_cpu_frequency(freq); + ets_update_cpu_frequency(cpu_freq); } static void rtc_clk_cpu_freq_to_8m(void) @@ -226,7 +238,8 @@ void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config) soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src(); if (config->source == SOC_CPU_CLK_SRC_XTAL) { rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div); - if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) && !rtc_clk_set_bbpll_always_on()) { + if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) && !s_bbpll_digi_consumers_ref_count) { + // We don't turn off the bbpll if some consumers depend on bbpll rtc_clk_bbpll_disable(); } } else if (config->source == SOC_CPU_CLK_SRC_PLL) { @@ -237,7 +250,8 @@ void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config) rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz); } else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) { rtc_clk_cpu_freq_to_8m(); - if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) && !rtc_clk_set_bbpll_always_on()) { + if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) && !s_bbpll_digi_consumers_ref_count) { + // We don't turn off the bbpll if some consumers depend on bbpll rtc_clk_bbpll_disable(); } } @@ -295,14 +309,19 @@ void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config) } void rtc_clk_cpu_freq_set_xtal(void) +{ + rtc_clk_cpu_set_to_default_config(); + // We don't turn off the bbpll if some consumers depend on bbpll + if (!s_bbpll_digi_consumers_ref_count) { + rtc_clk_bbpll_disable(); + } +} + +void rtc_clk_cpu_set_to_default_config(void) { int freq_mhz = (int)rtc_clk_xtal_freq_get(); rtc_clk_cpu_freq_to_xtal(freq_mhz, 1); - // We don't turn off the bbpll if some consumers only depends on bbpll - if (!rtc_clk_set_bbpll_always_on()) { - rtc_clk_bbpll_disable(); - } } rtc_xtal_freq_t rtc_clk_xtal_freq_get(void) @@ -370,21 +389,6 @@ bool rtc_dig_8m_enabled(void) return clk_ll_rc_fast_digi_is_enabled(); } -static bool rtc_clk_set_bbpll_always_on(void) -{ - /* We just keep the rtc bbpll clock on just under the case that - user selects the `RTC_CLOCK_BBPLL_POWER_ON_WITH_USB` as well as - the USB_SERIAL_JTAG is connected with PC. - */ - bool is_bbpll_on = false; -#if CONFIG_RTC_CLOCK_BBPLL_POWER_ON_WITH_USB - if (usb_serial_jtag_ll_txfifo_writable() == 1) { - is_bbpll_on = true; - } -#endif - return is_bbpll_on; -} - /* Name used in libphy.a:phy_chip_v7.o * TODO: update the library to use rtc_clk_xtal_freq_get */ diff --git a/components/esp_hw_support/port/esp32h2/rtc_clk.c b/components/esp_hw_support/port/esp32h2/rtc_clk.c index 3494112553fa..93c66b0f7002 100644 --- a/components/esp_hw_support/port/esp32h2/rtc_clk.c +++ b/components/esp_hw_support/port/esp32h2/rtc_clk.c @@ -13,20 +13,31 @@ #include "esp32h2/rom/ets_sys.h" #include "esp32h2/rom/rtc.h" #include "soc/rtc.h" +#include "esp_private/rtc_clk.h" #include "esp_hw_log.h" #include "esp_rom_sys.h" -#include "hal/usb_serial_jtag_ll.h" #include "hal/clk_tree_ll.h" #include "hal/regi2c_ctrl_ll.h" #include "soc/io_mux_reg.h" #include "soc/lp_aon_reg.h" +#include "soc/lp_clkrst_reg.h" static const char *TAG = "rtc_clk"; // Current PLL frequency, in 96MHz. Zero if PLL is not enabled. static int s_cur_pll_freq; -static bool rtc_clk_set_bbpll_always_on(void); +static uint32_t s_bbpll_digi_consumers_ref_count = 0; // Currently, it only tracks whether the 48MHz PHY clock is in-use by USB Serial/JTAG + +void rtc_clk_bbpll_add_consumer(void) +{ + s_bbpll_digi_consumers_ref_count += 1; +} + +void rtc_clk_bbpll_remove_consumer(void) +{ + s_bbpll_digi_consumers_ref_count -= 1; +} void rtc_clk_32k_enable(bool enable) { @@ -161,16 +172,18 @@ static void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq) } /** - * Switch to XTAL frequency. Does not disable the PLL. + * Switch to use XTAL as the CPU clock source. + * Must satisfy: cpu_freq = XTAL_FREQ / div. + * Does not disable the PLL. */ -static void rtc_clk_cpu_freq_to_xtal(int freq, int div) +static void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div) { // let f_cpu = f_ahb clk_ll_cpu_set_divider(div); clk_ll_ahb_set_divider(div); clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL); clk_ll_bus_update(); - ets_update_cpu_frequency(freq); + ets_update_cpu_frequency(cpu_freq); } static void rtc_clk_cpu_freq_to_8m(void) @@ -271,7 +284,7 @@ void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config) if (config->source == SOC_CPU_CLK_SRC_XTAL) { rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div); if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL || old_cpu_clk_src == SOC_CPU_CLK_SRC_FLASH_PLL) && - !rtc_clk_set_bbpll_always_on()) { + !s_bbpll_digi_consumers_ref_count) { rtc_clk_bbpll_disable(); } } else if (config->source == SOC_CPU_CLK_SRC_PLL) { @@ -283,7 +296,7 @@ void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config) } else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) { rtc_clk_cpu_freq_to_8m(); if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL || old_cpu_clk_src == SOC_CPU_CLK_SRC_FLASH_PLL) && - !rtc_clk_set_bbpll_always_on()) { + !s_bbpll_digi_consumers_ref_count) { rtc_clk_bbpll_disable(); } } else if (config->source == SOC_CPU_CLK_SRC_FLASH_PLL) { @@ -356,16 +369,20 @@ void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config) void rtc_clk_cpu_freq_set_xtal(void) { - int freq_mhz = (int)rtc_clk_xtal_freq_get(); - - rtc_clk_cpu_freq_to_xtal(freq_mhz, 1); - // TODO: IDF-6243 MSPI clock source could also depend on bbpll, cpu restart should not disable bbpll + rtc_clk_cpu_set_to_default_config(); // We don't turn off the bbpll if some consumers only depends on bbpll - if (!rtc_clk_set_bbpll_always_on()) { + if (!s_bbpll_digi_consumers_ref_count) { rtc_clk_bbpll_disable(); } } +void rtc_clk_cpu_set_to_default_config(void) +{ + int freq_mhz = (int)rtc_clk_xtal_freq_get(); + + rtc_clk_cpu_freq_to_xtal(freq_mhz, 1); +} + rtc_xtal_freq_t rtc_clk_xtal_freq_get(void) { uint32_t xtal_freq_mhz = clk_ll_xtal_load_freq_mhz(); @@ -429,18 +446,3 @@ bool rtc_dig_8m_enabled(void) { return clk_ll_rc_fast_digi_is_enabled(); } - -static bool rtc_clk_set_bbpll_always_on(void) -{ - /* We just keep the rtc bbpll clock on just under the case that - user selects the `RTC_CLOCK_BBPLL_POWER_ON_WITH_USB` as well as - the USB_SERIAL_JTAG is connected with PC. - */ - bool is_bbpll_on = false; -#if CONFIG_RTC_CLOCK_BBPLL_POWER_ON_WITH_USB - if (usb_serial_jtag_ll_txfifo_writable() == 1) { - is_bbpll_on = true; - } -#endif - return is_bbpll_on; -} diff --git a/components/esp_hw_support/port/esp32h4/rtc_clk.c b/components/esp_hw_support/port/esp32h4/rtc_clk.c index c483ccd83ac6..417d5be1a8db 100644 --- a/components/esp_hw_support/port/esp32h4/rtc_clk.c +++ b/components/esp_hw_support/port/esp32h4/rtc_clk.c @@ -15,6 +15,7 @@ #include "esp32h4/rom/uart.h" #include "esp32h4/rom/gpio.h" #include "soc/rtc.h" +#include "esp_private/rtc_clk.h" #include "soc/io_mux_reg.h" #include "hal/clk_tree_ll.h" #include "hal/regi2c_ctrl_ll.h" @@ -33,6 +34,19 @@ static uint32_t rtc_clk_ahb_freq_get(void); static void rtc_clk_cpu_freq_to_xtal(int freq, int div); void rtc_clk_cpu_freq_to_8m(void); +// Unused as unsupported yet +static uint32_t __attribute((unused)) s_bbpll_digi_consumers_ref_count = 0; // Currently, it only tracks whether the 48MHz PHY clock is in-use by USB Serial/JTAG + +void rtc_clk_bbpll_add_consumer(void) +{ + s_bbpll_digi_consumers_ref_count += 1; +} + +void rtc_clk_bbpll_remove_consumer(void) +{ + s_bbpll_digi_consumers_ref_count -= 1; +} + static void rtc_gpio_hangup(uint32_t gpio_no) { gpio_ll_pulldown_dis(&GPIO, gpio_no); @@ -302,19 +316,26 @@ void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config) } void rtc_clk_cpu_freq_set_xtal(void) +{ + rtc_clk_cpu_set_to_default_config(); + rtc_clk_bbpll_disable(); +} + +void rtc_clk_cpu_set_to_default_config(void) { int freq_mhz = (int)rtc_clk_xtal_freq_get(); rtc_clk_cpu_freq_to_xtal(freq_mhz, 1); - rtc_clk_bbpll_disable(); } /** - * Switch to XTAL frequency. Does not disable the PLL. + * Switch to use XTAL as the CPU clock source. + * Must satisfy: cpu_freq = XTAL_FREQ / div. + * Does not disable the PLL. */ -static void rtc_clk_cpu_freq_to_xtal(int freq, int div) +static void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div) { - ets_update_cpu_frequency(freq); + ets_update_cpu_frequency(cpu_freq); /* Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0) first. */ rtc_clk_cpu_freq_set(SOC_CPU_CLK_SRC_XTAL, div); /* no need to adjust the REF_TICK */ diff --git a/components/esp_hw_support/port/esp32s2/rtc_clk.c b/components/esp_hw_support/port/esp32s2/rtc_clk.c index 6bb02ceea2b2..703ddd006f78 100644 --- a/components/esp_hw_support/port/esp32s2/rtc_clk.c +++ b/components/esp_hw_support/port/esp32s2/rtc_clk.c @@ -13,6 +13,7 @@ #include "esp32s2/rom/ets_sys.h" // for ets_update_cpu_frequency #include "esp32s2/rom/rtc.h" #include "soc/rtc.h" +#include "esp_private/rtc_clk.h" #include "soc/rtc_cntl_reg.h" #include "soc/rtc_io_reg.h" #include "soc/soc_caps.h" @@ -395,25 +396,32 @@ void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t* config) void rtc_clk_cpu_freq_set_xtal(void) { + rtc_clk_cpu_set_to_default_config(); /* BBPLL is kept enabled */ +} + +void rtc_clk_cpu_set_to_default_config(void) +{ rtc_clk_cpu_freq_to_xtal(CLK_LL_XTAL_FREQ_MHZ, 1); } /** - * Switch to XTAL frequency. Does not disable the PLL. + * Switch to use XTAL as the CPU clock source. + * Must satisfy: cpu_freq = XTAL_FREQ / div. + * Does not disable the PLL. */ -static void rtc_clk_cpu_freq_to_xtal(int freq, int div) +static void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div) { - ets_update_cpu_frequency(freq); + ets_update_cpu_frequency(cpu_freq); /* Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0) first. */ clk_ll_cpu_set_divider(1); clk_ll_cpu_set_divider(div); /* no need to adjust the REF_TICK, default register value already set it to 1MHz with any cpu clock source */ /* switch clock source */ clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL); - rtc_clk_apb_freq_update(freq * MHZ); + rtc_clk_apb_freq_update(cpu_freq * MHZ); /* lower the voltage */ - int dbias = (freq <= 2) ? DIG_DBIAS_2M : DIG_DBIAS_XTAL; + int dbias = (cpu_freq <= 2) ? DIG_DBIAS_2M : DIG_DBIAS_XTAL; REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, dbias); } diff --git a/components/esp_hw_support/port/esp32s3/rtc_clk.c b/components/esp_hw_support/port/esp32s3/rtc_clk.c index d595ca20e2ef..481436e4be3a 100644 --- a/components/esp_hw_support/port/esp32s3/rtc_clk.c +++ b/components/esp_hw_support/port/esp32s3/rtc_clk.c @@ -13,10 +13,10 @@ #include "esp32s3/rom/ets_sys.h" #include "esp32s3/rom/rtc.h" #include "soc/rtc.h" +#include "esp_private/rtc_clk.h" #include "soc/rtc_io_reg.h" #include "esp_rom_sys.h" #include "esp_hw_log.h" -#include "hal/usb_serial_jtag_ll.h" #include "hal/clk_tree_ll.h" #include "hal/regi2c_ctrl_ll.h" #include "esp_private/regi2c_ctrl.h" @@ -32,13 +32,24 @@ static uint32_t s_apb_freq; void rtc_clk_cpu_freq_to_xtal(int freq, int div); static void rtc_clk_cpu_freq_to_8m(void); -static bool rtc_clk_set_bbpll_always_on(void); extern uint32_t g_dig_dbias_pvt_240m; extern uint32_t g_rtc_dbias_pvt_240m; extern uint32_t g_dig_dbias_pvt_non_240m; extern uint32_t g_rtc_dbias_pvt_non_240m; +static uint32_t s_bbpll_digi_consumers_ref_count = 0; // Currently, it only tracks whether the 48MHz PHY clock is in-use by USB Serial/JTAG + +void rtc_clk_bbpll_add_consumer(void) +{ + s_bbpll_digi_consumers_ref_count += 1; +} + +void rtc_clk_bbpll_remove_consumer(void) +{ + s_bbpll_digi_consumers_ref_count -= 1; +} + void rtc_clk_32k_enable(bool enable) { if (enable) { @@ -267,8 +278,8 @@ void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config) soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src(); if (config->source == SOC_CPU_CLK_SRC_XTAL) { rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div); - if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) && !rtc_clk_set_bbpll_always_on()) { - // We don't turn off the bbpll if some consumers only depends on bbpll + if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) && !s_bbpll_digi_consumers_ref_count) { + // We don't turn off the bbpll if some consumers depend on bbpll rtc_clk_bbpll_disable(); } } else if (config->source == SOC_CPU_CLK_SRC_PLL) { @@ -279,8 +290,8 @@ void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config) rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz); } else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) { rtc_clk_cpu_freq_to_8m(); - if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) && !rtc_clk_set_bbpll_always_on()) { - // We don't turn off the bbpll if some consumers only depends on bbpll + if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) && !s_bbpll_digi_consumers_ref_count) { + // We don't turn off the bbpll if some consumers depend on bbpll rtc_clk_bbpll_disable(); } } @@ -345,32 +356,37 @@ void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config) } void rtc_clk_cpu_freq_set_xtal(void) +{ + rtc_clk_cpu_set_to_default_config(); + rtc_clk_bbpll_disable(); +} + +void rtc_clk_cpu_set_to_default_config(void) { int freq_mhz = (int)rtc_clk_xtal_freq_get(); rtc_clk_cpu_freq_to_xtal(freq_mhz, 1); - // We don't turn off the bbpll if some consumers only depends on bbpll - if (!rtc_clk_set_bbpll_always_on()) { - rtc_clk_bbpll_disable(); - } } /** - * Switch to XTAL frequency. Does not disable the PLL. + * Switch to use XTAL as the CPU clock source. + * Must satisfy: cpu_freq = XTAL_FREQ / div. + * Does not disable the PLL. + * * Public function for testing only. */ -void rtc_clk_cpu_freq_to_xtal(int freq, int div) +void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div) { REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG, g_rtc_dbias_pvt_non_240m); REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, g_dig_dbias_pvt_non_240m); esp_rom_delay_us(40); - ets_update_cpu_frequency(freq); + ets_update_cpu_frequency(cpu_freq); /* Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0) first. */ clk_ll_cpu_set_divider(1); clk_ll_cpu_set_divider(div); /* switch clock source */ clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL); - rtc_clk_apb_freq_update(freq * MHZ); + rtc_clk_apb_freq_update(cpu_freq * MHZ); REG_SET_FIELD(RTC_CNTL_DATE_REG, RTC_CNTL_SLAVE_PD, DEFAULT_LDO_SLAVE); } @@ -438,21 +454,6 @@ bool rtc_dig_8m_enabled(void) return clk_ll_rc_fast_digi_is_enabled(); } -static bool rtc_clk_set_bbpll_always_on(void) -{ - /* We just keep the rtc bbpll clock on just under the case that - user selects the `RTC_CLOCK_BBPLL_POWER_ON_WITH_USB` as well as - the USB_SERIAL_JTAG is connected with PC. - */ - bool is_bbpll_on = false; -#if CONFIG_RTC_CLOCK_BBPLL_POWER_ON_WITH_USB - if (usb_serial_jtag_ll_txfifo_writable() == 1) { - is_bbpll_on = true; - } -#endif - return is_bbpll_on; -} - /* Name used in libphy.a:phy_chip_v7.o * TODO: update the library to use rtc_clk_xtal_freq_get */ diff --git a/components/esp_system/Kconfig b/components/esp_system/Kconfig index 7e31e667ba2a..7cc0ddbe5634 100644 --- a/components/esp_system/Kconfig +++ b/components/esp_system/Kconfig @@ -268,6 +268,10 @@ menu "ESP System Settings" please change the primary config to ESP_CONSOLE_USB_SERIAL_JTAG above. endchoice + config ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED + # Internal option, indicates that console USB SERIAL JTAG is used + bool + default y if ESP_CONSOLE_USB_SERIAL_JTAG || ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG config ESP_CONSOLE_UART # Internal option, indicates that console UART is used (and not USB, for example) diff --git a/components/esp_system/port/esp_system_chip.c b/components/esp_system/port/esp_system_chip.c index 4e45e8500360..464cc6101e12 100644 --- a/components/esp_system/port/esp_system_chip.c +++ b/components/esp_system/port/esp_system_chip.c @@ -1,12 +1,13 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include #include "esp_cpu.h" -#include "soc/rtc.h" +#include "soc/soc.h" +#include "esp_private/rtc_clk.h" #include "esp_private/panic_internal.h" #include "esp_private/system_internal.h" #include "esp_heap_caps.h" @@ -31,7 +32,7 @@ void IRAM_ATTR esp_restart_noos_dig(void) } // switch to XTAL (otherwise we will keep running from the PLL) - rtc_clk_cpu_freq_set_xtal(); + rtc_clk_cpu_set_to_default_config(); // esp_restart_noos_dig() will generates a core reset, which does not reset the // registers of the RTC domain, so the CPU's stall state remains after the reset, diff --git a/components/esp_system/port/soc/esp32/system_internal.c b/components/esp_system/port/soc/esp32/system_internal.c index 1aa19f934a29..964712cee34a 100644 --- a/components/esp_system/port/soc/esp32/system_internal.c +++ b/components/esp_system/port/soc/esp32/system_internal.c @@ -20,6 +20,7 @@ #include "soc/timer_periph.h" #include "esp_cpu.h" #include "soc/rtc.h" +#include "esp_private/rtc_clk.h" #include "hal/wdt_hal.h" #include "freertos/xtensa_api.h" #include "soc/soc_memory_layout.h" @@ -120,8 +121,8 @@ void IRAM_ATTR esp_restart_noos(void) DPORT_TIMERS_RST | DPORT_SPI01_RST | DPORT_SPI2_RST | DPORT_SPI3_RST | DPORT_SPI_DMA_RST | DPORT_UART_RST | DPORT_UART1_RST | DPORT_UART2_RST | DPORT_UART_MEM_RST); DPORT_REG_WRITE(DPORT_PERIP_RST_EN_REG, 0); - // Set CPU back to XTAL source, no PLL, same as hard reset - rtc_clk_cpu_freq_set_xtal(); + // Set CPU back to XTAL source, same as hard reset. PLL keeps on to match the behavior with chips. + rtc_clk_cpu_set_to_default_config(); // Clear entry point for APP CPU DPORT_REG_WRITE(DPORT_APPCPU_CTRL_D_REG, 0); diff --git a/components/esp_system/port/soc/esp32c2/system_internal.c b/components/esp_system/port/soc/esp32c2/system_internal.c index f14e225df459..87535f35e106 100644 --- a/components/esp_system/port/soc/esp32c2/system_internal.c +++ b/components/esp_system/port/soc/esp32c2/system_internal.c @@ -14,10 +14,10 @@ #include "riscv/rv_utils.h" #include "esp_rom_uart.h" #include "soc/gpio_reg.h" -#include "soc/rtc_cntl_reg.h" #include "soc/timer_group_reg.h" #include "esp_cpu.h" #include "soc/rtc.h" +#include "esp_private/rtc_clk.h" #include "soc/rtc_periph.h" #include "soc/syscon_reg.h" #include "soc/system_reg.h" @@ -90,9 +90,9 @@ void IRAM_ATTR esp_restart_noos(void) SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST); REG_WRITE(SYSTEM_PERIP_RST_EN1_REG, 0); - // Set CPU back to XTAL source, no PLL, same as hard reset + // Set CPU back to XTAL source, same as hard reset. PLL keeps on to match the behavior with chips. #if !CONFIG_IDF_ENV_FPGA - rtc_clk_cpu_freq_set_xtal(); + rtc_clk_cpu_set_to_default_config(); #endif #if !CONFIG_FREERTOS_UNICORE diff --git a/components/esp_system/port/soc/esp32c3/system_internal.c b/components/esp_system/port/soc/esp32c3/system_internal.c index f5ca5ddda024..7a4e72a34fa2 100644 --- a/components/esp_system/port/soc/esp32c3/system_internal.c +++ b/components/esp_system/port/soc/esp32c3/system_internal.c @@ -14,10 +14,10 @@ #include "riscv/rv_utils.h" #include "esp_rom_uart.h" #include "soc/gpio_reg.h" -#include "soc/rtc_cntl_reg.h" #include "soc/timer_group_reg.h" #include "esp_cpu.h" #include "soc/rtc.h" +#include "esp_private/rtc_clk.h" #include "soc/rtc_periph.h" #include "soc/syscon_reg.h" #include "soc/system_reg.h" @@ -104,9 +104,9 @@ void IRAM_ATTR esp_restart_noos(void) SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST); REG_WRITE(SYSTEM_PERIP_RST_EN1_REG, 0); - // Set CPU back to XTAL source, no PLL, same as hard reset + // Set CPU back to XTAL source, same as hard reset, but keep BBPLL on so that USB Serial JTAG can log at 1st stage bootloader. #if !CONFIG_IDF_ENV_FPGA - rtc_clk_cpu_freq_set_xtal(); + rtc_clk_cpu_set_to_default_config(); #endif #if !CONFIG_FREERTOS_UNICORE diff --git a/components/esp_system/port/soc/esp32c6/system_internal.c b/components/esp_system/port/soc/esp32c6/system_internal.c index da785728216c..2d8b0183f4e6 100644 --- a/components/esp_system/port/soc/esp32c6/system_internal.c +++ b/components/esp_system/port/soc/esp32c6/system_internal.c @@ -16,6 +16,7 @@ #include "soc/gpio_reg.h" #include "esp_cpu.h" #include "soc/rtc.h" +#include "esp_private/rtc_clk.h" #include "soc/rtc_periph.h" #include "soc/uart_reg.h" #include "hal/wdt_hal.h" @@ -97,9 +98,9 @@ void IRAM_ATTR esp_restart_noos(void) CLEAR_PERI_REG_MASK(PCR_SDIO_SLAVE_CONF_REG, PCR_SDIO_SLAVE_RST_EN); CLEAR_PERI_REG_MASK(PCR_MODEM_APB_CONF_REG, PCR_MODEM_RST_EN); - // Set CPU back to XTAL source, no PLL, same as hard reset + // Set CPU back to XTAL source, same as hard reset, but keep BBPLL on so that USB Serial JTAG can log at 1st stage bootloader. #if !CONFIG_IDF_ENV_FPGA - rtc_clk_cpu_freq_set_xtal(); + rtc_clk_cpu_set_to_default_config(); #endif // Reset PRO CPU diff --git a/components/esp_system/port/soc/esp32h2/system_internal.c b/components/esp_system/port/soc/esp32h2/system_internal.c index 40c72975e85d..2bf451d23a77 100644 --- a/components/esp_system/port/soc/esp32h2/system_internal.c +++ b/components/esp_system/port/soc/esp32h2/system_internal.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 */ @@ -17,6 +17,7 @@ #include "soc/gpio_reg.h" #include "esp_cpu.h" #include "soc/rtc.h" +#include "esp_private/rtc_clk.h" #include "soc/rtc_periph.h" #include "soc/uart_reg.h" #include "hal/wdt_hal.h" @@ -97,9 +98,9 @@ void IRAM_ATTR esp_restart_noos(void) CLEAR_PERI_REG_MASK(PCR_GDMA_CONF_REG, PCR_GDMA_RST_EN); CLEAR_PERI_REG_MASK(PCR_MODEM_CONF_REG, PCR_MODEM_RST_EN); - // Set CPU back to XTAL source, no PLL, same as hard reset + // Set CPU back to XTAL source, same as hard reset, but keep BBPLL on so that USB Serial JTAG can log at 1st stage bootloader. #if !CONFIG_IDF_ENV_FPGA - rtc_clk_cpu_freq_set_xtal(); + rtc_clk_cpu_set_to_default_config(); #endif #if !CONFIG_FREERTOS_UNICORE diff --git a/components/esp_system/port/soc/esp32h4/system_internal.c b/components/esp_system/port/soc/esp32h4/system_internal.c index cd69a2ff2b7e..836c0d6c44f5 100644 --- a/components/esp_system/port/soc/esp32h4/system_internal.c +++ b/components/esp_system/port/soc/esp32h4/system_internal.c @@ -14,10 +14,10 @@ #include "riscv/rv_utils.h" #include "esp_rom_uart.h" #include "soc/gpio_reg.h" -#include "soc/rtc_cntl_reg.h" #include "soc/timer_group_reg.h" #include "esp_cpu.h" #include "soc/rtc.h" +#include "esp_private/rtc_clk.h" #include "soc/rtc_periph.h" #include "soc/syscon_reg.h" #include "soc/system_reg.h" @@ -99,9 +99,9 @@ void IRAM_ATTR esp_restart_noos(void) SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST); REG_WRITE(SYSTEM_PERIP_RST_EN1_REG, 0); - // Set CPU back to XTAL source, no PLL, same as hard reset + // Set CPU back to XTAL source, same as hard reset, but keep BBPLL on so that USB Serial JTAG can log at 1st stage bootloader. #if !CONFIG_IDF_ENV_FPGA - rtc_clk_cpu_freq_set_xtal(); + rtc_clk_cpu_set_to_default_config(); #endif #if !CONFIG_FREERTOS_UNICORE diff --git a/components/esp_system/port/soc/esp32s2/system_internal.c b/components/esp_system/port/soc/esp32s2/system_internal.c index 1ed1bc363e43..525626d752fa 100644 --- a/components/esp_system/port/soc/esp32s2/system_internal.c +++ b/components/esp_system/port/soc/esp32s2/system_internal.c @@ -15,10 +15,10 @@ #include "esp_rom_uart.h" #include "soc/dport_reg.h" #include "soc/gpio_reg.h" -#include "soc/rtc_cntl_reg.h" #include "soc/timer_group_reg.h" #include "esp_cpu.h" #include "soc/rtc.h" +#include "esp_private/rtc_clk.h" #include "soc/syscon_reg.h" #include "soc/rtc_periph.h" #include "hal/wdt_hal.h" @@ -114,8 +114,8 @@ void IRAM_ATTR esp_restart_noos(void) DPORT_TIMERS_RST | DPORT_SPI01_RST | DPORT_SPI2_RST | DPORT_SPI3_RST | DPORT_SPI2_DMA_RST | DPORT_SPI3_DMA_RST | DPORT_UART_RST); DPORT_REG_WRITE(DPORT_PERIP_RST_EN_REG, 0); - // Set CPU back to XTAL source, no PLL, same as hard reset - rtc_clk_cpu_freq_set_xtal(); + // Set CPU back to XTAL source, same as hard reset, but keep BBPLL on so that USB CDC can log at 1st stage bootloader. + rtc_clk_cpu_set_to_default_config(); // Reset CPUs if (core_id == 0) { diff --git a/components/esp_system/port/soc/esp32s3/system_internal.c b/components/esp_system/port/soc/esp32s3/system_internal.c index 8af34f401db3..9a0d811224a9 100644 --- a/components/esp_system/port/soc/esp32s3/system_internal.c +++ b/components/esp_system/port/soc/esp32s3/system_internal.c @@ -14,10 +14,10 @@ #include "esp_rom_uart.h" #include "soc/dport_reg.h" #include "soc/gpio_reg.h" -#include "soc/rtc_cntl_reg.h" #include "soc/timer_group_reg.h" #include "esp_cpu.h" #include "soc/rtc.h" +#include "esp_private/rtc_clk.h" #include "soc/syscon_reg.h" #include "soc/rtc_periph.h" #include "hal/wdt_hal.h" @@ -121,9 +121,9 @@ void IRAM_ATTR esp_restart_noos(void) SET_PERI_REG_MASK(SYSTEM_EDMA_CTRL_REG, SYSTEM_EDMA_RESET); CLEAR_PERI_REG_MASK(SYSTEM_EDMA_CTRL_REG, SYSTEM_EDMA_RESET); - // Set CPU back to XTAL source, no PLL, same as hard reset + // Set CPU back to XTAL source, same as hard reset, but keep BBPLL on so that USB Serial JTAG can log at 1st stage bootloader. #if !CONFIG_IDF_ENV_FPGA - rtc_clk_cpu_freq_set_xtal(); + rtc_clk_cpu_set_to_default_config(); #endif #if !CONFIG_FREERTOS_UNICORE diff --git a/components/esp_system/system_init_fn.txt b/components/esp_system/system_init_fn.txt index e8454171af0a..1b699c3fa8f0 100644 --- a/components/esp_system/system_init_fn.txt +++ b/components/esp_system/system_init_fn.txt @@ -32,3 +32,7 @@ # usb_console needs to create an esp_timer at startup. # This can be done only after esp_timer initialization, which is now in init_components0. 220: esp_usb_console_init_restart_timer in components/esp_system/port/soc/esp32s2/usb_console.c on BIT(0) + +# usb_serial_jtag needs to create and acquire a PM clock at startup. +# This makes more sense to be done after esp_pm_impl_init, which is initialized in init_components0. +230: usb_serial_jtag_conn_status_init in components/driver/usb_serial_jtag/usb_serial_jtag_connection_monitor.c on BIT(0) diff --git a/components/hal/esp32c3/include/hal/usb_serial_jtag_ll.h b/components/hal/esp32c3/include/hal/usb_serial_jtag_ll.h index 8e295a4181ae..0a6e382efd0c 100644 --- a/components/hal/esp32c3/include/hal/usb_serial_jtag_ll.h +++ b/components/hal/esp32c3/include/hal/usb_serial_jtag_ll.h @@ -1,16 +1,8 @@ -// Copyright 2021 Espressif Systems (Shanghai) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ // The LL layer of the USB-serial-jtag controller @@ -73,6 +65,16 @@ static inline uint32_t usb_serial_jtag_ll_get_intsts_mask(void) return USB_SERIAL_JTAG.int_st.val; } +/** + * @brief Get the USB_SERIAL_JTAG raw interrupt status. + * + * @return The USB_SERIAL_JTAG raw interrupt status. + */ +static inline __attribute__((always_inline)) uint32_t usb_serial_jtag_ll_get_intraw_mask(void) +{ + return USB_SERIAL_JTAG.int_raw.val; +} + /** * @brief Clear the USB_SERIAL_JTAG interrupt status based on the given mask. * @@ -80,7 +82,7 @@ static inline uint32_t usb_serial_jtag_ll_get_intsts_mask(void) * * @return None */ -static inline void usb_serial_jtag_ll_clr_intsts_mask(uint32_t mask) +static inline __attribute__((always_inline)) void usb_serial_jtag_ll_clr_intsts_mask(uint32_t mask) { USB_SERIAL_JTAG.int_clr.val = mask; } diff --git a/components/hal/esp32c6/include/hal/usb_serial_jtag_ll.h b/components/hal/esp32c6/include/hal/usb_serial_jtag_ll.h index 06ade12c7006..56abbf38b9fb 100644 --- a/components/hal/esp32c6/include/hal/usb_serial_jtag_ll.h +++ b/components/hal/esp32c6/include/hal/usb_serial_jtag_ll.h @@ -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 */ @@ -65,6 +65,16 @@ static inline uint32_t usb_serial_jtag_ll_get_intsts_mask(void) return USB_SERIAL_JTAG.int_st.val; } +/** + * @brief Get the USB_SERIAL_JTAG raw interrupt status. + * + * @return The USB_SERIAL_JTAG raw interrupt status. + */ +static inline __attribute__((always_inline)) uint32_t usb_serial_jtag_ll_get_intraw_mask(void) +{ + return USB_SERIAL_JTAG.int_raw.val; +} + /** * @brief Clear the USB_SERIAL_JTAG interrupt status based on the given mask. * @@ -72,7 +82,7 @@ static inline uint32_t usb_serial_jtag_ll_get_intsts_mask(void) * * @return None */ -static inline void usb_serial_jtag_ll_clr_intsts_mask(uint32_t mask) +static inline __attribute__((always_inline)) void usb_serial_jtag_ll_clr_intsts_mask(uint32_t mask) { USB_SERIAL_JTAG.int_clr.val = mask; } diff --git a/components/hal/esp32h2/include/hal/usb_serial_jtag_ll.h b/components/hal/esp32h2/include/hal/usb_serial_jtag_ll.h index 58bf06ef13a0..0ad398021396 100644 --- a/components/hal/esp32h2/include/hal/usb_serial_jtag_ll.h +++ b/components/hal/esp32h2/include/hal/usb_serial_jtag_ll.h @@ -65,6 +65,16 @@ static inline uint32_t usb_serial_jtag_ll_get_intsts_mask(void) return USB_SERIAL_JTAG.int_st.val; } +/** + * @brief Get the USB_SERIAL_JTAG raw interrupt status. + * + * @return The USB_SERIAL_JTAG raw interrupt status. + */ +static inline __attribute__((always_inline)) uint32_t usb_serial_jtag_ll_get_intraw_mask(void) +{ + return USB_SERIAL_JTAG.int_raw.val; +} + /** * @brief Clear the USB_SERIAL_JTAG interrupt status based on the given mask. * @@ -72,7 +82,7 @@ static inline uint32_t usb_serial_jtag_ll_get_intsts_mask(void) * * @return None */ -static inline void usb_serial_jtag_ll_clr_intsts_mask(uint32_t mask) +static inline __attribute__((always_inline)) void usb_serial_jtag_ll_clr_intsts_mask(uint32_t mask) { USB_SERIAL_JTAG.int_clr.val = mask; } diff --git a/components/hal/esp32h4/include/hal/usb_serial_jtag_ll.h b/components/hal/esp32h4/include/hal/usb_serial_jtag_ll.h index 81b7b3c736c8..304bbeaa4299 100644 --- a/components/hal/esp32h4/include/hal/usb_serial_jtag_ll.h +++ b/components/hal/esp32h4/include/hal/usb_serial_jtag_ll.h @@ -67,6 +67,16 @@ static inline uint32_t usb_serial_jtag_ll_get_intsts_mask(void) return USB_SERIAL_JTAG.int_st.val; } +/** + * @brief Get the USB_SERIAL_JTAG raw interrupt status. + * + * @return The USB_SERIAL_JTAG raw interrupt status. + */ +static inline __attribute__((always_inline)) uint32_t usb_serial_jtag_ll_get_intraw_mask(void) +{ + return USB_SERIAL_JTAG.int_raw.val; +} + /** * @brief Clear the USB_SERIAL_JTAG interrupt status based on the given mask. * @@ -74,7 +84,7 @@ static inline uint32_t usb_serial_jtag_ll_get_intsts_mask(void) * * @return None */ -static inline void usb_serial_jtag_ll_clr_intsts_mask(uint32_t mask) +static inline __attribute__((always_inline)) void usb_serial_jtag_ll_clr_intsts_mask(uint32_t mask) { USB_SERIAL_JTAG.int_clr.val = mask; } diff --git a/components/hal/esp32s3/include/hal/usb_serial_jtag_ll.h b/components/hal/esp32s3/include/hal/usb_serial_jtag_ll.h index 335663ff12c4..3c0053385c8f 100644 --- a/components/hal/esp32s3/include/hal/usb_serial_jtag_ll.h +++ b/components/hal/esp32s3/include/hal/usb_serial_jtag_ll.h @@ -1,16 +1,8 @@ -// Copyright 2021 Espressif Systems (Shanghai) -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ // The LL layer of the USB-serial-jtag controller @@ -73,6 +65,16 @@ static inline uint32_t usb_serial_jtag_ll_get_intsts_mask(void) return USB_SERIAL_JTAG.int_st.val; } +/** + * @brief Get the USB_SERIAL_JTAG raw interrupt status. + * + * @return The USB_SERIAL_JTAG raw interrupt status. + */ +static inline __attribute__((always_inline)) uint32_t usb_serial_jtag_ll_get_intraw_mask(void) +{ + return USB_SERIAL_JTAG.int_raw.val; +} + /** * @brief Clear the USB_SERIAL_JTAG interrupt status based on the given mask. * @@ -80,7 +82,7 @@ static inline uint32_t usb_serial_jtag_ll_get_intsts_mask(void) * * @return None */ -static inline void usb_serial_jtag_ll_clr_intsts_mask(uint32_t mask) +static inline __attribute__((always_inline)) void usb_serial_jtag_ll_clr_intsts_mask(uint32_t mask) { USB_SERIAL_JTAG.int_clr.val = mask; } diff --git a/components/soc/esp32c3/include/soc/rtc.h b/components/soc/esp32c3/include/soc/rtc.h index 59b1dcdd21a6..1db8df34850c 100644 --- a/components/soc/esp32c3/include/soc/rtc.h +++ b/components/soc/esp32c3/include/soc/rtc.h @@ -398,6 +398,10 @@ void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config); * Short form for filling in rtc_cpu_freq_config_t structure and calling * rtc_clk_cpu_freq_set_config when a switch to XTAL is needed. * Assumes that XTAL frequency has been determined — don't call in startup code. + * + * @note This function always disables BBPLL after switching the CPU clock source to XTAL for power saving purpose. + * If this is unwanted, please use rtc_clk_cpu_freq_set_config. It helps to check whether USB Serial JTAG is in use, + * if so, then BBPLL will not be turned off. */ void rtc_clk_cpu_freq_set_xtal(void); diff --git a/components/soc/esp32c6/include/soc/rtc.h b/components/soc/esp32c6/include/soc/rtc.h index f0c6c2fc13e7..407e6d636e06 100644 --- a/components/soc/esp32c6/include/soc/rtc.h +++ b/components/soc/esp32c6/include/soc/rtc.h @@ -366,6 +366,9 @@ void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config); * Short form for filling in rtc_cpu_freq_config_t structure and calling * rtc_clk_cpu_freq_set_config when a switch to XTAL is needed. * Assumes that XTAL frequency has been determined — don't call in startup code. + * + * @note On ESP32C6, this function will check whether BBPLL can be disabled. If there is no consumer, then BBPLL will be + * turned off. The behaviour is the same as using rtc_clk_cpu_freq_set_config to switch cpu clock source to XTAL. */ void rtc_clk_cpu_freq_set_xtal(void); diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 5524cde7f867..864b51f03a7a 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -275,6 +275,9 @@ #define SOC_MCPWM_SUPPORT_ETM (1) ///< Support ETM (Event Task Matrix) #define SOC_MCPWM_CAPTURE_CLK_FROM_GROUP (1) ///< Capture timer shares clock with other PWM timers +/*------------------------ USB SERIAL JTAG CAPS ------------------------------*/ +// #define SOC_USB_SERIAL_JTAG_SUPPORT_LIGHT_SLEEP (1) /*!< Support to maintain minimum usb communication during light sleep */ // TODO: IDF-6395 + /*--------------------------- RSA CAPS ---------------------------------------*/ #define SOC_RSA_MAX_BIT_LEN (3072) diff --git a/components/soc/esp32h2/include/soc/rtc.h b/components/soc/esp32h2/include/soc/rtc.h index ed752215448d..82c9016049b3 100644 --- a/components/soc/esp32h2/include/soc/rtc.h +++ b/components/soc/esp32h2/include/soc/rtc.h @@ -381,6 +381,9 @@ void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config); * Short form for filling in rtc_cpu_freq_config_t structure and calling * rtc_clk_cpu_freq_set_config when a switch to XTAL is needed. * Assumes that XTAL frequency has been determined — don't call in startup code. + * + * @note On ESP32H2, this function will check whether BBPLL can be disabled. If there is no consumer, then BBPLL will be + * turned off. The behaviour is the same as using rtc_clk_cpu_freq_set_config to switch cpu clock source to XTAL. */ void rtc_clk_cpu_freq_set_xtal(void); diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index b973516e5931..da91974171e3 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -264,6 +264,9 @@ #define SOC_MCPWM_SUPPORT_ETM (1) ///< Support ETM (Event Task Matrix) #define SOC_MCPWM_CAPTURE_CLK_FROM_GROUP (1) ///< Capture timer shares clock with other PWM timers +/*------------------------ USB SERIAL JTAG CAPS ------------------------------*/ +// #define SOC_USB_SERIAL_JTAG_SUPPORT_LIGHT_SLEEP (1) /*!< Support to maintain minimum usb communication during light sleep */ // TODO: IDF-6395 + // TODO: IDF-6267 (Copy from esp32c6, need check) /*-------------------------- RTC CAPS --------------------------------------*/ #define SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH (128) diff --git a/components/soc/esp32s2/include/soc/rtc.h b/components/soc/esp32s2/include/soc/rtc.h index 0436e5b86fb2..71d038e2673c 100644 --- a/components/soc/esp32s2/include/soc/rtc.h +++ b/components/soc/esp32s2/include/soc/rtc.h @@ -423,6 +423,9 @@ void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t* out_config); * Short form for filling in rtc_cpu_freq_config_t structure and calling * rtc_clk_cpu_freq_set_config when a switch to XTAL is needed. * Assumes that XTAL frequency has been determined — don't call in startup code. + * + * @note Unlike on other chips, on ESP32S2, this function does not disable BBPLL after switching the CPU clock source + * to XTAL. If BBPLL wants to be turned off for power saving purpose, please use rtc_clk_cpu_freq_set_config. */ void rtc_clk_cpu_freq_set_xtal(void); diff --git a/components/soc/esp32s3/include/soc/rtc.h b/components/soc/esp32s3/include/soc/rtc.h index 2a45f36a7e36..0ff7929c4452 100644 --- a/components/soc/esp32s3/include/soc/rtc.h +++ b/components/soc/esp32s3/include/soc/rtc.h @@ -424,6 +424,10 @@ void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config); * Short form for filling in rtc_cpu_freq_config_t structure and calling * rtc_clk_cpu_freq_set_config when a switch to XTAL is needed. * Assumes that XTAL frequency has been determined — don't call in startup code. + * + * @note This function always disables BBPLL after switching the CPU clock source to XTAL for power saving purpose. + * If this is unwanted, please use rtc_clk_cpu_freq_set_config. It helps to check whether USB Serial JTAG is in use, + * if so, then BBPLL will not be turned off. */ void rtc_clk_cpu_freq_set_xtal(void); diff --git a/docs/en/api-guides/usb-serial-jtag-console.rst b/docs/en/api-guides/usb-serial-jtag-console.rst index fcb9a3e7fbd1..d72f989e1fcb 100644 --- a/docs/en/api-guides/usb-serial-jtag-console.rst +++ b/docs/en/api-guides/usb-serial-jtag-console.rst @@ -65,16 +65,12 @@ There are several limitations to the USB Serial/JTAG console feature. These may 4. For data sent in the PC Terminal to {IDF_TARGET_NAME} direction (e.g. console commands), many PC Terminals will wait for the {IDF_TARGET_NAME} to ingest the bytes before allowing you to sending more data. This is in contrast to using a USB-to-Serial (UART) bridge chip, which will always ingest the bytes and send them to a (possibly not listening) {IDF_TARGET_NAME}. -5. The USB Serial/JTAG device won't work in sleep modes as normal due to the lack of APB clock in sleep modes. This includes deep-sleep, light-sleep (automataic light-sleep as well). +.. only:: not SOC_USB_SERIAL_JTAG_SUPPORT_LIGHT_SLEEP -6. The power consumption in sleep modes will be higher if the USB Serial/JTAG device is in use. + 5. The USB Serial/JTAG controller will not work during sleep (both light and deep sleep) due to the lack of an APB and USB PHY clock during sleep. Thus, entering sleep has the following implications on the USB Serial/JTAG controller: - This is because we want to keep the USB Serial/JTAG device alive during software reset by default. + i. Both the APB clock and the USB PHY clock (derived form the main PLL clock) will be disabled during sleep. As a result, the USB Serial/JTAG controller will not be able receive or respond to any USB transactions from the connected host (including periodic CDC Data IN transactions). Thus it may appear to the host that the USB Serial/JTAG controller has disconnected. - However there is an issue that this might also increase the power consumption in sleep modes. This is because the software keeps a clock source on during the reset to keep the USB Serial/JTAG device alive. As a side-effect, the clock is also kept on during sleep modes. There is one exception: the clock will only be kept on when your USB Serial/JTAG port is really in use (like data transaction), therefore, if your USB Serial/JTAG is connected to power bank or battery, etc., instead of a valid USB host (for example, a PC), the power consumption will not increase. + ii. If users enter sleep manually (via :cpp:func:`esp_light_sleep_start` or :cpp:func:`esp_deep_sleep_start`), users should be cognizant of the fact that USB Serial/JTAG controller will not work during sleep. ESP-IDF **does not add any safety check to reject entry to sleep** even if the USB Serial/JTAG controller is connected. In the case where sleep is entered while the USB Serial/JTAG controller is connected, connection can be re-established by unplugging and re-plugging the USB cable. - If you still want to keep low power consumption in sleep modes: - - 1. If you are not using the USB Serial/JTAG port, you don't need to do anything. Software will detect if the USB Serial/JTAG is connected to a valid host before going to sleep, and keep the clocks only when the host is connected. Otherwise the clocks will be turned off as normal. - - 2. If you are using the USB Serial/JTAG port, please disable the menuconfig option ``CONFIG_RTC_CLOCK_BBPLL_POWER_ON_WITH_USB``. The clock will be switched off as normal during software reset and in sleep modes. In these cases, the USB Serial/JTAG device may be unplugged from the host. \ No newline at end of file + iii. If users enter sleep automatically (via :cpp:func:`esp_pm_configure`), enabling the :ref:`CONFIG_USJ_NO_AUTO_LS_ON_CONNECTION` option will allow the {IDF_TARGET_NAME} to automatically detect whether the USB Serial/JTAG controller is currently connected to a host, and prevent automatic entry to sleep as long as the connection persists. However, note that this option will increase power consumption. diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index bb90ca46a1a0..f182c9615845 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -647,7 +647,6 @@ components/hal/esp32c3/include/hal/mpu_ll.h components/hal/esp32c3/include/hal/sha_ll.h components/hal/esp32c3/include/hal/spi_flash_encrypted_ll.h components/hal/esp32c3/include/hal/uhci_ll.h -components/hal/esp32c3/include/hal/usb_serial_jtag_ll.h components/hal/esp32c3/rtc_cntl_hal.c components/hal/esp32s2/include/hal/crypto_dma_ll.h components/hal/esp32s2/include/hal/dedic_gpio_ll.h @@ -661,7 +660,6 @@ components/hal/esp32s3/include/hal/sha_ll.h components/hal/esp32s3/include/hal/spi_flash_encrypted_ll.h components/hal/esp32s3/include/hal/uhci_ll.h components/hal/esp32s3/include/hal/usb_ll.h -components/hal/esp32s3/include/hal/usb_serial_jtag_ll.h components/hal/include/hal/aes_hal.h components/hal/include/hal/aes_types.h components/hal/include/hal/dac_types.h