mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
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
This commit is contained in:
commit
2c4097b4d2
@ -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
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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
|
@ -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
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user