mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
esp_pm: check sleep retention frame integrity in ci UT
This commit is contained in:
parent
5ccf93d788
commit
46deef434f
@ -14,6 +14,7 @@
|
||||
#include "esp_check.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_crc.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_heap_caps.h"
|
||||
@ -25,6 +26,12 @@
|
||||
#include "hal/rtc_hal.h"
|
||||
#endif
|
||||
|
||||
#if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME
|
||||
#include "esp_private/system_internal.h"
|
||||
#include "hal/clk_gate_ll.h"
|
||||
#include "hal/uart_hal.h"
|
||||
#endif
|
||||
|
||||
#include "soc/rtc_periph.h"
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S3
|
||||
@ -557,6 +564,32 @@ static IRAM_ATTR void cpu_domain_dev_regs_restore(cpu_domain_dev_sleep_frame_t *
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME
|
||||
static void update_retention_frame_crc(uint32_t *frame_ptr, uint32_t frame_check_size, uint32_t *frame_crc_ptr)
|
||||
{
|
||||
*(frame_crc_ptr) = esp_crc32_le(0, (void *)frame_ptr, frame_check_size);
|
||||
}
|
||||
|
||||
static void validate_retention_frame_crc(uint32_t *frame_ptr, uint32_t frame_check_size, uint32_t *frame_crc_ptr)
|
||||
{
|
||||
if(*(frame_crc_ptr) != esp_crc32_le(0, (void *)(frame_ptr), frame_check_size)){
|
||||
// resume uarts
|
||||
for (int i = 0; i < SOC_UART_NUM; ++i) {
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32
|
||||
if (!periph_ll_periph_enabled(PERIPH_UART0_MODULE + i)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
uart_ll_force_xon(i);
|
||||
}
|
||||
|
||||
/* Since it is still in the critical now, use ESP_EARLY_LOG */
|
||||
ESP_EARLY_LOGE(TAG, "Sleep retention frame is corrupted");
|
||||
esp_restart_noos();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
extern RvCoreCriticalSleepFrame * rv_core_critical_regs_save(void);
|
||||
extern RvCoreCriticalSleepFrame * rv_core_critical_regs_restore(void);
|
||||
typedef uint32_t (* sleep_cpu_entry_cb_t)(uint32_t, uint32_t, uint32_t, bool);
|
||||
@ -566,9 +599,18 @@ static IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep,
|
||||
{
|
||||
RvCoreCriticalSleepFrame * frame = rv_core_critical_regs_save();
|
||||
if ((frame->pmufunc & 0x3) == 0x1) {
|
||||
#if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME
|
||||
/* Minus 2 * sizeof(long) is for bypass `pmufunc` and `frame_crc` field */
|
||||
update_retention_frame_crc((uint32_t*)frame, RV_SLEEP_CTX_FRMSZ - 2 * sizeof(long), (uint32_t *)(&frame->frame_crc));
|
||||
#endif
|
||||
REG_WRITE(LIGHT_SLEEP_WAKE_STUB_ADDR_REG, (uint32_t)rv_core_critical_regs_restore);
|
||||
return (*goto_sleep)(wakeup_opt, reject_opt, lslp_mem_inf_fpu, dslp);
|
||||
}
|
||||
#if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME
|
||||
else {
|
||||
validate_retention_frame_crc((uint32_t*)frame, RV_SLEEP_CTX_FRMSZ - 2 * sizeof(long), (uint32_t *)(&frame->frame_crc));
|
||||
}
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -588,8 +630,17 @@ esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uin
|
||||
cpu_domain_dev_regs_save(s_cpu_retention.retent.cache_config_frame);
|
||||
RvCoreNonCriticalSleepFrame *frame = rv_core_noncritical_regs_save();
|
||||
|
||||
#if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME
|
||||
/* Minus sizeof(long) is for bypass `frame_crc` field */
|
||||
update_retention_frame_crc((uint32_t*)frame, sizeof(RvCoreNonCriticalSleepFrame) - sizeof(long), (uint32_t *)(&frame->frame_crc));
|
||||
#endif
|
||||
|
||||
esp_err_t err = do_cpu_retention(goto_sleep, wakeup_opt, reject_opt, lslp_mem_inf_fpu, dslp);
|
||||
|
||||
#if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME
|
||||
validate_retention_frame_crc((uint32_t*)frame, sizeof(RvCoreNonCriticalSleepFrame) - sizeof(long), (uint32_t *)(&frame->frame_crc));
|
||||
#endif
|
||||
|
||||
rv_core_noncritical_regs_restore(frame);
|
||||
cpu_domain_dev_regs_restore(s_cpu_retention.retent.cache_config_frame);
|
||||
cpu_domain_dev_regs_restore(s_cpu_retention.retent.intpri_frame);
|
||||
|
@ -2,6 +2,6 @@
|
||||
|
||||
components/esp_pm/test_apps/esp_pm:
|
||||
disable:
|
||||
- if: IDF_TARGET in ["esp32c6", "esp32h2"]
|
||||
- if: IDF_TARGET in ["esp32h2"]
|
||||
temporary: true
|
||||
reason: Not supported yet
|
||||
|
@ -85,6 +85,14 @@ menu "Power Management"
|
||||
bool
|
||||
default n
|
||||
|
||||
config PM_CHECK_SLEEP_RETENTION_FRAME
|
||||
bool
|
||||
depends on PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
|
||||
default n if !IDF_CI_BUILD
|
||||
help
|
||||
This option is invisible to users, and it is only used for ci testing,
|
||||
enabling it in the application will increase the sleep and wake-up time overhead
|
||||
|
||||
config PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
|
||||
bool "Power down CPU in light sleep"
|
||||
depends on IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C6
|
||||
|
@ -1,2 +1,2 @@
|
||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- |
|
||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- |
|
||||
|
@ -62,7 +62,7 @@ static void switch_freq(int mhz)
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C3
|
||||
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6
|
||||
static const int test_freqs[] = {40, CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ, 80, 40, 80, 10, 80, 20, 40};
|
||||
#elif CONFIG_IDF_TARGET_ESP32C2
|
||||
static const int test_freqs[] = {CONFIG_XTAL_FREQ, CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ, 80, CONFIG_XTAL_FREQ, 80,
|
||||
|
@ -5,9 +5,9 @@ import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
CONFIGS = [
|
||||
pytest.param('default', marks=[pytest.mark.supported_targets, pytest.mark.temp_skip_ci(targets=['esp32c6', 'esp32h2'], reason='c6/h2 support TBD')]),
|
||||
pytest.param('limits', marks=[pytest.mark.supported_targets, pytest.mark.temp_skip_ci(targets=['esp32c6', 'esp32h2'], reason='c6/h2 support TBD')]),
|
||||
pytest.param('options', marks=[pytest.mark.supported_targets, pytest.mark.temp_skip_ci(targets=['esp32c6', 'esp32h2'], reason='c6/h2 support TBD')]),
|
||||
pytest.param('default', marks=[pytest.mark.supported_targets, pytest.mark.temp_skip_ci(targets=['esp32h2'], reason='h2 support TBD')]),
|
||||
pytest.param('limits', marks=[pytest.mark.supported_targets, pytest.mark.temp_skip_ci(targets=['esp32h2'], reason='h2 support TBD')]),
|
||||
pytest.param('options', marks=[pytest.mark.supported_targets, pytest.mark.temp_skip_ci(targets=['esp32h2'], reason='h2 support TBD')]),
|
||||
]
|
||||
|
||||
|
||||
|
@ -7,6 +7,8 @@
|
||||
#ifndef __RVSLEEP_FRAMES_H__
|
||||
#define __RVSLEEP_FRAMES_H__
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
/* Align a value up to nearest n-byte boundary, where n is a power of 2. */
|
||||
#define ALIGNUP(n, val) (((val) + (n) - 1) & -(n))
|
||||
|
||||
@ -86,6 +88,9 @@ STRUCT_BEGIN
|
||||
* to sleep or has just been awakened. We use the
|
||||
* lowest 2 bits as indication infomation, 3 means
|
||||
* being awakened, 1 means going to sleep */
|
||||
#if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CSF_CTX_CRC, frame_crc) /* Used to check RvCoreCriticalSleepFrame integrity */
|
||||
#endif
|
||||
STRUCT_END(RvCoreCriticalSleepFrame)
|
||||
|
||||
#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__)
|
||||
@ -148,6 +153,9 @@ STRUCT_BEGIN
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_UGPIO_OEN, ugpio_oen)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_UGPIO_IN, ugpio_in)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_UGPIO_OUT, ugpio_out)
|
||||
#if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME
|
||||
STRUCT_FIELD (long, 4, RV_SLP_NCSF_CTX_CRC, frame_crc) /* Used to check RvCoreNonCriticalSleepFrame integrity */
|
||||
#endif
|
||||
STRUCT_END(RvCoreNonCriticalSleepFrame)
|
||||
|
||||
#endif /* #ifndef __RVSLEEP_FRAMES_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user