mirror of
https://github.com/espressif/esp-idf.git
synced 2026-08-18 06:35:35 +03:00
feat(pm): add light sleep tick overflow protection configuration
This commit is contained in:
@@ -241,6 +241,44 @@ menu "Power Management"
|
||||
NOTE: Enabling these callbacks may change sleep duration calculations based on time spent in callback and
|
||||
hence it is highly recommended to keep them as short as possible
|
||||
|
||||
config PM_LIGHTSLEEP_TICK_OVERFLOW_PROTECTION
|
||||
bool "Enable light sleep tick overflow protection"
|
||||
depends on FREERTOS_USE_TICKLESS_IDLE
|
||||
default n
|
||||
help
|
||||
Limits tick compensation after light sleep wakeup to prevent vTaskStepTick() assertion
|
||||
failure when actual wakeup overhead exceeds estimation (due to cache misses, CPU
|
||||
frequency changes, or flash latency variations).
|
||||
|
||||
When enabled:
|
||||
- Silently limits slept_ticks to xExpectedIdleTime when oversleep is within tolerance
|
||||
(configured by PM_LIGHTSLEEP_TICK_OVERFLOW_TOLERANCE), preventing assertion failure
|
||||
- Does not limit when oversleep exceeds tolerance (may indicate a bug), assertion failure may occur
|
||||
- May lose ticks in rare cases, causing xTickCount to lag behind esp_timer
|
||||
|
||||
When disabled (default):
|
||||
- Accurate tick compensation, better precision
|
||||
- May trigger assertion failure and system crash if overslept
|
||||
|
||||
Keep disabled by default to maintain RTOS tick accuracy. Enable only when you experience
|
||||
assertion failures related to vTaskStepTick() and can accept slight inaccuracy of RTOS
|
||||
tick time compared to real time.
|
||||
|
||||
config PM_LIGHTSLEEP_TICK_OVERFLOW_TOLERANCE
|
||||
int "Light sleep tick overflow tolerance"
|
||||
depends on PM_LIGHTSLEEP_TICK_OVERFLOW_PROTECTION
|
||||
default 2
|
||||
range 1 10
|
||||
help
|
||||
Maximum number of ticks that can be overslept before triggering.
|
||||
When oversleep is within this tolerance, the system silently limits slept_ticks to
|
||||
prevent assertion failure. When oversleep exceeds this tolerance, assertion failure
|
||||
may occur and system may crash.
|
||||
|
||||
Higher values provide more tolerance for estimation variance but may hide real issues
|
||||
and cause more tick loss, leading to greater RTOS tick time inaccuracy compared to real time.
|
||||
Lower values provide better RTOS tick accuracy but may cause false positives.
|
||||
|
||||
config PM_WORKAROUND_FREQ_LIMIT_ENABLED
|
||||
bool
|
||||
default y if SPI_FLASH_FREQ_LIMIT_C5_240MHZ
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2016-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2016-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/param.h>
|
||||
#include <assert.h>
|
||||
@@ -834,10 +835,21 @@ static inline void IRAM_ATTR other_core_should_skip_light_sleep(int core_id)
|
||||
}
|
||||
|
||||
// Adjust RTOS tick count based on the amount of time spent in sleep.
|
||||
FORCE_INLINE_ATTR void pm_step_tick(int64_t slept_us)
|
||||
FORCE_INLINE_ATTR void pm_step_tick(int64_t slept_us, TickType_t xExpectedIdleTime)
|
||||
{
|
||||
uint32_t slept_ticks = slept_us / (portTICK_PERIOD_MS * 1000LL);
|
||||
if (slept_ticks) {
|
||||
#if CONFIG_PM_LIGHTSLEEP_TICK_OVERFLOW_PROTECTION
|
||||
/* Limit slept_ticks when oversleep is within tolerance to prevent assertion failure */
|
||||
if ((slept_ticks > xExpectedIdleTime) &&
|
||||
(slept_ticks <= (xExpectedIdleTime + CONFIG_PM_LIGHTSLEEP_TICK_OVERFLOW_TOLERANCE))) {
|
||||
slept_ticks = xExpectedIdleTime;
|
||||
}
|
||||
#endif // CONFIG_PM_LIGHTSLEEP_TICK_OVERFLOW_PROTECTION
|
||||
if (slept_ticks > xExpectedIdleTime) {
|
||||
ESP_EARLY_LOGE(TAG, "Light sleep overslept: expect %"PRIu32" idle ticks but slept %"PRIu32" ticks.",
|
||||
(uint32_t)xExpectedIdleTime, slept_ticks);
|
||||
}
|
||||
/* Adjust RTOS tick count based on the amount of time spent in sleep */
|
||||
vTaskStepTick(slept_ticks);
|
||||
|
||||
@@ -886,7 +898,7 @@ void vApplicationSleep( TickType_t xExpectedIdleTime )
|
||||
// In this case, there is no need to call vTaskStepTick, because the OS tick count will
|
||||
// automatically catch up in the next systick interrupt handler.
|
||||
if (err == ESP_OK) {
|
||||
pm_step_tick(slept_us);
|
||||
pm_step_tick(slept_us, xExpectedIdleTime);
|
||||
}
|
||||
other_core_should_skip_light_sleep(core_id);
|
||||
#ifdef WITH_PROFILING
|
||||
|
||||
Reference in New Issue
Block a user