mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'bugfix/fix_esp32p4_sleep_psram_access_failure' into 'master'
fix(esp_hw_support): support esp32p4 psram sleep retention Closes PM-138, PM-177, PM-187, PM-189, and PM-190 See merge request espressif/esp-idf!32190
This commit is contained in:
commit
82e76abaa8
@ -88,6 +88,7 @@ static void test_gptimer_sleep_retention(bool back_up_before_sleep)
|
||||
TEST_ASSERT_EQUAL(PMU_SLEEP_PD_TOP, sleep_ctx.sleep_flags & PMU_SLEEP_PD_TOP);
|
||||
}
|
||||
#endif
|
||||
esp_sleep_set_sleep_context(NULL);
|
||||
|
||||
uint64_t count_value_after_sleep = 0;
|
||||
TEST_ESP_OK(gptimer_get_raw_count(timer, &count_value_after_sleep));
|
||||
|
@ -115,6 +115,7 @@ static void test_rmt_tx_rx_sleep_retention(bool back_up_before_sleep)
|
||||
TEST_ASSERT_EQUAL(PMU_SLEEP_PD_TOP, sleep_ctx.sleep_flags & PMU_SLEEP_PD_TOP);
|
||||
}
|
||||
#endif
|
||||
esp_sleep_set_sleep_context(NULL);
|
||||
|
||||
TEST_ESP_OK(rmt_enable(tx_channel));
|
||||
TEST_ESP_OK(rmt_enable(rx_channel));
|
||||
|
@ -26,7 +26,8 @@ void mspi_timing_config_set_psram_clock(uint32_t psram_freq_mhz, mspi_timing_spe
|
||||
ESP_EARLY_LOGD(TAG, "psram_freq_mhz: %" PRIu32 " mhz, bus clock div: %" PRIu32, psram_freq_mhz, freqdiv);
|
||||
PERIPH_RCC_ATOMIC() {
|
||||
//MSPI2 and MSPI3 share the register for core clock. So we only set MSPI2 here.
|
||||
psram_ctrlr_ll_set_core_clock(PSRAM_CTRLR_LL_MSPI_ID_2, MSPI_TIMING_CORE_CLOCK_DIV);
|
||||
psram_ctrlr_ll_enable_core_clock(PSRAM_CTRLR_LL_MSPI_ID_2, true);
|
||||
psram_ctrlr_ll_set_core_clock_div(PSRAM_CTRLR_LL_MSPI_ID_2, MSPI_TIMING_CORE_CLOCK_DIV);
|
||||
psram_ctrlr_ll_set_bus_clock(PSRAM_CTRLR_LL_MSPI_ID_3, freqdiv);
|
||||
psram_ctrlr_ll_set_bus_clock(PSRAM_CTRLR_LL_MSPI_ID_2, freqdiv);
|
||||
}
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "hal/lp_aon_hal.h"
|
||||
#include "soc/lp_system_reg.h"
|
||||
#include "hal/pmu_hal.h"
|
||||
#include "hal/psram_ctrlr_ll.h"
|
||||
#include "hal/lp_sys_ll.h"
|
||||
#include "esp_private/esp_pmu.h"
|
||||
#include "pmu_param.h"
|
||||
@ -135,6 +136,8 @@ static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default(
|
||||
return param;
|
||||
}
|
||||
|
||||
TCM_DRAM_ATTR static uint32_t s_saved_pd_flags = 0;
|
||||
|
||||
const pmu_sleep_config_t* pmu_sleep_config_default(
|
||||
pmu_sleep_config_t *config,
|
||||
uint32_t pd_flags,
|
||||
@ -144,6 +147,7 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
|
||||
bool dslp
|
||||
)
|
||||
{
|
||||
s_saved_pd_flags = pd_flags;
|
||||
pmu_sleep_power_config_t power_default = PMU_SLEEP_POWER_CONFIG_DEFAULT(pd_flags);
|
||||
|
||||
uint32_t iram_pd_flags = 0;
|
||||
@ -168,8 +172,8 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
|
||||
// Get light sleep analog 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;
|
||||
analog_default.hp_sys.analog.pd_cur = 0;
|
||||
analog_default.lp_sys[PMU_MODE_LP_SLEEP].analog.pd_cur = 0;
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP_SLEEP_KEEP_DCDC_ALWAYS_ON
|
||||
@ -290,11 +294,6 @@ void pmu_sleep_shutdown_ldo(void) {
|
||||
CLEAR_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_XPD);
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void sleep_writeback_l1_dcache(void) {
|
||||
Cache_WriteBack_All(CACHE_MAP_L1_DCACHE);
|
||||
while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE));
|
||||
}
|
||||
|
||||
static TCM_DRAM_ATTR uint32_t s_mpll_freq_mhz_before_sleep = 0;
|
||||
|
||||
TCM_IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp)
|
||||
@ -309,12 +308,28 @@ TCM_IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt,
|
||||
pmu_ll_hp_clear_reject_intr_status(PMU_instance()->hal->dev);
|
||||
pmu_ll_hp_clear_reject_cause(PMU_instance()->hal->dev);
|
||||
|
||||
// !!! Need to manually check that data in L2 memory will not be modified from now on. !!!
|
||||
sleep_writeback_l1_dcache();
|
||||
if (s_saved_pd_flags & PMU_SLEEP_PD_TOP) {
|
||||
// L1 Cache will be powered down during PD_TOP sleep, write it back to L2 Cache here.
|
||||
// !!! Need to manually check that data in L2 memory will not be modified from now on. !!!
|
||||
Cache_WriteBack_All(CACHE_MAP_L1_DCACHE);
|
||||
}
|
||||
|
||||
// !!! Need to manually check that data in PSRAM will not be accessed from now on. !!!
|
||||
#if CONFIG_SPIRAM
|
||||
psram_ctrlr_ll_wait_all_transaction_done();
|
||||
#endif
|
||||
s_mpll_freq_mhz_before_sleep = rtc_clk_mpll_get_freq();
|
||||
if (s_mpll_freq_mhz_before_sleep) {
|
||||
#if CONFIG_SPIRAM
|
||||
_psram_ctrlr_ll_select_clk_source(PSRAM_CTRLR_LL_MSPI_ID_2, PSRAM_CLK_SRC_XTAL);
|
||||
_psram_ctrlr_ll_select_clk_source(PSRAM_CTRLR_LL_MSPI_ID_3, PSRAM_CLK_SRC_XTAL);
|
||||
if (!s_pmu_sleep_regdma_backup_enabled) {
|
||||
// MSPI2 and MSPI3 share the register for core clock. So we only set MSPI2 here.
|
||||
// If it's a PD_TOP sleep, psram MSPI core clock will be disabled by REGDMA
|
||||
// !!! Need to manually check that data in PSRAM will not be accessed from now on. !!!
|
||||
_psram_ctrlr_ll_enable_core_clock(PSRAM_CTRLR_LL_MSPI_ID_2, false);
|
||||
_psram_ctrlr_ll_enable_module_clock(PSRAM_CTRLR_LL_MSPI_ID_2, false);
|
||||
}
|
||||
#endif
|
||||
rtc_clk_mpll_disable();
|
||||
}
|
||||
|
||||
@ -353,6 +368,16 @@ TCM_IRAM_ATTR bool pmu_sleep_finish(bool dslp)
|
||||
if (s_mpll_freq_mhz_before_sleep) {
|
||||
rtc_clk_mpll_enable();
|
||||
rtc_clk_mpll_configure(clk_hal_xtal_get_freq_mhz(), s_mpll_freq_mhz_before_sleep);
|
||||
#if CONFIG_SPIRAM
|
||||
if (!s_pmu_sleep_regdma_backup_enabled) {
|
||||
// MSPI2 and MSPI3 share the register for core clock. So we only set MSPI2 here.
|
||||
// If it's a PD_TOP sleep, psram MSPI core clock will be enabled by REGDMA
|
||||
_psram_ctrlr_ll_enable_core_clock(PSRAM_CTRLR_LL_MSPI_ID_2, true);
|
||||
_psram_ctrlr_ll_enable_module_clock(PSRAM_CTRLR_LL_MSPI_ID_2, true);
|
||||
}
|
||||
_psram_ctrlr_ll_select_clk_source(PSRAM_CTRLR_LL_MSPI_ID_2, PSRAM_CLK_SRC_MPLL);
|
||||
_psram_ctrlr_ll_select_clk_source(PSRAM_CTRLR_LL_MSPI_ID_3, PSRAM_CLK_SRC_MPLL);
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned chip_version = efuse_hal_chip_revision();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -63,11 +63,17 @@ void esp_sleep_config_gpio_isolate(void)
|
||||
}
|
||||
|
||||
#if CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND && CONFIG_SPIRAM
|
||||
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_CS1), GPIO_PULLUP_ONLY);
|
||||
int32_t mspi_io_cs1_io_num = esp_mspi_get_io(ESP_MSPI_IO_CS1);
|
||||
if (GPIO_IS_VALID_GPIO(mspi_io_cs1_io_num)) {
|
||||
gpio_sleep_set_pull_mode(mspi_io_cs1_io_num, GPIO_PULLUP_ONLY);
|
||||
}
|
||||
#endif // CONFIG_ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND && CONFIG_SPIRAM
|
||||
|
||||
#if CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND
|
||||
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_CS0), GPIO_PULLUP_ONLY);
|
||||
int32_t mspi_io_cs0_io_num = esp_mspi_get_io(ESP_MSPI_IO_CS0);
|
||||
if (GPIO_IS_VALID_GPIO(mspi_io_cs0_io_num)) {
|
||||
gpio_sleep_set_pull_mode(esp_mspi_get_io(ESP_MSPI_IO_CS0), GPIO_PULLUP_ONLY);
|
||||
}
|
||||
#endif // CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND
|
||||
|
||||
#if CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU
|
||||
|
@ -73,14 +73,24 @@ static __attribute__((unused)) esp_err_t sleep_sys_periph_iomux_retention_init(v
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static __attribute__((unused)) esp_err_t sleep_sys_periph_spimem_retention_init(void *arg)
|
||||
static __attribute__((unused)) esp_err_t sleep_sys_periph_flash_spimem_retention_init(void *arg)
|
||||
{
|
||||
esp_err_t err = sleep_retention_entries_create(spimem_regs_retention, ARRAY_SIZE(spimem_regs_retention), REGDMA_LINK_PRI_SYS_PERIPH_LOW, SLEEP_RETENTION_MODULE_SYS_PERIPH);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (%s) retention", "SPI mem");
|
||||
ESP_LOGD(TAG, "SPI Mem sleep retention initialization");
|
||||
esp_err_t err = sleep_retention_entries_create(flash_spimem_regs_retention, ARRAY_SIZE(flash_spimem_regs_retention), REGDMA_LINK_PRI_SYS_PERIPH_LOW, SLEEP_RETENTION_MODULE_SYS_PERIPH);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (%s) retention", "Flash SPI mem");
|
||||
ESP_LOGD(TAG, "Flash SPI Mem sleep retention initialization");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if CONFIG_SPIRAM
|
||||
static __attribute__((unused)) esp_err_t sleep_sys_periph_psram_spimem_retention_init(void *arg)
|
||||
{
|
||||
esp_err_t err = sleep_retention_entries_create(psram_spimem_regs_retention, ARRAY_SIZE(psram_spimem_regs_retention), REGDMA_LINK_PRI_SYS_PERIPH_LOW, SLEEP_RETENTION_MODULE_SYS_PERIPH);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (%s) retention", "PSRAM SPI mem");
|
||||
ESP_LOGD(TAG, "PSRAM SPI Mem sleep retention initialization");
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
static __attribute__((unused)) esp_err_t sleep_sys_periph_systimer_retention_init(void *arg)
|
||||
{
|
||||
esp_err_t err = sleep_retention_entries_create(systimer_regs_retention, ARRAY_SIZE(systimer_regs_retention), REGDMA_LINK_PRI_SYS_PERIPH_LOW, SLEEP_RETENTION_MODULE_SYS_PERIPH);
|
||||
@ -130,8 +140,12 @@ static __attribute__((unused)) esp_err_t sleep_sys_periph_retention_init(void *a
|
||||
#endif
|
||||
err = sleep_sys_periph_iomux_retention_init(arg);
|
||||
if(err) goto error;
|
||||
err = sleep_sys_periph_spimem_retention_init(arg);
|
||||
err = sleep_sys_periph_flash_spimem_retention_init(arg);
|
||||
if(err) goto error;
|
||||
#if CONFIG_SPIRAM
|
||||
err = sleep_sys_periph_psram_spimem_retention_init(arg);
|
||||
if(err) goto error;
|
||||
#endif
|
||||
err = sleep_sys_periph_systimer_retention_init(arg);
|
||||
if(err) goto error;
|
||||
#if SOC_PAU_IN_TOP_DOMAIN
|
||||
|
@ -7,6 +7,7 @@ components/esp_system/test_apps/console:
|
||||
components/esp_system/test_apps/esp_system_unity_tests:
|
||||
disable:
|
||||
- if: (CONFIG_NAME == "psram" and SOC_SPIRAM_SUPPORTED != 1)
|
||||
- if: (CONFIG_NAME == "psram_with_pd_top" and (SOC_SPIRAM_SUPPORTED != 1 or SOC_PM_SUPPORT_TOP_PD != 1))
|
||||
|
||||
components/esp_system/test_apps/linux_apis:
|
||||
enable:
|
||||
|
@ -11,11 +11,14 @@ set(SRC "test_app_main.c"
|
||||
"test_ipc.c"
|
||||
"test_reset_reason.c"
|
||||
"test_shared_stack_printf.c"
|
||||
"test_sleep.c"
|
||||
"test_stack_check.c"
|
||||
"test_system_time.c"
|
||||
"test_task_wdt.c")
|
||||
|
||||
if(CONFIG_SOC_LIGHT_SLEEP_SUPPORTED OR CONFIG_SOC_DEEP_SLEEP_SUPPORTED)
|
||||
list(APPEND SRC "test_sleep.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_SYSTIMER_SUPPORT_ETM)
|
||||
list(APPEND SRC "test_systick_etm.c")
|
||||
endif()
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <sys/time.h>
|
||||
#include <sys/param.h>
|
||||
#include "esp_sleep.h"
|
||||
#include "esp_private/esp_sleep_internal.h"
|
||||
#include "driver/rtc_io.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
@ -31,7 +32,14 @@
|
||||
#include "nvs_flash.h"
|
||||
#include "nvs.h"
|
||||
|
||||
#if SOC_DEEP_SLEEP_SUPPORTED
|
||||
#if CONFIG_SPIRAM
|
||||
#include "esp_private/esp_psram_extram.h"
|
||||
#endif
|
||||
|
||||
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||
#include "esp_private/sleep_cpu.h"
|
||||
#endif
|
||||
|
||||
#if SOC_PMU_SUPPORTED
|
||||
#include "esp_private/esp_pmu.h"
|
||||
#else
|
||||
@ -42,6 +50,297 @@
|
||||
#define ESP_EXT0_WAKEUP_LEVEL_HIGH 1
|
||||
__attribute__((unused)) static struct timeval tv_start, tv_stop;
|
||||
|
||||
/////////////////////////// Light Sleep Test Cases ////////////////////////////////////
|
||||
#if SOC_LIGHT_SLEEP_SUPPORTED
|
||||
TEST_CASE("wake up from light sleep using timer", "[lightsleep]")
|
||||
{
|
||||
esp_sleep_enable_timer_wakeup(2000000);
|
||||
gettimeofday(&tv_start, NULL);
|
||||
esp_light_sleep_start();
|
||||
gettimeofday(&tv_stop, NULL);
|
||||
float dt = (tv_stop.tv_sec - tv_start.tv_sec) * 1e3f +
|
||||
(tv_stop.tv_usec - tv_start.tv_usec) * 1e-3f;
|
||||
TEST_ASSERT_INT32_WITHIN(500, 2000, (int) dt);
|
||||
}
|
||||
|
||||
//NOTE: Explained in IDF-1445 | MR !14996
|
||||
#if !(CONFIG_SPIRAM) || (CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL >= 16384)
|
||||
static void test_light_sleep(void* arg)
|
||||
{
|
||||
vTaskDelay(2);
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
printf("%d %d\n", xPortGetCoreID(), i);
|
||||
fflush(stdout);
|
||||
esp_light_sleep_start();
|
||||
}
|
||||
SemaphoreHandle_t done = (SemaphoreHandle_t) arg;
|
||||
xSemaphoreGive(done);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
TEST_CASE("light sleep stress test", "[lightsleep]")
|
||||
{
|
||||
SemaphoreHandle_t done = xSemaphoreCreateCounting(2, 0);
|
||||
esp_sleep_enable_timer_wakeup(1000);
|
||||
xTaskCreatePinnedToCore(&test_light_sleep, "ls0", 4096, done, UNITY_FREERTOS_PRIORITY + 1, NULL, 0);
|
||||
#if CONFIG_FREERTOS_NUMBER_OF_CORES == 2
|
||||
xTaskCreatePinnedToCore(&test_light_sleep, "ls1", 4096, done, UNITY_FREERTOS_PRIORITY + 1, NULL, 1);
|
||||
#endif
|
||||
xSemaphoreTake(done, portMAX_DELAY);
|
||||
#if CONFIG_FREERTOS_NUMBER_OF_CORES == 2
|
||||
xSemaphoreTake(done, portMAX_DELAY);
|
||||
#endif
|
||||
vSemaphoreDelete(done);
|
||||
}
|
||||
|
||||
static void timer_func(void* arg)
|
||||
{
|
||||
esp_rom_delay_us(50);
|
||||
}
|
||||
|
||||
TEST_CASE("light sleep stress test with periodic esp_timer", "[lightsleep]")
|
||||
{
|
||||
SemaphoreHandle_t done = xSemaphoreCreateCounting(2, 0);
|
||||
esp_sleep_enable_timer_wakeup(1000);
|
||||
esp_timer_handle_t timer;
|
||||
esp_timer_create_args_t config = {
|
||||
.callback = &timer_func,
|
||||
};
|
||||
TEST_ESP_OK(esp_timer_create(&config, &timer));
|
||||
esp_timer_start_periodic(timer, 500);
|
||||
xTaskCreatePinnedToCore(&test_light_sleep, "ls1", 4096, done, UNITY_FREERTOS_PRIORITY + 1, NULL, 0);
|
||||
#if CONFIG_FREERTOS_NUMBER_OF_CORES == 2
|
||||
xTaskCreatePinnedToCore(&test_light_sleep, "ls1", 4096, done, UNITY_FREERTOS_PRIORITY + 1, NULL, 1);
|
||||
#endif
|
||||
xSemaphoreTake(done, portMAX_DELAY);
|
||||
#if CONFIG_FREERTOS_NUMBER_OF_CORES == 2
|
||||
xSemaphoreTake(done, portMAX_DELAY);
|
||||
#endif
|
||||
vSemaphoreDelete(done);
|
||||
esp_timer_stop(timer);
|
||||
esp_timer_delete(timer);
|
||||
}
|
||||
#endif // !(CONFIG_SPIRAM) || (CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL >= 16384)
|
||||
|
||||
#if defined(CONFIG_ESP_SYSTEM_RTC_EXT_XTAL)
|
||||
#define MAX_SLEEP_TIME_ERROR_US 200
|
||||
#else
|
||||
#define MAX_SLEEP_TIME_ERROR_US 100
|
||||
#endif
|
||||
|
||||
TEST_CASE("light sleep duration is correct", "[lightsleep][ignore]")
|
||||
{
|
||||
// don't power down XTAL — powering it up takes different time on
|
||||
// different boards
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON);
|
||||
|
||||
// run one light sleep without checking timing, to warm up the cache
|
||||
esp_sleep_enable_timer_wakeup(1000);
|
||||
esp_light_sleep_start();
|
||||
|
||||
const int sleep_intervals_ms[] = {
|
||||
1, 1, 2, 3, 4, 5, 6, 7, 8, 10, 15,
|
||||
20, 25, 50, 100, 200, 500,
|
||||
};
|
||||
|
||||
const int sleep_intervals_count = sizeof(sleep_intervals_ms) / sizeof(sleep_intervals_ms[0]);
|
||||
for (int i = 0; i < sleep_intervals_count; ++i) {
|
||||
uint64_t sleep_time = sleep_intervals_ms[i] * 1000;
|
||||
esp_sleep_enable_timer_wakeup(sleep_time);
|
||||
for (int repeat = 0; repeat < 5; ++repeat) {
|
||||
uint64_t start = esp_clk_rtc_time();
|
||||
int64_t start_hs = esp_timer_get_time();
|
||||
esp_light_sleep_start();
|
||||
int64_t stop_hs = esp_timer_get_time();
|
||||
uint64_t stop = esp_clk_rtc_time();
|
||||
|
||||
int diff_us = (int)(stop - start);
|
||||
int diff_hs_us = (int)(stop_hs - start_hs);
|
||||
printf("%lld %d\n", sleep_time, (int)(diff_us - sleep_time));
|
||||
int32_t threshold = MAX(sleep_time / 100, MAX_SLEEP_TIME_ERROR_US);
|
||||
TEST_ASSERT_INT32_WITHIN(threshold, sleep_time, diff_us);
|
||||
TEST_ASSERT_INT32_WITHIN(threshold, sleep_time, diff_hs_us);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("light sleep and frequency switching", "[lightsleep]")
|
||||
{
|
||||
#ifndef CONFIG_PM_ENABLE
|
||||
uart_sclk_t clk_source = UART_SCLK_DEFAULT;
|
||||
#if SOC_UART_SUPPORT_REF_TICK
|
||||
clk_source = UART_SCLK_REF_TICK;
|
||||
#elif SOC_UART_SUPPORT_XTAL_CLK
|
||||
clk_source = UART_SCLK_XTAL;
|
||||
#endif
|
||||
HP_UART_SRC_CLK_ATOMIC() {
|
||||
uart_ll_set_sclk(UART_LL_GET_HW(CONFIG_ESP_CONSOLE_UART_NUM), (soc_module_clk_t)clk_source);
|
||||
}
|
||||
uint32_t sclk_freq;
|
||||
TEST_ESP_OK(uart_get_sclk_freq(clk_source, &sclk_freq));
|
||||
HP_UART_SRC_CLK_ATOMIC() {
|
||||
uart_ll_set_baudrate(UART_LL_GET_HW(CONFIG_ESP_CONSOLE_UART_NUM), CONFIG_ESP_CONSOLE_UART_BAUDRATE, sclk_freq);
|
||||
}
|
||||
#endif
|
||||
|
||||
rtc_cpu_freq_config_t config_xtal, config_default;
|
||||
rtc_clk_cpu_freq_get_config(&config_default);
|
||||
rtc_clk_cpu_freq_mhz_to_config(esp_clk_xtal_freq() / MHZ, &config_xtal);
|
||||
|
||||
esp_sleep_enable_timer_wakeup(1000);
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
if (i % 2 == 0) {
|
||||
rtc_clk_cpu_freq_set_config_fast(&config_xtal);
|
||||
} else {
|
||||
rtc_clk_cpu_freq_set_config_fast(&config_default);
|
||||
}
|
||||
printf("%d\n", i);
|
||||
fflush(stdout);
|
||||
esp_light_sleep_start();
|
||||
}
|
||||
}
|
||||
|
||||
#if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
|
||||
__attribute__((unused)) static float get_time_ms(void)
|
||||
{
|
||||
gettimeofday(&tv_stop, NULL);
|
||||
|
||||
float dt = (tv_stop.tv_sec - tv_start.tv_sec) * 1e3f +
|
||||
(tv_stop.tv_usec - tv_start.tv_usec) * 1e-3f;
|
||||
return fabs(dt);
|
||||
}
|
||||
|
||||
__attribute__((unused)) static uint32_t get_cause(void)
|
||||
{
|
||||
#if SOC_PMU_SUPPORTED
|
||||
uint32_t wakeup_cause = pmu_ll_hp_get_wakeup_cause(&PMU);
|
||||
#else
|
||||
uint32_t wakeup_cause = rtc_cntl_ll_get_wakeup_cause();
|
||||
#endif
|
||||
return wakeup_cause;
|
||||
}
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3) && SOC_PM_SUPPORT_EXT0_WAKEUP
|
||||
// Fails on S2 IDF-2903
|
||||
|
||||
// This test case verifies deactivation of trigger for wake up sources
|
||||
TEST_CASE("disable source trigger behavior", "[lightsleep]")
|
||||
{
|
||||
float dt = 0;
|
||||
|
||||
printf("Setup timer and ext0 to wake up immediately from GPIO_13 \n");
|
||||
|
||||
// Setup ext0 configuration to wake up almost immediately
|
||||
// The wakeup time is proportional to input capacitance * pullup resistance
|
||||
ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13));
|
||||
ESP_ERROR_CHECK(gpio_pullup_en(GPIO_NUM_13));
|
||||
ESP_ERROR_CHECK(gpio_pulldown_dis(GPIO_NUM_13));
|
||||
ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, ESP_EXT0_WAKEUP_LEVEL_HIGH));
|
||||
|
||||
// Setup timer to wakeup with timeout
|
||||
esp_sleep_enable_timer_wakeup(2000000);
|
||||
|
||||
// Save start time
|
||||
gettimeofday(&tv_start, NULL);
|
||||
esp_light_sleep_start();
|
||||
|
||||
dt = get_time_ms();
|
||||
printf("Ext0 sleep time = %d \n", (int) dt);
|
||||
|
||||
// Check wakeup from Ext0 using time measurement because wakeup cause is
|
||||
// not available in light sleep mode
|
||||
TEST_ASSERT_INT32_WITHIN(100, 100, (int) dt);
|
||||
|
||||
TEST_ASSERT((get_cause() & RTC_EXT0_TRIG_EN) != 0);
|
||||
|
||||
// Disable Ext0 source. Timer source should be triggered
|
||||
ESP_ERROR_CHECK(esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_EXT0));
|
||||
printf("Disable ext0 trigger and leave timer active.\n");
|
||||
|
||||
gettimeofday(&tv_start, NULL);
|
||||
esp_light_sleep_start();
|
||||
|
||||
dt = get_time_ms();
|
||||
printf("Timer sleep time = %d \n", (int) dt);
|
||||
|
||||
TEST_ASSERT_INT32_WITHIN(500, 2000, (int) dt);
|
||||
|
||||
// Additionally check wakeup cause
|
||||
TEST_ASSERT((get_cause() & RTC_TIMER_TRIG_EN) != 0);
|
||||
|
||||
// Disable timer source.
|
||||
ESP_ERROR_CHECK(esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER));
|
||||
|
||||
// Setup ext0 configuration to wake up immediately
|
||||
ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13));
|
||||
ESP_ERROR_CHECK(gpio_pullup_en(GPIO_NUM_13));
|
||||
ESP_ERROR_CHECK(gpio_pulldown_dis(GPIO_NUM_13));
|
||||
ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, ESP_EXT0_WAKEUP_LEVEL_HIGH));
|
||||
|
||||
printf("Disable timer trigger to wake up from ext0 source.\n");
|
||||
|
||||
gettimeofday(&tv_start, NULL);
|
||||
esp_light_sleep_start();
|
||||
|
||||
dt = get_time_ms();
|
||||
printf("Ext0 sleep time = %d \n", (int) dt);
|
||||
|
||||
TEST_ASSERT_INT32_WITHIN(100, 100, (int) dt);
|
||||
TEST_ASSERT((get_cause() & RTC_EXT0_TRIG_EN) != 0);
|
||||
|
||||
// Check error message when source is already disabled
|
||||
esp_err_t err_code = esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER);
|
||||
TEST_ASSERT(err_code == ESP_ERR_INVALID_STATE);
|
||||
|
||||
// Disable ext0 wakeup source, as this might interfere with other tests
|
||||
ESP_ERROR_CHECK(esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_EXT0));
|
||||
}
|
||||
#endif // !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3)
|
||||
#endif //SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
|
||||
|
||||
#if CONFIG_SPIRAM
|
||||
static void test_psram_accessible_after_lightsleep(void)
|
||||
{
|
||||
esp_sleep_context_t sleep_ctx;
|
||||
esp_sleep_set_sleep_context(&sleep_ctx);
|
||||
|
||||
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||
TEST_ESP_OK(sleep_cpu_configure(true));
|
||||
#endif
|
||||
|
||||
esp_sleep_enable_timer_wakeup(100 * 1000);
|
||||
esp_light_sleep_start();
|
||||
TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result);
|
||||
|
||||
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||
TEST_ASSERT_EQUAL(PMU_SLEEP_PD_TOP, sleep_ctx.sleep_flags & PMU_SLEEP_PD_TOP);
|
||||
TEST_ESP_OK(sleep_cpu_configure(false));
|
||||
#endif
|
||||
|
||||
TEST_ASSERT_EQUAL(true, esp_psram_extram_test());
|
||||
|
||||
esp_sleep_set_sleep_context(NULL);
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
static void restart_for_reinit_psram(void)
|
||||
{
|
||||
TEST_ASSERT_EQUAL(ESP_RST_SW, esp_reset_reason());
|
||||
printf("PSRAM survives after lightsleep test - OK\n");
|
||||
}
|
||||
|
||||
TEST_CASE_MULTIPLE_STAGES("Test PSRAM survives after lightsleep", "[lightsleep]",
|
||||
test_psram_accessible_after_lightsleep,
|
||||
restart_for_reinit_psram);
|
||||
#endif
|
||||
|
||||
#endif // SOC_LIGHT_SLEEP_SUPPORTED
|
||||
|
||||
/////////////////////////// Deep Sleep Test Cases ////////////////////////////////////
|
||||
#if SOC_DEEP_SLEEP_SUPPORTED
|
||||
static void check_sleep_reset(void)
|
||||
{
|
||||
TEST_ASSERT_EQUAL(ESP_RST_DEEPSLEEP, esp_reset_reason());
|
||||
@ -99,158 +398,6 @@ TEST_CASE_MULTIPLE_STAGES("light sleep followed by deep sleep", "[deepsleep][res
|
||||
do_light_sleep_deep_sleep_timer,
|
||||
check_sleep_reset)
|
||||
|
||||
TEST_CASE("wake up from light sleep using timer", "[deepsleep]")
|
||||
{
|
||||
esp_sleep_enable_timer_wakeup(2000000);
|
||||
struct timeval tv_start, tv_stop;
|
||||
gettimeofday(&tv_start, NULL);
|
||||
esp_light_sleep_start();
|
||||
gettimeofday(&tv_stop, NULL);
|
||||
float dt = (tv_stop.tv_sec - tv_start.tv_sec) * 1e3f +
|
||||
(tv_stop.tv_usec - tv_start.tv_usec) * 1e-3f;
|
||||
TEST_ASSERT_INT32_WITHIN(500, 2000, (int) dt);
|
||||
}
|
||||
|
||||
//NOTE: Explained in IDF-1445 | MR !14996
|
||||
#if !(CONFIG_SPIRAM) || (CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL >= 16384)
|
||||
static void test_light_sleep(void* arg)
|
||||
{
|
||||
vTaskDelay(2);
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
printf("%d %d\n", xPortGetCoreID(), i);
|
||||
fflush(stdout);
|
||||
esp_light_sleep_start();
|
||||
}
|
||||
SemaphoreHandle_t done = (SemaphoreHandle_t) arg;
|
||||
xSemaphoreGive(done);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
TEST_CASE("light sleep stress test", "[deepsleep]")
|
||||
{
|
||||
SemaphoreHandle_t done = xSemaphoreCreateCounting(2, 0);
|
||||
esp_sleep_enable_timer_wakeup(1000);
|
||||
xTaskCreatePinnedToCore(&test_light_sleep, "ls0", 4096, done, UNITY_FREERTOS_PRIORITY + 1, NULL, 0);
|
||||
#if CONFIG_FREERTOS_NUMBER_OF_CORES == 2
|
||||
xTaskCreatePinnedToCore(&test_light_sleep, "ls1", 4096, done, UNITY_FREERTOS_PRIORITY + 1, NULL, 1);
|
||||
#endif
|
||||
xSemaphoreTake(done, portMAX_DELAY);
|
||||
#if CONFIG_FREERTOS_NUMBER_OF_CORES == 2
|
||||
xSemaphoreTake(done, portMAX_DELAY);
|
||||
#endif
|
||||
vSemaphoreDelete(done);
|
||||
}
|
||||
|
||||
static void timer_func(void* arg)
|
||||
{
|
||||
esp_rom_delay_us(50);
|
||||
}
|
||||
|
||||
TEST_CASE("light sleep stress test with periodic esp_timer", "[deepsleep]")
|
||||
{
|
||||
SemaphoreHandle_t done = xSemaphoreCreateCounting(2, 0);
|
||||
esp_sleep_enable_timer_wakeup(1000);
|
||||
esp_timer_handle_t timer;
|
||||
esp_timer_create_args_t config = {
|
||||
.callback = &timer_func,
|
||||
};
|
||||
TEST_ESP_OK(esp_timer_create(&config, &timer));
|
||||
esp_timer_start_periodic(timer, 500);
|
||||
xTaskCreatePinnedToCore(&test_light_sleep, "ls1", 4096, done, UNITY_FREERTOS_PRIORITY + 1, NULL, 0);
|
||||
#if CONFIG_FREERTOS_NUMBER_OF_CORES == 2
|
||||
xTaskCreatePinnedToCore(&test_light_sleep, "ls1", 4096, done, UNITY_FREERTOS_PRIORITY + 1, NULL, 1);
|
||||
#endif
|
||||
xSemaphoreTake(done, portMAX_DELAY);
|
||||
#if CONFIG_FREERTOS_NUMBER_OF_CORES == 2
|
||||
xSemaphoreTake(done, portMAX_DELAY);
|
||||
#endif
|
||||
vSemaphoreDelete(done);
|
||||
esp_timer_stop(timer);
|
||||
esp_timer_delete(timer);
|
||||
}
|
||||
#endif // !(CONFIG_SPIRAM) || (CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL >= 16384)
|
||||
|
||||
#if defined(CONFIG_ESP_SYSTEM_RTC_EXT_XTAL)
|
||||
#define MAX_SLEEP_TIME_ERROR_US 200
|
||||
#else
|
||||
#define MAX_SLEEP_TIME_ERROR_US 100
|
||||
#endif
|
||||
|
||||
TEST_CASE("light sleep duration is correct", "[deepsleep][ignore]")
|
||||
{
|
||||
// don't power down XTAL — powering it up takes different time on
|
||||
// different boards
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON);
|
||||
|
||||
// run one light sleep without checking timing, to warm up the cache
|
||||
esp_sleep_enable_timer_wakeup(1000);
|
||||
esp_light_sleep_start();
|
||||
|
||||
const int sleep_intervals_ms[] = {
|
||||
1, 1, 2, 3, 4, 5, 6, 7, 8, 10, 15,
|
||||
20, 25, 50, 100, 200, 500,
|
||||
};
|
||||
|
||||
const int sleep_intervals_count = sizeof(sleep_intervals_ms) / sizeof(sleep_intervals_ms[0]);
|
||||
for (int i = 0; i < sleep_intervals_count; ++i) {
|
||||
uint64_t sleep_time = sleep_intervals_ms[i] * 1000;
|
||||
esp_sleep_enable_timer_wakeup(sleep_time);
|
||||
for (int repeat = 0; repeat < 5; ++repeat) {
|
||||
uint64_t start = esp_clk_rtc_time();
|
||||
int64_t start_hs = esp_timer_get_time();
|
||||
esp_light_sleep_start();
|
||||
int64_t stop_hs = esp_timer_get_time();
|
||||
uint64_t stop = esp_clk_rtc_time();
|
||||
|
||||
int diff_us = (int)(stop - start);
|
||||
int diff_hs_us = (int)(stop_hs - start_hs);
|
||||
printf("%lld %d\n", sleep_time, (int)(diff_us - sleep_time));
|
||||
int32_t threshold = MAX(sleep_time / 100, MAX_SLEEP_TIME_ERROR_US);
|
||||
TEST_ASSERT_INT32_WITHIN(threshold, sleep_time, diff_us);
|
||||
TEST_ASSERT_INT32_WITHIN(threshold, sleep_time, diff_hs_us);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("light sleep and frequency switching", "[deepsleep]")
|
||||
{
|
||||
#ifndef CONFIG_PM_ENABLE
|
||||
uart_sclk_t clk_source = UART_SCLK_DEFAULT;
|
||||
#if SOC_UART_SUPPORT_REF_TICK
|
||||
clk_source = UART_SCLK_REF_TICK;
|
||||
#elif SOC_UART_SUPPORT_XTAL_CLK
|
||||
clk_source = UART_SCLK_XTAL;
|
||||
#endif
|
||||
HP_UART_SRC_CLK_ATOMIC() {
|
||||
uart_ll_set_sclk(UART_LL_GET_HW(CONFIG_ESP_CONSOLE_UART_NUM), (soc_module_clk_t)clk_source);
|
||||
}
|
||||
uint32_t sclk_freq;
|
||||
TEST_ESP_OK(uart_get_sclk_freq(clk_source, &sclk_freq));
|
||||
HP_UART_SRC_CLK_ATOMIC() {
|
||||
uart_ll_set_baudrate(UART_LL_GET_HW(CONFIG_ESP_CONSOLE_UART_NUM), CONFIG_ESP_CONSOLE_UART_BAUDRATE, sclk_freq);
|
||||
}
|
||||
#endif
|
||||
|
||||
rtc_cpu_freq_config_t config_xtal, config_default;
|
||||
rtc_clk_cpu_freq_get_config(&config_default);
|
||||
rtc_clk_cpu_freq_mhz_to_config(esp_clk_xtal_freq() / MHZ, &config_xtal);
|
||||
|
||||
esp_sleep_enable_timer_wakeup(1000);
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
if (i % 2 == 0) {
|
||||
rtc_clk_cpu_freq_set_config_fast(&config_xtal);
|
||||
} else {
|
||||
rtc_clk_cpu_freq_set_config_fast(&config_default);
|
||||
}
|
||||
printf("%d\n", i);
|
||||
fflush(stdout);
|
||||
esp_light_sleep_start();
|
||||
}
|
||||
}
|
||||
|
||||
static void do_deep_sleep(void)
|
||||
{
|
||||
esp_sleep_enable_timer_wakeup(100000);
|
||||
@ -382,106 +529,6 @@ TEST_CASE_MULTIPLE_STAGES("can set sleep wake stub from stack in RTC RAM", "[dee
|
||||
#endif // CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
|
||||
#endif // ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB
|
||||
|
||||
#if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
|
||||
|
||||
__attribute__((unused)) static float get_time_ms(void)
|
||||
{
|
||||
gettimeofday(&tv_stop, NULL);
|
||||
|
||||
float dt = (tv_stop.tv_sec - tv_start.tv_sec) * 1e3f +
|
||||
(tv_stop.tv_usec - tv_start.tv_usec) * 1e-3f;
|
||||
return fabs(dt);
|
||||
}
|
||||
|
||||
__attribute__((unused)) static uint32_t get_cause(void)
|
||||
{
|
||||
#if SOC_PMU_SUPPORTED
|
||||
uint32_t wakeup_cause = pmu_ll_hp_get_wakeup_cause(&PMU);
|
||||
#else
|
||||
uint32_t wakeup_cause = rtc_cntl_ll_get_wakeup_cause();
|
||||
#endif
|
||||
return wakeup_cause;
|
||||
}
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3) && SOC_PM_SUPPORT_EXT0_WAKEUP
|
||||
// Fails on S2 IDF-2903
|
||||
|
||||
// This test case verifies deactivation of trigger for wake up sources
|
||||
TEST_CASE("disable source trigger behavior", "[deepsleep]")
|
||||
{
|
||||
float dt = 0;
|
||||
|
||||
printf("Setup timer and ext0 to wake up immediately from GPIO_13 \n");
|
||||
|
||||
// Setup ext0 configuration to wake up almost immediately
|
||||
// The wakeup time is proportional to input capacitance * pullup resistance
|
||||
ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13));
|
||||
ESP_ERROR_CHECK(gpio_pullup_en(GPIO_NUM_13));
|
||||
ESP_ERROR_CHECK(gpio_pulldown_dis(GPIO_NUM_13));
|
||||
ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, ESP_EXT0_WAKEUP_LEVEL_HIGH));
|
||||
|
||||
// Setup timer to wakeup with timeout
|
||||
esp_sleep_enable_timer_wakeup(2000000);
|
||||
|
||||
// Save start time
|
||||
gettimeofday(&tv_start, NULL);
|
||||
esp_light_sleep_start();
|
||||
|
||||
dt = get_time_ms();
|
||||
printf("Ext0 sleep time = %d \n", (int) dt);
|
||||
|
||||
// Check wakeup from Ext0 using time measurement because wakeup cause is
|
||||
// not available in light sleep mode
|
||||
TEST_ASSERT_INT32_WITHIN(100, 100, (int) dt);
|
||||
|
||||
TEST_ASSERT((get_cause() & RTC_EXT0_TRIG_EN) != 0);
|
||||
|
||||
// Disable Ext0 source. Timer source should be triggered
|
||||
ESP_ERROR_CHECK(esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_EXT0));
|
||||
printf("Disable ext0 trigger and leave timer active.\n");
|
||||
|
||||
gettimeofday(&tv_start, NULL);
|
||||
esp_light_sleep_start();
|
||||
|
||||
dt = get_time_ms();
|
||||
printf("Timer sleep time = %d \n", (int) dt);
|
||||
|
||||
TEST_ASSERT_INT32_WITHIN(500, 2000, (int) dt);
|
||||
|
||||
// Additionally check wakeup cause
|
||||
TEST_ASSERT((get_cause() & RTC_TIMER_TRIG_EN) != 0);
|
||||
|
||||
// Disable timer source.
|
||||
ESP_ERROR_CHECK(esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER));
|
||||
|
||||
// Setup ext0 configuration to wake up immediately
|
||||
ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13));
|
||||
ESP_ERROR_CHECK(gpio_pullup_en(GPIO_NUM_13));
|
||||
ESP_ERROR_CHECK(gpio_pulldown_dis(GPIO_NUM_13));
|
||||
ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, ESP_EXT0_WAKEUP_LEVEL_HIGH));
|
||||
|
||||
printf("Disable timer trigger to wake up from ext0 source.\n");
|
||||
|
||||
gettimeofday(&tv_start, NULL);
|
||||
esp_light_sleep_start();
|
||||
|
||||
dt = get_time_ms();
|
||||
printf("Ext0 sleep time = %d \n", (int) dt);
|
||||
|
||||
TEST_ASSERT_INT32_WITHIN(100, 100, (int) dt);
|
||||
TEST_ASSERT((get_cause() & RTC_EXT0_TRIG_EN) != 0);
|
||||
|
||||
// Check error message when source is already disabled
|
||||
esp_err_t err_code = esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER);
|
||||
TEST_ASSERT(err_code == ESP_ERR_INVALID_STATE);
|
||||
|
||||
// Disable ext0 wakeup source, as this might interfere with other tests
|
||||
ESP_ERROR_CHECK(esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_EXT0));
|
||||
}
|
||||
#endif // !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3)
|
||||
|
||||
#endif //SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
|
||||
|
||||
static void trigger_deepsleep(void)
|
||||
{
|
||||
struct timeval start;
|
||||
|
@ -68,6 +68,7 @@ TEST_CASE("Task WDT task timeout after peripheral powerdown lightsleep", "[task_
|
||||
|
||||
TEST_ASSERT_EQUAL(PMU_SLEEP_PD_TOP, sleep_ctx.sleep_flags & PMU_SLEEP_PD_TOP);
|
||||
TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result);
|
||||
esp_sleep_set_sleep_context(NULL);
|
||||
|
||||
// Short delay to allow timeout to occur
|
||||
esp_rom_delay_us(TASK_WDT_TIMEOUT_MS * 1000);
|
||||
|
@ -11,6 +11,7 @@ from pytest_embedded import Dut
|
||||
pytest.param('default', marks=[pytest.mark.supported_targets]),
|
||||
pytest.param('pd_vddsdio', marks=[pytest.mark.supported_targets]),
|
||||
pytest.param('psram', marks=[pytest.mark.esp32, pytest.mark.esp32s2, pytest.mark.esp32s3, pytest.mark.esp32p4]),
|
||||
pytest.param('psram_with_pd_top', marks=[pytest.mark.esp32p4]),
|
||||
pytest.param('single_core_esp32', marks=[pytest.mark.esp32]),
|
||||
]
|
||||
)
|
||||
|
@ -1,5 +1,4 @@
|
||||
# Default configuration
|
||||
# Used for testing stack smashing protection
|
||||
CONFIG_COMPILER_STACK_CHECK=y
|
||||
CONFIG_ESP_SLEEP_DEBUG=y
|
||||
CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y
|
||||
|
@ -0,0 +1,4 @@
|
||||
CONFIG_SPIRAM=y
|
||||
CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y
|
||||
CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y
|
||||
CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y
|
@ -4,3 +4,4 @@ CONFIG_ESP_TASK_WDT_INIT=n
|
||||
# esp_sleep_enable_gpio_switch() has the change to break UART RX during light sleep stress tests
|
||||
# Remove this when IDF-4897 is fixed
|
||||
CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND=n
|
||||
CONFIG_ESP_SLEEP_DEBUG=y
|
||||
|
@ -289,15 +289,16 @@ static inline void psram_ctrlr_ll_enable_rd_splice(uint32_t mspi_id, bool en)
|
||||
* @param en enable / disable
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void psram_ctrlr_ll_enable_module_clock(uint32_t mspi_id, bool en)
|
||||
static inline void _psram_ctrlr_ll_enable_module_clock(uint32_t mspi_id, bool en)
|
||||
{
|
||||
(void)mspi_id;
|
||||
HP_SYS_CLKRST.soc_clk_ctrl0.reg_psram_sys_clk_en = en;
|
||||
HP_SYS_CLKRST.peri_clk_ctrl00.reg_psram_pll_clk_en = en;
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
|
||||
#define psram_ctrlr_ll_enable_module_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; psram_ctrlr_ll_enable_module_clock(__VA_ARGS__)
|
||||
#define psram_ctrlr_ll_enable_module_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _psram_ctrlr_ll_enable_module_clock(__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Reset PSRAM module clock
|
||||
@ -325,7 +326,7 @@ static inline void psram_ctrlr_ll_reset_module_clock(uint32_t mspi_id)
|
||||
* @param clk_src clock source, see valid sources in type `soc_periph_psram_clk_src_t`
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void psram_ctrlr_ll_select_clk_source(uint32_t mspi_id, soc_periph_psram_clk_src_t clk_src)
|
||||
static inline void _psram_ctrlr_ll_select_clk_source(uint32_t mspi_id, soc_periph_psram_clk_src_t clk_src)
|
||||
{
|
||||
(void)mspi_id;
|
||||
uint32_t clk_val = 0;
|
||||
@ -347,13 +348,12 @@ static inline void psram_ctrlr_ll_select_clk_source(uint32_t mspi_id, soc_periph
|
||||
break;
|
||||
}
|
||||
|
||||
HP_SYS_CLKRST.peri_clk_ctrl00.reg_psram_pll_clk_en = 1;
|
||||
HP_SYS_CLKRST.peri_clk_ctrl00.reg_psram_clk_src_sel = clk_val;
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
|
||||
#define psram_ctrlr_ll_select_clk_source(...) (void)__DECLARE_RCC_ATOMIC_ENV; psram_ctrlr_ll_select_clk_source(__VA_ARGS__)
|
||||
#define psram_ctrlr_ll_select_clk_source(...) (void)__DECLARE_RCC_ATOMIC_ENV; _psram_ctrlr_ll_select_clk_source(__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Set PSRAM core clock
|
||||
@ -362,15 +362,29 @@ static inline void psram_ctrlr_ll_select_clk_source(uint32_t mspi_id, soc_periph
|
||||
* @param freqdiv Divider value
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void psram_ctrlr_ll_set_core_clock(uint8_t spi_num, uint32_t freqdiv)
|
||||
static inline void _psram_ctrlr_ll_set_core_clock_div(uint8_t spi_num, uint32_t freqdiv)
|
||||
{
|
||||
HP_SYS_CLKRST.peri_clk_ctrl00.reg_psram_core_clk_en = 1;
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl00, reg_psram_core_clk_div_num, freqdiv - 1);
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
|
||||
#define psram_ctrlr_ll_set_core_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; psram_ctrlr_ll_set_core_clock(__VA_ARGS__)
|
||||
#define psram_ctrlr_ll_set_core_clock_div(...) (void)__DECLARE_RCC_ATOMIC_ENV; _psram_ctrlr_ll_set_core_clock_div(__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Enable or disable the PSRAM core clock
|
||||
*
|
||||
* @param en enable / disable
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void _psram_ctrlr_ll_enable_core_clock(uint8_t spi_num, bool en)
|
||||
{
|
||||
HP_SYS_CLKRST.peri_clk_ctrl00.reg_psram_core_clk_en = en;
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
|
||||
#define psram_ctrlr_ll_enable_core_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _psram_ctrlr_ll_enable_core_clock(__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Set PSRAM bus clock
|
||||
@ -735,6 +749,24 @@ static inline void psram_ctrlr_ll_common_transaction(uint32_t mspi_id,
|
||||
is_write_erase_operation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wait MSPI PSRAM controller transaction done
|
||||
*
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void psram_ctrlr_ll_wait_all_transaction_done(void)
|
||||
{
|
||||
#define ALL_TRANSACTION_DONE ( SPI_MEM_S_ALL_FIFO_EMPTY | \
|
||||
SPI_MEM_S_RDATA_AFIFO_REMPTY | \
|
||||
SPI_MEM_S_RADDR_AFIFO_REMPTY | \
|
||||
SPI_MEM_S_WDATA_AFIFO_REMPTY | \
|
||||
SPI_MEM_S_WBLEN_AFIFO_REMPTY | \
|
||||
SPI_MEM_S_ALL_AXI_TRANS_AFIFO_EMPTY)
|
||||
while (SPIMEM2.smem_axi_addr_ctrl.val != ALL_TRANSACTION_DONE) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -75,7 +75,7 @@ extern const regdma_entries_config_t iomux_regs_retention[IOMUX_RETENTION_LINK_L
|
||||
* useful for external use.
|
||||
*/
|
||||
#define SPIMEM_RETENTION_LINK_LEN 8
|
||||
extern const regdma_entries_config_t spimem_regs_retention[SPIMEM_RETENTION_LINK_LEN];
|
||||
extern const regdma_entries_config_t flash_spimem_regs_retention[SPIMEM_RETENTION_LINK_LEN];
|
||||
|
||||
/**
|
||||
* @brief Provide access to systimer configuration registers retention
|
||||
|
@ -67,7 +67,7 @@ _Static_assert(ARRAY_SIZE(iomux_regs_retention) == IOMUX_RETENTION_LINK_LEN, "In
|
||||
#define N_REGS_SPI0_MEM_1() (((SPI_MEM_SPI_SMEM_AC_REG(0) - SPI_MEM_SPI_FMEM_PMS0_ATTR_REG(0)) / 4) + 1)
|
||||
#define N_REGS_SPI0_MEM_2() (1)
|
||||
#define N_REGS_SPI0_MEM_3() (((SPI_MEM_DATE_REG(0) - SPI_MEM_MMU_POWER_CTRL_REG(0)) / 4) + 1)
|
||||
const regdma_entries_config_t spimem_regs_retention[] = {
|
||||
const regdma_entries_config_t flash_spimem_regs_retention[] = {
|
||||
/* Note: SPI mem should not to write mmu SPI_MEM_MMU_ITEM_CONTENT_REG and SPI_MEM_MMU_ITEM_INDEX_REG */
|
||||
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x00), REG_SPI_MEM_BASE(1), REG_SPI_MEM_BASE(1), N_REGS_SPI1_MEM_0(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* spi1_mem */
|
||||
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x01), SPI_MEM_SPI_FMEM_PMS0_ATTR_REG(1), SPI_MEM_SPI_FMEM_PMS0_ATTR_REG(1), N_REGS_SPI1_MEM_1(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
@ -80,7 +80,7 @@ const regdma_entries_config_t spimem_regs_retention[] = {
|
||||
[6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x06), SPI_MEM_CLOCK_GATE_REG(0), SPI_MEM_CLOCK_GATE_REG(0), N_REGS_SPI0_MEM_2(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
[7] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x07), SPI_MEM_MMU_POWER_CTRL_REG(0), SPI_MEM_MMU_POWER_CTRL_REG(0), N_REGS_SPI0_MEM_3(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }
|
||||
};
|
||||
_Static_assert(ARRAY_SIZE(spimem_regs_retention) == SPIMEM_RETENTION_LINK_LEN, "Inconsistent SPI Mem retention link length definitions");
|
||||
_Static_assert(ARRAY_SIZE(flash_spimem_regs_retention) == SPIMEM_RETENTION_LINK_LEN, "Inconsistent SPI Mem retention link length definitions");
|
||||
|
||||
/* Systimer Registers Context */
|
||||
#define N_REGS_SYSTIMER_0() (((SYSTIMER_TARGET2_CONF_REG - SYSTIMER_TARGET0_HI_REG) / 4) + 1)
|
||||
|
@ -75,7 +75,7 @@ extern const regdma_entries_config_t iomux_regs_retention[IOMUX_RETENTION_LINK_L
|
||||
* useful for external use.
|
||||
*/
|
||||
#define SPIMEM_RETENTION_LINK_LEN 8
|
||||
extern const regdma_entries_config_t spimem_regs_retention[SPIMEM_RETENTION_LINK_LEN];
|
||||
extern const regdma_entries_config_t flash_spimem_regs_retention[SPIMEM_RETENTION_LINK_LEN];
|
||||
|
||||
/**
|
||||
* @brief Provide access to systimer configuration registers retention
|
||||
|
@ -66,7 +66,7 @@ _Static_assert(ARRAY_SIZE(iomux_regs_retention) == IOMUX_RETENTION_LINK_LEN, "In
|
||||
#define N_REGS_SPI0_MEM_1() (((SPI_MEM_SPI_SMEM_AC_REG(0) - SPI_MEM_SPI_FMEM_PMS0_ATTR_REG(0)) / 4) + 1)
|
||||
#define N_REGS_SPI0_MEM_2() (1)
|
||||
#define N_REGS_SPI0_MEM_3() (((SPI_MEM_DATE_REG(0) - SPI_MEM_MMU_POWER_CTRL_REG(0)) / 4) + 1)
|
||||
const regdma_entries_config_t spimem_regs_retention[] = {
|
||||
const regdma_entries_config_t flash_spimem_regs_retention[] = {
|
||||
/* Note: SPI mem should not to write mmu SPI_MEM_MMU_ITEM_CONTENT_REG and SPI_MEM_MMU_ITEM_INDEX_REG */
|
||||
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x00), REG_SPI_MEM_BASE(1), REG_SPI_MEM_BASE(1), N_REGS_SPI1_MEM_0(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* spi1_mem */
|
||||
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x01), SPI_MEM_SPI_FMEM_PMS0_ATTR_REG(1), SPI_MEM_SPI_FMEM_PMS0_ATTR_REG(1), N_REGS_SPI1_MEM_1(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
@ -79,7 +79,7 @@ const regdma_entries_config_t spimem_regs_retention[] = {
|
||||
[6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x06), SPI_MEM_CLOCK_GATE_REG(0), SPI_MEM_CLOCK_GATE_REG(0), N_REGS_SPI0_MEM_2(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
[7] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x07), SPI_MEM_MMU_POWER_CTRL_REG(0), SPI_MEM_MMU_POWER_CTRL_REG(0), N_REGS_SPI0_MEM_3(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }
|
||||
};
|
||||
_Static_assert(ARRAY_SIZE(spimem_regs_retention) == SPIMEM_RETENTION_LINK_LEN, "Inconsistent SPI Mem retention link length definitions");
|
||||
_Static_assert(ARRAY_SIZE(flash_spimem_regs_retention) == SPIMEM_RETENTION_LINK_LEN, "Inconsistent SPI Mem retention link length definitions");
|
||||
|
||||
/* Systimer Registers Context */
|
||||
#define N_REGS_SYSTIMER_0() (((SYSTIMER_TARGET2_CONF_REG - SYSTIMER_TARGET0_HI_REG) / 4) + 1)
|
||||
|
@ -62,18 +62,28 @@ extern const regdma_entries_config_t tg_regs_retention[TIMG_RETENTION_LINK_LEN];
|
||||
* This is an internal function of the sleep retention driver, and is not
|
||||
* useful for external use.
|
||||
*/
|
||||
#define IOMUX_RETENTION_LINK_LEN 2
|
||||
#define IOMUX_RETENTION_LINK_LEN 3
|
||||
extern const regdma_entries_config_t iomux_regs_retention[IOMUX_RETENTION_LINK_LEN];
|
||||
|
||||
/**
|
||||
* @brief Provide access to spimem configuration registers retention
|
||||
* @brief Provide access to FLASH spimem configuration registers retention
|
||||
* context definition.
|
||||
*
|
||||
* This is an internal function of the sleep retention driver, and is not
|
||||
* useful for external use.
|
||||
*/
|
||||
#define SPIMEM_RETENTION_LINK_LEN 8
|
||||
extern const regdma_entries_config_t spimem_regs_retention[SPIMEM_RETENTION_LINK_LEN];
|
||||
#define SPIMEM_FLASH_RETENTION_LINK_LEN 8
|
||||
extern const regdma_entries_config_t flash_spimem_regs_retention[SPIMEM_FLASH_RETENTION_LINK_LEN];
|
||||
|
||||
/**
|
||||
* @brief Provide access to PSRAM spimem configuration registers retention
|
||||
* context definition.
|
||||
*
|
||||
* This is an internal function of the sleep retention driver, and is not
|
||||
* useful for external use.
|
||||
*/
|
||||
#define SPIMEM_PSRAM_RETENTION_LINK_LEN 14
|
||||
extern const regdma_entries_config_t psram_spimem_regs_retention[SPIMEM_PSRAM_RETENTION_LINK_LEN];
|
||||
|
||||
/**
|
||||
* @brief Provide access to systimer configuration registers retention
|
||||
|
@ -7,13 +7,17 @@
|
||||
#include "soc/cache_reg.h"
|
||||
#include "soc/gpio_reg.h"
|
||||
#include "soc/hp_system_reg.h"
|
||||
#include "soc/hp_sys_clkrst_reg.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "soc/iomux_mspi_pin_reg.h"
|
||||
#include "soc/interrupt_core0_reg.h"
|
||||
#include "soc/interrupt_core1_reg.h"
|
||||
#include "soc/pau_reg.h"
|
||||
#include "soc/regdma.h"
|
||||
#include "soc/system_periph_retention.h"
|
||||
#include "soc/spi_mem_reg.h"
|
||||
#include "soc/spi_mem_s_reg.h"
|
||||
#include "soc/spi1_mem_s_reg.h"
|
||||
#include "soc/systimer_reg.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "soc/timer_periph.h"
|
||||
@ -44,36 +48,71 @@ _Static_assert(ARRAY_SIZE(hp_system_regs_retention) == HP_SYSTEM_RETENTION_LINK_
|
||||
|
||||
/* IO MUX Registers Context */
|
||||
#define N_REGS_IOMUX_0() (((IO_MUX_GPIO54_REG - REG_IO_MUX_BASE) / 4) + 1)
|
||||
#define N_REGS_IOMUX_1() (((GPIO_ZERO_DET1_FILTER_CNT_REG - DR_REG_GPIO_BASE) / 4) + 1)
|
||||
#define N_REGS_GPIO_MTX() (((GPIO_ZERO_DET1_FILTER_CNT_REG - DR_REG_GPIO_BASE) / 4) + 1)
|
||||
#define N_REGS_MSPI_IOMUX() (((IOMUX_MSPI_PIN_PSRAM_DQS_1_PIN0_REG - IOMUX_MSPI_PIN_CLK_EN0_REG) / 4) + 1)
|
||||
const regdma_entries_config_t iomux_regs_retention[] = {
|
||||
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x00), REG_IO_MUX_BASE, REG_IO_MUX_BASE, N_REGS_IOMUX_0(), 0, 0), .owner = ENTRY(0) }, /* io_mux */
|
||||
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x01), DR_REG_GPIO_BASE, DR_REG_GPIO_BASE, N_REGS_IOMUX_1(), 0, 0), .owner = ENTRY(0) },
|
||||
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x00), REG_IO_MUX_BASE, REG_IO_MUX_BASE, N_REGS_IOMUX_0(), 0, 0), .owner = ENTRY(0) }, /* io_mux */
|
||||
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x01), DR_REG_GPIO_BASE, DR_REG_GPIO_BASE, N_REGS_GPIO_MTX(), 0, 0), .owner = ENTRY(0) },
|
||||
[2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x01), IOMUX_MSPI_PIN_CLK_EN0_REG, IOMUX_MSPI_PIN_CLK_EN0_REG, N_REGS_GPIO_MTX(), 0, 0), .owner = ENTRY(0) },
|
||||
};
|
||||
_Static_assert(ARRAY_SIZE(iomux_regs_retention) == IOMUX_RETENTION_LINK_LEN, "Inconsistent IOMUX retention link length definitions");
|
||||
|
||||
/* Memory SPI Registers Context */
|
||||
#define N_REGS_SPI1_MEM_0() (((SPI1_MEM_C_SUS_STATUS_REG - DR_REG_FLASH_SPI1_BASE) / 4) + 1)
|
||||
#define N_REGS_SPI1_MEM_1() (((SPI1_MEM_C_DDR_REG - SPI1_MEM_C_INT_ENA_REG) / 4) + 1)
|
||||
#define N_REGS_SPI1_MEM_2() (1)
|
||||
#define N_REGS_SPI1_MEM_3() (1)
|
||||
#define N_REGS_SPI0_MEM_0() ((SPI_MEM_C_SMEM_DDR_REG - DR_REG_FLASH_SPI0_BASE) / 4 + 1)
|
||||
#define N_REGS_SPI0_MEM_1() (((SPI_MEM_C_SMEM_AC_REG - SPI_MEM_C_FMEM__PMS0_ATTR_REG) / 4) + 1)
|
||||
#define N_REGS_SPI0_MEM_2() (1)
|
||||
#define N_REGS_SPI0_MEM_3() (((SPI_MEM_C_DATE_REG - SPI_MEM_C_MMU_POWER_CTRL_REG) / 4) + 1)
|
||||
const regdma_entries_config_t spimem_regs_retention[] = {
|
||||
#define N_REGS_SPI1_C_MEM_0() (((SPI1_MEM_C_SUS_STATUS_REG - DR_REG_FLASH_SPI1_BASE) / 4) + 1)
|
||||
#define N_REGS_SPI1_C_MEM_1() (((SPI1_MEM_C_DDR_REG - SPI1_MEM_C_INT_ENA_REG) / 4) + 1)
|
||||
#define N_REGS_SPI1_C_MEM_2() (1)
|
||||
#define N_REGS_SPI1_C_MEM_3() (1)
|
||||
#define N_REGS_SPI0_C_MEM_0() ((SPI_MEM_C_SMEM_DDR_REG - DR_REG_FLASH_SPI0_BASE) / 4 + 1)
|
||||
#define N_REGS_SPI0_C_MEM_1() (((SPI_MEM_C_SMEM_AC_REG - SPI_MEM_C_FMEM__PMS0_ATTR_REG) / 4) + 1)
|
||||
#define N_REGS_SPI0_C_MEM_2() (1)
|
||||
#define N_REGS_SPI0_C_MEM_3() (((SPI_MEM_C_DPA_CTRL_REG - SPI_MEM_C_MMU_POWER_CTRL_REG) / 4) + 1)
|
||||
|
||||
const regdma_entries_config_t flash_spimem_regs_retention[] = {
|
||||
/* Note: SPI mem should not to write mmu SPI_MEM_MMU_ITEM_CONTENT_REG and SPI_MEM_MMU_ITEM_INDEX_REG */
|
||||
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x00), DR_REG_FLASH_SPI1_BASE, DR_REG_FLASH_SPI1_BASE, N_REGS_SPI1_MEM_0(), 0, 0), .owner = ENTRY(0) }, /* spi1_mem */
|
||||
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x01), SPI1_MEM_C_INT_ENA_REG, SPI1_MEM_C_INT_ENA_REG, N_REGS_SPI1_MEM_1(), 0, 0), .owner = ENTRY(0) },
|
||||
[2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x02), SPI1_MEM_C_TIMING_CALI_REG, SPI1_MEM_C_TIMING_CALI_REG, N_REGS_SPI1_MEM_2(), 0, 0), .owner = ENTRY(0) },
|
||||
[3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x03), SPI1_MEM_C_CLOCK_GATE_REG, SPI1_MEM_C_CLOCK_GATE_REG, N_REGS_SPI1_MEM_3(), 0, 0), .owner = ENTRY(0) },
|
||||
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x00), DR_REG_FLASH_SPI1_BASE, DR_REG_FLASH_SPI1_BASE, N_REGS_SPI1_C_MEM_0(), 0, 0), .owner = ENTRY(0) }, /* spi1_mem */
|
||||
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x01), SPI1_MEM_C_INT_ENA_REG, SPI1_MEM_C_INT_ENA_REG, N_REGS_SPI1_C_MEM_1(), 0, 0), .owner = ENTRY(0) },
|
||||
[2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x02), SPI1_MEM_C_TIMING_CALI_REG, SPI1_MEM_C_TIMING_CALI_REG, N_REGS_SPI1_C_MEM_2(), 0, 0), .owner = ENTRY(0) },
|
||||
|
||||
/* Note: SPI mem should not to write mmu SPI_MEM_MMU_ITEM_CONTENT_REG and SPI_MEM_MMU_ITEM_INDEX_REG */
|
||||
[4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x04), DR_REG_FLASH_SPI0_BASE, DR_REG_FLASH_SPI0_BASE, N_REGS_SPI0_MEM_0(), 0, 0), .owner = ENTRY(0) }, /* spi0_mem */
|
||||
[5] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x05), SPI_MEM_C_FMEM__PMS0_ATTR_REG, SPI_MEM_C_FMEM__PMS0_ATTR_REG, N_REGS_SPI0_MEM_1(), 0, 0), .owner = ENTRY(0) },
|
||||
[6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x06), SPI_MEM_C_CLOCK_GATE_REG, SPI_MEM_C_CLOCK_GATE_REG, N_REGS_SPI0_MEM_2(), 0, 0), .owner = ENTRY(0) },
|
||||
[7] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x07), SPI_MEM_C_MMU_POWER_CTRL_REG, SPI_MEM_C_MMU_POWER_CTRL_REG, N_REGS_SPI0_MEM_3(), 0, 0), .owner = ENTRY(0) }
|
||||
[3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x04), DR_REG_FLASH_SPI0_BASE, DR_REG_FLASH_SPI0_BASE, N_REGS_SPI0_C_MEM_0(), 0, 0), .owner = ENTRY(0) }, /* spi0_mem */
|
||||
[4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x05), SPI_MEM_C_FMEM__PMS0_ATTR_REG, SPI_MEM_C_FMEM__PMS0_ATTR_REG, N_REGS_SPI0_C_MEM_1(), 0, 0), .owner = ENTRY(0) },
|
||||
[5] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x06), SPI_MEM_C_CLOCK_GATE_REG, SPI_MEM_C_CLOCK_GATE_REG, N_REGS_SPI0_C_MEM_2(), 0, 0), .owner = ENTRY(0) },
|
||||
[6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x07), SPI_MEM_C_MMU_POWER_CTRL_REG, SPI_MEM_C_MMU_POWER_CTRL_REG, N_REGS_SPI0_C_MEM_3(), 0, 0), .owner = ENTRY(0) },
|
||||
[7] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SPIMEM_LINK(0x08), SPI_MEM_C_TIMING_CALI_REG, SPI_MEM_C_TIMING_CALI_UPDATE, SPI_MEM_C_TIMING_CALI_UPDATE_M, 1, 0), .owner = ENTRY(0) },
|
||||
};
|
||||
_Static_assert(ARRAY_SIZE(spimem_regs_retention) == SPIMEM_RETENTION_LINK_LEN, "Inconsistent SPI Mem retention link length definitions");
|
||||
_Static_assert(ARRAY_SIZE(flash_spimem_regs_retention) == SPIMEM_FLASH_RETENTION_LINK_LEN, "Inconsistent Flash SPI Mem retention link length definitions");
|
||||
|
||||
#if CONFIG_SPIRAM
|
||||
#define N_REGS_SPI0_S_MEM_0() (((SPI_MEM_S_USER2_REG - SPI_MEM_S_CTRL_REG) / 4) + 1)
|
||||
#define N_REGS_SPI0_S_MEM_1() (((SPI_MEM_S_FSM_REG - SPI_MEM_S_MISC_REG) / 4) + 1)
|
||||
#define N_REGS_SPI0_S_MEM_2() (((SPI_MEM_S_SMEM_DDR_REG - SPI_MEM_S_INT_ENA_REG) / 4) + 1)
|
||||
#define N_REGS_SPI0_S_MEM_3() (((SPI_MEM_S_SMEM_DOUT_HEX_MODE_REG - SPI_MEM_S_ECC_CTRL_REG) / 4) + 1)
|
||||
#define N_REGS_SPI0_S_MEM_4() (((SPI_MEM_S_DPA_CTRL_REG - SPI_MEM_S_MMU_POWER_CTRL_REG) / 4) + 1)
|
||||
#define N_REGS_SPI1_S_MEM_0() ((SPI1_MEM_S_CACHE_FCTRL_REG - SPI1_MEM_S_CMD_REG) / 4 + 1)
|
||||
#define N_REGS_SPI1_S_MEM_1() (((SPI1_MEM_S_SUS_STATUS_REG - SPI1_MEM_S_FLASH_WAITI_CTRL_REG) / 4) + 1)
|
||||
#define N_REGS_SPI1_S_MEM_2() (((SPI1_MEM_S_DDR_REG - SPI1_MEM_S_INT_ENA_REG) / 4) + 1)
|
||||
#define N_REGS_SPI1_S_MEM_3() (1)
|
||||
#define N_REGS_SPI1_S_MEM_4() (1)
|
||||
|
||||
const regdma_entries_config_t psram_spimem_regs_retention[SPIMEM_PSRAM_RETENTION_LINK_LEN] = {
|
||||
[0] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_SPIMEM_LINK(0x08), HP_SYS_CLKRST_PERI_CLK_CTRL00_REG, HP_SYS_CLKRST_REG_PSRAM_CORE_CLK_EN, HP_SYS_CLKRST_REG_PSRAM_CORE_CLK_EN_M, 1, 0), .owner = ENTRY(0) }, // Enable PSRAM mspi core clock on restore
|
||||
[1] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_SPIMEM_LINK(0x09), HP_SYS_CLKRST_SOC_CLK_CTRL0_REG, HP_SYS_CLKRST_REG_PSRAM_SYS_CLK_EN, HP_SYS_CLKRST_REG_PSRAM_SYS_CLK_EN_M, 1, 0), .owner = ENTRY(0) }, // Enable PSRAM mspi core clock on restore
|
||||
[2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x0a), SPI_MEM_S_CTRL_REG, SPI_MEM_S_CTRL_REG, N_REGS_SPI0_S_MEM_0(), 0, 0), .owner = ENTRY(0) }, /* spi0_mem */
|
||||
[3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x0b), SPI_MEM_S_MISC_REG, SPI_MEM_S_MISC_REG, N_REGS_SPI0_S_MEM_1(), 0, 0), .owner = ENTRY(0) },
|
||||
[4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x0c), SPI_MEM_S_INT_ENA_REG, SPI_MEM_S_INT_ENA_REG, N_REGS_SPI0_S_MEM_2(), 0, 0), .owner = ENTRY(0) },
|
||||
[5] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x0d), SPI_MEM_S_ECC_CTRL_REG, SPI_MEM_S_ECC_CTRL_REG, N_REGS_SPI0_S_MEM_3(), 0, 0), .owner = ENTRY(0) },
|
||||
[6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x0e), SPI_MEM_S_MMU_POWER_CTRL_REG, SPI_MEM_S_MMU_POWER_CTRL_REG, N_REGS_SPI0_S_MEM_4(), 0, 0), .owner = ENTRY(0) },
|
||||
[7] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x0f), SPI1_MEM_S_CMD_REG, SPI1_MEM_S_CMD_REG, N_REGS_SPI1_S_MEM_0(), 0, 0), .owner = ENTRY(0) }, /* spi1_mem */
|
||||
[8] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x10), SPI1_MEM_S_FLASH_WAITI_CTRL_REG, SPI1_MEM_S_FLASH_WAITI_CTRL_REG, N_REGS_SPI1_S_MEM_1(), 0, 0), .owner = ENTRY(0) },
|
||||
[9] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x11), SPI1_MEM_S_INT_ENA_REG, SPI1_MEM_S_INT_ENA_REG, N_REGS_SPI1_S_MEM_2(), 0, 0), .owner = ENTRY(0) },
|
||||
[10] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x12), SPI1_MEM_S_TIMING_CALI_REG, SPI1_MEM_S_TIMING_CALI_REG, N_REGS_SPI1_S_MEM_3(), 0, 0), .owner = ENTRY(0) },
|
||||
[11] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x13), SPI1_MEM_S_CLOCK_GATE_REG, SPI1_MEM_S_CLOCK_GATE_REG, N_REGS_SPI1_S_MEM_4(), 0, 0), .owner = ENTRY(0) },
|
||||
[12] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_SPIMEM_LINK(0x14), HP_SYS_CLKRST_PERI_CLK_CTRL00_REG, 0, HP_SYS_CLKRST_REG_PSRAM_CORE_CLK_EN_M, 0, 1), .owner = ENTRY(0) }, // Enable PSRAM mspi core clock on backup
|
||||
[13] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_SPIMEM_LINK(0x15), HP_SYS_CLKRST_SOC_CLK_CTRL0_REG, 0, HP_SYS_CLKRST_REG_PSRAM_SYS_CLK_EN_M, 0, 1), .owner = ENTRY(0) }, // Enable PSRAM mspi core clock on backup
|
||||
};
|
||||
|
||||
_Static_assert(ARRAY_SIZE(psram_spimem_regs_retention) == SPIMEM_PSRAM_RETENTION_LINK_LEN, "Inconsistent PSRAM SPI Mem retention link length definitions");
|
||||
#endif
|
||||
|
||||
/* Systimer Registers Context */
|
||||
#define N_REGS_SYSTIMER_0() (((SYSTIMER_TARGET2_CONF_REG - SYSTIMER_TARGET0_HI_REG) / 4) + 1)
|
||||
|
Loading…
x
Reference in New Issue
Block a user