Skip to content

Commit

Permalink
Merge branch 'bugfix/fix_cache_data_mem_corrupt_after_sleep_v4.4' int…
Browse files Browse the repository at this point in the history
…o 'release/v4.4'

fix(lightsleep): Suspend cache before goto sleep to avoid cache load wrong data (backport v4.4)

See merge request espressif/esp-idf!25104
  • Loading branch information
jack0c committed Aug 3, 2023
2 parents 8a38bc2 + 2df2c1c commit 6b27c05
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 11 deletions.
5 changes: 3 additions & 2 deletions components/esp_hw_support/port/esp32c3/rtc_sleep.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <stdint.h>
#include <stdlib.h>
#include "esp_attr.h"
#include "soc/soc.h"
#include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h"
Expand All @@ -28,6 +29,8 @@
#include "soc/systimer_reg.h"
#endif

static const DRAM_ATTR rtc_sleep_pu_config_t pu_cfg = RTC_SLEEP_PU_CONFIG_ALL(1);

/**
* Configure whether certain peripherals are powered down in deep sleep
* @param cfg power down flags as rtc_sleep_pu_config_t structure
Expand Down Expand Up @@ -170,7 +173,6 @@ void rtc_sleep_get_default_config(uint32_t sleep_flags, rtc_sleep_config_t *out_
void rtc_sleep_init(rtc_sleep_config_t cfg)
{
if (cfg.lslp_mem_inf_fpu) {
rtc_sleep_pu_config_t pu_cfg = RTC_SLEEP_PU_CONFIG_ALL(1);
rtc_sleep_pu(pu_cfg);
}
/* mem force pu */
Expand Down Expand Up @@ -372,7 +374,6 @@ static uint32_t rtc_sleep_finish(uint32_t lslp_mem_inf_fpu)

/* restore config if it is a light sleep */
if (lslp_mem_inf_fpu) {
rtc_sleep_pu_config_t pu_cfg = RTC_SLEEP_PU_CONFIG_ALL(1);
rtc_sleep_pu(pu_cfg);
}
return reject;
Expand Down
5 changes: 3 additions & 2 deletions components/esp_hw_support/port/esp32h2/rtc_sleep.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <stdint.h>
#include <stdlib.h>
#include "esp_attr.h"
#include "soc/soc.h"
#include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h"
Expand All @@ -30,6 +31,8 @@
*/
static const char *TAG = "rtc_sleep";

static const DRAM_ATTR rtc_sleep_pu_config_t pu_cfg = RTC_SLEEP_PU_CONFIG_ALL(1);

void rtc_sleep_pu(rtc_sleep_pu_config_t cfg)
{
REG_SET_FIELD(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_LSLP_MEM_FORCE_PU, cfg.dig_fpu);
Expand Down Expand Up @@ -201,7 +204,6 @@ void rtc_sleep_get_default_config(uint32_t sleep_flags, rtc_sleep_config_t *out_
void rtc_sleep_init(rtc_sleep_config_t cfg)
{
if (cfg.lslp_mem_inf_fpu) {
rtc_sleep_pu_config_t pu_cfg = RTC_SLEEP_PU_CONFIG_ALL(1);
rtc_sleep_pu(pu_cfg);
}
if (cfg.bt_pd_en) {
Expand Down Expand Up @@ -382,7 +384,6 @@ static uint32_t rtc_sleep_finish(uint32_t lslp_mem_inf_fpu)

/* restore config if it is a light sleep */
if (lslp_mem_inf_fpu) {
rtc_sleep_pu_config_t pu_cfg = RTC_SLEEP_PU_CONFIG_ALL(1);
rtc_sleep_pu(pu_cfg);
}
return reject;
Expand Down
5 changes: 3 additions & 2 deletions components/esp_hw_support/port/esp32s3/rtc_sleep.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/

#include <stdint.h>
#include "esp_attr.h"
#include "soc/soc.h"
#include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h"
Expand All @@ -22,6 +23,8 @@

#define RTC_CNTL_MEM_FOLW_CPU (RTC_CNTL_SLOWMEM_FOLW_CPU | RTC_CNTL_FASTMEM_FOLW_CPU)

static const DRAM_ATTR rtc_sleep_pu_config_t pu_cfg = RTC_SLEEP_PU_CONFIG_ALL(1);

/**
* Configure whether certain peripherals are powered up in sleep
* @param cfg power down flags as rtc_sleep_pu_config_t structure
Expand Down Expand Up @@ -175,7 +178,6 @@ void rtc_sleep_get_default_config(uint32_t sleep_flags, rtc_sleep_config_t *out_
void rtc_sleep_init(rtc_sleep_config_t cfg)
{
if (cfg.lslp_mem_inf_fpu) {
rtc_sleep_pu_config_t pu_cfg = RTC_SLEEP_PU_CONFIG_ALL(1);
rtc_sleep_pu(pu_cfg);
}
/* mem force pu */
Expand Down Expand Up @@ -303,7 +305,6 @@ static uint32_t rtc_sleep_finish(uint32_t lslp_mem_inf_fpu)

/* restore config if it is a light sleep */
if (lslp_mem_inf_fpu) {
rtc_sleep_pu_config_t pu_cfg = RTC_SLEEP_PU_CONFIG_ALL(1);
rtc_sleep_pu(pu_cfg);
}

Expand Down
5 changes: 5 additions & 0 deletions components/esp_hw_support/sleep_modes.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "esp_attr.h"
#include "esp_sleep.h"
#include "esp_spi_flash.h"
#include "esp_private/esp_timer_private.h"
#include "esp_private/system_internal.h"
#include "esp_private/esp_sleep_internal.h"
Expand Down Expand Up @@ -551,7 +552,11 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
#endif
#endif // SOC_PM_SUPPORT_DEEPSLEEP_VERIFY_STUB_ONLY
} 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, config.lslp_mem_inf_fpu);
spi_flash_restore_cache(cpuid, cache_state);
}

#if CONFIG_ESP_SLEEP_SYSTIMER_STALL_WORKAROUND
Expand Down
7 changes: 2 additions & 5 deletions components/spi_flash/cache_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,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_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];

#ifndef CONFIG_FREERTOS_UNICORE
Expand Down Expand Up @@ -300,7 +297,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
* 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
uint32_t ret = 0;
Expand Down Expand Up @@ -336,7 +333,7 @@ static void IRAM_ATTR spi_flash_disable_cache(uint32_t cpuid, uint32_t *saved_st
#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
const uint32_t cache_mask = DPORT_CACHE_GET_MASK(cpuid);
Expand Down
14 changes: 14 additions & 0 deletions components/spi_flash/include/esp_spi_flash.h
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,20 @@ bool spi_flash_cache_enabled(void);
*/
void spi_flash_enable_cache(uint32_t cpuid);

/**
* Suspend the I/DCACHE for core,suspends 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.
*
Expand Down

0 comments on commit 6b27c05

Please sign in to comment.