Selaa lähdekoodia

Merge branch 'bugfix/fix_deep_sleep_crash_when_psram_high_freq' into 'master'

mspi: turn down freq to fix crash when sleep

Closes IDF-6881

See merge request espressif/esp-idf!22491
Wan Lei 2 vuotta sitten
vanhempi
sitoutus
3b62bf59c4
32 muutettua tiedostoa jossa 159 lisäystä ja 47 poistoa
  1. 24 0
      .gitlab/ci/target-test.yml
  2. 1 1
      components/bootloader_support/bootloader_flash/src/bootloader_flash.c
  3. 5 0
      components/esp_hw_support/.build-test-rules.yml
  4. 11 0
      components/esp_hw_support/sleep_modes.c
  5. 5 0
      components/esp_hw_support/test_apps/mspi/CMakeLists.txt
  6. 0 0
      components/esp_hw_support/test_apps/mspi/README.md
  7. 10 0
      components/esp_hw_support/test_apps/mspi/main/CMakeLists.txt
  8. 30 0
      components/esp_hw_support/test_apps/mspi/main/test_app_main.c
  9. 8 28
      components/esp_hw_support/test_apps/mspi/main/test_flash_psram.c
  10. 52 0
      components/esp_hw_support/test_apps/mspi/main/test_mspi.c
  11. 0 0
      components/esp_hw_support/test_apps/mspi/partitions.csv
  12. 8 8
      components/esp_hw_support/test_apps/mspi/pytest_flash_psram.py
  13. 0 0
      components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_120sdr
  14. 0 0
      components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_120sdr_120sdr
  15. 0 0
      components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_120sdr_40sdr
  16. 0 0
      components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_120sdr_os_silent
  17. 0 0
      components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_40sdr_120sdr
  18. 0 0
      components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_80sdr_80sdr
  19. 0 0
      components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r8_120sdr
  20. 0 0
      components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r8_80sdr_40ddr
  21. 0 0
      components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r8_80sdr_80ddr
  22. 0 0
      components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_120sdr
  23. 0 0
      components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_40ddr_40ddr
  24. 0 0
      components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_40ddr_80ddr
  25. 0 0
      components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_80ddr_40ddr
  26. 0 0
      components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_80ddr_80ddr
  27. 0 0
      components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_80ddr_80ddr_ecc
  28. 0 0
      components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_80sdr_80ddr
  29. 5 0
      components/esp_hw_support/test_apps/mspi/sdkconfig.defaults
  30. 0 6
      tools/test_apps/system/flash_psram/CMakeLists.txt
  31. 0 2
      tools/test_apps/system/flash_psram/main/CMakeLists.txt
  32. 0 2
      tools/test_apps/system/flash_psram/sdkconfig.ci.default

+ 24 - 0
.gitlab/ci/target-test.yml

@@ -696,6 +696,30 @@ component_ut_pytest_esp32s3_flash_multi:
     - build_pytest_components_esp32s3
   tags: [ esp32s3, flash_multi ]
 
+component_ut_pytest_esp32s3_mspi_f4r4:
+  extends:
+    - .pytest_components_dir_template
+    - .rules:test:component_ut-esp32s3
+  needs:
+    - build_pytest_components_esp32s3
+  tags: [ esp32s3, MSPI_F4R4 ]
+
+component_ut_pytest_esp32s3_mspi_f4r8:
+  extends:
+    - .pytest_components_dir_template
+    - .rules:test:component_ut-esp32s3
+  needs:
+    - build_pytest_components_esp32s3
+  tags: [ esp32s3, MSPI_F4R8 ]
+
+component_ut_pytest_esp32s3_mspi_f8r8:
+  extends:
+    - .pytest_components_dir_template
+    - .rules:test:component_ut-esp32s3
+  needs:
+    - build_pytest_components_esp32s3
+  tags: [ esp32s3, MSPI_F8R8 ]
+
 component_ut_pytest_esp32c2_generic:
   extends:
     - .pytest_components_dir_template

+ 1 - 1
components/bootloader_support/bootloader_flash/src/bootloader_flash.c

@@ -746,7 +746,7 @@ esp_err_t IRAM_ATTR bootloader_flash_reset_chip(void)
     return ESP_OK;
 }
 
-bool bootloader_flash_is_octal_mode_enabled(void)
+bool IRAM_ATTR bootloader_flash_is_octal_mode_enabled(void)
 {
 #if SOC_SPI_MEM_SUPPORT_OPI_MODE
     return efuse_ll_get_flash_type();

+ 5 - 0
components/esp_hw_support/.build-test-rules.yml

@@ -14,6 +14,10 @@ components/esp_hw_support/test_apps/etm:
   disable:
     - if: SOC_ETM_SUPPORTED != 1
 
+components/esp_hw_support/test_apps/mspi:
+  disable:
+    - if: IDF_TARGET != "esp32s3"
+
 components/esp_hw_support/test_apps/rtc_clk:
   disable:
     - if: IDF_TARGET in ["esp32c6", "esp32h2"]
@@ -25,6 +29,7 @@ components/esp_hw_support/test_apps/security_support/esp_hw_support_unity_tests:
     - if: IDF_TARGET in ["esp32h2"]
       temporary: true
       reason: H2 fails IDF-6898
+
 components/heap/host_test/host_test_linux:
   enable:
     - if: IDF_TARGET == "linux"

+ 11 - 0
components/esp_hw_support/sleep_modes.c

@@ -72,6 +72,7 @@
 #include "esp_private/gpio.h"
 #elif CONFIG_IDF_TARGET_ESP32S3
 #include "esp32s3/rom/rtc.h"
+#include "esp_private/mspi_timing_tuning.h"
 #elif CONFIG_IDF_TARGET_ESP32C3
 #include "esp32c3/rom/rtc.h"
 #elif CONFIG_IDF_TARGET_ESP32H4
@@ -461,6 +462,11 @@ 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
+#if SOC_SPI_MEM_SUPPORT_TIME_TUNING
+    mspi_timing_change_speed_mode_cache_safe(true);
+#endif
+
     // Set mspi clock to a low-power one.
 #if SOC_MEMSPI_CLOCK_IS_INDEPENDENT
     spi_flash_set_clock_src(MSPI_CLK_SRC_ROM_DEFAULT);
@@ -639,6 +645,11 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo
     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);
+#endif
+
     if (!deep_sleep) {
         s_config.ccount_ticks_record = esp_cpu_get_cycle_count();
         misc_modules_wake_prepare();

+ 5 - 0
components/esp_hw_support/test_apps/mspi/CMakeLists.txt

@@ -0,0 +1,5 @@
+# This is the project CMakeLists.txt file for the test subproject
+cmake_minimum_required(VERSION 3.16)
+
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+project(mspi_test_app)

+ 0 - 0
tools/test_apps/system/flash_psram/README.md → components/esp_hw_support/test_apps/mspi/README.md


+ 10 - 0
components/esp_hw_support/test_apps/mspi/main/CMakeLists.txt

@@ -0,0 +1,10 @@
+set(srcs
+    "test_app_main.c"
+    "test_flash_psram.c"
+    "test_mspi.c"
+)
+
+# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
+# the component can be registered as WHOLE_ARCHIVE
+idf_component_register(SRCS ${srcs}
+                       WHOLE_ARCHIVE)

+ 30 - 0
components/esp_hw_support/test_apps/mspi/main/test_app_main.c

@@ -0,0 +1,30 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "unity.h"
+#include "unity_test_utils.h"
+#include "esp_heap_caps.h"
+
+// load partition table in tests will use memory
+#define TEST_MEMORY_LEAK_THRESHOLD (450)
+
+void setUp(void)
+{
+    unity_utils_record_free_mem();
+}
+
+void tearDown(void)
+{
+    esp_reent_cleanup();    //clean up some of the newlib's lazy allocations
+    unity_utils_evaluate_leaks_direct(TEST_MEMORY_LEAK_THRESHOLD);
+}
+
+void app_main(void)
+{
+    printf("\n");
+    printf("===================TEST MSPI=================\n");
+    unity_run_menu();
+}

+ 8 - 28
tools/test_apps/system/flash_psram/main/test_flash_psram.c → components/esp_hw_support/test_apps/mspi/main/test_flash_psram.c

@@ -6,6 +6,7 @@
 
 #include <stdio.h>
 #include <string.h>
+#include "unity.h"
 #include "sdkconfig.h"
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
@@ -31,7 +32,7 @@
 #define LENGTH_PER_TIME        1024
 #endif
 
-static esp_err_t spi0_psram_test(void)
+TEST_CASE("MSPI: Test_SPI0_PSRAM", "[mspi]")
 {
     printf("----------SPI0 PSRAM Test----------\n");
 
@@ -55,17 +56,14 @@ static esp_err_t spi0_psram_test(void)
         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;
+            TEST_FAIL_MESSAGE("SPI0 PSRAM Test Fail");
         }
     }
-
     free(psram_rd_buf);
     free(psram_wr_buf);
     printf(DRAM_STR("----------SPI0 PSRAM Test Success----------\n\n"));
-    return ESP_OK;
 }
 #endif
 
@@ -76,8 +74,6 @@ static esp_err_t spi0_psram_test(void)
 #define SPI1_FLASH_TEST_NUM     (SECTOR_LEN / SPI1_FLASH_TEST_LEN)
 #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 wr_buf[SPI1_FLASH_TEST_LEN];
 
@@ -90,7 +86,7 @@ static const esp_partition_t *get_test_flash_partition(void)
     return result;
 }
 
-static NOINLINE_ATTR IRAM_ATTR esp_err_t spi1_flash_test(void)
+TEST_CASE("MSPI: Test_SPI1_Flash", "[mspi]")
 {
     printf(DRAM_STR("----------SPI1 Flash Test----------\n"));
 
@@ -114,16 +110,15 @@ static NOINLINE_ATTR IRAM_ATTR esp_err_t spi1_flash_test(void)
                     printf(DRAM_STR("err: wr[%d]: 0x%02x -- rd[%d]: 0x%02x\n"), i, wr_buf[i], i, rd_buf[i]);
                 }
             }
-            return ESP_FAIL;
+            TEST_FAIL_MESSAGE("SPI1 Flash Test Fail");
         }
         memset(rd_buf, 0x0, SPI1_FLASH_TEST_LEN);
     }
 
     printf(DRAM_STR("----------SPI1 Flash Test Success----------\n\n"));
-
-    return ESP_OK;
 }
 
+
 //-----------------------------------------SPI0 FLASH TEST-----------------------------------------------//
 #define SPI0_FLASH_TEST_LEN    32
 #define SPI0_FLASH_TEST_BUF    {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, \
@@ -133,8 +128,7 @@ static const uint8_t flash_rd_buf[SPI0_FLASH_TEST_LEN] = SPI0_FLASH_TEST_BUF;
 extern int _flash_rodata_start;
 extern int _rodata_reserved_end;
 
-
-static IRAM_ATTR esp_err_t spi0_flash_test(void)
+TEST_CASE("MSPI: Test_SPI0_Flash", "[mspi]")
 {
     printf("----------SPI0 Flash Test----------\n");
     //Check if the flash_rd_buf is in .rodata
@@ -144,22 +138,8 @@ static IRAM_ATTR esp_err_t spi0_flash_test(void)
 
     for (int i = 0; i < SPI0_FLASH_TEST_LEN; i++) {
         if (flash_rd_buf[i] != cmp_buf[i]) {
-            return ESP_FAIL;
+            TEST_FAIL_MESSAGE("SPI0 Flash Test Fail");
         }
     }
     printf(DRAM_STR("----------SPI0 Flash Test Success----------\n\n"));
-
-    return ESP_OK;
-}
-
-void app_main(void)
-{
-    ESP_ERROR_CHECK(spi0_flash_test());
-
-#if CONFIG_SPIRAM
-    ESP_ERROR_CHECK(spi0_psram_test());
-#endif
-    ESP_ERROR_CHECK(spi1_flash_test());
-
-    printf("flash psram test success\n");
 }

+ 52 - 0
components/esp_hw_support/test_apps/mspi/main/test_mspi.c

@@ -0,0 +1,52 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Unlicense OR CC0-1.0
+ */
+
+#include "unity.h"
+#include "esp_timer.h"
+#include "esp_private/mspi_timing_tuning.h"
+
+
+static void sorted_array_insert(uint32_t *array, uint32_t *size, uint32_t item)
+{
+    uint32_t pos;
+    for (pos = *size; pos > 0; pos--) {
+        if (array[pos - 1] <= item) {
+            break;
+        }
+        array[pos] = array[pos - 1];
+    }
+    array[pos] = item;
+    (*size)++;
+}
+
+#define TEST_TIME_CNT           10
+#define TEST_TIME_LIMIT_US      10
+TEST_CASE("MSPI: Test mspi timing turning time cost", "[mspi]")
+{
+    uint64_t start, end;
+    uint32_t cost, index_1 = 0, index_2 = 0;
+    uint32_t slow_down_time[TEST_TIME_CNT], speed_up_time[TEST_TIME_CNT];
+
+    printf("\nFunc call `mspi_timing_change_speed_mode_cache_safe` should spend time less than %d us\n", TEST_TIME_LIMIT_US);
+    for (uint8_t i = 0; i < TEST_TIME_CNT; i++) {
+        start = esp_timer_get_time();
+        mspi_timing_change_speed_mode_cache_safe(true);
+        end = esp_timer_get_time();
+        cost = end - start;
+        sorted_array_insert(slow_down_time, &index_1, cost);
+        printf("mspi psram slow down cost %ld\t", cost);
+
+        start = esp_timer_get_time();
+        mspi_timing_change_speed_mode_cache_safe(false);
+        end = esp_timer_get_time();
+        cost = end - start;
+        sorted_array_insert(speed_up_time, &index_2, cost);
+        printf("mspi psram speed up cost %ld\n", cost);
+    }
+
+    TEST_ASSERT_LESS_THAN_UINT32(TEST_TIME_LIMIT_US, slow_down_time[TEST_TIME_CNT / 2]);
+    TEST_ASSERT_LESS_THAN_UINT32(TEST_TIME_LIMIT_US, speed_up_time[TEST_TIME_CNT / 2]);
+}

+ 0 - 0
tools/test_apps/system/flash_psram/partitions.csv → components/esp_hw_support/test_apps/mspi/partitions.csv


+ 8 - 8
tools/test_apps/system/flash_psram/pytest_flash_psram.py → components/esp_hw_support/test_apps/mspi/pytest_flash_psram.py

@@ -1,11 +1,11 @@
-# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
 # SPDX-License-Identifier: CC0-1.0
 
 import os
 import pathlib
 
 import pytest
-from pytest_embedded import Dut
+from pytest_embedded_idf import IdfDut
 
 MSPI_F8R8_configs = [p.name.replace('sdkconfig.ci.', '') for p in pathlib.Path(os.path.dirname(__file__)).glob('sdkconfig.ci.f8r8*')]
 
@@ -13,8 +13,8 @@ MSPI_F8R8_configs = [p.name.replace('sdkconfig.ci.', '') for p in pathlib.Path(o
 @pytest.mark.esp32s3
 @pytest.mark.MSPI_F8R8
 @pytest.mark.parametrize('config', MSPI_F8R8_configs, indirect=True)
-def test_flash8_psram8(dut: Dut) -> None:
-    dut.expect_exact('flash psram test success')
+def test_flash8_psram8(dut: IdfDut) -> None:
+    dut.run_all_single_board_cases()
 
 
 # For F4R8 board (Quad Flash and Octal PSRAM)
@@ -24,8 +24,8 @@ MSPI_F4R8_configs = [p.name.replace('sdkconfig.ci.', '') for p in pathlib.Path(o
 @pytest.mark.esp32s3
 @pytest.mark.MSPI_F4R8
 @pytest.mark.parametrize('config', MSPI_F4R8_configs, indirect=True)
-def test_flash4_psram8(dut: Dut) -> None:
-    dut.expect_exact('flash psram test success')
+def test_flash4_psram8(dut: IdfDut) -> None:
+    dut.run_all_single_board_cases()
 
 
 # For F4R4 board (Quad Flash and Quad PSRAM)
@@ -35,5 +35,5 @@ MSPI_F4R4_configs = [p.name.replace('sdkconfig.ci.', '') for p in pathlib.Path(o
 @pytest.mark.esp32s3
 @pytest.mark.MSPI_F4R4
 @pytest.mark.parametrize('config', MSPI_F4R4_configs, indirect=True)
-def test_flash4_psram4(dut: Dut) -> None:
-    dut.expect_exact('flash psram test success', timeout=40)
+def test_flash4_psram4(dut: IdfDut) -> None:
+    dut.run_all_single_board_cases()

+ 0 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f4r4_120sdr → components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_120sdr


+ 0 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f4r4_120sdr_120sdr → components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_120sdr_120sdr


+ 0 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f4r4_120sdr_40sdr → components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_120sdr_40sdr


+ 0 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f4r4_120sdr_os_silent → components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_120sdr_os_silent


+ 0 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f4r4_40sdr_120sdr → components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_40sdr_120sdr


+ 0 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f4r4_80sdr_80sdr → components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r4_80sdr_80sdr


+ 0 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f4r8_120sdr → components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r8_120sdr


+ 0 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f4r8_80sdr_40ddr → components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r8_80sdr_40ddr


+ 0 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f4r8_80sdr_80ddr → components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f4r8_80sdr_80ddr


+ 0 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f8r8_120sdr → components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_120sdr


+ 0 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f8r8_40ddr_40ddr → components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_40ddr_40ddr


+ 0 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f8r8_40ddr_80ddr → components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_40ddr_80ddr


+ 0 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f8r8_80ddr_40ddr → components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_80ddr_40ddr


+ 0 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f8r8_80ddr_80ddr → components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_80ddr_80ddr


+ 0 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f8r8_80ddr_80ddr_ecc → components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_80ddr_80ddr_ecc


+ 0 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f8r8_80sdr_80ddr → components/esp_hw_support/test_apps/mspi/sdkconfig.ci.f8r8_80sdr_80ddr


+ 5 - 0
components/esp_hw_support/test_apps/mspi/sdkconfig.defaults

@@ -0,0 +1,5 @@
+CONFIG_FREERTOS_HZ=1000
+CONFIG_ESP_TASK_WDT_EN=n
+
+CONFIG_SPIRAM_RODATA=y
+CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y

+ 0 - 6
tools/test_apps/system/flash_psram/CMakeLists.txt

@@ -1,6 +0,0 @@
-# The following lines of boilerplate have to be in your project's
-# CMakeLists in this exact order for cmake to work correctly
-cmake_minimum_required(VERSION 3.16)
-
-include($ENV{IDF_PATH}/tools/cmake/project.cmake)
-project(test_flash_psram)

+ 0 - 2
tools/test_apps/system/flash_psram/main/CMakeLists.txt

@@ -1,2 +0,0 @@
-idf_component_register(SRCS "test_flash_psram.c"
-                       INCLUDE_DIRS ".")

+ 0 - 2
tools/test_apps/system/flash_psram/sdkconfig.ci.default

@@ -1,2 +0,0 @@
-CONFIG_IDF_TARGET="esp32s3"
-CONFIG_IDF_TARGET_ESP32S3=y