Skip to content

Commit

Permalink
Merge branch 'feature/optimize_chips_active_power' into 'master'
Browse files Browse the repository at this point in the history
feat(system): Optimize the power consumption of esp32h2 and esp32c6 in the active state

Closes IDF-5658

See merge request espressif/esp-idf!27798
  • Loading branch information
esp-wzh committed Mar 14, 2024
2 parents 79d8057 + 0fc97f0 commit 5a682c3
Show file tree
Hide file tree
Showing 45 changed files with 618 additions and 228 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include "hal/cache_hal.h"
#include "hal/lpwdt_ll.h"
#include "soc/lp_wdt_reg.h"
#include "soc/pmu_reg.h"
#include "hal/efuse_hal.h"
#include "modem/modem_lpcon_reg.h"

Expand Down Expand Up @@ -85,6 +86,9 @@ static void bootloader_super_wdt_auto_feed(void)

static inline void bootloader_hardware_init(void)
{
/* Disable RF pll by default */
CLEAR_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_RFPLL);
SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_FORCE_RFPLL);
/* Enable analog i2c master clock */
SET_PERI_REG_MASK(MODEM_LPCON_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_EN);
}
Expand Down
29 changes: 29 additions & 0 deletions components/esp_driver_gpio/src/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@
#include "hal/gpio_hal.h"
#include "esp_rom_gpio.h"
#include "esp_private/esp_gpio_reserve.h"
#include "esp_private/periph_ctrl.h"

#if SOC_LP_IO_CLOCK_IS_INDEPENDENT && !SOC_RTCIO_RCC_IS_INDEPENDENT
#define RTCIO_RCC_ATOMIC() PERIPH_RCC_ATOMIC()
#else
#define RTCIO_RCC_ATOMIC()
#endif

#if (SOC_RTCIO_PIN_COUNT > 0)
#include "hal/rtc_io_hal.h"
Expand Down Expand Up @@ -59,6 +66,9 @@ typedef struct {
gpio_isr_func_t *gpio_isr_func;
gpio_isr_handle_t gpio_isr_handle;
uint64_t isr_clr_on_entry_mask; // for edge-triggered interrupts, interrupt status bits should be cleared before entering per-pin handlers
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP && SOC_LP_IO_CLOCK_IS_INDEPENDENT
uint32_t gpio_wakeup_mask;
#endif
} gpio_context_t;

static gpio_hal_context_t _gpio_hal = {
Expand All @@ -71,6 +81,9 @@ static gpio_context_t gpio_context = {
.isr_core_id = GPIO_ISR_CORE_ID_UNINIT,
.gpio_isr_func = NULL,
.isr_clr_on_entry_mask = 0,
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP && SOC_LP_IO_CLOCK_IS_INDEPENDENT
.gpio_wakeup_mask = 0,
#endif
};

esp_err_t gpio_pullup_en(gpio_num_t gpio_num)
Expand Down Expand Up @@ -978,6 +991,14 @@ esp_err_t gpio_deep_sleep_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t int
return ESP_ERR_INVALID_ARG;
}
portENTER_CRITICAL(&gpio_context.gpio_spinlock);
#if SOC_LP_IO_CLOCK_IS_INDEPENDENT
if (gpio_context.gpio_wakeup_mask == 0) {
RTCIO_RCC_ATOMIC() {
rtcio_ll_enable_io_clock(true);
}
}
gpio_context.gpio_wakeup_mask |= (1ULL << gpio_num);
#endif
gpio_hal_deepsleep_wakeup_enable(gpio_context.gpio_hal, gpio_num, intr_type);
#if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND || CONFIG_PM_SLP_DISABLE_GPIO
gpio_hal_sleep_sel_dis(gpio_context.gpio_hal, gpio_num);
Expand All @@ -996,6 +1017,14 @@ esp_err_t gpio_deep_sleep_wakeup_disable(gpio_num_t gpio_num)
gpio_hal_deepsleep_wakeup_disable(gpio_context.gpio_hal, gpio_num);
#if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND || CONFIG_PM_SLP_DISABLE_GPIO
gpio_hal_sleep_sel_en(gpio_context.gpio_hal, gpio_num);
#endif
#if SOC_LP_IO_CLOCK_IS_INDEPENDENT
gpio_context.gpio_wakeup_mask &= ~(1ULL << gpio_num);
if (gpio_context.gpio_wakeup_mask == 0) {
RTCIO_RCC_ATOMIC() {
rtcio_ll_enable_io_clock(false);
}
}
#endif
portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
return ESP_OK;
Expand Down
23 changes: 19 additions & 4 deletions components/esp_driver_gpio/src/rtc_io.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand All @@ -8,6 +8,7 @@
#include "esp_log.h"
#include "esp_err.h"
#include "esp_check.h"
#include "esp_private/periph_ctrl.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "freertos/timers.h"
Expand All @@ -17,6 +18,16 @@
#include "soc/rtc_io_periph.h"
#include "soc/soc_caps.h"

#if SOC_LP_IO_CLOCK_IS_INDEPENDENT && !SOC_RTCIO_RCC_IS_INDEPENDENT
// For `rtcio_hal_function_select` using, clock reg option is inlined in it,
// so remove the declaration check of __DECLARE_RCC_RC_ATOMIC_ENV
#define RTCIO_RCC_ATOMIC() \
for (int i = 1; i ? (periph_rcc_enter(), 1) : 0; \
periph_rcc_exit(), i--)
#else
#define RTCIO_RCC_ATOMIC()
#endif

static const char __attribute__((__unused__)) *RTCIO_TAG = "RTCIO";

extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
Expand Down Expand Up @@ -45,7 +56,9 @@ esp_err_t rtc_gpio_init(gpio_num_t gpio_num)
{
ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error");
RTCIO_ENTER_CRITICAL();
rtcio_hal_function_select(rtc_io_number_get(gpio_num), RTCIO_LL_FUNC_RTC);
RTCIO_RCC_ATOMIC() {
rtcio_hal_function_select(rtc_io_number_get(gpio_num), RTCIO_LL_FUNC_RTC);
}
RTCIO_EXIT_CRITICAL();

return ESP_OK;
Expand All @@ -55,8 +68,10 @@ esp_err_t rtc_gpio_deinit(gpio_num_t gpio_num)
{
ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error");
RTCIO_ENTER_CRITICAL();
// Select Gpio as Digital Gpio
rtcio_hal_function_select(rtc_io_number_get(gpio_num), RTCIO_LL_FUNC_DIGITAL);
RTCIO_RCC_ATOMIC() {
// Select Gpio as Digital Gpio
rtcio_hal_function_select(rtc_io_number_get(gpio_num), RTCIO_LL_FUNC_DIGITAL);
}
RTCIO_EXIT_CRITICAL();

return ESP_OK;
Expand Down
14 changes: 13 additions & 1 deletion components/esp_driver_usb_serial_jtag/Kconfig
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
menu "ESP-Driver:USB Serial/JTAG Configuration"
depends on SOC_USB_SERIAL_JTAG_SUPPORTED

config USJ_ENABLE_USB_SERIAL_JTAG
bool "Enable USB-Serial-JTAG Module"
default y
help
The USB-Serial-JTAG module on ESP chips is turned on by default after power-on.
If your application does not need it and not rely on it to be used as system
console or use the built-in JTAG for debugging, you can disable this option,
then the clock of this module will be disabled at startup, which will save
some power consumption.

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
depends on PM_ENABLE && ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED && !SOC_USB_SERIAL_JTAG_SUPPORT_LIGHT_SLEEP \
&& USJ_ENABLE_USB_SERIAL_JTAG
default n
help
If enabled, the chip will constantly monitor the connection status of the USB Serial/JTAG port. As long
Expand Down
9 changes: 8 additions & 1 deletion components/esp_hw_support/esp_clock_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "esp_rom_gpio.h"
#include "clkout_channel.h"
#include "hal/gpio_hal.h"
#include "hal/clk_tree_ll.h"
#include "soc/soc_caps.h"
#include "soc/io_mux_reg.h"

Expand Down Expand Up @@ -89,6 +90,9 @@ static clkout_channel_handle_t* clkout_channel_alloc(soc_clkout_sig_id_t clk_sig

if (allocated_channel->ref_cnt == 1) {
portENTER_CRITICAL(&s_clkout_lock);
#if SOC_CLOCKOUT_HAS_SOURCE_GATE
clk_ll_enable_clkout_source(clk_sig, true);
#endif
gpio_ll_set_pin_ctrl(clk_sig, CLKOUT_CHANNEL_MASK(allocated_channel->channel_id), CLKOUT_CHANNEL_SHIFT(allocated_channel->channel_id));
portEXIT_CRITICAL(&s_clkout_lock);
}
Expand Down Expand Up @@ -142,10 +146,13 @@ static void clkout_channel_free(clkout_channel_handle_t *channel_hdl)
{
portENTER_CRITICAL(&channel_hdl->clkout_channel_lock);
if (--channel_hdl->ref_cnt == 0) {
channel_hdl->mapped_clock = CLKOUT_SIG_INVALID;
portENTER_CRITICAL(&s_clkout_lock);
#if SOC_CLOCKOUT_HAS_SOURCE_GATE
clk_ll_enable_clkout_source(channel_hdl->mapped_clock, false);
#endif
gpio_ll_set_pin_ctrl(0, CLKOUT_CHANNEL_MASK(channel_hdl->channel_id), CLKOUT_CHANNEL_SHIFT(channel_hdl->channel_id));
portEXIT_CRITICAL(&s_clkout_lock);
channel_hdl->mapped_clock = CLKOUT_SIG_INVALID;
channel_hdl->is_mapped = false;
}
portEXIT_CRITICAL(&channel_hdl->clkout_channel_lock);
Expand Down
16 changes: 15 additions & 1 deletion components/esp_hw_support/hw_random.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2016-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2016-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand All @@ -13,11 +13,17 @@
#include "esp_cpu.h"
#include "soc/wdev_reg.h"
#include "esp_private/esp_clk.h"
#include "esp_private/startup_internal.h"
#include "soc/soc_caps.h"

#if SOC_LP_TIMER_SUPPORTED
#include "hal/lp_timer_hal.h"
#endif

#if SOC_RNG_CLOCK_IS_INDEPENDENT
#include "hal/lp_clkrst_ll.h"
#endif

#if defined CONFIG_IDF_TARGET_ESP32S3
#define APB_CYCLE_WAIT_NUM (1778) /* If APB clock is 80 MHz, the maximum sampling frequency is around 45 KHz*/
/* 45 KHz reading frequency is the maximum we have tested so far on S3 */
Expand Down Expand Up @@ -103,3 +109,11 @@ void esp_fill_random(void *buf, size_t len)
len -= to_copy;
}
}

#if SOC_RNG_CLOCK_IS_INDEPENDENT
ESP_SYSTEM_INIT_FN(init_rng_clock, SECONDARY, BIT(0), 102)
{
_lp_clkrst_ll_enable_rng_clock(true);
return ESP_OK;
}
#endif
7 changes: 6 additions & 1 deletion components/esp_hw_support/port/esp32c6/rtc_time.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <stdint.h>
#include "esp32c6/rom/ets_sys.h"
#include "soc/rtc.h"
#include "soc/pcr_reg.h"
#include "hal/lp_timer_hal.h"
#include "hal/clk_tree_ll.h"
#include "hal/timer_ll.h"
Expand Down Expand Up @@ -154,10 +155,13 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc

/*The Fosc CLK of calibration circuit is divided by 32 for ECO1.
So we need to multiply the frequency of the Fosc for ECO1 and above chips by 32 times.
And ensure that this modification will not affect ECO0.*/
And ensure that this modification will not affect ECO0.
And the 32-divider belongs to REF_TICK module, so we need to enable its clock during
calibration. */
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 1)) {
if (cal_clk == RTC_CAL_RC_FAST) {
cal_val = cal_val >> 5;
CLEAR_PERI_REG_MASK(PCR_CTRL_TICK_CONF_REG, PCR_TICK_ENABLE);
}
}
break;
Expand Down Expand Up @@ -218,6 +222,7 @@ uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 1)) {
if (cal_clk == RTC_CAL_RC_FAST) {
slowclk_cycles = slowclk_cycles >> 5;
SET_PERI_REG_MASK(PCR_CTRL_TICK_CONF_REG, PCR_TICK_ENABLE);
}
}

Expand Down
7 changes: 6 additions & 1 deletion components/esp_hw_support/port/esp32h2/rtc_time.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "hal/clk_tree_ll.h"
#include "hal/timer_ll.h"
#include "soc/timer_group_reg.h"
#include "soc/pcr_reg.h"
#include "esp_rom_sys.h"
#include "assert.h"
#include "hal/efuse_hal.h"
Expand Down Expand Up @@ -154,10 +155,13 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc

/*The Fosc CLK of calibration circuit is divided by 32 for ECO2.
So we need to multiply the frequency of the Fosc for ECO2 and above chips by 32 times.
And ensure that this modification will not affect ECO0 and ECO1.*/
And ensure that this modification will not affect ECO0 and ECO1.
And the 32-divider belongs to REF_TICK module, so we need to enable its clock during
calibration. */
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 2)) {
if (cal_clk == RTC_CAL_RC_FAST) {
cal_val = cal_val >> 5;
CLEAR_PERI_REG_MASK(PCR_CTRL_TICK_CONF_REG, PCR_TICK_ENABLE);
}
}
break;
Expand Down Expand Up @@ -218,6 +222,7 @@ uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 2)) {
if (cal_clk == RTC_CAL_RC_FAST) {
slowclk_cycles = slowclk_cycles >> 5;
SET_PERI_REG_MASK(PCR_CTRL_TICK_CONF_REG, PCR_TICK_ENABLE);
}
}

Expand Down
23 changes: 20 additions & 3 deletions components/esp_hw_support/sleep_modes.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "esp_sleep.h"
#include "esp_private/esp_sleep_internal.h"
#include "esp_private/esp_timer_private.h"
#include "esp_private/periph_ctrl.h"
#include "esp_private/sleep_event.h"
#include "esp_private/system_internal.h"
#include "esp_log.h"
Expand Down Expand Up @@ -107,6 +108,16 @@
#include "esp_private/sleep_retention.h"
#endif

#if SOC_LP_IO_CLOCK_IS_INDEPENDENT && !SOC_RTCIO_RCC_IS_INDEPENDENT
// For `rtcio_hal_function_select` using, clock reg option is inlined in it,
// so remove the declaration check of __DECLARE_RCC_RC_ATOMIC_ENV
#define RTCIO_RCC_ATOMIC() \
for (int i = 1; i ? (periph_rcc_enter(), 1) : 0; \
periph_rcc_exit(), i--)
#else
#define RTCIO_RCC_ATOMIC()
#endif

// If light sleep time is less than that, don't power down flash
#define FLASH_PD_MIN_SLEEP_TIME_US 2000

Expand Down Expand Up @@ -1530,7 +1541,9 @@ static void ext0_wakeup_prepare(void)
{
int rtc_gpio_num = s_config.ext0_rtc_gpio_num;
rtcio_hal_ext0_set_wakeup_pin(rtc_gpio_num, s_config.ext0_trigger_level);
rtcio_hal_function_select(rtc_gpio_num, RTCIO_LL_FUNC_RTC);
RTCIO_RCC_ATOMIC() {
rtcio_hal_function_select(rtc_gpio_num, RTCIO_LL_FUNC_RTC);
}
rtcio_hal_input_enable(rtc_gpio_num);
}

Expand Down Expand Up @@ -1661,7 +1674,9 @@ static void ext1_wakeup_prepare(void)
}
#if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
// Route pad to RTC
rtcio_hal_function_select(rtc_pin, RTCIO_LL_FUNC_RTC);
RTCIO_RCC_ATOMIC() {
rtcio_hal_function_select(rtc_pin, RTCIO_LL_FUNC_RTC);
}
// set input enable in sleep mode
rtcio_hal_input_enable(rtc_pin);
#if SOC_PM_SUPPORT_RTC_PERIPH_PD
Expand All @@ -1676,7 +1691,9 @@ static void ext1_wakeup_prepare(void)
* a pathway to EXT1. */

// Route pad to DIGITAL
rtcio_hal_function_select(rtc_pin, RTCIO_LL_FUNC_DIGITAL);
RTCIO_RCC_ATOMIC() {
rtcio_hal_function_select(rtc_pin, RTCIO_LL_FUNC_DIGITAL);
}
// set input enable
gpio_ll_input_enable(&GPIO, gpio);
// hold rtc_pin to use it during sleep state
Expand Down
9 changes: 9 additions & 0 deletions components/esp_system/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ menu "ESP System Settings"
# 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
select USJ_ENABLE_USB_SERIAL_JTAG

config ESP_CONSOLE_UART
# Internal option, indicates that console UART is used (and not USB, for example)
Expand Down Expand Up @@ -586,6 +587,14 @@ menu "ESP System Settings"
which may increase about the boot-up time by about 200 us. Disable this when your bootloader is built with
ESP-IDF version v5.2 and above.

config ESP_SYSTEM_HW_PC_RECORD
bool "Hardware PC recording"
depends on SOC_ASSIST_DEBUG_SUPPORTED
default y
help
This option will enable the PC recording function of assist_debug module. The PC value of the CPU will be
recorded to PC record register in assist_debug module in real time. When an exception occurs and the CPU
is reset, this register will be kept, then we can use the recorded PC to debug the causes of the reset.
endmenu # ESP System Settings

menu "IPC (Inter-Processor Call)"
Expand Down
7 changes: 7 additions & 0 deletions components/esp_system/port/soc/esp32c2/clk.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,13 @@ __attribute__((weak)) void esp_perip_clk_init(void)
SYSTEM_I2C_EXT0_CLK_EN;
common_perip_clk1 = 0;

#if !CONFIG_ESP_SYSTEM_HW_PC_RECORD
/* Disable ASSIST Debug module clock if PC recoreding function is not used,
* if stack guard function needs it, it will be re-enabled at esp_hw_stack_guard_init */
CLEAR_PERI_REG_MASK(SYSTEM_CPU_PERI_CLK_EN_REG, SYSTEM_CLK_EN_ASSIST_DEBUG);
SET_PERI_REG_MASK(SYSTEM_CPU_PERI_RST_EN_REG, SYSTEM_RST_EN_ASSIST_DEBUG);
#endif

/* Disable some peripheral clocks. */
CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN0_REG, common_perip_clk);
SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG, common_perip_clk);
Expand Down
Loading

0 comments on commit 5a682c3

Please sign in to comment.