Skip to content

Commit

Permalink
Merge branch 'bugfix/fix_esp32s3_psram_access_failed_in_dfs_v5.1' int…
Browse files Browse the repository at this point in the history
…o 'release/v5.1'

esp_pm: fix esp32s3 psram access failed when dfs is enabled (backport v5.1)

See merge request espressif/esp-idf!24202
  • Loading branch information
jack0c committed Jul 4, 2023
2 parents 4647045 + f0860ac commit 27a5a6f
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 22 deletions.
4 changes: 2 additions & 2 deletions components/esp_hw_support/mspi_timing_tuning.c
Expand Up @@ -563,8 +563,8 @@ void mspi_timing_enter_high_speed_mode(bool control_spi1)

void mspi_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
mspi_timing_enter_low_speed_mode(false);
Expand Down
11 changes: 6 additions & 5 deletions components/esp_hw_support/sleep_modes.c
Expand Up @@ -512,7 +512,7 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo
pd_flags &= ~RTC_SLEEP_PD_INT_8M;
}

// Turn down mspi clock speed
// Will switch to XTAL turn down MSPI speed
#if SOC_SPI_MEM_SUPPORT_TIME_TUNING
mspi_timing_change_speed_mode_cache_safe(true);
#endif
Expand Down Expand Up @@ -704,14 +704,15 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo
}

// Set mspi clock to ROM default one.
if (cpu_freq_config.source == SOC_CPU_CLK_SRC_PLL) {
#if SOC_MEMSPI_CLOCK_IS_INDEPENDENT
spi_flash_set_clock_src(MSPI_CLK_SRC_DEFAULT);
spi_flash_set_clock_src(MSPI_CLK_SRC_DEFAULT);
#endif

// Speed up mspi clock freq
#if SOC_SPI_MEM_SUPPORT_TIME_TUNING
mspi_timing_change_speed_mode_cache_safe(false);
// Turn up MSPI speed if switch to PLL
mspi_timing_change_speed_mode_cache_safe(false);
#endif
}

if (!deep_sleep) {
s_config.ccount_ticks_record = esp_cpu_get_cycle_count();
Expand Down
152 changes: 139 additions & 13 deletions components/esp_hw_support/test_apps/mspi/main/test_flash_psram.c
Expand Up @@ -10,11 +10,14 @@
#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_flash.h"
#include "esp_partition.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 @@ -32,38 +35,161 @@
#define LENGTH_PER_TIME 1024
#endif

TEST_CASE("MSPI: Test_SPI0_PSRAM", "[mspi]")
#define MHZ (1000000)
#ifndef MIN
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#endif

static SemaphoreHandle_t DoneSemphr;
static SemaphoreHandle_t StopSemphr;

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

uint8_t *psram_wr_buf = (uint8_t *)heap_caps_malloc(LENGTH_PER_TIME, MALLOC_CAP_32BIT | MALLOC_CAP_SPIRAM);
if (!psram_wr_buf) {
printf("no memory\n");
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) {
free(psram_rd_buf);
free(psram_wr_buf);
TEST_FAIL_MESSAGE("SPI0 PSRAM Test 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);
TEST_FAIL_MESSAGE("SPI0 PSRAM Test Fail");
}
}
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
};
TEST_ESP_OK( 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,
};
TEST_ESP_OK( 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),
};
TEST_ESP_OK( 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(CONFIG_ESP_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);
}
}

TEST_CASE("MSPI: Test_SPI0_PSRAM", "[mspi]")
{
DoneSemphr = xSemaphoreCreateCounting(1, 0);
xTaskCreate(psram_read_write_task, "", 2048, (void *)(1), 3, NULL);
if (xSemaphoreTake(DoneSemphr, pdMS_TO_TICKS(100)) == pdTRUE) {
printf(DRAM_STR("----------SPI0 PSRAM Test Success----------\n\n"));
} else {
TEST_FAIL_MESSAGE(DRAM_STR("SPI0 PSRAM Test Timeout"));
}

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


TEST_CASE("MSPI: Test_SPI0_PSRAM with DFS", "[mspi]")
{
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);
TEST_FAIL_MESSAGE(DRAM_STR("SPI0 PSRAM Test Timeout"));
}
}
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"));
}
#endif

Expand Down
7 changes: 7 additions & 0 deletions components/esp_hw_support/test_apps/mspi/sdkconfig.defaults
Expand Up @@ -4,3 +4,10 @@ CONFIG_ESP_TASK_WDT_EN=n
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"

# 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
16 changes: 15 additions & 1 deletion components/esp_pm/pm_impl.c
Expand Up @@ -31,6 +31,10 @@
#include "xtensa/core-macros.h"
#endif

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

#include "esp_private/pm_impl.h"
#include "esp_private/pm_trace.h"
#include "esp_private/esp_timer_private.h"
Expand Down Expand Up @@ -475,7 +479,17 @@ 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 == SOC_CPU_CLK_SRC_PLL) {
rtc_clk_cpu_freq_set_config_fast(&new_config);
#if SOC_SPI_MEM_SUPPORT_TIME_TUNING
mspi_timing_change_speed_mode_cache_safe(false);
#endif
} else {
#if SOC_SPI_MEM_SUPPORT_TIME_TUNING
mspi_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
9 changes: 8 additions & 1 deletion components/esp_pm/pm_trace.c
Expand Up @@ -15,13 +15,20 @@
* Feel free to change when debugging.
*/
static const int DRAM_ATTR s_trace_io[] = {
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#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
Expand Down

0 comments on commit 27a5a6f

Please sign in to comment.