mirror of
https://github.com/espressif/esp-idf.git
synced 2025-12-25 21:03:54 +00:00
change(esp_hw_support): reject sleep request if task stack in PSRAM
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
#include "soc/soc.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_cpu.h"
|
||||
#include "esp_memory_utils.h"
|
||||
#if CONFIG_SPIRAM
|
||||
#include "esp_private/esp_psram_extram.h"
|
||||
@@ -94,4 +95,10 @@ bool esp_stack_ptr_in_extram(uint32_t sp)
|
||||
//Check if stack ptr is on PSRAM, and 16 byte aligned.
|
||||
return (esp_psram_check_ptr_addr((void *)sp) && ((sp & 0xF) == 0));
|
||||
}
|
||||
|
||||
bool IRAM_ATTR esp_task_stack_is_sane_cache_disabled(void)
|
||||
{
|
||||
const void *sp = (const void *)esp_cpu_get_sp();
|
||||
return !esp_stack_ptr_in_extram((uint32_t)sp);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -383,6 +383,15 @@ inline static bool esp_stack_ptr_in_dram(uint32_t sp)
|
||||
* @return true: is in external ram; false: not in external ram
|
||||
*/
|
||||
bool esp_stack_ptr_in_extram(uint32_t sp);
|
||||
|
||||
/**
|
||||
* @brief Check if the current task's stack is in internal memory (DRAM or RTC fast memory = not in PSRAM)
|
||||
*
|
||||
* This function verifies that the current task's stack is located in internal memory,
|
||||
*
|
||||
* @return true if the stack is in non-cacheable memory, false otherwise
|
||||
*/
|
||||
bool esp_task_stack_is_sane_cache_disabled(void);
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
@@ -612,6 +612,8 @@ esp_err_t esp_sleep_pd_config(esp_sleep_pd_domain_t domain,
|
||||
*
|
||||
* @return
|
||||
* - No return - If the sleep is not rejected.
|
||||
* - ESP_ERR_NOT_ALLOWED Since the sleep process disables the cache, the task requesting to enter sleep must have its
|
||||
* stack located in internal RAM. Tasks with their stacks in PSRAM are not allowed to request sleep.
|
||||
* - ESP_ERR_INVALID_STATE VBAT power does not meet the requirements for entering deepsleep
|
||||
* - ESP_ERR_SLEEP_REJECT sleep request is rejected(wakeup source set before the sleep request)
|
||||
*/
|
||||
@@ -630,6 +632,8 @@ void esp_deep_sleep_start(void) __attribute__((__noreturn__));
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success (returned after wakeup)
|
||||
* - ESP_ERR_NOT_ALLOWED Since the sleep process disables the cache, the task requesting to enter sleep must have its
|
||||
* stack located in internal RAM. Tasks with their stacks in PSRAM are not allowed to request sleep.
|
||||
* - ESP_ERR_SLEEP_REJECT sleep request is rejected(wakeup source set before the sleep request)
|
||||
* - ESP_ERR_SLEEP_TOO_SHORT_SLEEP_DURATION after deducting the sleep flow overhead, the final sleep duration
|
||||
* is too short to cover the minimum sleep duration of the chip, when
|
||||
|
||||
@@ -1282,7 +1282,14 @@ static esp_err_t FORCE_IRAM_ATTR deep_sleep_start(bool allow_sleep_rejection)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_SPIRAM && CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM
|
||||
if (!esp_task_stack_is_sane_cache_disabled()) {
|
||||
ESP_LOGE(TAG, "Deep sleep requests are not allowed from tasks with stacks in PSRAM");
|
||||
if (allow_sleep_rejection) {
|
||||
return ESP_ERR_NOT_ALLOWED;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
/* Due to hardware limitations, on S2 the brownout detector sometimes trigger during deep sleep
|
||||
to circumvent this we disable the brownout detector before sleeping */
|
||||
@@ -1665,7 +1672,13 @@ esp_err_t esp_light_sleep_start(void)
|
||||
// if rtc timer wakeup source is enabled, need to compare final sleep duration and min sleep duration to avoid late wakeup
|
||||
if ((s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) && (final_sleep_duration_us <= min_sleep_duration_us)) {
|
||||
err = ESP_ERR_SLEEP_TOO_SHORT_SLEEP_DURATION;
|
||||
} else {
|
||||
}
|
||||
#if CONFIG_SPIRAM && CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM
|
||||
else if (!esp_task_stack_is_sane_cache_disabled()) {
|
||||
err = ESP_ERR_NOT_ALLOWED;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
// Enter sleep, then wait for flash to be ready on wakeup
|
||||
err = esp_light_sleep_inner(sleep_flags, clk_flags, flash_enable_time_us);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -8,11 +8,10 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_private/cache_utils.h"
|
||||
|
||||
#include "esp_rom_sys.h"
|
||||
|
||||
#ifndef CONFIG_IDF_TARGET_LINUX
|
||||
#include "esp_private/cache_utils.h"
|
||||
#include "esp_cpu.h"
|
||||
#else
|
||||
/* esp_cpu.h isn't available when building for Linux */
|
||||
@@ -30,7 +29,7 @@ static void esp_error_check_failed_print(const char *msg, esp_err_t rc, const ch
|
||||
esp_rom_printf(" (%s)", esp_err_to_name(rc));
|
||||
#endif //CONFIG_ESP_ERR_TO_NAME_LOOKUP
|
||||
esp_rom_printf(" at 0x%08x\n", esp_cpu_get_call_addr(addr));
|
||||
#if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP
|
||||
#if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP && !CONFIG_IDF_TARGET_LINUX
|
||||
if (spi_flash_cache_enabled()) // strings may be in flash cache
|
||||
#endif
|
||||
{
|
||||
|
||||
@@ -43,8 +43,6 @@ ESP_LOG_ATTR_TAG(TAG, "cache");
|
||||
|
||||
// Used only on ROM impl. in idf, this param unused, cache status hold by hal
|
||||
static uint32_t s_flash_op_cache_state[2];
|
||||
|
||||
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
static SemaphoreHandle_t s_flash_op_mutex;
|
||||
static volatile bool s_flash_op_can_start = false;
|
||||
@@ -53,17 +51,6 @@ static volatile bool s_flash_op_complete = false;
|
||||
static volatile int s_flash_op_cpu = -1;
|
||||
#endif
|
||||
|
||||
static inline bool esp_task_stack_is_sane_cache_disabled(void)
|
||||
{
|
||||
const void *sp = (const void *)esp_cpu_get_sp();
|
||||
|
||||
return esp_ptr_in_dram(sp)
|
||||
#if CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
|
||||
|| esp_ptr_in_rtc_dram_fast(sp)
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
void spi_flash_init_lock(void)
|
||||
{
|
||||
s_flash_op_mutex = xSemaphoreCreateRecursiveMutex();
|
||||
@@ -124,7 +111,9 @@ void IRAM_ATTR spi_flash_op_block_func(void *arg)
|
||||
|
||||
void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu(void)
|
||||
{
|
||||
#if CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM
|
||||
assert(esp_task_stack_is_sane_cache_disabled());
|
||||
#endif
|
||||
|
||||
spi_flash_op_lock();
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "esp_err.h"
|
||||
#include "esp_memory_utils.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
@@ -477,6 +477,10 @@ Entering Sleep
|
||||
|
||||
It is also possible to enter sleep modes with no wakeup sources configured. In this case, the chip will be in sleep modes indefinitely until external reset is applied.
|
||||
|
||||
.. note::
|
||||
|
||||
The sleep process will disable the cache, so the task stack of the task requesting sleep must be located in internal memory (DRAM or RTC fast memory). If a task with its stack in PSRAM requests Light-sleep or Deep-sleep, it will be rejected and an error will be returned.
|
||||
|
||||
UART Output Handling
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
@@ -477,6 +477,10 @@ flash 进入 deep power-down 模式
|
||||
|
||||
允许在未配置唤醒源的情况下进入睡眠模式。在此情况下,芯片将一直处于睡眠模式,直到从外部被复位。
|
||||
|
||||
.. note::
|
||||
|
||||
睡眠流程会禁用 cache,因此请求睡眠的任务其任务栈必须位于内部内存(DRAM 或 RTC fast memory)。如果任务栈位于 PSRAM 的任务请求 Light-sleep 或 Deep-sleep,将被拒绝并返回错误。
|
||||
|
||||
UART 输出处理
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
Reference in New Issue
Block a user