Ver código fonte

Merge branch 'feature/support_auto_detect_oct_flash_vendor' into 'master'

mspi: support auto detect oct flash vendor

Closes IDF-3523 and IDF-3857

See merge request espressif/esp-idf!14741
Armando (Dou Yiwen) 4 anos atrás
pai
commit
8ab29b7877
39 arquivos alterados com 717 adições e 187 exclusões
  1. 23 0
      .gitlab/ci/target-test.yml
  2. 5 0
      components/esp_hw_support/linker.lf
  3. 17 19
      components/esp_hw_support/port/esp32s3/opiram_psram.c
  4. 50 1
      components/esp_hw_support/port/esp32s3/rtc_init.c
  5. 6 6
      components/esp_hw_support/port/esp32s3/spiram_psram.c
  6. 18 19
      components/esp_system/port/cpu_start.c
  7. 11 21
      components/esptool_py/Kconfig.projbuild
  8. 7 7
      components/spi_flash/esp32s3/opi_flash_cmd_format_mxic.h
  9. 36 0
      components/spi_flash/esp32s3/opi_flash_private.h
  10. 97 17
      components/spi_flash/esp32s3/spi_flash_oct_flash_init.c
  11. 2 2
      components/spi_flash/esp32s3/spi_timing_config.h
  12. 8 16
      components/spi_flash/esp_flash_spi_init.c
  13. 27 13
      components/spi_flash/flash_ops.c
  14. 15 3
      components/spi_flash/include/esp_private/spi_flash_os.h
  15. 42 40
      components/spi_flash/sim/Makefile.files
  16. 3 3
      components/spi_flash/spi_flash_timing_tuning.c
  17. 7 15
      components/spi_flash/test/test_read_write.c
  18. 0 4
      tools/ci/check_copyright_ignore.txt
  19. 0 1
      tools/ci/check_public_headers_exceptions.txt
  20. 6 0
      tools/test_apps/system/flash_psram/CMakeLists.txt
  21. 7 0
      tools/test_apps/system/flash_psram/README.md
  22. 54 0
      tools/test_apps/system/flash_psram/app_test.py
  23. 2 0
      tools/test_apps/system/flash_psram/main/CMakeLists.txt
  24. 160 0
      tools/test_apps/system/flash_psram/main/test_flash_psram.c
  25. 2 0
      tools/test_apps/system/flash_psram/sdkconfig.ci.default
  26. 5 0
      tools/test_apps/system/flash_psram/sdkconfig.ci.f4r4_120sdr
  27. 7 0
      tools/test_apps/system/flash_psram/sdkconfig.ci.f4r4_120sdr_120sdr
  28. 7 0
      tools/test_apps/system/flash_psram/sdkconfig.ci.f4r4_120sdr_40sdr
  29. 7 0
      tools/test_apps/system/flash_psram/sdkconfig.ci.f4r4_40sdr_120sdr
  30. 7 0
      tools/test_apps/system/flash_psram/sdkconfig.ci.f4r4_80sdr_80sdr
  31. 5 0
      tools/test_apps/system/flash_psram/sdkconfig.ci.f4r8_120sdr
  32. 8 0
      tools/test_apps/system/flash_psram/sdkconfig.ci.f4r8_80sdr_40ddr
  33. 8 0
      tools/test_apps/system/flash_psram/sdkconfig.ci.f4r8_80sdr_80ddr
  34. 8 0
      tools/test_apps/system/flash_psram/sdkconfig.ci.f8r8_120sdr
  35. 10 0
      tools/test_apps/system/flash_psram/sdkconfig.ci.f8r8_40ddr_40ddr
  36. 10 0
      tools/test_apps/system/flash_psram/sdkconfig.ci.f8r8_40ddr_80ddr
  37. 10 0
      tools/test_apps/system/flash_psram/sdkconfig.ci.f8r8_80ddr_40ddr
  38. 10 0
      tools/test_apps/system/flash_psram/sdkconfig.ci.f8r8_80ddr_80ddr
  39. 10 0
      tools/test_apps/system/flash_psram/sdkconfig.ci.f8r8_80sdr_80ddr

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

@@ -303,6 +303,11 @@ example_test_ESP32C3_SDSPI:
     - .test_app_template
     - .rules:test:custom_test-esp32c3
 
+.test_app_esp32s3_template:
+  extends:
+    - .test_app_template
+    - .rules:test:custom_test-esp32s3
+
 test_app_test_001:
   extends: .test_app_esp32_template
   tags:
@@ -345,6 +350,24 @@ test_app_test_esp32_generic:
   variables:
     SETUP_TOOLS: "1"
 
+test_app_test_flash_psram_f4r4:
+  extends: .test_app_esp32s3_template
+  tags:
+    - ESP32S3
+    - MSPI_F4R4
+
+test_app_test_flash_psram_f4r8:
+  extends: .test_app_esp32s3_template
+  tags:
+    - ESP32S3
+    - MSPI_F4R8
+
+test_app_test_flash_psram_f8r8:
+  extends: .test_app_esp32s3_template
+  tags:
+    - ESP32S3
+    - MSPI_F8R8
+
 .component_ut_template:
   extends: .target_test_job_template
   variables:

+ 5 - 0
components/esp_hw_support/linker.lf

@@ -11,3 +11,8 @@ entries:
     rtc_time (noflash_text)
     if IDF_TARGET_ESP32C3 = n && IDF_TARGET_ESP32H2 = n:
         rtc_wdt (noflash_text)
+    if IDF_TARGET_ESP32S3 = y:
+        if SPIRAM_MODE_QUAD = y:
+            spiram_psram (noflash)
+        if SPIRAM_MODE_OCT = y:
+            opiram_psram (noflash)

+ 17 - 19
components/esp_hw_support/port/esp32s3/opiram_psram.c

@@ -27,7 +27,7 @@
 
 #if CONFIG_SPIRAM_MODE_OCT
 #include "soc/rtc.h"
-#include "spi_flash_private.h"
+#include "esp_private/spi_flash_os.h"
 
 #define OPI_PSRAM_SYNC_READ             0x0000
 #define OPI_PSRAM_SYNC_WRITE            0x8080
@@ -99,10 +99,10 @@ typedef struct {
 } opi_psram_mode_reg_t;
 
 static const char* TAG = "opi psram";
-static DRAM_ATTR psram_size_t s_psram_size;
-static void IRAM_ATTR s_config_psram_spi_phases(void);
+static psram_size_t s_psram_size;
+static void s_config_psram_spi_phases(void);
 
-uint8_t IRAM_ATTR psram_get_cs_io(void)
+uint8_t psram_get_cs_io(void)
 {
     return OCT_PSRAM_CS1_IO;
 }
@@ -110,7 +110,7 @@ uint8_t IRAM_ATTR psram_get_cs_io(void)
 /**
  * Initialise mode registers of the PSRAM
  */
-static void IRAM_ATTR s_init_psram_mode_reg(int spi_num, opi_psram_mode_reg_t *mode_reg_config)
+static void s_init_psram_mode_reg(int spi_num, opi_psram_mode_reg_t *mode_reg_config)
 {
     esp_rom_spiflash_read_mode_t mode = ESP_ROM_SPIFLASH_OPI_DTR_MODE;
     int cmd_len = 16;
@@ -145,7 +145,7 @@ static void IRAM_ATTR s_init_psram_mode_reg(int spi_num, opi_psram_mode_reg_t *m
                              false);
 }
 
-static void IRAM_ATTR s_get_psram_mode_reg(int spi_num, opi_psram_mode_reg_t *out_reg)
+static void s_get_psram_mode_reg(int spi_num, opi_psram_mode_reg_t *out_reg)
 {
     esp_rom_spiflash_read_mode_t mode = ESP_ROM_SPIFLASH_OPI_DTR_MODE;
     int cmd_len = 16;
@@ -153,7 +153,7 @@ static void IRAM_ATTR s_get_psram_mode_reg(int spi_num, opi_psram_mode_reg_t *ou
     int dummy = OCT_PSRAM_RD_DUMMY_BITLEN;
     int data_bit_len = 16;
 
-    //Read MR0 register
+    //Read MR0~1 register
     esp_rom_opiflash_exec_cmd(spi_num, mode,
                              OPI_PSRAM_REG_READ, cmd_len,
                              0x0, addr_bit_len,
@@ -162,7 +162,7 @@ static void IRAM_ATTR s_get_psram_mode_reg(int spi_num, opi_psram_mode_reg_t *ou
                              &out_reg->mr0.val, data_bit_len,
                              BIT(1),
                              false);
-    //Read MR2 register
+    //Read MR2~3 register
     esp_rom_opiflash_exec_cmd(spi_num, mode,
                             OPI_PSRAM_REG_READ, cmd_len,
                             0x2, addr_bit_len,
@@ -171,6 +171,7 @@ static void IRAM_ATTR s_get_psram_mode_reg(int spi_num, opi_psram_mode_reg_t *ou
                             &out_reg->mr2.val, data_bit_len,
                             BIT(1),
                             false);
+    data_bit_len = 8;
     //Read MR4 register
     esp_rom_opiflash_exec_cmd(spi_num, mode,
                             OPI_PSRAM_REG_READ, cmd_len,
@@ -191,7 +192,7 @@ static void IRAM_ATTR s_get_psram_mode_reg(int spi_num, opi_psram_mode_reg_t *ou
                             false);
 }
 
-static void IRAM_ATTR s_print_psram_info(opi_psram_mode_reg_t *reg_val)
+static void s_print_psram_info(opi_psram_mode_reg_t *reg_val)
 {
     ESP_EARLY_LOGI(TAG, "vendor id : 0x%02x (%s)", reg_val->mr1.vendor_id, reg_val->mr1.vendor_id == 0x0d ? "AP" : "UNKNOWN");
     ESP_EARLY_LOGI(TAG, "dev id    : 0x%02x (generation %d)", reg_val->mr2.dev_id, reg_val->mr2.dev_id + 1);
@@ -224,7 +225,7 @@ static void psram_set_cs_timing(void)
     SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(0), SPI_MEM_SPI_SMEM_CS_HOLD_DELAY_V, OCT_PSRAM_CS_HOLD_DELAY, SPI_MEM_SPI_SMEM_CS_HOLD_DELAY_S);
 }
 
-static void IRAM_ATTR s_init_psram_pins(void)
+static void s_init_psram_pins(void)
 {
     //Set cs1 pin function
     PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[OCT_PSRAM_CS1_IO],  FUNC_SPICS1_SPICS1);
@@ -234,7 +235,7 @@ static void IRAM_ATTR s_init_psram_pins(void)
     REG_SET_FIELD(SPI_MEM_DATE_REG(0), SPI_MEM_SPI_SMEM_SPICLK_FUN_DRV, 3);
 }
 
-esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode)
+esp_err_t psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode)
 {
     s_init_psram_pins();
     psram_set_cs_timing();
@@ -244,12 +245,10 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad
 
     //set to variable dummy mode
     SET_PERI_REG_MASK(SPI_MEM_DDR_REG(1), SPI_MEM_SPI_FMEM_VAR_DUMMY);
-#if CONFIG_ESPTOOLPY_FLASH_VENDOR_MXIC && CONFIG_ESPTOOLPY_FLASHMODE_OPI_DTR
     esp_rom_spi_set_dtr_swap_mode(1, false, false);
-#endif
 
     //Set PSRAM read latency and drive strength
-    static DRAM_ATTR opi_psram_mode_reg_t mode_reg = {0};
+    static opi_psram_mode_reg_t mode_reg = {0};
     mode_reg.mr0.lt = 1;
     mode_reg.mr0.read_latency = 2;
     mode_reg.mr0.drive_str = 0;
@@ -262,12 +261,9 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad
                    mode_reg.mr2.density == 0x5 ? PSRAM_SIZE_128MBITS :
                    mode_reg.mr2.density == 0x7 ? PSRAM_SIZE_256MBITS : 0;
 
-#if CONFIG_ESPTOOLPY_FLASH_VENDOR_MXIC && CONFIG_ESPTOOLPY_FLASHMODE_OPI_DTR
-    esp_rom_spi_set_dtr_swap_mode(1, true, true);
-#endif
     //Do PSRAM timing tuning, we use SPI1 to do the tuning, and set the SPI0 PSRAM timing related registers accordingly
     spi_timing_psram_tuning();
-    ////Back to the high speed mode. Flash/PSRAM clocks are set to the clock that user selected. SPI0/1 registers are all set correctly
+    //Back to the high speed mode. Flash/PSRAM clocks are set to the clock that user selected. SPI0/1 registers are all set correctly
     spi_timing_enter_mspi_high_speed_mode(true);
 
     /**
@@ -275,13 +271,15 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad
      * This function is to restore SPI1 init state.
      */
     spi_flash_set_rom_required_regs();
+    //Flash chip requires MSPI specifically, call this function to set them
+    spi_flash_set_vendor_required_regs();
 
     s_config_psram_spi_phases();
     return ESP_OK;
 }
 
 //Configure PSRAM SPI0 phase related registers here according to the PSRAM chip requirement
-static void IRAM_ATTR s_config_psram_spi_phases(void)
+static void s_config_psram_spi_phases(void)
 {
     //Config Write CMD phase for SPI0 to access PSRAM
     SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_CACHE_SRAM_USR_WCMD_M);

+ 50 - 1
components/esp_hw_support/port/esp32s3/rtc_init.c

@@ -18,9 +18,23 @@
 #include "regi2c_ulp.h"
 #include "soc_log.h"
 #include "esp_err.h"
+#include "esp_attr.h"
 #include "esp_efuse.h"
 #include "esp_efuse_table.h"
 
+#ifndef BOOTLOADER_BUILD
+/**
+ * TODO: IDF-3204
+ * Temporarily solution. Depends on MSPI
+ * Final solution: the rtc should not depend on MSPI. We should do rtc related before Flash init
+ */
+#include "esp_private/spi_flash_os.h"
+#include "esp32s3/rom/cache.h"
+#include "freertos/portmacro.h"
+portMUX_TYPE rtc_init_spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
+#endif
+
+
 #define RTC_CNTL_MEM_FORCE_NOISO (RTC_CNTL_SLOWMEM_FORCE_NOISO | RTC_CNTL_FASTMEM_FORCE_NOISO)
 
 static const char *TAG = "rtcinit";
@@ -231,8 +245,40 @@ static void set_ocode_by_efuse(int calib_version)
     REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_CODE, 1);
 }
 
-static void calibrate_ocode(void)
+#ifndef BOOTLOADER_BUILD
+//TODO: IDF-3204
+//Temporary solution, these 2 functions should be defined elsewhere, because similar operations are also needed elsewhere
+//Final solution: the rtc should not depend on MSPI. We should do rtc related before Flash init
+static void IRAM_ATTR enter_mspi_low_speed_mode_safe(void)
+{
+    portENTER_CRITICAL(&rtc_init_spinlock);
+    Cache_Freeze_ICache_Enable(1);
+    Cache_Freeze_DCache_Enable(1);
+    spi_timing_enter_mspi_low_speed_mode(false);
+    Cache_Freeze_DCache_Disable();
+    Cache_Freeze_ICache_Disable();
+    portEXIT_CRITICAL(&rtc_init_spinlock);
+}
+
+static void IRAM_ATTR enter_mspi_high_speed_mode_safe(void)
+{
+    portENTER_CRITICAL(&rtc_init_spinlock);
+    Cache_Freeze_ICache_Enable(1);
+    Cache_Freeze_DCache_Enable(1);
+    spi_timing_enter_mspi_high_speed_mode(false);
+    Cache_Freeze_DCache_Disable();
+    Cache_Freeze_ICache_Disable();
+    portEXIT_CRITICAL(&rtc_init_spinlock);
+}
+#endif
+
+//TODO: IDF-3204
+//This function will change the system clock source to XTAL. Under lower frequency (e.g. XTAL), MSPI timing tuning configures should be modified accordingly.
+static void IRAM_ATTR calibrate_ocode(void)
 {
+#ifndef BOOTLOADER_BUILD
+    enter_mspi_low_speed_mode_safe();
+#endif
     /*
     Bandgap output voltage is not precise when calibrate o-code by hardware sometimes, so need software o-code calibration (must turn off PLL).
     Method:
@@ -280,4 +326,7 @@ static void calibrate_ocode(void)
         }
     }
     rtc_clk_cpu_freq_set_config(&old_config);
+#ifndef BOOTLOADER_BUILD
+    enter_mspi_high_speed_mode_safe();
+#endif
 }

+ 6 - 6
components/esp_hw_support/port/esp32s3/spiram_psram.c

@@ -39,7 +39,7 @@
 
 #if CONFIG_SPIRAM_MODE_QUAD
 #include "soc/rtc.h"
-#include "spi_flash_private.h"
+#include "esp_private/spi_flash_os.h"
 
 static const char* TAG = "psram";
 
@@ -118,7 +118,7 @@ typedef enum {
 typedef esp_rom_spi_cmd_t psram_cmd_t;
 
 static uint32_t s_psram_id = 0;
-static void IRAM_ATTR config_psram_spi_phases(void);
+static void config_psram_spi_phases(void);
 extern void esp_rom_spi_set_op_mode(int spi_num, esp_rom_spiflash_read_mode_t mode);
 
 static uint8_t s_psram_cs_io = (uint8_t)-1;
@@ -278,7 +278,7 @@ static void psram_read_id(int spi_num, uint32_t* dev_id)
 }
 
 //enter QPI mode
-static void IRAM_ATTR psram_enable_qio_mode(int spi_num)
+static void psram_enable_qio_mode(int spi_num)
 {
     psram_exec_cmd(spi_num, PSRAM_CMD_SPI,
     PSRAM_ENTER_QMODE, 8,             /* command and command bit len*/
@@ -298,7 +298,7 @@ static void psram_set_cs_timing(void)
     SET_PERI_REG_MASK(SPI_MEM_SPI_SMEM_AC_REG(0), SPI_MEM_SPI_SMEM_CS_HOLD_M | SPI_MEM_SPI_SMEM_CS_SETUP_M);
 }
 
-static void IRAM_ATTR psram_gpio_config(void)
+static void psram_gpio_config(void)
 {
     //CS1
     uint8_t cs1_io = PSRAM_CS_IO;
@@ -341,7 +341,7 @@ psram_size_t psram_get_size(void)
  * Psram mode init will overwrite original flash speed mode, so that it is possible to change psram and flash speed after OTA.
  * Flash read mode(QIO/QOUT/DIO/DOUT) will not be changed in app bin. It is decided by bootloader, OTA can not change this mode.
  */
-esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode)   //psram init
+esp_err_t psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode)   //psram init
 {
     assert(mode < PSRAM_CACHE_MAX && "we don't support any other mode for now.");
 
@@ -383,7 +383,7 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad
 }
 
 //Configure PSRAM SPI0 phase related registers here according to the PSRAM chip requirement
-static void IRAM_ATTR config_psram_spi_phases(void)
+static void config_psram_spi_phases(void)
 {
     //Config CMD phase
     CLEAR_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_USR_SRAM_DIO_M);       //disable dio mode for cache command

+ 18 - 19
components/esp_system/port/cpu_start.c

@@ -1,16 +1,8 @@
-// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
 
 #include <stdint.h>
 #include <string.h>
@@ -64,7 +56,7 @@
 #include "esp32h2/memprot.h"
 #endif
 
-#include "spi_flash_private.h"
+#include "esp_private/spi_flash_os.h"
 #include "bootloader_flash_config.h"
 #include "bootloader_flash.h"
 #include "esp_private/crosscore_int.h"
@@ -371,18 +363,25 @@ void IRAM_ATTR call_start_cpu0(void)
     Cache_Set_IDROM_MMU_Size(cache_mmu_irom_size, CACHE_DROM_MMU_MAX_END - cache_mmu_irom_size);
 #endif // CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
 
-    esp_mspi_pin_init();
-    // For Octal flash, it's hard to implement a read_id function in OPI mode for all vendors.
-    // So we have to read it here in SPI mode, before entering the OPI mode.
-    bootloader_flash_update_id();
 #if CONFIG_ESPTOOLPY_OCT_FLASH
     bool efuse_opflash_en = REG_GET_FIELD(EFUSE_RD_REPEAT_DATA3_REG, EFUSE_FLASH_TYPE);
     if (!efuse_opflash_en) {
         ESP_EARLY_LOGE(TAG, "Octal Flash option selected, but EFUSE not configured!");
         abort();
     }
-    esp_opiflash_init();
 #endif
+    esp_mspi_pin_init();
+    // For Octal flash, it's hard to implement a read_id function in OPI mode for all vendors.
+    // So we have to read it here in SPI mode, before entering the OPI mode.
+    bootloader_flash_update_id();
+    /**
+     * This function initialise the Flash chip to the user-defined settings.
+     *
+     * In bootloader, we only init Flash (and MSPI) to a preliminary state, for being flexible to
+     * different chips.
+     * In this stage, we re-configure the Flash (and MSPI) to required configuration
+     */
+    spi_flash_init_chip_state();
 #if CONFIG_IDF_TARGET_ESP32S3
     //On other chips, this feature is not provided by HW, or hasn't been tested yet.
     spi_timing_flash_tuning();

+ 11 - 21
components/esptool_py/Kconfig.projbuild

@@ -66,15 +66,6 @@ menu "Serial flasher config"
         bool "Enable Octal Flash"
         default n
 
-    choice ESPTOOLPY_FLASH_VENDOR
-        depends on ESPTOOLPY_OCT_FLASH
-        prompt "Select OPI Flash Vendor"
-        default ESPTOOLPY_FLASH_VENDOR_MXIC
-
-        config ESPTOOLPY_FLASH_VENDOR_MXIC
-            bool "MXIC OPI FLASH(MX25UM25645G)"
-    endchoice
-
     choice ESPTOOLPY_FLASHMODE
         prompt "Flash SPI mode"
         default ESPTOOLPY_FLASHMODE_DIO
@@ -100,17 +91,16 @@ menu "Serial flasher config"
             bool "OPI"
     endchoice
 
-    choice ESPTOOLPY_FLASHMODE_OCT
-        depends on ESPTOOLPY_FLASHMODE_OPI
-        prompt "Flash OPI mode"
-        default ESPTOOLPY_FLASHMODE_OPI_DTR
-
-        config ESPTOOLPY_FLASHMODE_OPI_STR
-            depends on ESPTOOLPY_FLASH_VENDOR_MXIC
-            bool "OPI_STR"
-        config ESPTOOLPY_FLASHMODE_OPI_DTR
-            depends on ESPTOOLPY_FLASH_VENDOR_MXIC
-            bool "OPI_DTR"
+    choice ESPTOOLPY_FLASH_SAMPLE_MODE
+        prompt "Flash Sampling Mode"
+        default ESPTOOLPY_FLASH_SAMPLE_MODE_DTR if ESPTOOLPY_OCT_FLASH
+        default ESPTOOLPY_FLASH_SAMPLE_MODE_STR if !ESPTOOLPY_OCT_FLASH
+
+        config ESPTOOLPY_FLASH_SAMPLE_MODE_STR
+            bool "STR Mode"
+        config ESPTOOLPY_FLASH_SAMPLE_MODE_DTR
+            depends on ESPTOOLPY_OCT_FLASH
+            bool "DTR Mode"
     endchoice
 
     # Note: we use esptool.py to flash bootloader in
@@ -136,7 +126,7 @@ menu "Serial flasher config"
             The SPI flash frequency to be used.
 
         config ESPTOOLPY_FLASHFREQ_120M
-            depends on ESPTOOLPY_FLASHMODE_OPI_STR || !ESPTOOLPY_OCT_FLASH
+            depends on ESPTOOLPY_FLASH_SAMPLE_MODE_STR
             bool "120 MHz"
         config ESPTOOLPY_FLASHFREQ_80M
             bool "80 MHz"

+ 7 - 7
components/spi_flash/esp32s3/opi_flash_cmd_format_mxic.h

@@ -4,9 +4,9 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-#if CONFIG_ESPTOOLPY_FLASH_VENDOR_MXIC
-#if CONFIG_ESPTOOLPY_FLASHMODE_OPI_STR
-#define OPI_CMD_FORMAT() {   \
+#if CONFIG_SPI_FLASH_SUPPORT_MXIC_OPI_CHIP
+#if CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR
+#define OPI_CMD_FORMAT_MXIC() {   \
     .rdid = {              \
         .mode = ESP_ROM_SPIFLASH_OPI_STR_MODE, \
         .cmd_bit_len = 16, \
@@ -93,8 +93,8 @@
     } \
 }
 
-#elif CONFIG_ESPTOOLPY_FLASHMODE_OPI_DTR
-#define OPI_CMD_FORMAT() {   \
+#elif CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_DTR
+#define OPI_CMD_FORMAT_MXIC() {   \
     .rdid = {              \
         .mode = ESP_ROM_SPIFLASH_OPI_DTR_MODE, \
         .cmd_bit_len = 16, \
@@ -180,5 +180,5 @@
         .var_dummy_en = 1, \
     } \
 }
-#endif
-#endif
+#endif  // DTR / STR
+#endif  // #if CONFIG_SPI_FLASH_SUPPORT_MXIC_OPI_CHIP

+ 36 - 0
components/spi_flash/esp32s3/opi_flash_private.h

@@ -0,0 +1,36 @@
+/*
+ * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * System level OPI Flash APIs (private)
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "sdkconfig.h"
+#include "esp_err.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Register ROM functions and init flash device registers to make use of octal flash
+ *
+ * @param chip_id Full device ID read via RDID command
+ */
+esp_err_t esp_opiflash_init(uint32_t chip_id);
+
+/**
+ * @brief Set Octal Flash chip specifically required MSPI register settings here
+ */
+void esp_opiflash_set_required_regs(void);
+
+#ifdef __cplusplus
+}
+#endif

+ 97 - 17
components/spi_flash/esp32s3/spi_flash_oct_flash_init.c

@@ -5,27 +5,33 @@
  */
 
 #include "sdkconfig.h"
+#include "esp_log.h"
 #include "esp_err.h"
 #include "esp_rom_gpio.h"
 #include "esp32s3/rom/gpio.h"
 #include "esp32s3/rom/spi_flash.h"
 #include "esp32s3/rom/opi_flash.h"
-#include "spi_flash_private.h"
+#include "esp_private/spi_flash_os.h"
+#include "opi_flash_private.h"
 #include "soc/spi_mem_reg.h"
 #include "soc/io_mux_reg.h"
-#if CONFIG_ESPTOOLPY_FLASH_VENDOR_MXIC
 #include "opi_flash_cmd_format_mxic.h"
-#endif
 
 #define SPI_FLASH_SPI_CMD_WRCR2     0x72
 #define SPI_FLASH_SPI_CMD_RDSR      0x05
 #define SPI_FLASH_SPI_CMD_RDCR      0x15
 #define SPI_FLASH_SPI_CMD_WRSRCR    0x01
 
+/**
+ * Supported Flash chip vendor id
+ */
+#define ESP_FLASH_CHIP_MXIC_OCT     0xC2
+
+const static char *TAG = "Octal Flash";
 // default value is rom_default_spiflash_legacy_flash_func
 extern const spiflash_legacy_funcs_t *rom_spiflash_legacy_funcs;
 extern int SPI_write_enable(void *spi);
-DRAM_ATTR const esp_rom_opiflash_def_t opiflash_cmd_def = OPI_CMD_FORMAT();
+static uint32_t s_vendor_id;
 
 
 static void s_register_rom_function(void)
@@ -46,7 +52,24 @@ static void s_register_rom_function(void)
     rom_spiflash_legacy_funcs = &rom_func;
 }
 
-#if CONFIG_ESPTOOLPY_FLASH_VENDOR_MXIC
+#if CONFIG_SPI_FLASH_SUPPORT_MXIC_OPI_CHIP
+/*----------------------------------------------------------------------------------------------------
+                                MXIC Specific Functions
+-----------------------------------------------------------------------------------------------------*/
+static esp_err_t s_probe_mxic_chip(uint32_t chip_id, uint8_t *out_vendor_id)
+{
+    if (chip_id >> 16 != ESP_FLASH_CHIP_MXIC_OCT) {
+        return ESP_ERR_NOT_FOUND;
+    }
+    if (((chip_id >> 8) & 0xff) != 0x80) {
+        ESP_EARLY_LOGE(TAG, "Detected MXIC Flash, but memory type is not Octal");
+        return ESP_ERR_NOT_FOUND;
+    }
+    *out_vendor_id = ESP_FLASH_CHIP_MXIC_OCT;
+
+    return ESP_OK;
+}
+
 // 0x00: SPI; 0x01: STR OPI;  0x02: DTR OPI
 static void s_set_flash_dtr_str_opi_mode(int spi_num, uint8_t val)
 {
@@ -127,7 +150,8 @@ static void s_set_pin_drive_capability(uint8_t drv)
 
 static void s_flash_init_mxic(esp_rom_spiflash_read_mode_t mode)
 {
-    esp_rom_opiflash_legacy_driver_init(&opiflash_cmd_def);
+    static const esp_rom_opiflash_def_t opiflash_cmd_def_mxic = OPI_CMD_FORMAT_MXIC();
+    esp_rom_opiflash_legacy_driver_init(&opiflash_cmd_def_mxic);
     esp_rom_spiflash_wait_idle(&g_rom_flashchip);
 
     // increase flash output driver strength
@@ -135,13 +159,13 @@ static void s_flash_init_mxic(esp_rom_spiflash_read_mode_t mode)
 
     // STR/DTR specific setting
     esp_rom_spiflash_wait_idle(&g_rom_flashchip);
-#if CONFIG_ESPTOOLPY_FLASHMODE_OPI_STR
+#if CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR
     s_set_pin_drive_capability(3);
     s_set_flash_dtr_str_opi_mode(1, 0x1);
     esp_rom_opiflash_cache_mode_config(mode, &rom_opiflash_cmd_def->cache_rd_cmd);
     esp_rom_spi_set_dtr_swap_mode(0, false, false);
     esp_rom_spi_set_dtr_swap_mode(1, false, false);
-#else //CONFIG_ESPTOOLPY_FLASHMODE_OPI_DTR
+#else //CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_DTR
     s_set_pin_drive_capability(3);
     s_set_flash_dtr_str_opi_mode(1, 0x2);
     esp_rom_opiflash_cache_mode_config(mode, &rom_opiflash_cmd_def->cache_rd_cmd);
@@ -149,26 +173,82 @@ static void s_flash_init_mxic(esp_rom_spiflash_read_mode_t mode)
     esp_rom_spi_set_dtr_swap_mode(1, true, true);
 #endif
 
-    s_register_rom_function();
     esp_rom_opiflash_wait_idle();
 }
-#endif   // #if CONFIG_FLASH_VENDOR_XXX
+#endif   // #if CONFIG_SPI_FLASH_SUPPORT_MXIC_OPI_CHIP
+
+
+/*----------------------------------------------------------------------------------------------------
+                                General Functions
+-----------------------------------------------------------------------------------------------------*/
+typedef struct opi_flash_func_t {
+    esp_err_t (*probe)(uint32_t flash_id, uint8_t *out_vendor_id);      //Function pointer for detecting Flash chip vendor
+    void (*init)(esp_rom_spiflash_read_mode_t mode);                    //Function pointer for initialising certain Flash chips
+} opi_flash_func_t;
+
+#if CONFIG_SPI_FLASH_SUPPORT_MXIC_OPI_CHIP
+static const opi_flash_func_t opi_flash_func_mxic = {
+    .probe = &s_probe_mxic_chip,
+    .init = &s_flash_init_mxic
+};
+#endif
 
-esp_err_t esp_opiflash_init(void)
+static const opi_flash_func_t *registered_chip_funcs[] = {
+#if CONFIG_SPI_FLASH_SUPPORT_MXIC_OPI_CHIP
+    &opi_flash_func_mxic,
+#endif
+    NULL,
+};
+
+esp_err_t esp_opiflash_init(uint32_t chip_id)
 {
+    esp_err_t ret = ESP_FAIL;
     esp_rom_spiflash_read_mode_t mode;
-#if CONFIG_ESPTOOLPY_FLASHMODE_OPI_STR
+#if CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR
     mode = ESP_ROM_SPIFLASH_OPI_STR_MODE;
-#elif CONFIG_ESPTOOLPY_FLASHMODE_OPI_DTR
+#elif CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_DTR
     mode = ESP_ROM_SPIFLASH_OPI_DTR_MODE;
 #else
     mode = ESP_ROM_SPIFLASH_FASTRD_MODE;
 #endif
 
-#if CONFIG_ESPTOOLPY_FLASH_VENDOR_MXIC
-    s_flash_init_mxic(mode);
+    //To check which Flash chip is used
+    const opi_flash_func_t **chip_func = &registered_chip_funcs[0];
+
+    uint8_t vendor_id = 0;
+    while (*chip_func) {
+        ret = (*chip_func)->probe(chip_id, &vendor_id);
+        if (ret == ESP_OK) {
+            // Detect this is the supported chip type
+            (*chip_func)->init(mode);
+            s_vendor_id = vendor_id;
+            s_register_rom_function();
+            break;
+        }
+        chip_func++;
+    }
+
+    if (ret != ESP_OK) {
+        ESP_EARLY_LOGE(TAG, "No detected Flash chip, please check the menuconfig to see if the chip is supported");
+        abort();
+    }
+
+    return ESP_OK;
+}
+
+/**
+ * Add Flash chip specifically required MSPI register settings here
+ */
+void esp_opiflash_set_required_regs(void)
+{
+    bool is_swap = false;
+#if CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_DTR
+    if (s_vendor_id == ESP_FLASH_CHIP_MXIC_OCT) {
+        is_swap = true;
+    }
 #else
-    abort();
+    //STR mode does not need to enable ddr_swap registers
 #endif
-    return ESP_OK;
+    esp_rom_spi_set_dtr_swap_mode(0, is_swap, is_swap);
+    esp_rom_spi_set_dtr_swap_mode(1, is_swap, is_swap);
 }

+ 2 - 2
components/spi_flash/esp32s3/spi_timing_config.h

@@ -44,8 +44,8 @@ extern "C" {
  * 2. DDR mode requires the core clock divider (core_clk / div = module_clk) to be power of 2.
  */
 //--------------------------------------FLASH Sampling Mode --------------------------------------//
-#define SPI_TIMING_FLASH_DTR_MODE                   (CONFIG_ESPTOOLPY_FLASHMODE_OPI_DTR || CONFIG_ESPTOOLPY_FLASHMODE_OIO_DTR)
-#define SPI_TIMING_FLASH_STR_MODE                   (CONFIG_ESPTOOLPY_FLASHMODE_OPI_STR || !CONFIG_ESPTOOLPY_OCT_FLASH)
+#define SPI_TIMING_FLASH_DTR_MODE                   CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_DTR
+#define SPI_TIMING_FLASH_STR_MODE                   CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR
 //--------------------------------------FLASH Module Clock --------------------------------------//
 #if CONFIG_ESPTOOLPY_FLASHFREQ_20M
 #define SPI_TIMING_FLASH_MODULE_CLOCK               20

+ 8 - 16
components/spi_flash/esp_flash_spi_init.c

@@ -1,16 +1,8 @@
-// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
 
 #include "sdkconfig.h"
 #include "esp_flash.h"
@@ -27,7 +19,7 @@
 #include "hal/gpio_hal.h"
 #include "esp_flash_internal.h"
 #include "esp_rom_gpio.h"
-#include "spi_flash_private.h"
+#include "esp_private/spi_flash_os.h"
 #if CONFIG_IDF_TARGET_ESP32
 #include "esp32/rom/spi_flash.h"
 #elif CONFIG_IDF_TARGET_ESP32S2
@@ -71,9 +63,9 @@ esp_flash_t *esp_flash_default_chip = NULL;
 #define DEFAULT_FLASH_MODE  SPI_FLASH_DIO
 #elif defined(CONFIG_ESPTOOLPY_FLASHMODE_DOUT)
 #define DEFAULT_FLASH_MODE  SPI_FLASH_DOUT
-#elif defined(CONFIG_ESPTOOLPY_FLASHMODE_OPI_STR)
+#elif defined(CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR)
 #define DEFAULT_FLASH_MODE SPI_FLASH_OPI_STR
-#elif defined(CONFIG_ESPTOOLPY_FLASHMODE_OPI_DTR)
+#elif defined(CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_DTR)
 #define DEFAULT_FLASH_MODE SPI_FLASH_OPI_DTR
 #else
 #define DEFAULT_FLASH_MODE SPI_FLASH_FASTRD

+ 27 - 13
components/spi_flash/flash_ops.c

@@ -1,16 +1,8 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
 
 #include <stdlib.h>
 #include <assert.h>
@@ -28,6 +20,7 @@
 #include "esp_spi_flash.h"
 #include "esp_log.h"
 #include "esp_private/system_internal.h"
+#include "esp_private/spi_flash_os.h"
 #if CONFIG_IDF_TARGET_ESP32
 #include "esp32/rom/cache.h"
 #include "esp32/rom/spi_flash.h"
@@ -43,6 +36,7 @@
 #include "esp32s3/rom/cache.h"
 #include "esp32s3/clk.h"
 #include "esp32s3/clk.h"
+#include "esp32s3/opi_flash_private.h"
 #elif CONFIG_IDF_TARGET_ESP32C3
 #include "esp32c3/rom/cache.h"
 #include "esp32c3/rom/spi_flash.h"
@@ -175,6 +169,16 @@ void IRAM_ATTR esp_mspi_pin_init(void)
 #endif
 }
 
+esp_err_t IRAM_ATTR spi_flash_init_chip_state(void)
+{
+#if CONFIG_ESPTOOLPY_OCT_FLASH
+    return esp_opiflash_init(rom_spiflash_legacy_data->chip.device_id);
+#else
+    //currently we don't need other setup for initialising Quad Flash
+    return ESP_OK;
+#endif
+}
+
 void spi_flash_init(void)
 {
     spi_flash_init_lock();
@@ -906,3 +910,13 @@ void IRAM_ATTR spi_flash_set_rom_required_regs(void)
      */
 #endif
 }
+
+void IRAM_ATTR spi_flash_set_vendor_required_regs(void)
+{
+#if CONFIG_ESPTOOLPY_OCT_FLASH
+    //Flash chip requires MSPI specifically, call this function to set them
+    esp_opiflash_set_required_regs();
+#else
+    //currently we don't need to set other MSPI registers for Quad Flash
+#endif
+}

+ 15 - 3
components/spi_flash/include/spi_flash_private.h → components/spi_flash/include/esp_private/spi_flash_os.h

@@ -4,7 +4,9 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-
+/**
+ * System level MSPI APIs (private)
+ */
 /**
  * Currently the MSPI timing tuning related APIs are designed to be private.
  * Because:
@@ -17,6 +19,10 @@
  */
 #pragma once
 
+#include <stdint.h>
+#include <stdbool.h>
+#include "sdkconfig.h"
+#include "esp_err.h"
 #if CONFIG_IDF_TARGET_ESP32
 #include "esp32/rom/spi_flash.h"
 #elif CONFIG_IDF_TARGET_ESP32S2
@@ -34,9 +40,9 @@ extern "C" {
 #endif
 
 /**
- * @brief Register ROM functions and init flash device registers to make use of octal flash
+ * @brief To setup Flash chip
  */
-esp_err_t esp_opiflash_init(void);
+esp_err_t spi_flash_init_chip_state(void);
 
 /**
  * @brief Make MSPI work under 20Mhz
@@ -88,6 +94,12 @@ void spi_timing_get_flash_timing_param(spi_flash_hal_timing_config_t *out_timing
  */
 bool spi_timine_config_flash_is_tuned(void);
 
+/**
+ * @brief Set Flash chip specifically required MSPI register settings here
+ */
+void spi_flash_set_vendor_required_regs(void);
+
+
 #ifdef __cplusplus
 }
 #endif

+ 42 - 40
components/spi_flash/sim/Makefile.files

@@ -1,43 +1,45 @@
 SOURCE_FILES := \
-	SpiFlash.cpp \
-	flash_mock.cpp \
-	flash_mock_util.c \
-	$(addprefix ../, \
-	partition.c \
-	flash_ops.c \
-	esp32/flash_ops_esp32.c \
-	) \
+    SpiFlash.cpp \
+    flash_mock.cpp \
+    flash_mock_util.c \
+    $(addprefix ../, \
+    partition.c \
+    flash_ops.c \
+    esp32/flash_ops_esp32.c \
+    ) \
 
 INCLUDE_DIRS := \
-	. \
-	../ \
-	../include \
-	../private_include \
-	$(addprefix stubs/, \
-	app_update/include \
-	driver/include \
-	esp_timer/include \
-	freertos/include \
-	log/include \
-	newlib/include \
-	sdmmc/include \
-	vfs/include \
-	) \
-	$(addprefix ../../../components/, \
-	esp_rom/include \
-	esp_common/include \
-	esp_hw_support/include \
-	esp_hw_support/include/soc \
-	esp_system/include \
-	xtensa/include \
-	xtensa/esp32/include \
-	soc/esp32/include \
-       	heap/include \
-	soc/include \
-	esp32/include \
-	esp_timer/include \
-	bootloader_support/include \
-	app_update/include \
-	hal/include \
-	spi_flash/include \
-	)
+    . \
+    ../ \
+    ../include \
+    ../private_include \
+    $(addprefix stubs/, \
+    app_update/include \
+    driver/include \
+    esp_timer/include \
+    freertos/include \
+    log/include \
+    newlib/include \
+    sdmmc/include \
+    vfs/include \
+    ) \
+    $(addprefix ../../../components/, \
+    esp_rom/include \
+    esp_common/include \
+    esp_hw_support/include \
+    esp_hw_support/include/soc \
+    esp_system/include \
+    xtensa/include \
+    xtensa/esp32/include \
+    soc/esp32/include \
+        heap/include \
+    soc/include \
+    esp32/include \
+    esp_timer/include \
+    bootloader_support/include \
+    app_update/include \
+    hal/include \
+    hal/esp32/include \
+    hal/platform_port/include \
+    spi_flash/include \
+    )

+ 3 - 3
components/spi_flash/spi_flash_timing_tuning.c

@@ -13,7 +13,7 @@
 #include "esp_log.h"
 #include "soc/spi_mem_reg.h"
 #include "soc/io_mux_reg.h"
-#include "spi_flash_private.h"
+#include "esp_private/spi_flash_os.h"
 #include "soc/soc.h"
 #if CONFIG_IDF_TARGET_ESP32S3
 #include "esp32s3/spi_timing_config.h"
@@ -235,14 +235,14 @@ static void select_best_tuning_config(spi_timing_config_t *config, uint32_t cons
     if (is_flash) {
 #if SPI_TIMING_FLASH_DTR_MODE
         best_point = select_best_tuning_config_dtr(config, consecutive_length, end);
-#else   //#if SPI_TIMING_FLASH_STR_MODE
+#elif SPI_TIMING_FLASH_STR_MODE
         best_point = select_best_tuning_config_str(config, consecutive_length, end);
 #endif
         s_flash_best_timing_tuning_config = config->tuning_config_table[best_point];
     } else {
 #if SPI_TIMING_PSRAM_DTR_MODE
         best_point = select_best_tuning_config_dtr(config, consecutive_length, end);
-#else   //#if SPI_TIMING_PSRAM_STR_MODE
+#elif SPI_TIMING_PSRAM_STR_MODE
         best_point = select_best_tuning_config_str(config, consecutive_length, end);
 #endif
         s_psram_best_timing_tuning_config = config->tuning_config_table[best_point];

+ 7 - 15
components/spi_flash/test/test_read_write.c

@@ -1,16 +1,8 @@
-// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * SPDX-FileCopyrightText: 2010-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
 
 // Test for spi_flash_{read,write}.
 
@@ -197,9 +189,9 @@ static void IRAM_ATTR fix_rom_func(void)
     read_mode = ESP_ROM_SPIFLASH_DIO_MODE;
 #elif CONFIG_ESPTOOLPY_FLASHMODE_DOUT
     read_mode = ESP_ROM_SPIFLASH_DOUT_MODE;
-#elif CONFIG_ESPTOOLPY_FLASHMODE_OPI_STR
+#elif CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR
     read_mode = ESP_ROM_SPIFLASH_OPI_STR_MODE;
-#elif CONFIG_ESPTOOLPY_FLASHMODE_OPI_DTR
+#elif CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_DTR
     read_mode = ESP_ROM_SPIFLASH_OPI_DTR_MODE;
 #endif
 

+ 0 - 4
tools/ci/check_copyright_ignore.txt

@@ -1142,7 +1142,6 @@ components/esp_system/port/arch/xtensa/expression_with_stack.c
 components/esp_system/port/arch/xtensa/panic_arch.c
 components/esp_system/port/arch/xtensa/trax.c
 components/esp_system/port/brownout.c
-components/esp_system/port/cpu_start.c
 components/esp_system/port/include/esp_clk_internal.h
 components/esp_system/port/include/port/panic_funcs.h
 components/esp_system/port/include/riscv/eh_frame_parser_impl.h
@@ -2774,9 +2773,7 @@ components/spi_flash/esp32s2/flash_ops_esp32s2.c
 components/spi_flash/esp32s2/spi_flash_rom_patch.c
 components/spi_flash/esp32s3/flash_ops_esp32s3.c
 components/spi_flash/esp_flash_api.c
-components/spi_flash/esp_flash_spi_init.c
 components/spi_flash/flash_mmap.c
-components/spi_flash/flash_ops.c
 components/spi_flash/include/esp_flash.h
 components/spi_flash/include/esp_flash_internal.h
 components/spi_flash/include/esp_flash_spi_init.h
@@ -2817,7 +2814,6 @@ components/spi_flash/test/test_mmap.c
 components/spi_flash/test/test_out_of_bounds_write.c
 components/spi_flash/test/test_partition_ext.c
 components/spi_flash/test/test_partitions.c
-components/spi_flash/test/test_read_write.c
 components/spi_flash/test/test_spi_flash.c
 components/spiffs/esp_spiffs.c
 components/spiffs/include/esp_spiffs.h

+ 0 - 1
tools/ci/check_public_headers_exceptions.txt

@@ -148,4 +148,3 @@ components/ulp/include/esp32s2/ulp_riscv.h
 components/lwip/include/apps/sntp/sntp.h
 components/mbedtls/esp_crt_bundle/include/esp_crt_bundle.h
 components/wifi_provisioning/include/wifi_provisioning/scheme_softap.h
-components/spi_flash/include/spi_flash_private.h

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

@@ -0,0 +1,6 @@
+# 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.5)
+
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+project(test_flash_psram)

+ 7 - 0
tools/test_apps/system/flash_psram/README.md

@@ -0,0 +1,7 @@
+| Supported Targets | ESP32-S3 |
+| ----------------- | -------- |
+
+This project tests if Flash and PSRAM can work under different configurations.
+To add new configuration, create one more sdkconfig.ci.NAME file in this directory.
+
+If you need to test for anything other than flash and psram, create another test project.

+ 54 - 0
tools/test_apps/system/flash_psram/app_test.py

@@ -0,0 +1,54 @@
+# SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
+# SPDX-License-Identifier: Apache-2.0
+
+
+import glob
+import os
+from typing import Any
+
+import ttfw_idf
+from tiny_test_fw import Utility
+
+
+def test_loop(env, config_names):  # type: (Any, Any) -> None
+
+    for name in config_names:
+        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')
+        env.close_dut(dut.name)
+        Utility.console_log('done')
+
+
+# For F8R8 board (Octal Flash and Octal PSRAM)
+@ttfw_idf.idf_custom_test(env_tag='MSPI_F8R8', target=['esp32s3'])
+def test_flash8_psram8(env, _):  # type: (Any, Any) -> None
+
+    config_files = glob.glob(os.path.join(os.path.dirname(__file__), 'sdkconfig.ci.f8r8*'))
+    config_names = [os.path.basename(s).replace('sdkconfig.ci.', '') for s in config_files]
+    test_loop(env, config_names)
+
+
+# For F4R8 board (Quad Flash and Octal PSRAM)
+@ttfw_idf.idf_custom_test(env_tag='MSPI_F4R8', target=['esp32s3'])
+def test_flash4_psram8(env, _):  # type: (Any, Any) -> None
+
+    config_files = glob.glob(os.path.join(os.path.dirname(__file__), 'sdkconfig.ci.f4r8*'))
+    config_names = [os.path.basename(s).replace('sdkconfig.ci.', '') for s in config_files]
+    test_loop(env, config_names)
+
+
+# For F4R4 board (Quad Flash and Quad PSRAM)
+@ttfw_idf.idf_custom_test(env_tag='MSPI_F4R4', target=['esp32s3'])
+def test_flash4_psram4(env, _):  # type: (Any, Any) -> None
+
+    config_files = glob.glob(os.path.join(os.path.dirname(__file__), 'sdkconfig.ci.f4r4*'))
+    config_names = [os.path.basename(s).replace('sdkconfig.ci.', '') for s in config_files]
+    test_loop(env, config_names)
+
+
+if __name__ == '__main__':
+    test_flash8_psram8()
+    test_flash4_psram8()
+    test_flash4_psram4()

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

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

+ 160 - 0
tools/test_apps/system/flash_psram/main/test_flash_psram.c

@@ -0,0 +1,160 @@
+/*
+ * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "sdkconfig.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "esp_system.h"
+#include "esp_check.h"
+#include "esp_attr.h"
+#if CONFIG_IDF_TARGET_ESP32S3
+#include "esp32s3/rom/spi_flash.h"
+#include "esp32s3/rom/opi_flash.h"
+#endif
+
+const static char *TAG = "SPI0";
+
+//-----------------------------------------SPI0 PSRAM TEST-----------------------------------------------//
+#if CONFIG_SPIRAM
+
+#if CONFIG_SPIRAM_MODE_OCT
+#define SPI0_PSRAM_TEST_LEN    (512 * 1024)
+#define LENGTH_PER_TIME        1024
+#else
+#define SPI0_PSRAM_TEST_LEN    (128 * 1024)
+#define LENGTH_PER_TIME        1024
+#endif
+
+static esp_err_t spi0_psram_test(void)
+{
+    printf("----------SPI0 PSRAM 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);
+    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);
+
+        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;
+        }
+    }
+
+    free(psram_rd_buf);
+    free(psram_wr_buf);
+    printf(DRAM_STR("----------SPI0 PSRAM Test Success----------\n\n"));
+    return ESP_OK;
+}
+#endif
+
+
+//-----------------------------------------SPI1 FLASH TEST-----------------------------------------------//
+#define SPI1_FLASH_TEST_LEN     512
+#define SECTOR_LEN              4096
+#define SPI1_FLASH_TEST_NUM     (SECTOR_LEN / SPI1_FLASH_TEST_LEN)
+#define SPI1_FLASH_TEST_ADDR    0x200000
+
+extern void spi_flash_disable_interrupts_caches_and_other_cpu(void);
+extern void spi_flash_enable_interrupts_caches_and_other_cpu(void);
+static DRAM_ATTR uint8_t rd_buf[SPI1_FLASH_TEST_LEN];
+static DRAM_ATTR uint8_t wr_buf[SPI1_FLASH_TEST_LEN];
+
+
+static IRAM_ATTR esp_err_t spi1_flash_test(void)
+{
+    printf(DRAM_STR("----------SPI1 Flash Test----------\n"));
+
+    //We need to use SPI1
+    spi_flash_disable_interrupts_caches_and_other_cpu();
+    uint32_t sector_num = SPI1_FLASH_TEST_ADDR / SECTOR_LEN;
+    esp_rom_spiflash_erase_sector(sector_num);
+    spi_flash_enable_interrupts_caches_and_other_cpu();
+
+    for (int i = 0; i < SPI1_FLASH_TEST_NUM; i++) {
+        for (int j = i + 10; j < SPI1_FLASH_TEST_LEN; j++) {
+            wr_buf[j] = j;
+        }
+
+        spi_flash_disable_interrupts_caches_and_other_cpu();
+        uint32_t test_flash_addr = SPI1_FLASH_TEST_ADDR + i * SPI1_FLASH_TEST_LEN;
+        esp_rom_spiflash_write(test_flash_addr, (uint32_t*)wr_buf, SPI1_FLASH_TEST_LEN);
+        esp_rom_spiflash_read(test_flash_addr, (uint32_t*)rd_buf, SPI1_FLASH_TEST_LEN);
+        spi_flash_enable_interrupts_caches_and_other_cpu();
+
+        if (memcmp(wr_buf, rd_buf, SPI1_FLASH_TEST_LEN) != 0) {
+            printf(DRAM_STR("error happened between 0x%x and 0x%x!!!!\n"), test_flash_addr, test_flash_addr + SPI1_FLASH_TEST_LEN);
+            for (int i = 0; i < SPI1_FLASH_TEST_LEN; i++) {
+                if (wr_buf[i] != rd_buf[i]) {
+                    printf(DRAM_STR("err: wr[%d]: 0x%02x -- rd[%d]: 0x%02x\n"), i, wr_buf[i], i, rd_buf[i]);
+                }
+            }
+            return ESP_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, \
+                                0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F}
+
+uint8_t flash_rd_buf[SPI0_FLASH_TEST_LEN] __attribute__((section (".flash.rodata"))) = SPI0_FLASH_TEST_BUF;
+extern int _flash_rodata_start;
+extern int _rodata_reserved_end;
+
+
+static IRAM_ATTR esp_err_t spi0_flash_test(void)
+{
+    printf("----------SPI0 Flash Test----------\n");
+    //Check if the flash_rd_buf is in .rodata
+    ESP_RETURN_ON_ERROR(((intptr_t)flash_rd_buf >= (intptr_t)_flash_rodata_start) && ((intptr_t)flash_rd_buf < (intptr_t)_rodata_reserved_end), TAG, "psram_rd_buf not in rodata");
+
+    uint8_t cmp_buf[SPI0_FLASH_TEST_LEN] = SPI0_FLASH_TEST_BUF;
+
+    for (int i = 0; i < SPI0_FLASH_TEST_LEN; i++) {
+        if (flash_rd_buf[i] != cmp_buf[i]) {
+            return ESP_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");
+}

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

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

+ 5 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f4r4_120sdr

@@ -0,0 +1,5 @@
+# Legacy, F4R4, Flash 120M SDR, PSRAM disable
+
+CONFIG_SPI_FLASH_USE_LEGACY_IMPL=y
+CONFIG_ESPTOOLPY_FLASHFREQ_120M=y
+CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y

+ 7 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f4r4_120sdr_120sdr

@@ -0,0 +1,7 @@
+# Legacy, F4R4, Flash 120M SDR, PSRAM 120M SDR
+
+CONFIG_SPI_FLASH_USE_LEGACY_IMPL=y
+CONFIG_ESPTOOLPY_FLASHFREQ_120M=y
+CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
+CONFIG_ESP32S3_SPIRAM_SUPPORT=y
+CONFIG_SPIRAM_SPEED_120M=y

+ 7 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f4r4_120sdr_40sdr

@@ -0,0 +1,7 @@
+# Legacy, F4R4, Flash 120M SDR, PSRAM 40M SDR
+
+CONFIG_SPI_FLASH_USE_LEGACY_IMPL=y
+CONFIG_ESPTOOLPY_FLASHFREQ_120M=y
+CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
+CONFIG_ESP32S3_SPIRAM_SUPPORT=y
+CONFIG_SPIRAM_SPEED_40M=y

+ 7 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f4r4_40sdr_120sdr

@@ -0,0 +1,7 @@
+# Legacy, F4R4, Flash 40M SDR, PSRAM 120M SDR
+
+CONFIG_SPI_FLASH_USE_LEGACY_IMPL=y
+CONFIG_ESPTOOLPY_FLASHFREQ_40M=y
+CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
+CONFIG_ESP32S3_SPIRAM_SUPPORT=y
+CONFIG_SPIRAM_SPEED_120M=y

+ 7 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f4r4_80sdr_80sdr

@@ -0,0 +1,7 @@
+# Legacy, F4R4, Flash 80M SDR, PSRAM 80M SDR
+
+CONFIG_SPI_FLASH_USE_LEGACY_IMPL=y
+CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
+CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
+CONFIG_ESP32S3_SPIRAM_SUPPORT=y
+CONFIG_SPIRAM_SPEED_80M=y

+ 5 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f4r8_120sdr

@@ -0,0 +1,5 @@
+# Legacy, F4R8, Flash 120M SDR, PSRAM disable
+
+CONFIG_SPI_FLASH_USE_LEGACY_IMPL=y
+CONFIG_ESPTOOLPY_FLASHFREQ_120M=y
+CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y

+ 8 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f4r8_80sdr_40ddr

@@ -0,0 +1,8 @@
+# Legacy, F4R8, Flash 80M SDR, PSRAM 40M DDR
+
+CONFIG_SPI_FLASH_USE_LEGACY_IMPL=y
+CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
+CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
+CONFIG_ESP32S3_SPIRAM_SUPPORT=y
+CONFIG_SPIRAM_MODE_OCT=y
+CONFIG_SPIRAM_SPEED_40M=y

+ 8 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f4r8_80sdr_80ddr

@@ -0,0 +1,8 @@
+# Legacy, F4R8, Flash 80M SDR, PSRAM 80M DDR
+
+CONFIG_SPI_FLASH_USE_LEGACY_IMPL=y
+CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
+CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
+CONFIG_ESP32S3_SPIRAM_SUPPORT=y
+CONFIG_SPIRAM_MODE_OCT=y
+CONFIG_SPIRAM_SPEED_80M=y

+ 8 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f8r8_120sdr

@@ -0,0 +1,8 @@
+# Legacy, F8R8, Flash 120M SDR, PSRAM disable
+
+CONFIG_SPI_FLASH_USE_LEGACY_IMPL=y
+CONFIG_ESPTOOLPY_OCT_FLASH=y
+CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR=y
+CONFIG_ESPTOOLPY_FLASHFREQ_120M=y
+CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
+CONFIG_ESP32S3_SPIRAM_SUPPORT=n

+ 10 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f8r8_40ddr_40ddr

@@ -0,0 +1,10 @@
+# Legacy, F8R8, Flash 40M DDR, PSRAM 40M DDR
+
+CONFIG_SPI_FLASH_USE_LEGACY_IMPL=y
+CONFIG_ESPTOOLPY_OCT_FLASH=y
+CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_DTR=y
+CONFIG_ESPTOOLPY_FLASHFREQ_40M=y
+CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
+CONFIG_ESP32S3_SPIRAM_SUPPORT=y
+CONFIG_SPIRAM_MODE_OCT=y
+CONFIG_SPIRAM_SPEED_40M=y

+ 10 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f8r8_40ddr_80ddr

@@ -0,0 +1,10 @@
+# Legacy, F8R8, Flash 40M DDR, PSRAM 80M DDR
+
+CONFIG_SPI_FLASH_USE_LEGACY_IMPL=y
+CONFIG_ESPTOOLPY_OCT_FLASH=y
+CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_DTR=y
+CONFIG_ESPTOOLPY_FLASHFREQ_40M=y
+CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
+CONFIG_ESP32S3_SPIRAM_SUPPORT=y
+CONFIG_SPIRAM_MODE_OCT=y
+CONFIG_SPIRAM_SPEED_80M=y

+ 10 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f8r8_80ddr_40ddr

@@ -0,0 +1,10 @@
+# Legacy, F8R8, Flash 80M DDR, PSRAM 40M DDR
+
+CONFIG_SPI_FLASH_USE_LEGACY_IMPL=y
+CONFIG_ESPTOOLPY_OCT_FLASH=y
+CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_DTR=y
+CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
+CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
+CONFIG_ESP32S3_SPIRAM_SUPPORT=y
+CONFIG_SPIRAM_MODE_OCT=y
+CONFIG_SPIRAM_SPEED_40M=y

+ 10 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f8r8_80ddr_80ddr

@@ -0,0 +1,10 @@
+# Legacy, F8R8, Flash 80M DDR, PSRAM 80M DDR
+
+CONFIG_SPI_FLASH_USE_LEGACY_IMPL=y
+CONFIG_ESPTOOLPY_OCT_FLASH=y
+CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_DTR=y
+CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
+CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
+CONFIG_ESP32S3_SPIRAM_SUPPORT=y
+CONFIG_SPIRAM_MODE_OCT=y
+CONFIG_SPIRAM_SPEED_80M=y

+ 10 - 0
tools/test_apps/system/flash_psram/sdkconfig.ci.f8r8_80sdr_80ddr

@@ -0,0 +1,10 @@
+# Legacy, F8R8, Flash 80M SDR, PSRAM 80M DDR
+
+CONFIG_SPI_FLASH_USE_LEGACY_IMPL=y
+CONFIG_ESPTOOLPY_OCT_FLASH=y
+CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR=y
+CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
+CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
+CONFIG_ESP32S3_SPIRAM_SUPPORT=y
+CONFIG_SPIRAM_MODE_OCT=y
+CONFIG_SPIRAM_SPEED_80M=y