mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'bugfix/fix_wrong_frame_ptr_after_wake_restore' into 'master'
bugfix: fix wrong RvCoreCriticalSleepFrame ptr value after wake restore See merge request espressif/esp-idf!23113
This commit is contained in:
commit
98849634b3
@ -14,6 +14,7 @@
|
|||||||
#include "esp_check.h"
|
#include "esp_check.h"
|
||||||
#include "esp_sleep.h"
|
#include "esp_sleep.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
|
#include "esp_crc.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "esp_heap_caps.h"
|
#include "esp_heap_caps.h"
|
||||||
@ -25,6 +26,12 @@
|
|||||||
#include "hal/rtc_hal.h"
|
#include "hal/rtc_hal.h"
|
||||||
#endif
|
#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"
|
#include "soc/rtc_periph.h"
|
||||||
|
|
||||||
#ifdef CONFIG_IDF_TARGET_ESP32S3
|
#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_save(void);
|
||||||
extern RvCoreCriticalSleepFrame * rv_core_critical_regs_restore(void);
|
extern RvCoreCriticalSleepFrame * rv_core_critical_regs_restore(void);
|
||||||
typedef uint32_t (* sleep_cpu_entry_cb_t)(uint32_t, uint32_t, uint32_t, bool);
|
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();
|
RvCoreCriticalSleepFrame * frame = rv_core_critical_regs_save();
|
||||||
if ((frame->pmufunc & 0x3) == 0x1) {
|
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);
|
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);
|
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;
|
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);
|
cpu_domain_dev_regs_save(s_cpu_retention.retent.cache_config_frame);
|
||||||
RvCoreNonCriticalSleepFrame *frame = rv_core_noncritical_regs_save();
|
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);
|
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);
|
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.cache_config_frame);
|
||||||
cpu_domain_dev_regs_restore(s_cpu_retention.retent.intpri_frame);
|
cpu_domain_dev_regs_restore(s_cpu_retention.retent.intpri_frame);
|
||||||
|
@ -53,11 +53,12 @@ rv_core_critical_regs_save:
|
|||||||
sw t2, RV_SLP_CTX_T2(t0)
|
sw t2, RV_SLP_CTX_T2(t0)
|
||||||
sw s0, RV_SLP_CTX_S0(t0)
|
sw s0, RV_SLP_CTX_S0(t0)
|
||||||
sw s1, RV_SLP_CTX_S1(t0)
|
sw s1, RV_SLP_CTX_S1(t0)
|
||||||
sw a0, RV_SLP_CTX_A0(t0)
|
|
||||||
|
|
||||||
/* !! WARNING, do not use the a0 register below, a0 carries important sleep
|
/* a0 is caller saved, so it does not need to be saved, but it should be the
|
||||||
* information and will be returned as the return value !! */
|
pointer value of RvCoreCriticalSleepFrame for return.
|
||||||
|
*/
|
||||||
mv a0, t0
|
mv a0, t0
|
||||||
|
sw a0, RV_SLP_CTX_A0(t0)
|
||||||
|
|
||||||
sw a1, RV_SLP_CTX_A1(t0)
|
sw a1, RV_SLP_CTX_A1(t0)
|
||||||
sw a2, RV_SLP_CTX_A2(t0)
|
sw a2, RV_SLP_CTX_A2(t0)
|
||||||
|
@ -2,6 +2,6 @@
|
|||||||
|
|
||||||
components/esp_pm/test_apps/esp_pm:
|
components/esp_pm/test_apps/esp_pm:
|
||||||
disable:
|
disable:
|
||||||
- if: IDF_TARGET in ["esp32c6", "esp32h2"]
|
- if: IDF_TARGET in ["esp32h2"]
|
||||||
temporary: true
|
temporary: true
|
||||||
reason: Not supported yet
|
reason: Not supported yet
|
||||||
|
@ -85,6 +85,14 @@ menu "Power Management"
|
|||||||
bool
|
bool
|
||||||
default n
|
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
|
config PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
|
||||||
bool "Power down CPU in light sleep"
|
bool "Power down CPU in light sleep"
|
||||||
depends on IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C6
|
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};
|
static const int test_freqs[] = {40, CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ, 80, 40, 80, 10, 80, 20, 40};
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C2
|
#elif CONFIG_IDF_TARGET_ESP32C2
|
||||||
static const int test_freqs[] = {CONFIG_XTAL_FREQ, CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ, 80, CONFIG_XTAL_FREQ, 80,
|
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
|
from pytest_embedded import Dut
|
||||||
|
|
||||||
CONFIGS = [
|
CONFIGS = [
|
||||||
pytest.param('default', 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=['esp32c6', 'esp32h2'], reason='c6/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=['esp32c6', 'esp32h2'], reason='c6/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__
|
#ifndef __RVSLEEP_FRAMES_H__
|
||||||
#define __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. */
|
/* Align a value up to nearest n-byte boundary, where n is a power of 2. */
|
||||||
#define ALIGNUP(n, val) (((val) + (n) - 1) & -(n))
|
#define ALIGNUP(n, val) (((val) + (n) - 1) & -(n))
|
||||||
|
|
||||||
@ -86,6 +88,9 @@ STRUCT_BEGIN
|
|||||||
* to sleep or has just been awakened. We use the
|
* to sleep or has just been awakened. We use the
|
||||||
* lowest 2 bits as indication infomation, 3 means
|
* lowest 2 bits as indication infomation, 3 means
|
||||||
* being awakened, 1 means going to sleep */
|
* 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)
|
STRUCT_END(RvCoreCriticalSleepFrame)
|
||||||
|
|
||||||
#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__)
|
#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_OEN, ugpio_oen)
|
||||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_UGPIO_IN, ugpio_in)
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_UGPIO_IN, ugpio_in)
|
||||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_UGPIO_OUT, ugpio_out)
|
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)
|
STRUCT_END(RvCoreNonCriticalSleepFrame)
|
||||||
|
|
||||||
#endif /* #ifndef __RVSLEEP_FRAMES_H__ */
|
#endif /* #ifndef __RVSLEEP_FRAMES_H__ */
|
||||||
|
Loading…
Reference in New Issue
Block a user