fix(lightsleep): suspend cache before goto sleep to avoid cache load wrong data after spi io isolation

This commit is contained in:
wuzhenghui 2023-07-31 19:49:37 +08:00
parent a1e7766940
commit 46dd957c11
3 changed files with 21 additions and 5 deletions

View File

@ -19,6 +19,7 @@
#include "esp_attr.h" #include "esp_attr.h"
#include "esp_sleep.h" #include "esp_sleep.h"
#include "esp_spi_flash.h"
#include "esp_private/esp_timer_private.h" #include "esp_private/esp_timer_private.h"
#include "esp_private/system_internal.h" #include "esp_private/system_internal.h"
#include "esp_log.h" #include "esp_log.h"
@ -704,7 +705,11 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
portEXIT_CRITICAL(&spinlock_rtc_deep_sleep); portEXIT_CRITICAL(&spinlock_rtc_deep_sleep);
} else { } else {
uint32_t cache_state;
uint32_t cpuid = cpu_ll_get_core_id();
spi_flash_disable_cache(cpuid, &cache_state);
result = call_rtc_sleep_start(reject_triggers); result = call_rtc_sleep_start(reject_triggers);
spi_flash_restore_cache(cpuid, cache_state);
} }
// Restore CPU frequency // Restore CPU frequency

View File

@ -58,9 +58,6 @@ static __attribute__((unused)) const char *TAG = "cache";
#define DPORT_CACHE_GET_VAL(cpuid) (cpuid == 0) ? DPORT_CACHE_VAL(PRO) : DPORT_CACHE_VAL(APP) #define DPORT_CACHE_GET_VAL(cpuid) (cpuid == 0) ? DPORT_CACHE_VAL(PRO) : DPORT_CACHE_VAL(APP)
#define DPORT_CACHE_GET_MASK(cpuid) (cpuid == 0) ? DPORT_CACHE_MASK(PRO) : DPORT_CACHE_MASK(APP) #define DPORT_CACHE_GET_MASK(cpuid) (cpuid == 0) ? DPORT_CACHE_MASK(PRO) : DPORT_CACHE_MASK(APP)
static void IRAM_ATTR spi_flash_disable_cache(uint32_t cpuid, uint32_t *saved_state);
static void IRAM_ATTR spi_flash_restore_cache(uint32_t cpuid, uint32_t saved_state);
static uint32_t s_flash_op_cache_state[2]; static uint32_t s_flash_op_cache_state[2];
#ifndef CONFIG_FREERTOS_UNICORE #ifndef CONFIG_FREERTOS_UNICORE
@ -295,7 +292,7 @@ void IRAM_ATTR spi_flash_enable_interrupts_caches_no_os(void)
* function in ROM. They are used to work around a bug where Cache_Read_Disable requires a call to * function in ROM. They are used to work around a bug where Cache_Read_Disable requires a call to
* Cache_Flush before Cache_Read_Enable, even if cached data was not modified. * Cache_Flush before Cache_Read_Enable, even if cached data was not modified.
*/ */
static void IRAM_ATTR spi_flash_disable_cache(uint32_t cpuid, uint32_t *saved_state) void IRAM_ATTR spi_flash_disable_cache(uint32_t cpuid, uint32_t *saved_state)
{ {
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32
uint32_t ret = 0; uint32_t ret = 0;
@ -331,7 +328,7 @@ static void IRAM_ATTR spi_flash_disable_cache(uint32_t cpuid, uint32_t *saved_st
#endif #endif
} }
static void IRAM_ATTR spi_flash_restore_cache(uint32_t cpuid, uint32_t saved_state) void IRAM_ATTR spi_flash_restore_cache(uint32_t cpuid, uint32_t saved_state)
{ {
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32
const uint32_t cache_mask = DPORT_CACHE_GET_MASK(cpuid); const uint32_t cache_mask = DPORT_CACHE_GET_MASK(cpuid);

View File

@ -321,6 +321,20 @@ bool spi_flash_cache_enabled(void);
*/ */
void spi_flash_enable_cache(uint32_t cpuid); void spi_flash_enable_cache(uint32_t cpuid);
/**
* Suspend the I/DCACHE for coresuspends the CPU access to cache for a while, without invalidation.
* @param cpuid the core number to suspend cache for (valid only on esp32)
* @param saved_state uint32_t variable pointer to record cache autoload status
*/
void spi_flash_disable_cache(uint32_t cpuid, uint32_t *saved_state);
/**
* Resume the I/DCache for core.
* @param cpuid the core number to suspend cache for (valid only on esp32)
* @param saved_state uint32_t variable recorded the cache autoload status
*/
void spi_flash_restore_cache(uint32_t cpuid, uint32_t saved_state);
/** /**
* @brief SPI flash critical section enter function. * @brief SPI flash critical section enter function.
* *