Skip to content

Commit

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

esp_pm: fix esp32s3 psram access failed when dfs is enabled (backport v4.4)

See merge request espressif/esp-idf!24200
  • Loading branch information
jack0c committed Jun 20, 2023
2 parents 58544cf + bf3de23 commit ebcb29b
Show file tree
Hide file tree
Showing 8 changed files with 208 additions and 35 deletions.
6 changes: 4 additions & 2 deletions components/esp_hw_support/sleep_modes.c
Original file line number Diff line number Diff line change
Expand Up @@ -564,8 +564,10 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
rtc_clk_cpu_freq_set_config(&cpu_freq_config);

#if SOC_SPI_MEM_SUPPORT_TIME_TUNING
// Restore mspi clock freq
spi_timing_change_speed_mode_cache_safe(false);
if (cpu_freq_config.source == RTC_CPU_FREQ_SRC_PLL) {
// Restore mspi clock freq
spi_timing_change_speed_mode_cache_safe(false);
}
#endif

if (!deep_sleep) {
Expand Down
2 changes: 1 addition & 1 deletion components/esp_pm/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
idf_component_register(SRCS "pm_locks.c" "pm_trace.c" "pm_impl.c"
INCLUDE_DIRS include
PRIV_REQUIRES esp_system driver
PRIV_REQUIRES esp_system driver spi_flash
LDFRAGMENTS linker.lf)
19 changes: 18 additions & 1 deletion components/esp_pm/pm_impl.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "esp_private/crosscore_int.h"

#include "soc/rtc.h"
#include "soc/soc_caps.h"
#include "hal/cpu_hal.h"
#include "hal/uart_ll.h"
#include "hal/uart_types.h"
Expand All @@ -32,6 +33,10 @@
#include "esp_private/pm_trace.h"
#include "esp_private/esp_timer_private.h"

#if SOC_SPI_MEM_SUPPORT_TIME_TUNING
#include "esp_private/spi_flash_os.h"
#endif

#include "esp_sleep.h"

#include "sdkconfig.h"
Expand Down Expand Up @@ -501,7 +506,19 @@ static void IRAM_ATTR do_switch(pm_mode_t new_mode)
if (switch_down) {
on_freq_update(old_ticks_per_us, new_ticks_per_us);
}
rtc_clk_cpu_freq_set_config_fast(&new_config);

if (new_config.source == RTC_CPU_FREQ_SRC_PLL) {
rtc_clk_cpu_freq_set_config_fast(&new_config);
#if SOC_SPI_MEM_SUPPORT_TIME_TUNING
spi_timing_change_speed_mode_cache_safe(false);
#endif
} else {
#if SOC_SPI_MEM_SUPPORT_TIME_TUNING
spi_timing_change_speed_mode_cache_safe(true);
#endif
rtc_clk_cpu_freq_set_config_fast(&new_config);
}

if (!switch_down) {
on_freq_update(old_ticks_per_us, new_ticks_per_us);
}
Expand Down
33 changes: 20 additions & 13 deletions components/esp_pm/pm_trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,27 @@
* Feel free to change when debugging.
*/
static const int DRAM_ATTR s_trace_io[] = {
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32H2)
BIT(4), BIT(5), // ESP_PM_TRACE_IDLE
BIT(16), BIT(17), // ESP_PM_TRACE_TICK
BIT(18), BIT(18), // ESP_PM_TRACE_FREQ_SWITCH
BIT(19), BIT(19), // ESP_PM_TRACE_CCOMPARE_UPDATE
BIT(25), BIT(26), // ESP_PM_TRACE_ISR_HOOK
BIT(27), BIT(27), // ESP_PM_TRACE_SLEEP
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
BIT(4), BIT(5), // ESP_PM_TRACE_IDLE
BIT(16), BIT(17), // ESP_PM_TRACE_TICK
BIT(18), BIT(18), // ESP_PM_TRACE_FREQ_SWITCH
BIT(19), BIT(19), // ESP_PM_TRACE_CCOMPARE_UPDATE
BIT(25), BIT(26), // ESP_PM_TRACE_ISR_HOOK
BIT(27), BIT(27), // ESP_PM_TRACE_SLEEP
#elif CONFIG_IDF_TARGET_ESP32S3
BIT(4), BIT(5), // ESP_PM_TRACE_IDLE
BIT(6), BIT(7), // ESP_PM_TRACE_TICK
BIT(14), BIT(14), // ESP_PM_TRACE_FREQ_SWITCH
BIT(15), BIT(15), // ESP_PM_TRACE_CCOMPARE_UPDATE
BIT(16), BIT(17), // ESP_PM_TRACE_ISR_HOOK
BIT(18), BIT(18), // ESP_PM_TRACE_SLEEP
#else
BIT(2), BIT(3), // ESP_PM_TRACE_IDLE
BIT(4), BIT(5), // ESP_PM_TRACE_TICK
BIT(6), BIT(6), // ESP_PM_TRACE_FREQ_SWITCH
BIT(7), BIT(7), // ESP_PM_TRACE_CCOMPARE_UPDATE
BIT(8), BIT(9), // ESP_PM_TRACE_ISR_HOOK
BIT(18), BIT(18), // ESP_PM_TRACE_SLEEP
BIT(2), BIT(3), // ESP_PM_TRACE_IDLE
BIT(4), BIT(5), // ESP_PM_TRACE_TICK
BIT(6), BIT(6), // ESP_PM_TRACE_FREQ_SWITCH
BIT(7), BIT(7), // ESP_PM_TRACE_CCOMPARE_UPDATE
BIT(8), BIT(9), // ESP_PM_TRACE_ISR_HOOK
BIT(18), BIT(18), // ESP_PM_TRACE_SLEEP
#endif
};

Expand Down
4 changes: 2 additions & 2 deletions components/spi_flash/spi_flash_timing_tuning.c
Original file line number Diff line number Diff line change
Expand Up @@ -472,8 +472,8 @@ void spi_timing_enter_mspi_high_speed_mode(bool control_spi1)

void spi_timing_change_speed_mode_cache_safe(bool switch_down)
{
Cache_Freeze_ICache_Enable(1);
Cache_Freeze_DCache_Enable(1);
Cache_Freeze_ICache_Enable(CACHE_FREEZE_ACK_BUSY);
Cache_Freeze_DCache_Enable(CACHE_FREEZE_ACK_BUSY);
if (switch_down) {
//enter MSPI low speed mode, extra delays should be removed
spi_timing_enter_mspi_low_speed_mode(false);
Expand Down
2 changes: 1 addition & 1 deletion tools/test_apps/system/flash_psram/app_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def test_loop(env, config_names): # type: (Any, Any) -> None
Utility.console_log("Checking config \"{}\"... ".format(name), end='')
dut = env.get_dut('flash_psram', 'tools/test_apps/system/flash_psram', app_config_name=name)
dut.start_app()
dut.expect('flash psram test success')
dut.expect('flash psram test success', timeout=30)
env.close_dut(dut.name)
Utility.console_log('done')

Expand Down
168 changes: 153 additions & 15 deletions tools/test_apps/system/flash_psram/main/test_flash_psram.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand All @@ -9,9 +9,12 @@
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp_system.h"
#include "esp_check.h"
#include "esp_attr.h"
#include "esp_pm.h"
#include "esp_private/esp_clk.h"
#if CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/rom/spi_flash.h"
#include "esp32s3/rom/opi_flash.h"
Expand All @@ -29,7 +32,26 @@
#define LENGTH_PER_TIME 1024
#endif

static esp_err_t spi0_psram_test(void)
#define MHZ (1000000)
#ifndef MIN
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#endif

#if CONFIG_IDF_TARGET_ESP32
typedef esp_pm_config_esp32_t esp_pm_config_t;
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ
#elif CONFIG_IDF_TARGET_ESP32S2
typedef esp_pm_config_esp32s2_t esp_pm_config_t;
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ
#elif CONFIG_IDF_TARGET_ESP32S3
typedef esp_pm_config_esp32s3_t esp_pm_config_t;
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ
#endif

static SemaphoreHandle_t DoneSemphr;
static SemaphoreHandle_t StopSemphr;

static void psram_read_write_task(void* arg)
{
printf("----------SPI0 PSRAM Test----------\n");

Expand All @@ -39,30 +61,145 @@ static esp_err_t spi0_psram_test(void)
abort();
}

uint32_t *psram_rd_buf = (uint32_t *)heap_caps_malloc(SPI0_PSRAM_TEST_LEN, MALLOC_CAP_32BIT | MALLOC_CAP_SPIRAM);
uint8_t *psram_rd_buf = (uint8_t *)heap_caps_malloc(SPI0_PSRAM_TEST_LEN, MALLOC_CAP_32BIT | MALLOC_CAP_SPIRAM);
if (!psram_rd_buf) {
printf("no memory\n");
abort();
}

srand(399);
for (int i = 0; i < SPI0_PSRAM_TEST_LEN / LENGTH_PER_TIME; i++) {
for (int j = 0; j < sizeof(psram_wr_buf); j++) {
psram_wr_buf[j] = rand();
}
memcpy(psram_rd_buf + i * LENGTH_PER_TIME, psram_wr_buf, LENGTH_PER_TIME);
for (uint32_t loop = 0; loop < (uint32_t)(arg); loop++) {
for (int i = 0; i < SPI0_PSRAM_TEST_LEN / LENGTH_PER_TIME; i++) {
for (int j = 0; j < sizeof(psram_wr_buf); j++) {
psram_wr_buf[j] = rand();
}
memcpy(psram_rd_buf + i * LENGTH_PER_TIME, psram_wr_buf, LENGTH_PER_TIME);

if (memcmp(psram_rd_buf + i * LENGTH_PER_TIME, psram_wr_buf, LENGTH_PER_TIME) != 0) {
printf("Fail\n");
free(psram_rd_buf);
free(psram_wr_buf);
return ESP_FAIL;
if (memcmp(psram_rd_buf + i * LENGTH_PER_TIME, psram_wr_buf, LENGTH_PER_TIME) != 0) {
free(psram_rd_buf);
free(psram_wr_buf);
abort();
}
}
xSemaphoreGive(DoneSemphr);
vTaskDelay(10);
}

free(psram_rd_buf);
free(psram_wr_buf);
printf(DRAM_STR("----------SPI0 PSRAM Test Success----------\n\n"));
vTaskDelete(NULL);
}

static void pm_light_sleep_enable(void)
{
int cur_freq_mhz = esp_clk_cpu_freq() / MHZ;
int xtal_freq = esp_clk_xtal_freq() / MHZ;

esp_pm_config_t pm_config = {
.max_freq_mhz = cur_freq_mhz,
.min_freq_mhz = xtal_freq,
.light_sleep_enable = true
};
ESP_ERROR_CHECK( esp_pm_configure(&pm_config) );
}

static void pm_light_sleep_disable(void)
{
int cur_freq_mhz = esp_clk_cpu_freq() / MHZ;

esp_pm_config_t pm_config = {
.max_freq_mhz = cur_freq_mhz,
.min_freq_mhz = cur_freq_mhz,
};
ESP_ERROR_CHECK( esp_pm_configure(&pm_config) );
}

static void pm_switch_freq(int max_cpu_freq_mhz)
{
int xtal_freq_mhz = esp_clk_xtal_freq() / MHZ;

esp_pm_config_t pm_config = {
.max_freq_mhz = max_cpu_freq_mhz,
.min_freq_mhz = MIN(max_cpu_freq_mhz, xtal_freq_mhz),
};
ESP_ERROR_CHECK( esp_pm_configure(&pm_config) );
printf("Waiting for frequency to be set to %d MHz...\n", max_cpu_freq_mhz);
while (esp_clk_cpu_freq() / MHZ != max_cpu_freq_mhz)
{
vTaskDelay(pdMS_TO_TICKS(200));
printf("Frequency is %d MHz\n", esp_clk_cpu_freq() / MHZ);
}
}

static void goto_idle_and_check_stop(uint32_t period)
{
if (xSemaphoreTake(StopSemphr, pdMS_TO_TICKS(period)) == pdTRUE) {
pm_switch_freq(DEFAULT_CPU_FREQ_MHZ);
vSemaphoreDelete(StopSemphr);
vTaskDelete(NULL);
}
}

static void pm_switch_task(void *arg)
{
pm_light_sleep_disable();
uint32_t period = 100;
StopSemphr = xSemaphoreCreateBinary();
while (1) {
pm_light_sleep_enable();
goto_idle_and_check_stop(period);
pm_light_sleep_disable();
goto_idle_and_check_stop(period);
pm_switch_freq(10);
goto_idle_and_check_stop(period);
pm_switch_freq(80);
goto_idle_and_check_stop(period);
pm_switch_freq(40);
goto_idle_and_check_stop(period);
}
}

static esp_err_t spi0_psram_test(void)
{
DoneSemphr = xSemaphoreCreateCounting(1, 0);
xTaskCreate(psram_read_write_task, "", 2048, (void *)(1), 3, NULL);
if (xSemaphoreTake(DoneSemphr, pdMS_TO_TICKS(1000)) == pdTRUE) {
printf(DRAM_STR("----------SPI0 PSRAM Test Success----------\n\n"));
} else {
printf(DRAM_STR("----------SPI0 PSRAM Test Timeout----------\n\n"));
return ESP_FAIL;
}

vSemaphoreDelete(DoneSemphr);
/* Wait for test_task to finish up */
vTaskDelay(100);
return ESP_OK;
}

static esp_err_t spi0_psram_with_dfs_test(void)
{
printf("----------Access SPI0 PSRAM with DFS Test----------\n");

uint32_t test_loop = 50;
DoneSemphr = xSemaphoreCreateCounting(test_loop, 0);

xTaskCreatePinnedToCore(pm_switch_task, "", 4096, NULL, 3, NULL, 0);
xTaskCreatePinnedToCore(psram_read_write_task, "", 2048, (void *)(test_loop), 3, NULL, 1);

int cnt = 0;
while (cnt < test_loop) {
if (xSemaphoreTake(DoneSemphr, pdMS_TO_TICKS(1000)) == pdTRUE) {
cnt++;
} else {
vSemaphoreDelete(DoneSemphr);
printf(DRAM_STR("----------SPI0 PSRAM Test Timeout----------\n\n"));
return ESP_FAIL;
}
}
xSemaphoreGive(StopSemphr);
vSemaphoreDelete(DoneSemphr);
/* Wait for test_task to finish up */
vTaskDelay(pdMS_TO_TICKS(500));
printf(DRAM_STR("----------Access SPI0 PSRAM with DFS Test Success----------\n\n"));
return ESP_OK;
}
#endif
Expand Down Expand Up @@ -151,6 +288,7 @@ void app_main(void)

#if CONFIG_SPIRAM
ESP_ERROR_CHECK(spi0_psram_test());
ESP_ERROR_CHECK(spi0_psram_with_dfs_test());
#endif
ESP_ERROR_CHECK(spi1_flash_test());

Expand Down
9 changes: 9 additions & 0 deletions tools/test_apps/system/flash_psram/sdkconfig.defaults
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
CONFIG_FREERTOS_HZ=1000
CONFIG_ESP_TASK_WDT_EN=n

# For test access psram with DFS enabled
CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y
CONFIG_SPIRAM_RODATA=y
CONFIG_PM_ENABLE=y
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
CONFIG_FREERTOS_IDLE_TIME_BEFORE_SLEEP=5

0 comments on commit ebcb29b

Please sign in to comment.