forked from espressif/esp-idf
Merge branch 'bugfix/fix_esp32s3_psram_access_failed_in_dfs_v5.0' into 'release/v5.0'
esp_pm: fix esp32s3 psram access failed when dfs is enabled (backport v5.0) See merge request espressif/esp-idf!24199
This commit is contained in:
@ -583,7 +583,9 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
|
|||||||
|
|
||||||
#if SOC_SPI_MEM_SUPPORT_TIME_TUNING
|
#if SOC_SPI_MEM_SUPPORT_TIME_TUNING
|
||||||
// Restore mspi clock freq
|
// Restore mspi clock freq
|
||||||
spi_timing_change_speed_mode_cache_safe(false);
|
if (cpu_freq_config.source == SOC_CPU_CLK_SRC_PLL) {
|
||||||
|
spi_timing_change_speed_mode_cache_safe(false);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!deep_sleep) {
|
if (!deep_sleep) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
idf_component_register(SRCS "pm_locks.c" "pm_trace.c" "pm_impl.c"
|
idf_component_register(SRCS "pm_locks.c" "pm_trace.c" "pm_impl.c"
|
||||||
INCLUDE_DIRS include
|
INCLUDE_DIRS include
|
||||||
PRIV_REQUIRES esp_system driver esp_timer
|
PRIV_REQUIRES esp_system driver esp_timer spi_flash
|
||||||
LDFRAGMENTS linker.lf)
|
LDFRAGMENTS linker.lf)
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "esp_private/crosscore_int.h"
|
#include "esp_private/crosscore_int.h"
|
||||||
|
|
||||||
#include "soc/rtc.h"
|
#include "soc/rtc.h"
|
||||||
|
#include "soc/soc_caps.h"
|
||||||
#include "hal/uart_ll.h"
|
#include "hal/uart_ll.h"
|
||||||
#include "hal/uart_types.h"
|
#include "hal/uart_types.h"
|
||||||
#include "driver/uart.h"
|
#include "driver/uart.h"
|
||||||
@ -35,6 +36,10 @@
|
|||||||
#include "esp_private/esp_timer_private.h"
|
#include "esp_private/esp_timer_private.h"
|
||||||
#include "esp_private/esp_clk.h"
|
#include "esp_private/esp_clk.h"
|
||||||
|
|
||||||
|
#if SOC_SPI_MEM_SUPPORT_TIME_TUNING
|
||||||
|
#include "esp_private/spi_flash_os.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "esp_sleep.h"
|
#include "esp_sleep.h"
|
||||||
|
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
@ -503,7 +508,19 @@ static void IRAM_ATTR do_switch(pm_mode_t new_mode)
|
|||||||
if (switch_down) {
|
if (switch_down) {
|
||||||
on_freq_update(old_ticks_per_us, new_ticks_per_us);
|
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
|
||||||
|
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) {
|
if (!switch_down) {
|
||||||
on_freq_update(old_ticks_per_us, new_ticks_per_us);
|
on_freq_update(old_ticks_per_us, new_ticks_per_us);
|
||||||
}
|
}
|
||||||
|
@ -15,13 +15,20 @@
|
|||||||
* Feel free to change when debugging.
|
* Feel free to change when debugging.
|
||||||
*/
|
*/
|
||||||
static const int DRAM_ATTR s_trace_io[] = {
|
static const int DRAM_ATTR s_trace_io[] = {
|
||||||
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32H2) && !defined(CONFIG_IDF_TARGET_ESP32C2)
|
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
|
||||||
BIT(4), BIT(5), // ESP_PM_TRACE_IDLE
|
BIT(4), BIT(5), // ESP_PM_TRACE_IDLE
|
||||||
BIT(16), BIT(17), // ESP_PM_TRACE_TICK
|
BIT(16), BIT(17), // ESP_PM_TRACE_TICK
|
||||||
BIT(18), BIT(18), // ESP_PM_TRACE_FREQ_SWITCH
|
BIT(18), BIT(18), // ESP_PM_TRACE_FREQ_SWITCH
|
||||||
BIT(19), BIT(19), // ESP_PM_TRACE_CCOMPARE_UPDATE
|
BIT(19), BIT(19), // ESP_PM_TRACE_CCOMPARE_UPDATE
|
||||||
BIT(25), BIT(26), // ESP_PM_TRACE_ISR_HOOK
|
BIT(25), BIT(26), // ESP_PM_TRACE_ISR_HOOK
|
||||||
BIT(27), BIT(27), // ESP_PM_TRACE_SLEEP
|
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
|
#else
|
||||||
BIT(2), BIT(3), // ESP_PM_TRACE_IDLE
|
BIT(2), BIT(3), // ESP_PM_TRACE_IDLE
|
||||||
BIT(4), BIT(5), // ESP_PM_TRACE_TICK
|
BIT(4), BIT(5), // ESP_PM_TRACE_TICK
|
||||||
|
@ -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)
|
void spi_timing_change_speed_mode_cache_safe(bool switch_down)
|
||||||
{
|
{
|
||||||
Cache_Freeze_ICache_Enable(1);
|
Cache_Freeze_ICache_Enable(CACHE_FREEZE_ACK_BUSY);
|
||||||
Cache_Freeze_DCache_Enable(1);
|
Cache_Freeze_DCache_Enable(CACHE_FREEZE_ACK_BUSY);
|
||||||
if (switch_down) {
|
if (switch_down) {
|
||||||
//enter MSPI low speed mode, extra delays should be removed
|
//enter MSPI low speed mode, extra delays should be removed
|
||||||
spi_timing_enter_mspi_low_speed_mode(false);
|
spi_timing_enter_mspi_low_speed_mode(false);
|
||||||
|
@ -9,11 +9,14 @@
|
|||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
|
#include "freertos/semphr.h"
|
||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
#include "esp_check.h"
|
#include "esp_check.h"
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "esp_flash.h"
|
#include "esp_flash.h"
|
||||||
#include "esp_partition.h"
|
#include "esp_partition.h"
|
||||||
|
#include "esp_pm.h"
|
||||||
|
#include "esp_private/esp_clk.h"
|
||||||
#if CONFIG_IDF_TARGET_ESP32S3
|
#if CONFIG_IDF_TARGET_ESP32S3
|
||||||
#include "esp32s3/rom/spi_flash.h"
|
#include "esp32s3/rom/spi_flash.h"
|
||||||
#include "esp32s3/rom/opi_flash.h"
|
#include "esp32s3/rom/opi_flash.h"
|
||||||
@ -31,7 +34,23 @@
|
|||||||
#define LENGTH_PER_TIME 1024
|
#define LENGTH_PER_TIME 1024
|
||||||
#endif
|
#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;
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
typedef esp_pm_config_esp32s2_t esp_pm_config_t;
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||||
|
typedef esp_pm_config_esp32s3_t esp_pm_config_t;
|
||||||
|
#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 Test----------\n");
|
||||||
|
|
||||||
@ -41,30 +60,145 @@ static esp_err_t spi0_psram_test(void)
|
|||||||
abort();
|
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) {
|
if (!psram_rd_buf) {
|
||||||
printf("no memory\n");
|
printf("no memory\n");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
srand(399);
|
srand(399);
|
||||||
for (int i = 0; i < SPI0_PSRAM_TEST_LEN / LENGTH_PER_TIME; i++) {
|
for (uint32_t loop = 0; loop < (uint32_t)(arg); loop++) {
|
||||||
for (int j = 0; j < sizeof(psram_wr_buf); j++) {
|
for (int i = 0; i < SPI0_PSRAM_TEST_LEN / LENGTH_PER_TIME; i++) {
|
||||||
psram_wr_buf[j] = rand();
|
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);
|
}
|
||||||
|
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) {
|
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_rd_buf);
|
free(psram_wr_buf);
|
||||||
free(psram_wr_buf);
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xSemaphoreGive(DoneSemphr);
|
||||||
|
vTaskDelay(10);
|
||||||
|
}
|
||||||
|
free(psram_rd_buf);
|
||||||
|
free(psram_wr_buf);
|
||||||
|
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(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
xSemaphoreGive(StopSemphr);
|
||||||
free(psram_rd_buf);
|
vSemaphoreDelete(DoneSemphr);
|
||||||
free(psram_wr_buf);
|
/* Wait for test_task to finish up */
|
||||||
printf(DRAM_STR("----------SPI0 PSRAM Test Success----------\n\n"));
|
vTaskDelay(pdMS_TO_TICKS(500));
|
||||||
|
printf(DRAM_STR("----------Access SPI0 PSRAM with DFS Test Success----------\n\n"));
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -76,8 +210,6 @@ static esp_err_t spi0_psram_test(void)
|
|||||||
#define SPI1_FLASH_TEST_NUM (SECTOR_LEN / SPI1_FLASH_TEST_LEN)
|
#define SPI1_FLASH_TEST_NUM (SECTOR_LEN / SPI1_FLASH_TEST_LEN)
|
||||||
#define SPI1_FLASH_TEST_ADDR 0x2a0000
|
#define SPI1_FLASH_TEST_ADDR 0x2a0000
|
||||||
|
|
||||||
extern void spi_flash_disable_interrupts_caches_and_other_cpu(void);
|
|
||||||
extern void spi_flash_enable_interrupts_caches_and_other_cpu(void);
|
|
||||||
static uint8_t rd_buf[SPI1_FLASH_TEST_LEN];
|
static uint8_t rd_buf[SPI1_FLASH_TEST_LEN];
|
||||||
static uint8_t wr_buf[SPI1_FLASH_TEST_LEN];
|
static uint8_t wr_buf[SPI1_FLASH_TEST_LEN];
|
||||||
|
|
||||||
@ -158,6 +290,7 @@ void app_main(void)
|
|||||||
|
|
||||||
#if CONFIG_SPIRAM
|
#if CONFIG_SPIRAM
|
||||||
ESP_ERROR_CHECK(spi0_psram_test());
|
ESP_ERROR_CHECK(spi0_psram_test());
|
||||||
|
ESP_ERROR_CHECK(spi0_psram_with_dfs_test());
|
||||||
#endif
|
#endif
|
||||||
ESP_ERROR_CHECK(spi1_flash_test());
|
ESP_ERROR_CHECK(spi1_flash_test());
|
||||||
|
|
||||||
|
13
tools/test_apps/system/flash_psram/sdkconfig.defaults
Normal file
13
tools/test_apps/system/flash_psram/sdkconfig.defaults
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
CONFIG_FREERTOS_HZ=1000
|
||||||
|
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
|
Reference in New Issue
Block a user