Merge branch 'bugfix/fix_esp32p4_light_sleep_issues' into 'master'

fix(esp_hw_support): fix esp32p4 light sleep issues

Closes PM-96, PM-97, and IDF-9569

See merge request espressif/esp-idf!30089
pull/13557/merge
Wu Zheng Hui 2024-04-18 19:18:56 +08:00
commit 2c4097b4d2
14 zmienionych plików z 112 dodań i 19 usunięć

Wyświetl plik

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -32,7 +32,7 @@ void rtc_clk_cpu_set_to_default_config(void);
* 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`
* For light and deep sleep, whether to disable the BBPLL in the internal 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.
@ -65,6 +65,13 @@ void rtc_clk_mpll_disable(void);
* @param[in] mpll_freq MPLL frequency
*/
void rtc_clk_mpll_configure(uint32_t xtal_freq, uint32_t mpll_freq);
/**
* Get the MPLL frequency
* @return the value of MPLL frequency in MHz
*/
uint32_t rtc_clk_mpll_get_freq(void);
#endif //#if SOC_CLK_MPLL_SUPPORTED
/**

Wyświetl plik

@ -586,7 +586,6 @@ void sleep_smp_cpu_sleep_prepare(void)
esp_ipc_isr_call((esp_ipc_isr_func_t)smp_core_do_retention, NULL);
#else
esp_ipc_isr_stall_other_cpu();
esp_ipc_isr_stall_pause();
#endif
}
@ -601,7 +600,6 @@ void sleep_smp_cpu_wakeup_prepare(void)
}
atomic_store(&s_smp_retention_state[core_id], SMP_IDLE);
#else
esp_ipc_isr_stall_resume();
esp_ipc_isr_release_other_cpu();
#endif
}

Wyświetl plik

@ -159,6 +159,10 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
config->digital = digital_default;
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags);
#if CONFIG_SPIRAM
analog_default.hp_sys.analog.pd_cur = 1;
analog_default.lp_sys[PMU_MODE_LP_SLEEP].analog.pd_cur = 1;
#endif
config->analog = analog_default;
}
return config;
@ -257,13 +261,13 @@ void pmu_sleep_init(const pmu_sleep_config_t *config, bool dslp)
void pmu_sleep_increase_ldo_volt(void) {
REG_SET_FIELD(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS, 30);
REG_SET_BIT(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_XPD);
// Decrease the DCDC voltage to reduce the voltage difference between the DCDC and the LDO to avoid overshooting the DCDC voltage during wake-up.
REG_SET_FIELD(PMU_HP_ACTIVE_BIAS_REG, PMU_HP_ACTIVE_DCM_VSET, 24);
}
void pmu_sleep_shutdown_dcdc(void) {
SET_PERI_REG_MASK(LP_SYSTEM_REG_SYS_CTRL_REG, LP_SYSTEM_REG_LP_FIB_DCDC_SWITCH); //0: enable, 1: disable
REG_SET_BIT(PMU_DCM_CTRL_REG, PMU_DCDC_OFF_REQ);
// Decrease the DCDC voltage to reduce the voltage difference between the DCDC and the LDO to avoid overshooting the DCDC voltage during wake-up.
REG_SET_FIELD(PMU_HP_ACTIVE_BIAS_REG, PMU_HP_ACTIVE_DCM_VSET, 24);
// Decrease hp_ldo voltage.
REG_SET_FIELD(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS, 24);
}

Wyświetl plik

@ -13,6 +13,7 @@
#include "esp32p4/rom/rtc.h"
#include "soc/rtc.h"
#include "esp_private/rtc_clk.h"
#include "esp_attr.h"
#include "esp_hw_log.h"
#include "esp_rom_sys.h"
#include "hal/clk_tree_ll.h"
@ -26,6 +27,9 @@ static const char *TAG = "rtc_clk";
// CPLL frequency option, in 360/400MHz. Zero if CPLL is not enabled.
static int s_cur_cpll_freq = 0;
// MPLL frequency option, 400MHz. Zero if MPLL is not enabled.
static DRAM_ATTR uint32_t s_cur_mpll_freq = 0;
void rtc_clk_32k_enable(bool enable)
{
if (enable) {
@ -483,6 +487,7 @@ bool rtc_dig_8m_enabled(void)
void rtc_clk_mpll_disable(void)
{
clk_ll_mpll_disable();
s_cur_mpll_freq = 0;
}
void rtc_clk_mpll_enable(void)
@ -500,4 +505,10 @@ void rtc_clk_mpll_configure(uint32_t xtal_freq, uint32_t mpll_freq)
while(!regi2c_ctrl_ll_mpll_calibration_is_done());
/* MPLL calibration stop */
regi2c_ctrl_ll_mpll_calibration_stop();
s_cur_mpll_freq = mpll_freq;
}
uint32_t rtc_clk_mpll_get_freq(void)
{
return s_cur_mpll_freq;
}

Wyświetl plik

@ -16,6 +16,7 @@
#include "esp_private/esp_sleep_internal.h"
#include "esp_private/esp_timer_private.h"
#include "esp_private/periph_ctrl.h"
#include "esp_private/rtc_clk.h"
#include "esp_private/sleep_event.h"
#include "esp_private/system_internal.h"
#include "esp_log.h"
@ -27,6 +28,7 @@
#include "soc/soc_caps.h"
#include "driver/rtc_io.h"
#include "hal/rtc_io_hal.h"
#include "hal/clk_tree_hal.h"
#if SOC_PM_SUPPORT_PMU_MODEM_STATE
#include "esp_private/pm_impl.h"
@ -924,6 +926,13 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
#endif
#endif
#if SOC_CLK_MPLL_SUPPORTED
uint32_t mpll_freq_mhz = rtc_clk_mpll_get_freq();
if (mpll_freq_mhz) {
rtc_clk_mpll_disable();
}
#endif
#if SOC_DCDC_SUPPORTED
uint64_t ldo_increased_us = rtc_time_slowclk_to_us(rtc_time_get() - s_config.rtc_ticks_at_ldo_prepare, s_config.rtc_clk_cal_period);
if (ldo_increased_us < LDO_POWER_TAKEOVER_PREPARATION_TIME_US) {
@ -951,6 +960,13 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu, deep_sleep);
#endif
#if SOC_CLK_MPLL_SUPPORTED
if (mpll_freq_mhz) {
rtc_clk_mpll_enable();
rtc_clk_mpll_configure(clk_hal_xtal_get_freq_mhz(), mpll_freq_mhz);
}
#endif
/* Unhold the SPI CS pin */
#if (CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND)
#if !CONFIG_IDF_TARGET_ESP32H2 // ESP32H2 TODO IDF-7359: related rtcio ll func not supported yet
@ -1244,8 +1260,8 @@ esp_err_t esp_light_sleep_start(void)
sleep_smp_cpu_sleep_prepare();
#else
esp_ipc_isr_stall_other_cpu();
esp_ipc_isr_stall_pause();
#endif
esp_ipc_isr_stall_pause();
#endif
#if CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION && CONFIG_PM_SLP_IRAM_OPT
@ -1395,10 +1411,10 @@ esp_err_t esp_light_sleep_start(void)
#endif
#if !CONFIG_FREERTOS_UNICORE
esp_ipc_isr_stall_resume();
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && SOC_PM_CPU_RETENTION_BY_SW
sleep_smp_cpu_wakeup_prepare();
#else
esp_ipc_isr_stall_resume();
esp_ipc_isr_release_other_cpu();
#endif
#endif
@ -1408,7 +1424,6 @@ esp_err_t esp_light_sleep_start(void)
wdt_hal_disable(&rtc_wdt_ctx);
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
}
portEXIT_CRITICAL(&s_config.lock);
#if CONFIG_ESP_TASK_WDT_USE_ESP_TIMER
/* Restart the Task Watchdog timer as it was stopped before sleeping. */
@ -1425,6 +1440,8 @@ esp_err_t esp_light_sleep_start(void)
s_sleep_ctx->sleep_request_result = err;
}
#endif
portEXIT_CRITICAL(&s_config.lock);
return err;
}

Wyświetl plik

@ -5,5 +5,5 @@ set(sources "test_app_main.c"
# the component must be registered as a WHOLE_ARCHIVE
idf_component_register(SRCS ${sources}
INCLUDE_DIRS "."
PRIV_REQUIRES unity esp_pm ulp driver esp_timer
PRIV_REQUIRES unity esp_pm ulp driver esp_timer esp_psram
WHOLE_ARCHIVE)

Wyświetl plik

@ -14,3 +14,31 @@ from pytest_embedded import Dut
], indirect=True)
def test_esp_pm(dut: Dut) -> None:
dut.run_all_single_board_cases()
# psram attr tests with xip_psram
@pytest.mark.esp32s2
@pytest.mark.generic
@pytest.mark.parametrize(
'config',
[
'pm_xip_psram_esp32s2'
],
indirect=True,
)
def test_esp_attr_xip_psram_esp32s2(dut: Dut) -> None:
dut.run_all_single_board_cases()
# psram attr tests with xip_psram
@pytest.mark.esp32s3
@pytest.mark.generic
@pytest.mark.parametrize(
'config',
[
'pm_xip_psram_esp32s3'
],
indirect=True,
)
def test_esp_attr_xip_psram_esp32s3(dut: Dut) -> None:
dut.run_all_single_board_cases()

Wyświetl plik

@ -0,0 +1,6 @@
CONFIG_IDF_TARGET="esp32s2"
CONFIG_SPIRAM=y
CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y
CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y
CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y
CONFIG_SPIRAM_RODATA=y

Wyświetl plik

@ -0,0 +1,6 @@
CONFIG_IDF_TARGET="esp32s3"
CONFIG_SPIRAM=y
CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y
CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y
CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y
CONFIG_SPIRAM_RODATA=y

Wyświetl plik

@ -11,6 +11,7 @@
#include "sdkconfig.h"
#include "esp_attr.h"
#include "esp_log.h"
#include "esp_sleep.h"
#include "esp_clk_internal.h"
#include "esp32p4/rom/ets_sys.h"
#include "esp32p4/rom/uart.h"
@ -174,6 +175,21 @@ void rtc_clk_select_rtc_slow_clk(void)
*/
__attribute__((weak)) void esp_perip_clk_init(void)
{
soc_rtc_slow_clk_src_t rtc_slow_clk_src = rtc_clk_slow_src_get();
if (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC32K) {
esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL32K, ESP_PD_OPTION_AUTO);
esp_sleep_pd_config(ESP_PD_DOMAIN_RC32K, ESP_PD_OPTION_ON);
// RC slow (150K) always ON
} else if (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
esp_sleep_pd_config(ESP_PD_DOMAIN_RC32K, ESP_PD_OPTION_AUTO);
esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL32K, ESP_PD_OPTION_ON);
// RC slow (150K) always ON
} else {
esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL32K, ESP_PD_OPTION_AUTO);
esp_sleep_pd_config(ESP_PD_DOMAIN_RC32K, ESP_PD_OPTION_AUTO);
}
ESP_EARLY_LOGW(TAG, "esp_perip_clk_init() has not been implemented yet");
#if 0 // TODO: IDF-5658
uint32_t common_perip_clk, hwcrypto_perip_clk, wifi_bt_sdio_clk = 0;

Wyświetl plik

@ -78,7 +78,6 @@ TEST_CASE_MULTIPLE_STAGES("enter deep sleep on APP CPU and wake up using timer",
#endif
#if !(CONFIG_SPIRAM && CONFIG_IDF_TARGET_ESP32P4) // TODO: IDF-9569
static void do_deep_sleep_timer(void)
{
esp_sleep_enable_timer_wakeup(2000000);
@ -111,7 +110,6 @@ TEST_CASE("wake up from light sleep using timer", "[deepsleep]")
(tv_stop.tv_usec - tv_start.tv_usec) * 1e-3f;
TEST_ASSERT_INT32_WITHIN(500, 2000, (int) dt);
}
#endif
//NOTE: Explained in IDF-1445 | MR !14996
#if !(CONFIG_SPIRAM) || (CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL >= 16384)
@ -253,7 +251,6 @@ TEST_CASE("light sleep and frequency switching", "[deepsleep]")
}
}
#if !(CONFIG_SPIRAM && CONFIG_IDF_TARGET_ESP32P4) // TODO: IDF-9569
static void do_deep_sleep(void)
{
esp_sleep_enable_timer_wakeup(100000);
@ -289,7 +286,6 @@ TEST_CASE_MULTIPLE_STAGES("enter deep sleep after abort", "[deepsleep][reset=abo
do_abort,
check_abort_reset_and_sleep,
check_sleep_reset);
#endif
#if ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB
static RTC_DATA_ATTR uint32_t s_wake_stub_var;
@ -331,7 +327,7 @@ TEST_CASE_MULTIPLE_STAGES("can set sleep wake stub", "[deepsleep][reset=DEEPSLEE
trigger a CRC calculation (done in hardware) for the entire RTC FAST memory
before going to deep sleep and if it's invalid then the stub is not
run. Also, while the CRC is being calculated the RTC FAST memory is not
accesible by the CPU (reads all zeros).
accessible by the CPU (reads all zeros).
*/
static void increment_rtc_memory_cb(void *arg)
@ -491,7 +487,7 @@ static void trigger_deepsleep(void)
struct timeval start;
// Use NVS instead of RTC mem to store the start time of deep sleep
// Beacuse not all esp chips support RTC mem(such as esp32c2)
// Because not all esp chips support RTC mem(such as esp32c2)
// Initialize NVS
esp_err_t err = nvs_flash_init();
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {

Wyświetl plik

@ -1,6 +1,5 @@
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded import Dut
@ -16,7 +15,8 @@ from pytest_embedded import Dut
]
)
def test_esp_system(dut: Dut) -> None:
dut.run_all_single_board_cases()
# esp32p4 32MB PSRAM initialize in startup takes more than 30 sec
dut.run_all_single_board_cases(timeout=60)
@pytest.mark.generic

Wyświetl plik

@ -631,6 +631,8 @@ TEST_CASE("Test xTaskResumeAll resumes pended tasks", "[freertos]")
TEST_ASSERT_EQUAL(pdTRUE, xTaskCreatePinnedToCore(test_pended_running_task, "susp", 2048, (void *)xTaskGetCurrentTaskHandle(), UNITY_FREERTOS_PRIORITY + 1, &susp_tsk_hdl, i));
// Wait for to be notified to test completion
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
// Add a short delay to allow the test_pended_running_task to go to suspend state
vTaskDelay(1);
vTaskDelete(susp_tsk_hdl);
}
// Add a short delay to allow the idle task to free any remaining task memory

Wyświetl plik

@ -24,3 +24,5 @@ entries:
spi_flash_hal_gpspi (noflash)
if SOC_PMU_SUPPORTED = y:
pmu_hal (noflash)
if SOC_CLK_MPLL_SUPPORTED = y:
clk_tree_hal: clk_hal_xtal_get_freq_mhz (noflash)