usb_serial_jtag: Improve the code for the issue of usb cdc device unable to work during sleep

1. Remove RTC_CLOCK_BBPLL_POWER_ON_WITH_USB Kconfig option
   During sleep, BBPLL clock always gets disabled
   esp_restart does not disable BBPLL clock, so that first stage bootloader log can be printed
2. Add a new Kconfig option PM_NO_AUTO_LS_ON_USJ_CONNECTED
   When this option is selected, IDF will constantly monitor USB CDC port connection status.
   As long as it gets connected to a HOST, automatic light-sleep will not happen.

Closes https://github.com/espressif/esp-idf/issues/8507
This commit is contained in:
Song Ruo Jing 2022-11-08 01:54:23 +08:00
parent 30a46d0754
commit 1a66459b44
39 changed files with 501 additions and 234 deletions

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,89 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdbool.h>
#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
}

View File

@ -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"

View File

@ -0,0 +1,49 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#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

View File

@ -9,6 +9,7 @@
#include <stddef.h>
#include <stdlib.h>
#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)

View File

@ -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"
@ -270,24 +271,31 @@ 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);
rtc_clk_cpu_set_to_default_config();
rtc_clk_bbpll_disable();
}
/**
* Switch to XTAL frequency. Does not disable the PLL.
*/
void rtc_clk_cpu_freq_to_xtal(int freq, int div)
void rtc_clk_cpu_set_to_default_config(void)
{
ets_update_cpu_frequency(freq);
int freq_mhz = (int)rtc_clk_xtal_freq_get();
rtc_clk_cpu_freq_to_xtal(freq_mhz, 1);
}
/**
* 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 cpu_freq, int div)
{
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)

View File

@ -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
*/

View File

@ -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
*/

View File

@ -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) {
@ -355,15 +368,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 only depends 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);
// TODO: IDF-6243 MSPI clock source could also depend on bbpll, cpu restart should not disable bbpll
// 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)
@ -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;
}

View File

@ -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);
@ -303,18 +317,25 @@ 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);
rtc_clk_cpu_set_to_default_config();
rtc_clk_bbpll_disable();
}
/**
* Switch to XTAL frequency. Does not disable the PLL.
*/
static void rtc_clk_cpu_freq_to_xtal(int freq, int div)
void rtc_clk_cpu_set_to_default_config(void)
{
ets_update_cpu_frequency(freq);
int freq_mhz = (int)rtc_clk_xtal_freq_get();
rtc_clk_cpu_freq_to_xtal(freq_mhz, 1);
}
/**
* 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 cpu_freq, int div)
{
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 */

View File

@ -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);
}

View File

@ -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
*/

View File

@ -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)

View File

@ -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 <stdint.h>
#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,

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -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

View File

@ -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)

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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.
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.

View File

@ -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