Преглед изворни кода

ble_mesh_wifi_coexist example: Disable Wi-Fi RX IRAM optimisation

Otherwise IRAM usage is too high in this example.
Renz Christian Bagaporo пре 6 година
родитељ
комит
e6ad330018
34 измењених фајлова са 1383 додато и 270 уклоњено
  1. 0 20
      components/driver/spi_common.c
  2. 6 0
      components/esp32s2beta/cpu_start.c
  3. 7 5
      components/soc/CMakeLists.txt
  4. 19 9
      components/soc/esp32/include/hal/spi_flash_ll.h
  5. 1 0
      components/soc/esp32/include/soc/spi_caps.h
  6. 319 0
      components/soc/esp32s2beta/include/hal/gpspi_flash_ll.h
  7. 85 0
      components/soc/esp32s2beta/include/hal/spi_flash_ll.h
  8. 354 0
      components/soc/esp32s2beta/include/hal/spimem_flash_ll.h
  9. 1 1
      components/soc/esp32s2beta/include/soc/soc.h
  10. 5 1
      components/soc/esp32s2beta/include/soc/spi_caps.h
  11. 2 23
      components/soc/include/hal/spi_flash_hal.h
  12. 7 5
      components/soc/include/hal/spi_flash_types.h
  13. 1 0
      components/soc/include/soc/spi_periph.h
  14. 1 0
      components/soc/linker.lf
  15. 39 3
      components/soc/src/hal/spi_flash_hal.c
  16. 102 0
      components/soc/src/hal/spi_flash_hal_common.inc
  17. 39 0
      components/soc/src/hal/spi_flash_hal_gpspi.c
  18. 11 100
      components/soc/src/hal/spi_flash_hal_iram.c
  19. 5 7
      components/spi_flash/CMakeLists.txt
  20. 0 9
      components/spi_flash/Kconfig
  21. 4 4
      components/spi_flash/esp32s2beta/flash_ops_esp32s2beta.c
  22. 3 5
      components/spi_flash/esp_flash_spi_init.c
  23. 41 0
      components/spi_flash/include/memspi_host_driver.h
  24. 119 13
      components/spi_flash/memspi_host_driver.c
  25. 3 4
      components/spi_flash/private_include/spi_flash_defs.h
  26. 12 7
      components/spi_flash/spi_flash_chip_generic.c
  27. 23 8
      components/spi_flash/spi_flash_os_func_app.c
  28. 30 2
      components/spi_flash/spi_flash_os_func_noos.c
  29. 4 10
      components/spi_flash/test/CMakeLists.txt
  30. 132 32
      components/spi_flash/test/test_esp_flash.c
  31. 1 1
      components/spi_flash/test/test_partition_ext.c
  32. 2 0
      examples/bluetooth/esp_ble_mesh/ble_mesh_wifi_coexist/sdkconfig.defaults
  33. 1 1
      tools/ci/config/target-test.yml
  34. 4 0
      tools/unit-test-app/configs/spi_flash_legacy_s2

+ 0 - 20
components/driver/spi_common.c

@@ -275,43 +275,23 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf
         ESP_LOGD(SPI_TAG, "SPI%d use iomux pins.", host+1);
         ESP_LOGD(SPI_TAG, "SPI%d use iomux pins.", host+1);
         if (bus_config->mosi_io_num >= 0) {
         if (bus_config->mosi_io_num >= 0) {
             gpio_iomux_in(bus_config->mosi_io_num, spi_periph_signal[host].spid_in);
             gpio_iomux_in(bus_config->mosi_io_num, spi_periph_signal[host].spid_in);
-#if CONFIG_IDF_TARGET_ESP32
-            gpio_iomux_out(bus_config->mosi_io_num, spi_periph_signal[host].func, false);
-#elif CONFIG_IDF_TARGET_ESP32S2BETA
             gpio_iomux_out(bus_config->mosi_io_num, spi_periph_signal[host].func, false);
             gpio_iomux_out(bus_config->mosi_io_num, spi_periph_signal[host].func, false);
-#endif
         }
         }
         if (bus_config->miso_io_num >= 0) {
         if (bus_config->miso_io_num >= 0) {
             gpio_iomux_in(bus_config->miso_io_num, spi_periph_signal[host].spiq_in);
             gpio_iomux_in(bus_config->miso_io_num, spi_periph_signal[host].spiq_in);
-#if CONFIG_IDF_TARGET_ESP32
             gpio_iomux_out(bus_config->miso_io_num, spi_periph_signal[host].func, false);
             gpio_iomux_out(bus_config->miso_io_num, spi_periph_signal[host].func, false);
-#elif CONFIG_IDF_TARGET_ESP32S2BETA
-            gpio_iomux_out(bus_config->miso_io_num, spi_periph_signal[host].func, false);
-#endif
         }
         }
         if (bus_config->quadwp_io_num >= 0) {
         if (bus_config->quadwp_io_num >= 0) {
             gpio_iomux_in(bus_config->quadwp_io_num, spi_periph_signal[host].spiwp_in);
             gpio_iomux_in(bus_config->quadwp_io_num, spi_periph_signal[host].spiwp_in);
-#if CONFIG_IDF_TARGET_ESP32
-            gpio_iomux_out(bus_config->quadwp_io_num, spi_periph_signal[host].func, false);
-#elif CONFIG_IDF_TARGET_ESP32S2BETA
             gpio_iomux_out(bus_config->quadwp_io_num, spi_periph_signal[host].func, false);
             gpio_iomux_out(bus_config->quadwp_io_num, spi_periph_signal[host].func, false);
-#endif
         }
         }
         if (bus_config->quadhd_io_num >= 0) {
         if (bus_config->quadhd_io_num >= 0) {
             gpio_iomux_in(bus_config->quadhd_io_num, spi_periph_signal[host].spihd_in);
             gpio_iomux_in(bus_config->quadhd_io_num, spi_periph_signal[host].spihd_in);
-#if CONFIG_IDF_TARGET_ESP32
-            gpio_iomux_out(bus_config->quadhd_io_num, spi_periph_signal[host].func, false);
-#elif CONFIG_IDF_TARGET_ESP32S2BETA
             gpio_iomux_out(bus_config->quadhd_io_num, spi_periph_signal[host].func, false);
             gpio_iomux_out(bus_config->quadhd_io_num, spi_periph_signal[host].func, false);
-#endif
         }
         }
         if (bus_config->sclk_io_num >= 0) {
         if (bus_config->sclk_io_num >= 0) {
             gpio_iomux_in(bus_config->sclk_io_num, spi_periph_signal[host].spiclk_in);
             gpio_iomux_in(bus_config->sclk_io_num, spi_periph_signal[host].spiclk_in);
-#if CONFIG_IDF_TARGET_ESP32
             gpio_iomux_out(bus_config->sclk_io_num, spi_periph_signal[host].func, false);
             gpio_iomux_out(bus_config->sclk_io_num, spi_periph_signal[host].func, false);
-#elif CONFIG_IDF_TARGET_ESP32S2BETA
-            gpio_iomux_out(bus_config->sclk_io_num, spi_periph_signal[host].func, false);
-#endif
         }
         }
         temp_flag |= SPICOMMON_BUSFLAG_IOMUX_PINS;
         temp_flag |= SPICOMMON_BUSFLAG_IOMUX_PINS;
     } else {
     } else {

+ 6 - 0
components/esp32s2beta/cpu_start.c

@@ -46,6 +46,7 @@
 #include "esp_heap_caps_init.h"
 #include "esp_heap_caps_init.h"
 #include "esp_system.h"
 #include "esp_system.h"
 #include "esp_spi_flash.h"
 #include "esp_spi_flash.h"
+#include "esp_flash_internal.h"
 #include "nvs_flash.h"
 #include "nvs_flash.h"
 #include "esp_event.h"
 #include "esp_event.h"
 #include "esp_spi_flash.h"
 #include "esp_spi_flash.h"
@@ -318,6 +319,11 @@ void start_cpu0_default(void)
     spi_flash_init();
     spi_flash_init();
     /* init default OS-aware flash access critical section */
     /* init default OS-aware flash access critical section */
     spi_flash_guard_set(&g_flash_guard_default_ops);
     spi_flash_guard_set(&g_flash_guard_default_ops);
+
+    esp_flash_app_init();
+    esp_err_t flash_ret = esp_flash_init_default_chip();
+    assert(flash_ret == ESP_OK);
+
 #ifdef CONFIG_PM_ENABLE
 #ifdef CONFIG_PM_ENABLE
     esp_pm_impl_init();
     esp_pm_impl_init();
 #ifdef CONFIG_PM_DFS_INIT_AUTO
 #ifdef CONFIG_PM_DFS_INIT_AUTO

+ 7 - 5
components/soc/CMakeLists.txt

@@ -33,14 +33,16 @@ list(APPEND srcs
     "src/hal/gpio_hal.c"
     "src/hal/gpio_hal.c"
     "src/hal/uart_hal.c"
     "src/hal/uart_hal.c"
     "src/hal/uart_hal_iram.c"
     "src/hal/uart_hal_iram.c"
+    "src/hal/spi_flash_hal.c"
+    "src/hal/spi_flash_hal_iram.c"
     )
     )
 
 
-# TODO: SPI Flash HAL for ESP32S2Beta also
 if(IDF_TARGET STREQUAL "esp32")
 if(IDF_TARGET STREQUAL "esp32")
-    list(APPEND srcs "src/hal/spi_flash_hal.c"
-                     "src/hal/spi_flash_hal_iram.c"
-                     "src/hal/mcpwm_hal.c"
-                     )
+    list(APPEND srcs "src/hal/mcpwm_hal.c")
+endif()
+
+if(IDF_TARGET STREQUAL "esp32s2beta")
+    list(APPEND srcs "src/hal/spi_flash_hal_gpspi.c")
 endif()
 endif()
 
 
 idf_component_register(SRCS "${srcs}"
 idf_component_register(SRCS "${srcs}"

+ 19 - 9
components/soc/esp32/include/hal/spi_flash_ll.h

@@ -154,19 +154,16 @@ static inline void spi_flash_ll_write_word(spi_dev_t *dev, uint32_t word)
 }
 }
 
 
 /**
 /**
- * Program a page of the flash chip. Call ``spi_flash_ll_set_address`` before
- * this to set the address to program.
- *
+ * Set the data to be written in the data buffer.
+ * 
  * @param dev Beginning address of the peripheral registers.
  * @param dev Beginning address of the peripheral registers.
- * @param buffer Buffer holding the data to program
- * @param length Length to program.
+ * @param buffer Buffer holding the data 
+ * @param length Length of data in bytes.
  */
  */
-static inline void spi_flash_ll_program_page(spi_dev_t *dev, const void *buffer, uint32_t length)
+static inline void spi_flash_ll_set_buffer_data(spi_dev_t *dev, const void *buffer, uint32_t length) 
 {
 {
-    dev->user.usr_dummy = 0;
-
     // Load data registers, word at a time
     // Load data registers, word at a time
-    int num_words = (length + 3) / 4;
+    int num_words = (length + 3) >> 2;
     for (int i = 0; i < num_words; i++) {
     for (int i = 0; i < num_words; i++) {
         uint32_t word = 0;
         uint32_t word = 0;
         uint32_t word_len = MIN(length, sizeof(word));
         uint32_t word_len = MIN(length, sizeof(word));
@@ -175,7 +172,20 @@ static inline void spi_flash_ll_program_page(spi_dev_t *dev, const void *buffer,
         length -= word_len;
         length -= word_len;
         buffer = (void *)((intptr_t)buffer + word_len);
         buffer = (void *)((intptr_t)buffer + word_len);
     }
     }
+}
 
 
+/**
+ * Program a page of the flash chip. Call ``spi_flash_ll_set_address`` before
+ * this to set the address to program.
+ *
+ * @param dev Beginning address of the peripheral registers.
+ * @param buffer Buffer holding the data to program
+ * @param length Length to program.
+ */
+static inline void spi_flash_ll_program_page(spi_dev_t *dev, const void *buffer, uint32_t length)
+{
+    dev->user.usr_dummy = 0;
+    spi_flash_ll_set_buffer_data(dev, buffer, length);
     dev->cmd.flash_pp = 1;
     dev->cmd.flash_pp = 1;
 }
 }
 
 

+ 1 - 0
components/soc/esp32/include/soc/spi_caps.h

@@ -60,3 +60,4 @@
 //#define SOC_SPI_SLAVE_SUPPORT_SEG_TRANS
 //#define SOC_SPI_SLAVE_SUPPORT_SEG_TRANS
 //#define SOC_SPI_SUPPORT_CD_SIG
 //#define SOC_SPI_SUPPORT_CD_SIG
 
 
+#define SOC_SPI_PERIPH_SUPPORT_MULTILINE_MODE(SPI_HOST)  true

+ 319 - 0
components/soc/esp32s2beta/include/hal/gpspi_flash_ll.h

@@ -0,0 +1,319 @@
+// 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.
+
+/*******************************************************************************
+ * NOTICE
+ * The ll is not public api, don't use in application code.
+ * See readme.md in soc/include/hal/readme.md
+ ******************************************************************************/
+
+// The Lowlevel layer for SPI Flash
+
+#pragma once
+
+#include <stdlib.h>
+#include "soc/spi_periph.h"
+#include "hal/spi_types.h"
+#include "hal/spi_flash_types.h"
+#include <sys/param.h> // For MIN/MAX
+#include <stdbool.h>
+#include <string.h>
+
+
+#define gpspi_flash_ll_get_hw(host_id)  (((host_id)==SPI2_HOST ? &GPSPI2 \
+                                                : ((host_id)==SPI3_HOST ? &GPSPI3 \
+                                                : ((host_id)==SPI4_HOST ? &GPSPI4 \
+                                                : ({abort();(spi_dev_t*)0;})))))
+
+typedef typeof(GPSPI2.clock) gpspi_flash_ll_clock_reg_t;
+
+//Supported clock register values
+#define GPSPI_FLASH_LL_CLKREG_VAL_5MHZ   ((gpspi_flash_ll_clock_reg_t){.val=0x0000F1CF})   ///< Clock set to 5 MHz
+#define GPSPI_FLASH_LL_CLKREG_VAL_10MHZ  ((gpspi_flash_ll_clock_reg_t){.val=0x000070C7})   ///< Clock set to 10 MHz
+#define GPSPI_FLASH_LL_CLKREG_VAL_20MHZ  ((gpspi_flash_ll_clock_reg_t){.val=0x00003043})   ///< Clock set to 20 MHz
+#define GPSPI_FLASH_LL_CLKREG_VAL_26MHZ  ((gpspi_flash_ll_clock_reg_t){.val=0x00002002})   ///< Clock set to 26 MHz
+#define GPSPI_FLASH_LL_CLKREG_VAL_40MHZ  ((gpspi_flash_ll_clock_reg_t){.val=0x00001001})   ///< Clock set to 40 MHz
+#define GPSPI_FLASH_LL_CLKREG_VAL_80MHZ  ((gpspi_flash_ll_clock_reg_t){.val=0x80000000})   ///< Clock set to 80 MHz
+
+/*------------------------------------------------------------------------------
+ * Control
+ *----------------------------------------------------------------------------*/
+/**
+ * Reset peripheral registers before configuration and starting control
+ *
+ * @param dev Beginning address of the peripheral registers.
+ */
+static inline void gpspi_flash_ll_reset(spi_dev_t *dev)
+{
+    dev->user.val = 0;
+    dev->ctrl.val = 0;
+}
+
+/**
+ * Check whether the previous operation is done.
+ *
+ * @param dev Beginning address of the peripheral registers.
+ *
+ * @return true if last command is done, otherwise false.
+ */
+static inline bool gpspi_flash_ll_cmd_is_done(const spi_dev_t *dev)
+{
+    return (dev->cmd.val == 0);
+}
+
+/**
+ * Get the read data from the buffer after ``gpspi_flash_ll_read`` is done.
+ *
+ * @param dev Beginning address of the peripheral registers.
+ * @param buffer Buffer to hold the output data
+ * @param read_len Length to get out of the buffer
+ */
+static inline void gpspi_flash_ll_get_buffer_data(spi_dev_t *dev, void *buffer, uint32_t read_len)
+{
+    if (((intptr_t)buffer % 4 == 0) && (read_len % 4 == 0)) {
+        // If everything is word-aligned, do a faster memcpy
+        memcpy(buffer, (void *)dev->data_buf, read_len);
+    } else {
+        // Otherwise, slow(er) path copies word by word
+        int copy_len = read_len;
+        for (int i = 0; i < (read_len + 3) / 4; i++) {
+            int word_len = MIN(sizeof(uint32_t), copy_len);
+            uint32_t word = dev->data_buf[i];
+            memcpy(buffer, &word, word_len);
+            buffer = (void *)((intptr_t)buffer + word_len);
+            copy_len -= word_len;
+        }
+    }
+}
+
+/**
+ * Write a word to the data buffer.
+ *
+ * @param dev Beginning address of the peripheral registers.
+ * @param word Data to write at address 0.
+ */
+static inline void gpspi_flash_ll_write_word(spi_dev_t *dev, uint32_t word)
+{
+    dev->data_buf[0] = word;
+}
+
+/**
+ * Set the data to be written in the data buffer.
+ *
+ * @param dev Beginning address of the peripheral registers.
+ * @param buffer Buffer holding the data
+ * @param length Length of data in bytes.
+ */
+static inline void gpspi_flash_ll_set_buffer_data(spi_dev_t *dev, const void *buffer, uint32_t length)
+{
+    // Load data registers, word at a time
+    int num_words = (length + 3) / 4;
+    for (int i = 0; i < num_words; i++) {
+        uint32_t word = 0;
+        uint32_t word_len = MIN(length, sizeof(word));
+        memcpy(&word, buffer, word_len);
+        dev->data_buf[i] = word;
+        length -= word_len;
+        buffer = (void *)((intptr_t)buffer + word_len);
+    }
+}
+
+/**
+ * Trigger a user defined transaction. All phases, including command, address, dummy, and the data phases,
+ * should be configured before this is called.
+ *
+ * @param dev Beginning address of the peripheral registers.
+ */
+static inline void gpspi_flash_ll_user_start(spi_dev_t *dev)
+{
+    dev->cmd.usr = 1;
+}
+
+/**
+ * Check whether the host is idle to perform new commands.
+ *
+ * @param dev Beginning address of the peripheral registers.
+ *
+ * @return true if the host is idle, otherwise false
+ */
+static inline bool gpspi_flash_ll_host_idle(const spi_dev_t *dev)
+{
+    return dev->fsm.st != 0;
+}
+
+/**
+ * Set phases for user-defined transaction to read
+ *
+ * @param dev Beginning address of the peripheral registers.
+ */
+static inline void gpspi_flash_ll_read_phase(spi_dev_t *dev)
+{
+    typeof (dev->user) user = {
+        .usr_command = 1,
+        .usr_mosi = 0,
+        .usr_miso = 1,
+        .usr_addr = 1,
+    };
+    dev->user = user;
+}
+/*------------------------------------------------------------------------------
+ * Configs
+ *----------------------------------------------------------------------------*/
+/**
+ * Select which pin to use for the flash
+ *
+ * @param dev Beginning address of the peripheral registers.
+ * @param pin Pin ID to use, 0-2. Set to other values to disable all the CS pins.
+ */
+static inline void gpspi_flash_ll_set_cs_pin(spi_dev_t *dev, int pin)
+{
+    dev->misc.cs0_dis = (pin == 0) ? 0 : 1;
+    dev->misc.cs1_dis = (pin == 1) ? 0 : 1;
+}
+
+/**
+ * Set the read io mode.
+ *
+ * @param dev Beginning address of the peripheral registers.
+ * @param read_mode I/O mode to use in the following transactions.
+ */
+static inline void gpspi_flash_ll_set_read_mode(spi_dev_t *dev, esp_flash_io_mode_t read_mode)
+{
+    typeof (dev->ctrl) ctrl = dev->ctrl;
+    typeof (dev->user) user = dev->user;
+
+    ctrl.val &= ~(SPI_FCMD_QUAD_M | SPI_FADDR_QUAD_M | SPI_FREAD_QUAD_M | SPI_FCMD_DUAL_M | SPI_FADDR_DUAL_M | SPI_FREAD_DUAL_M);
+    user.val &= ~(SPI_FWRITE_QUAD_M | SPI_FWRITE_DUAL_M);
+
+    ctrl.val |= SPI_FAST_RD_MODE_M;
+    switch (read_mode) {
+    case SPI_FLASH_FASTRD:
+        //the default option
+        break;
+    case SPI_FLASH_QIO:
+        ctrl.fread_quad = 1;
+        ctrl.faddr_quad = 1;
+        user.fwrite_quad = 1;
+        break;
+    case SPI_FLASH_QOUT:
+        ctrl.fread_quad = 1;
+        user.fwrite_quad = 1;
+        break;
+    case SPI_FLASH_DIO:
+        ctrl.fread_dual = 1;
+        ctrl.faddr_dual = 1;
+        user.fwrite_dual = 1;
+        break;
+    case SPI_FLASH_DOUT:
+        ctrl.fread_dual = 1;
+        user.fwrite_dual = 1;
+        break;
+    case SPI_FLASH_SLOWRD:
+        ctrl.fast_rd_mode = 0;
+        break;
+    default:
+        abort();
+    }
+
+    dev->ctrl = ctrl;
+    dev->user = user;
+}
+
+/**
+ * Set clock frequency to work at.
+ *
+ * @param dev Beginning address of the peripheral registers.
+ * @param clock_val pointer to the clock value to set
+ */
+static inline void gpspi_flash_ll_set_clock(spi_dev_t *dev, gpspi_flash_ll_clock_reg_t *clock_val)
+{
+    dev->clock = *clock_val;
+}
+
+/**
+ * Set the input length, in bits.
+ *
+ * @param dev Beginning address of the peripheral registers.
+ * @param bitlen Length of input, in bits.
+ */
+static inline void gpspi_flash_ll_set_miso_bitlen(spi_dev_t *dev, uint32_t bitlen)
+{
+    dev->user.usr_miso = bitlen > 0;
+    dev->miso_dlen.usr_miso_bit_len = bitlen ? (bitlen - 1) : 0;
+}
+
+/**
+ * Set the output length, in bits (not including command, address and dummy
+ * phases)
+ *
+ * @param dev Beginning address of the peripheral registers.
+ * @param bitlen Length of output, in bits.
+ */
+static inline void gpspi_flash_ll_set_mosi_bitlen(spi_dev_t *dev, uint32_t bitlen)
+{
+    dev->user.usr_mosi = bitlen > 0;
+    dev->mosi_dlen.usr_mosi_bit_len = bitlen ? (bitlen - 1) : 0;
+}
+
+/**
+ * Set the command with fixed length (8 bits).
+ *
+ * @param dev Beginning address of the peripheral registers.
+ * @param command Command to send
+ */
+static inline void gpspi_flash_ll_set_command8(spi_dev_t *dev, uint8_t command)
+{
+    dev->user.usr_command = 1;
+    typeof(dev->user2) user2 = {
+        .usr_command_value = command,
+        .usr_command_bitlen = (8 - 1),
+    };
+    dev->user2 = user2;
+}
+
+/**
+ * Set the address length to send, in bits. Should be called before commands that requires the address e.g. erase sector, read, write...
+ *
+ * @param dev Beginning address of the peripheral registers.
+ * @param bitlen Length of the address, in bits
+ */
+static inline void gpspi_flash_ll_set_addr_bitlen(spi_dev_t *dev, uint32_t bitlen)
+{
+    dev->user1.usr_addr_bitlen = (bitlen - 1);
+    dev->user.usr_addr = bitlen ? 1 : 0;
+}
+
+/**
+ * Set the address to send. Should be called before commands that requires the address e.g. erase sector, read, write...
+ *
+ * @param dev Beginning address of the peripheral registers.
+ * @param addr Address to send
+ */
+static inline void gpspi_flash_ll_set_address(spi_dev_t *dev, uint32_t addr)
+{
+    dev->addr = addr;
+}
+
+/**
+ * Set the length of dummy cycles.
+ *
+ * @param dev Beginning address of the peripheral registers.
+ * @param dummy_n Cycles of dummy phases
+ */
+static inline void gpspi_flash_ll_set_dummy(spi_dev_t *dev, uint32_t dummy_n)
+{
+    dev->user.usr_dummy = dummy_n ? 1 : 0;
+    dev->user1.usr_dummy_cyclelen = dummy_n - 1;
+}
+

+ 85 - 0
components/soc/esp32s2beta/include/hal/spi_flash_ll.h

@@ -0,0 +1,85 @@
+// 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.
+
+/*******************************************************************************
+ * NOTICE
+ * The ll is not public api, don't use in application code.
+ * See readme.md in soc/include/hal/readme.md
+ ******************************************************************************/
+
+// The Lowlevel layer for SPI Flash
+
+#pragma once
+
+#include "gpspi_flash_ll.h"
+#include "spimem_flash_ll.h"
+
+// For esp32s2beta, spimem is equivalent to traditional spi peripherals found
+// in esp32. Let the spi flash clock reg definitions reflect this.
+#define SPI_FLASH_LL_CLKREG_VAL_5MHZ   {.spimem=SPIMEM_FLASH_LL_CLKREG_VAL_5MHZ}
+#define SPI_FLASH_LL_CLKREG_VAL_10MHZ  {.spimem=SPIMEM_FLASH_LL_CLKREG_VAL_10MHZ}
+#define SPI_FLASH_LL_CLKREG_VAL_20MHZ  {.spimem=SPIMEM_FLASH_LL_CLKREG_VAL_20MHZ}
+#define SPI_FLASH_LL_CLKREG_VAL_26MHZ  {.spimem=SPIMEM_FLASH_LL_CLKREG_VAL_26MHZ}
+#define SPI_FLASH_LL_CLKREG_VAL_40MHZ  {.spimem=SPIMEM_FLASH_LL_CLKREG_VAL_40MHZ}
+#define SPI_FLASH_LL_CLKREG_VAL_80MHZ  {.spimem=SPIMEM_FLASH_LL_CLKREG_VAL_80MHZ}
+
+#define spi_flash_ll_get_hw(host_id)  (((host_id)<=SPI1_HOST ? (spi_dev_t*) spimem_flash_ll_get_hw(host_id) \
+                                      : gpspi_flash_ll_get_hw(host_id)))
+
+
+typedef union  {
+    gpspi_flash_ll_clock_reg_t gpspi;
+    spimem_flash_ll_clock_reg_t spimem;
+} spi_flash_ll_clock_reg_t;
+
+#ifdef GPSPI_BUILD
+#define spi_flash_ll_reset(dev)                              gpspi_flash_ll_reset((spi_dev_t*)dev)
+#define spi_flash_ll_cmd_is_done(dev)                        gpspi_flash_ll_cmd_is_done((spi_dev_t*)dev)
+#define spi_flash_ll_get_buffer_data(dev, buffer, read_len)  gpspi_flash_ll_get_buffer_data((spi_dev_t*)dev, buffer, read_len)
+#define spi_flash_ll_set_buffer_data(dev, buffer, len)       gpspi_flash_ll_set_buffer_data((spi_dev_t*)dev, buffer, len)
+#define spi_flash_ll_user_start(dev)                         gpspi_flash_ll_user_start((spi_dev_t*)dev)
+#define spi_flash_ll_host_idle(dev)                          gpspi_flash_ll_host_idle((spi_dev_t*)dev)
+#define spi_flash_ll_read_phase(dev)                         gpspi_flash_ll_read_phase((spi_dev_t*)dev)
+#define spi_flash_ll_set_cs_pin(dev, pin)                    gpspi_flash_ll_set_cs_pin((spi_dev_t*)dev, pin)
+#define spi_flash_ll_set_read_mode(dev, read_mode)           gpspi_flash_ll_set_read_mode((spi_dev_t*)dev, read_mode)
+#define spi_flash_ll_set_clock(dev, clk)                     gpspi_flash_ll_set_clock((spi_dev_t*)dev, (gpspi_flash_ll_clock_reg_t*)clk)
+#define spi_flash_ll_set_miso_bitlen(dev, bitlen)            gpspi_flash_ll_set_miso_bitlen((spi_dev_t*)dev, bitlen)
+#define spi_flash_ll_set_mosi_bitlen(dev, bitlen)            gpspi_flash_ll_set_mosi_bitlen((spi_dev_t*)dev, bitlen)
+#define spi_flash_ll_set_command8(dev, cmd)                  gpspi_flash_ll_set_command8((spi_dev_t*)dev, cmd)
+#define spi_flash_ll_set_addr_bitlen(dev, bitlen)            gpspi_flash_ll_set_addr_bitlen((spi_dev_t*)dev, bitlen)
+#define spi_flash_ll_set_address(dev, addr)                  gpspi_flash_ll_set_address((spi_dev_t*)dev, addr)
+#define spi_flash_ll_set_dummy(dev, dummy)                   gpspi_flash_ll_set_dummy((spi_dev_t*)dev, dummy)
+#else
+#define spi_flash_ll_reset(dev)                              spimem_flash_ll_reset((spi_mem_dev_t*)dev)
+#define spi_flash_ll_cmd_is_done(dev)                        spimem_flash_ll_cmd_is_done((spi_mem_dev_t*)dev)
+#define spi_flash_ll_erase_chip(dev)                         spimem_flash_ll_erase_chip((spi_mem_dev_t*)dev)
+#define spi_flash_ll_erase_sector(dev)                       spimem_flash_ll_erase_sector((spi_mem_dev_t*)dev)
+#define spi_flash_ll_erase_block(dev)                        spimem_flash_ll_erase_block((spi_mem_dev_t*)dev)
+#define spi_flash_ll_set_write_protect(dev, wp)              spimem_flash_ll_set_write_protect((spi_mem_dev_t*)dev, wp)
+#define spi_flash_ll_get_buffer_data(dev, buffer, read_len)  spimem_flash_ll_get_buffer_data((spi_mem_dev_t*)dev, buffer, read_len)
+#define spi_flash_ll_set_buffer_data(dev, buffer, len)       spimem_flash_ll_set_buffer_data((spi_mem_dev_t*)dev, buffer, len)
+#define spi_flash_ll_program_page(dev, buffer, len)          spimem_flash_ll_program_page((spi_mem_dev_t*)dev, buffer, len)
+#define spi_flash_ll_user_start(dev)                         spimem_flash_ll_user_start((spi_mem_dev_t*)dev)
+#define spi_flash_ll_host_idle(dev)                          spimem_flash_ll_host_idle((spi_mem_dev_t*)dev)
+#define spi_flash_ll_read_phase(dev)                         spimem_flash_ll_read_phase((spi_mem_dev_t*)dev)
+#define spi_flash_ll_set_cs_pin(dev, pin)                    spimem_flash_ll_set_cs_pin((spi_mem_dev_t*)dev, pin)
+#define spi_flash_ll_set_read_mode(dev, read_mode)           spimem_flash_ll_set_read_mode((spi_mem_dev_t*)dev, read_mode)
+#define spi_flash_ll_set_clock(dev, clk)                     spimem_flash_ll_set_clock((spi_mem_dev_t*)dev, (spimem_flash_ll_clock_reg_t*)clk)
+#define spi_flash_ll_set_miso_bitlen(dev, bitlen)            spimem_flash_ll_set_miso_bitlen((spi_mem_dev_t*)dev, bitlen)
+#define spi_flash_ll_set_mosi_bitlen(dev, bitlen)            spimem_flash_ll_set_mosi_bitlen((spi_mem_dev_t*)dev, bitlen)
+#define spi_flash_ll_set_command8(dev, cmd)                  spimem_flash_ll_set_command8((spi_mem_dev_t*)dev, cmd)
+#define spi_flash_ll_set_addr_bitlen(dev, bitlen)            spimem_flash_ll_set_addr_bitlen((spi_mem_dev_t*)dev, bitlen)
+#define spi_flash_ll_set_address(dev, addr)                  spimem_flash_ll_set_address((spi_mem_dev_t*)dev, addr)
+#define spi_flash_ll_set_dummy(dev, dummy)                   spimem_flash_ll_set_dummy((spi_mem_dev_t*)dev, dummy)
+#endif

+ 354 - 0
components/soc/esp32s2beta/include/hal/spimem_flash_ll.h

@@ -0,0 +1,354 @@
+// 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.
+
+/*******************************************************************************
+ * NOTICE
+ * The ll is not public api, don't use in application code.
+ * See readme.md in soc/include/hal/readme.md
+ ******************************************************************************/
+
+// The Lowlevel layer for SPI Flash
+
+#pragma once
+
+#include <stdlib.h>
+#include <sys/param.h> // For MIN/MAX
+#include <stdbool.h>
+#include <string.h>
+
+#include "soc/spi_periph.h"
+#include "hal/spi_types.h"
+#include "hal/spi_flash_types.h"
+
+#define spimem_flash_ll_get_hw(host_id)  (((host_id)==SPI1_HOST ?  &SPIMEM1 : NULL ))
+
+typedef typeof(SPIMEM1.clock) spimem_flash_ll_clock_reg_t;
+
+//Supported clock register values
+#define SPIMEM_FLASH_LL_CLKREG_VAL_5MHZ   ((spimem_flash_ll_clock_reg_t){.val=0x000F070F})   ///< Clock set to 5 MHz
+#define SPIMEM_FLASH_LL_CLKREG_VAL_10MHZ  ((spimem_flash_ll_clock_reg_t){.val=0x00070307})   ///< Clock set to 10 MHz
+#define SPIMEM_FLASH_LL_CLKREG_VAL_20MHZ  ((spimem_flash_ll_clock_reg_t){.val=0x00030103})   ///< Clock set to 20 MHz
+#define SPIMEM_FLASH_LL_CLKREG_VAL_26MHZ  ((spimem_flash_ll_clock_reg_t){.val=0x00020002})   ///< Clock set to 26 MHz
+#define SPIMEM_FLASH_LL_CLKREG_VAL_40MHZ  ((spimem_flash_ll_clock_reg_t){.val=0x00010001})   ///< Clock set to 40 MHz
+#define SPIMEM_FLASH_LL_CLKREG_VAL_80MHZ  ((spimem_flash_ll_clock_reg_t){.val=0x80000000})   ///< Clock set to 80 MHz
+
+/*------------------------------------------------------------------------------
+ * Control
+ *----------------------------------------------------------------------------*/
+/**
+ * Reset peripheral registers before configuration and starting control
+ *
+ * @param dev Beginning address of the peripheral registers.
+ */
+static inline void spimem_flash_ll_reset(spi_mem_dev_t *dev)
+{
+    dev->user.val = 0;
+    dev->ctrl.val = 0;
+}
+
+/**
+ * Check whether the previous operation is done.
+ *
+ * @param dev Beginning address of the peripheral registers.
+ *
+ * @return true if last command is done, otherwise false.
+ */
+static inline bool spimem_flash_ll_cmd_is_done(const spi_mem_dev_t *dev)
+{
+    return (dev->cmd.val == 0);
+}
+
+/**
+ * Erase the flash chip.
+ *
+ * @param dev Beginning address of the peripheral registers.
+ */
+static inline void spimem_flash_ll_erase_chip(spi_mem_dev_t *dev)
+{
+    dev->cmd.flash_ce = 1;
+}
+
+/**
+ * Erase the sector, the address should be set by spimem_flash_ll_set_address.
+ *
+ * @param dev Beginning address of the peripheral registers.
+ */
+static inline void spimem_flash_ll_erase_sector(spi_mem_dev_t *dev)
+{
+    dev->ctrl.val = 0;
+    dev->cmd.flash_se = 1;
+}
+
+/**
+ * Erase the block, the address should be set by spimem_flash_ll_set_address.
+ *
+ * @param dev Beginning address of the peripheral registers.
+ */
+static inline void spimem_flash_ll_erase_block(spi_mem_dev_t *dev)
+{
+    dev->cmd.flash_be = 1;
+}
+
+/**
+ * Enable/disable write protection for the flash chip.
+ *
+ * @param dev Beginning address of the peripheral registers.
+ * @param wp true to enable the protection, false to disable (write enable).
+ */
+static inline void spimem_flash_ll_set_write_protect(spi_mem_dev_t *dev, bool wp)
+{
+    if (wp) {
+        dev->cmd.flash_wrdi = 1;
+    } else {
+        dev->cmd.flash_wren = 1;
+    }
+}
+
+/**
+ * Get the read data from the buffer after ``spimem_flash_ll_read`` is done.
+ *
+ * @param dev Beginning address of the peripheral registers.
+ * @param buffer Buffer to hold the output data
+ * @param read_len Length to get out of the buffer
+ */
+static inline void spimem_flash_ll_get_buffer_data(spi_mem_dev_t *dev, void *buffer, uint32_t read_len)
+{
+    if (((intptr_t)buffer % 4 == 0) && (read_len % 4 == 0)) {
+        // If everything is word-aligned, do a faster memcpy
+        memcpy(buffer, (void *)dev->data_buf, read_len);
+    } else {
+        // Otherwise, slow(er) path copies word by word
+        int copy_len = read_len;
+        for (int i = 0; i < (read_len + 3) / 4; i++) {
+            int word_len = MIN(sizeof(uint32_t), copy_len);
+            uint32_t word = dev->data_buf[i];
+            memcpy(buffer, &word, word_len);
+            buffer = (void *)((intptr_t)buffer + word_len);
+            copy_len -= word_len;
+        }
+    }
+}
+
+/**
+ * Set the data to be written in the data buffer.
+ *
+ * @param dev Beginning address of the peripheral registers.
+ * @param buffer Buffer holding the data
+ * @param length Length of data in bytes.
+ */
+static inline void spimem_flash_ll_set_buffer_data(spi_mem_dev_t *dev, const void *buffer, uint32_t length)
+{
+    // Load data registers, word at a time
+    int num_words = (length + 3) / 4;
+    for (int i = 0; i < num_words; i++) {
+        uint32_t word = 0;
+        uint32_t word_len = MIN(length, sizeof(word));
+        memcpy(&word, buffer, word_len);
+        dev->data_buf[i] = word;
+        length -= word_len;
+        buffer = (void *)((intptr_t)buffer + word_len);
+    }
+}
+
+
+/**
+ * Program a page of the flash chip. Call ``spimem_flash_ll_set_address`` before
+ * this to set the address to program.
+ *
+ * @param dev Beginning address of the peripheral registers.
+ * @param buffer Buffer holding the data to program
+ * @param length Length to program.
+ */
+static inline void spimem_flash_ll_program_page(spi_mem_dev_t *dev, const void *buffer, uint32_t length)
+{
+    dev->user.usr_dummy = 0;
+    spimem_flash_ll_set_buffer_data(dev, buffer, length);
+    dev->cmd.flash_pp = 1;
+}
+
+/**
+ * Trigger a user defined transaction. All phases, including command, address, dummy, and the data phases,
+ * should be configured before this is called.
+ *
+ * @param dev Beginning address of the peripheral registers.
+ */
+static inline void spimem_flash_ll_user_start(spi_mem_dev_t *dev)
+{
+    dev->cmd.usr = 1;
+}
+
+/**
+ * Check whether the host is idle to perform new commands.
+ *
+ * @param dev Beginning address of the peripheral registers.
+ *
+ * @return true if the host is idle, otherwise false
+ */
+static inline bool spimem_flash_ll_host_idle(const spi_mem_dev_t *dev)
+{
+    return dev->fsm.st != 0;
+}
+
+/**
+ * Set phases for user-defined transaction to read
+ *
+ * @param dev Beginning address of the peripheral registers.
+ */
+static inline void spimem_flash_ll_read_phase(spi_mem_dev_t *dev)
+{
+    typeof (dev->user) user = {
+        .usr_command = 1,
+        .usr_mosi = 0,
+        .usr_miso = 1,
+        .usr_addr = 1,
+    };
+    dev->user = user;
+}
+/*------------------------------------------------------------------------------
+ * Configs
+ *----------------------------------------------------------------------------*/
+/**
+ * Select which pin to use for the flash
+ *
+ * @param dev Beginning address of the peripheral registers.
+ * @param pin Pin ID to use, 0-2. Set to other values to disable all the CS pins.
+ */
+static inline void spimem_flash_ll_set_cs_pin(spi_mem_dev_t *dev, int pin)
+{
+    dev->misc.cs0_dis = (pin == 0) ? 0 : 1;
+    dev->misc.cs1_dis = (pin == 1) ? 0 : 1;
+}
+
+/**
+ * Set the read io mode.
+ *
+ * @param dev Beginning address of the peripheral registers.
+ * @param read_mode I/O mode to use in the following transactions.
+ */
+static inline void spimem_flash_ll_set_read_mode(spi_mem_dev_t *dev, esp_flash_io_mode_t read_mode)
+{
+    typeof (dev->ctrl) ctrl = dev->ctrl;
+    ctrl.val &= ~(SPI_MEM_FREAD_QIO_M | SPI_MEM_FREAD_QUAD_M | SPI_MEM_FREAD_DIO_M | SPI_MEM_FREAD_DUAL_M);
+    ctrl.val |= SPI_MEM_FASTRD_MODE_M;
+    switch (read_mode) {
+    case SPI_FLASH_FASTRD:
+        //the default option
+        break;
+    case SPI_FLASH_QIO:
+        ctrl.fread_qio = 1;
+        break;
+    case SPI_FLASH_QOUT:
+        ctrl.fread_quad = 1;
+        break;
+    case SPI_FLASH_DIO:
+        ctrl.fread_dio = 1;
+        break;
+    case SPI_FLASH_DOUT:
+        ctrl.fread_dual = 1;
+        break;
+    case SPI_FLASH_SLOWRD:
+        ctrl.fastrd_mode = 0;
+        break;
+    default:
+        abort();
+    }
+    dev->ctrl = ctrl;
+}
+
+/**
+ * Set clock frequency to work at.
+ *
+ * @param dev Beginning address of the peripheral registers.
+ * @param clock_val pointer to the clock value to set
+ */
+static inline void spimem_flash_ll_set_clock(spi_mem_dev_t *dev, spimem_flash_ll_clock_reg_t *clock_val)
+{
+    dev->clock = *clock_val;
+}
+
+/**
+ * Set the input length, in bits.
+ *
+ * @param dev Beginning address of the peripheral registers.
+ * @param bitlen Length of input, in bits.
+ */
+static inline void spimem_flash_ll_set_miso_bitlen(spi_mem_dev_t *dev, uint32_t bitlen)
+{
+    dev->user.usr_miso = bitlen > 0;
+    dev->miso_dlen.usr_miso_bit_len = bitlen ? (bitlen - 1) : 0;
+}
+
+/**
+ * Set the output length, in bits (not including command, address and dummy
+ * phases)
+ *
+ * @param dev Beginning address of the peripheral registers.
+ * @param bitlen Length of output, in bits.
+ */
+static inline void spimem_flash_ll_set_mosi_bitlen(spi_mem_dev_t *dev, uint32_t bitlen)
+{
+    dev->user.usr_mosi = bitlen > 0;
+    dev->mosi_dlen.usr_mosi_bit_len = bitlen ? (bitlen - 1) : 0;
+}
+
+/**
+ * Set the command with fixed length (8 bits).
+ *
+ * @param dev Beginning address of the peripheral registers.
+ * @param command Command to send
+ */
+static inline void spimem_flash_ll_set_command8(spi_mem_dev_t *dev, uint8_t command)
+{
+    dev->user.usr_command = 1;
+    typeof(dev->user2) user2 = {
+        .usr_command_value = command,
+        .usr_command_bitlen = (8 - 1),
+    };
+    dev->user2 = user2;
+}
+
+/**
+ * Set the address length to send, in bits. Should be called before commands that requires the address e.g. erase sector, read, write...
+ *
+ * @param dev Beginning address of the peripheral registers.
+ * @param bitlen Length of the address, in bits
+ */
+static inline void spimem_flash_ll_set_addr_bitlen(spi_mem_dev_t *dev, uint32_t bitlen)
+{
+    dev->user1.usr_addr_bitlen = (bitlen - 1);
+    dev->user.usr_addr = bitlen ? 1 : 0;
+}
+
+/**
+ * Set the address to send. Should be called before commands that requires the address e.g. erase sector, read, write...
+ *
+ * @param dev Beginning address of the peripheral registers.
+ * @param addr Address to send
+ */
+static inline void spimem_flash_ll_set_address(spi_mem_dev_t *dev, uint32_t addr)
+{
+    dev->addr = addr;
+}
+
+/**
+ * Set the length of dummy cycles.
+ *
+ * @param dev Beginning address of the peripheral registers.
+ * @param dummy_n Cycles of dummy phases
+ */
+static inline void spimem_flash_ll_set_dummy(spi_mem_dev_t *dev, uint32_t dummy_n)
+{
+    dev->user.usr_dummy = dummy_n ? 1 : 0;
+    dev->user1.usr_dummy_cyclelen = dummy_n - 1;
+}

+ 1 - 1
components/soc/esp32s2beta/include/soc/soc.h

@@ -176,7 +176,7 @@
 #define  TIMER_CLK_FREQ                              (80000000>>4) //80MHz divided by 16
 #define  TIMER_CLK_FREQ                              (80000000>>4) //80MHz divided by 16
 #define  SPI_CLK_DIV                                 4
 #define  SPI_CLK_DIV                                 4
 #define  TICKS_PER_US_ROM                            40              // CPU is 80MHz
 #define  TICKS_PER_US_ROM                            40              // CPU is 80MHz
-#define  GPIO_MATRIX_DELAY_NS                        25
+#define  GPIO_MATRIX_DELAY_NS                        15
 //}}
 //}}
 
 
 /* Overall memory map */
 /* Overall memory map */

+ 5 - 1
components/soc/esp32s2beta/include/soc/spi_caps.h

@@ -26,7 +26,7 @@
 #define SPI_IOMUX_PIN_NUM_WP    28
 #define SPI_IOMUX_PIN_NUM_WP    28
 //TODO: add the next slot
 //TODO: add the next slot
 
 
-#define FSPI_FUNC_NUM           0
+#define FSPI_FUNC_NUM           2
 #define FSPI_IOMUX_PIN_NUM_HD   9
 #define FSPI_IOMUX_PIN_NUM_HD   9
 #define FSPI_IOMUX_PIN_NUM_CS   10
 #define FSPI_IOMUX_PIN_NUM_CS   10
 #define FSPI_IOMUX_PIN_NUM_MOSI 11
 #define FSPI_IOMUX_PIN_NUM_MOSI 11
@@ -43,3 +43,7 @@
 #define SOC_SPI_SUPPORT_DDRCLK              1
 #define SOC_SPI_SUPPORT_DDRCLK              1
 #define SOC_SPI_SLAVE_SUPPORT_SEG_TRANS     1
 #define SOC_SPI_SLAVE_SUPPORT_SEG_TRANS     1
 #define SOC_SPI_SUPPORT_CD_SIG              1
 #define SOC_SPI_SUPPORT_CD_SIG              1
+
+// Peripheral supports DIO, DOUT, QIO, or QOUT
+#define SOC_SPI_PERIPH_SUPPORT_MULTILINE_MODE(spi_dev)  (!((void*)spi_dev == (void*)&GPSPI3 \
+                                                           || (void*)spi_dev == (void*)&GPSPI4))

+ 2 - 23
components/soc/include/hal/spi_flash_hal.h

@@ -204,17 +204,7 @@ void spi_flash_hal_poll_cmd_done(spi_flash_host_driver_t *driver);
  *
  *
  * @return True if the buffer can be used to send data, otherwise false.
  * @return True if the buffer can be used to send data, otherwise false.
  */
  */
-static inline bool spi_flash_hal_supports_direct_write(spi_flash_host_driver_t *driver, const void *p)
-{
-#ifdef ESP_PLATFORM
-    bool direct_write = ( ((spi_flash_memspi_data_t *)driver->driver_data)->spi != &SPI1
-                          || esp_ptr_in_dram(p) );
-#else
-    //If it is not on real chips, there is no limitation that the data has to be in DRAM.
-    bool direct_write = true;
-#endif
-    return direct_write;
-}
+bool spi_flash_hal_supports_direct_write(spi_flash_host_driver_t *driver, const void *p);
 
 
 /**
 /**
  * Check whether the given buffer can be used as the read buffer directly. If 'chip' is connected to the main SPI bus, we can only read directly from
  * Check whether the given buffer can be used as the read buffer directly. If 'chip' is connected to the main SPI bus, we can only read directly from
@@ -225,15 +215,4 @@ static inline bool spi_flash_hal_supports_direct_write(spi_flash_host_driver_t *
  *
  *
  * @return True if the buffer can be used to receive data, otherwise false.
  * @return True if the buffer can be used to receive data, otherwise false.
  */
  */
-static inline bool spi_flash_hal_supports_direct_read(spi_flash_host_driver_t *driver, const void *p)
-{
-#ifdef ESP_PLATFORM
-//currently the driver doesn't support to read through DMA, no word-aligned requirements
-    bool direct_read = ( ((spi_flash_memspi_data_t *)driver->driver_data)->spi != &SPI1
-                          || esp_ptr_in_dram(p) );
-#else
-    //If it is not on real chips, there is no limitation that the data has to be in DRAM.
-    bool direct_read = true;
-#endif
-    return direct_read;
-}
+bool spi_flash_hal_supports_direct_read(spi_flash_host_driver_t *driver, const void *p);

+ 7 - 5
components/soc/include/hal/spi_flash_types.h

@@ -23,11 +23,13 @@ extern "C" {
 
 
 /** Definition of a common transaction. Also holds the return value. */
 /** Definition of a common transaction. Also holds the return value. */
 typedef struct {
 typedef struct {
-    uint8_t command;        ///< Command to send, always 8bits
-    uint8_t mosi_len;       ///< Output data length, in bits
-    uint8_t miso_len;       ///< Input data length, in bits
-    uint32_t mosi_data;     ///< Output data to slave
-    uint32_t miso_data[2];  ///< [out] Input data from slave, little endian
+    uint8_t command;            ///< Command to send, always 8bits
+    uint8_t mosi_len;           ///< Output data length, in bytes
+    uint8_t miso_len;           ///< Input data length, in bytes
+    uint8_t address_bitlen;     ///< Length of address in bits, set to 0 if command does not need an address
+    uint32_t address;           ///< Address to perform operation on
+    const uint8_t *mosi_data;   ///< Output data to salve
+    uint8_t *miso_data;         ///< [out] Input data from slave, little endian
 } spi_flash_trans_t;
 } spi_flash_trans_t;
 
 
 /**
 /**

+ 1 - 0
components/soc/include/soc/spi_periph.h

@@ -25,6 +25,7 @@
 #include "sdkconfig.h"
 #include "sdkconfig.h"
 #if CONFIG_IDF_TARGET_ESP32S2BETA
 #if CONFIG_IDF_TARGET_ESP32S2BETA
 #include "soc/spi_mem_struct.h"
 #include "soc/spi_mem_struct.h"
+#include "soc/spi_mem_reg.h"
 #endif
 #endif
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus

+ 1 - 0
components/soc/linker.lf

@@ -19,4 +19,5 @@ entries:
     spi_flash_hal_iram (noflash)
     spi_flash_hal_iram (noflash)
     ledc_hal_iram (noflash_text)
     ledc_hal_iram (noflash_text)
     i2c_hal_iram (noflash)
     i2c_hal_iram (noflash)
+    spi_flash_hal_gpspi (noflash)
     lldesc (noflash_text)
     lldesc (noflash_text)

+ 39 - 3
components/soc/src/hal/spi_flash_hal.c

@@ -36,12 +36,23 @@ static const spi_flash_hal_clock_config_t spi_flash_clk_cfg_reg[ESP_FLASH_SPEED_
     {80e6, SPI_FLASH_LL_CLKREG_VAL_80MHZ},
     {80e6, SPI_FLASH_LL_CLKREG_VAL_80MHZ},
 };
 };
 
 
+#ifdef CONFIG_IDF_TARGET_ESP32S2BETA
+static const spi_flash_hal_clock_config_t spi_flash_gpspi_clk_cfg_reg[ESP_FLASH_SPEED_MAX] = {
+    {5e6,  {.gpspi=GPSPI_FLASH_LL_CLKREG_VAL_5MHZ}},
+    {10e6, {.gpspi=GPSPI_FLASH_LL_CLKREG_VAL_10MHZ}},
+    {20e6, {.gpspi=GPSPI_FLASH_LL_CLKREG_VAL_20MHZ}},
+    {26e6, {.gpspi=GPSPI_FLASH_LL_CLKREG_VAL_26MHZ}},
+    {40e6, {.gpspi=GPSPI_FLASH_LL_CLKREG_VAL_40MHZ}},
+    {80e6, {.gpspi=GPSPI_FLASH_LL_CLKREG_VAL_80MHZ}},
+};
+#endif
+
 static inline int get_dummy_n(bool gpio_is_used, int input_delay_ns, int eff_clk)
 static inline int get_dummy_n(bool gpio_is_used, int input_delay_ns, int eff_clk)
 {
 {
     const int apbclk_kHz = APB_CLK_FREQ / 1000;
     const int apbclk_kHz = APB_CLK_FREQ / 1000;
     //calculate how many apb clocks a period has
     //calculate how many apb clocks a period has
     const int apbclk_n = APB_CLK_FREQ / eff_clk;
     const int apbclk_n = APB_CLK_FREQ / eff_clk;
-    const int gpio_delay_ns = gpio_is_used ? (APB_CYCLE_NS * 2) : 0;
+    const int gpio_delay_ns = gpio_is_used ? GPIO_MATRIX_DELAY_NS : 0;
 
 
     //calculate how many apb clocks the delay is, the 1 is to compensate in case ``input_delay_ns`` is rounded off.
     //calculate how many apb clocks the delay is, the 1 is to compensate in case ``input_delay_ns`` is rounded off.
     int apb_period_n = (1 + input_delay_ns + gpio_delay_ns) * apbclk_kHz / 1000 / 1000;
     int apb_period_n = (1 + input_delay_ns + gpio_delay_ns) * apbclk_kHz / 1000 / 1000;
@@ -57,13 +68,38 @@ esp_err_t spi_flash_hal_init(spi_flash_memspi_data_t *data_out, const spi_flash_
     if (!esp_ptr_internal(data_out)) {
     if (!esp_ptr_internal(data_out)) {
         return ESP_ERR_INVALID_ARG;
         return ESP_ERR_INVALID_ARG;
     }
     }
+
+    spi_flash_hal_clock_config_t clock_cfg = spi_flash_clk_cfg_reg[cfg->speed];
+
+#ifdef CONFIG_IDF_TARGET_ESP32S2BETA
+    if (cfg->host_id > SPI_HOST) {
+        clock_cfg = spi_flash_gpspi_clk_cfg_reg[cfg->speed];
+    }
+#endif
+
     *data_out = (spi_flash_memspi_data_t) {
     *data_out = (spi_flash_memspi_data_t) {
         .spi = spi_flash_ll_get_hw(cfg->host_id),
         .spi = spi_flash_ll_get_hw(cfg->host_id),
         .cs_num = cfg->cs_num,
         .cs_num = cfg->cs_num,
-        .extra_dummy = get_dummy_n(!cfg->iomux, cfg->input_delay_ns, spi_flash_clk_cfg_reg[cfg->speed].freq),
-        .clock_conf = spi_flash_clk_cfg_reg[cfg->speed].clock_reg_val,
+        .extra_dummy = get_dummy_n(!cfg->iomux, cfg->input_delay_ns, clock_cfg.freq),
+        .clock_conf = clock_cfg.clock_reg_val,
     };
     };
 
 
     ESP_EARLY_LOGD(TAG, "extra_dummy: %d", data_out->extra_dummy);
     ESP_EARLY_LOGD(TAG, "extra_dummy: %d", data_out->extra_dummy);
     return ESP_OK;
     return ESP_OK;
 }
 }
+
+bool spi_flash_hal_supports_direct_write(spi_flash_host_driver_t *host, const void *p)
+{
+    bool direct_write = ( ((spi_flash_memspi_data_t *)host->driver_data)->spi != spi_flash_ll_get_hw(SPI_HOST)
+                          || esp_ptr_in_dram(p) );
+    return direct_write;
+}
+
+
+bool spi_flash_hal_supports_direct_read(spi_flash_host_driver_t *host, const void *p)
+{
+  //currently the host doesn't support to read through dma, no word-aligned requirements
+    bool direct_read = ( ((spi_flash_memspi_data_t *)host->driver_data)->spi != spi_flash_ll_get_hw(SPI_HOST)
+                         || esp_ptr_in_dram(p) );
+    return direct_read;
+}

+ 102 - 0
components/soc/src/hal/spi_flash_hal_common.inc

@@ -0,0 +1,102 @@
+// 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.
+
+#include <stdlib.h>
+#include "hal/spi_flash_hal.h"
+#include "string.h"
+#include "hal/hal_defs.h"
+#include "sdkconfig.h"
+
+#define ADDRESS_MASK_24BIT 0xFFFFFF
+#define COMPUTE_DUMMY_CYCLELEN(host, base)    ((base) + ((spi_flash_memspi_data_t *)(host)->driver_data)->extra_dummy)
+
+static inline spi_dev_t *get_spi_dev(spi_flash_host_driver_t *host)
+{
+    return ((spi_flash_memspi_data_t *)host->driver_data)->spi;
+}
+
+void spi_flash_hal_poll_cmd_done(spi_flash_host_driver_t *host)
+{
+    while (!spi_flash_ll_cmd_is_done(get_spi_dev(host))) {
+        //nop
+    }
+}
+
+esp_err_t spi_flash_hal_device_config(spi_flash_host_driver_t *host)
+{
+    spi_flash_memspi_data_t *drv_data = (spi_flash_memspi_data_t *)host->driver_data;
+    spi_dev_t *dev = get_spi_dev(host);
+    spi_flash_ll_reset(dev);
+    spi_flash_ll_set_cs_pin(dev, drv_data->cs_num);
+    spi_flash_ll_set_clock(dev, &drv_data->clock_conf);
+    return ESP_OK;
+}
+
+esp_err_t spi_flash_hal_configure_host_io_mode(
+    spi_flash_host_driver_t *host,
+    uint32_t command,
+    uint32_t addr_bitlen,
+    int dummy_cyclelen_base,
+    esp_flash_io_mode_t io_mode)
+{
+    spi_dev_t *dev = get_spi_dev(host);
+
+    if (!SOC_SPI_PERIPH_SUPPORT_MULTILINE_MODE(dev) && io_mode > SPI_FLASH_FASTRD) {
+        return ESP_ERR_NOT_SUPPORTED;
+    }
+
+    spi_flash_ll_set_command8(dev, command);
+    spi_flash_ll_set_addr_bitlen(dev, addr_bitlen);
+    // Add dummy cycles to compensate for latency of GPIO matrix and external delay, if necessary...
+    spi_flash_ll_set_dummy(dev, COMPUTE_DUMMY_CYCLELEN(host, dummy_cyclelen_base));
+    //disable all data phases, enable them later if needed
+    spi_flash_ll_set_miso_bitlen(dev, 0);
+    spi_flash_ll_set_mosi_bitlen(dev, 0);
+    spi_flash_ll_set_read_mode(dev, io_mode);
+    return ESP_OK;
+}
+
+esp_err_t spi_flash_hal_common_command(spi_flash_host_driver_t *host, spi_flash_trans_t *trans)
+{
+    host->configure_host_io_mode(host, trans->command, trans->address_bitlen, 0, SPI_FLASH_FASTRD);
+
+    spi_dev_t *dev = get_spi_dev(host);
+
+    //disable dummy if no input phase
+    if (trans->miso_len == 0) {
+        spi_flash_ll_set_dummy(dev, 0);
+    }
+
+    spi_flash_ll_set_address(dev, (trans->address & ADDRESS_MASK_24BIT) << 8);
+
+    spi_flash_ll_set_mosi_bitlen(dev, trans->mosi_len * 8);
+    spi_flash_ll_set_buffer_data(dev, trans->mosi_data, trans->mosi_len);
+
+    spi_flash_ll_set_miso_bitlen(dev, trans->miso_len * 8);
+    spi_flash_ll_user_start(dev);
+    host->poll_cmd_done(host);
+    spi_flash_ll_get_buffer_data(dev, trans->miso_data, trans->miso_len);
+    return ESP_OK;
+}
+
+esp_err_t spi_flash_hal_read(spi_flash_host_driver_t *host, void *buffer, uint32_t address, uint32_t read_len)
+{
+    spi_dev_t *dev = get_spi_dev(host);
+    spi_flash_ll_set_address(dev, address << 8);
+    spi_flash_ll_set_miso_bitlen(dev, read_len * 8);
+    spi_flash_ll_user_start(dev);
+    host->poll_cmd_done(host);
+    spi_flash_ll_get_buffer_data(dev, buffer, read_len);
+    return ESP_OK;
+}

+ 39 - 0
components/soc/src/hal/spi_flash_hal_gpspi.c

@@ -0,0 +1,39 @@
+// 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.
+
+#define GPSPI_BUILD
+
+#define spi_flash_hal_common_command            spi_flash_hal_gpspi_common_command
+#define spi_flash_hal_poll_cmd_done             spi_flash_hal_gpspi_poll_cmd_done
+#define spi_flash_hal_device_config             spi_flash_hal_gpspi_device_config
+#define spi_flash_hal_configure_host_io_mode    spi_flash_hal_gpspi_configure_host_io_mode
+#define spi_flash_hal_read                      spi_flash_hal_gpspi_read
+
+#include "spi_flash_hal_common.inc"
+
+bool spi_flash_hal_gpspi_supports_direct_write(spi_flash_host_driver_t *host, const void *p)
+{
+    return true;
+}
+
+bool spi_flash_hal_gpspi_supports_direct_read(spi_flash_host_driver_t *host, const void *p)
+{
+    return true;
+}
+
+bool spi_flash_hal_gpspi_host_idle(spi_flash_host_driver_t *chip_drv)
+{
+    spi_dev_t *dev = get_spi_dev(chip_drv);
+    return spi_flash_ll_host_idle(dev);
+}

+ 11 - 100
components/soc/src/hal/spi_flash_hal_iram.c

@@ -12,87 +12,7 @@
 // See the License for the specific language governing permissions and
 // See the License for the specific language governing permissions and
 // limitations under the License.
 // limitations under the License.
 
 
-#include <stdlib.h>
-#include "hal/spi_flash_hal.h"
-#include "string.h"
-#include "hal/hal_defs.h"
-
-#define ADDRESS_MASK_24BIT 0xFFFFFF
-
-static inline spi_dev_t *get_spi_dev(spi_flash_host_driver_t *host)
-{
-    return ((spi_flash_memspi_data_t *)host->driver_data)->spi;
-}
-
-void spi_flash_hal_poll_cmd_done(spi_flash_host_driver_t *host)
-{
-    while (!spi_flash_ll_cmd_is_done(get_spi_dev(host))) {
-        //nop
-    }
-}
-
-esp_err_t spi_flash_hal_device_config(spi_flash_host_driver_t *host)
-{
-    spi_flash_memspi_data_t *drv_data = (spi_flash_memspi_data_t *)host->driver_data;
-    spi_dev_t *dev = get_spi_dev(host);
-    spi_flash_ll_reset(dev);
-    spi_flash_ll_set_cs_pin(dev, drv_data->cs_num);
-    spi_flash_ll_set_clock(dev, &drv_data->clock_conf);
-
-    /*
-     * workaround for the ROM: the ROM, as well as the OpenOCD, don't know the
-     * clock registers and the dummy are modified this help the ROM to read and
-     * write correctly according to the new dummy len.
-     */
-    if (dev == &SPI1) {
-        //0 for cache, 1 for SPI1
-        extern uint8_t g_rom_spiflash_dummy_len_plus[];
-        g_rom_spiflash_dummy_len_plus[1] = drv_data->extra_dummy;
-    }
-    return ESP_OK;
-}
-
-esp_err_t spi_flash_hal_configure_host_io_mode(
-    spi_flash_host_driver_t *host,
-    uint32_t command,
-    uint32_t addr_bitlen,
-    int dummy_cyclelen_base,
-    esp_flash_io_mode_t io_mode)
-{
-    // Add dummy cycles to compensate for latency of GPIO matrix and external delay, if necessary...
-    int dummy_cyclelen = dummy_cyclelen_base + ((spi_flash_memspi_data_t *)host->driver_data)->extra_dummy;
-
-    spi_dev_t *dev = get_spi_dev(host);
-    spi_flash_ll_set_command8(dev, command);
-    spi_flash_ll_set_addr_bitlen(dev, addr_bitlen);
-    spi_flash_ll_set_dummy(dev, dummy_cyclelen);
-    //disable all data phases, enable them later if needed
-    spi_flash_ll_set_miso_bitlen(dev, 0);
-    spi_flash_ll_set_mosi_bitlen(dev, 0);
-    spi_flash_ll_set_read_mode(dev, io_mode);
-    return ESP_OK;
-}
-
-esp_err_t spi_flash_hal_common_command(spi_flash_host_driver_t *host, spi_flash_trans_t *trans)
-{
-    host->configure_host_io_mode(host, trans->command, 0, 0, SPI_FLASH_FASTRD);
-
-    spi_dev_t *dev = get_spi_dev(host);
-    //disable dummy if no input phase
-    if (trans->miso_len == 0) {
-        spi_flash_ll_set_dummy(dev, 0);
-    }
-
-    spi_flash_ll_set_miso_bitlen(dev, trans->miso_len);
-    spi_flash_ll_set_mosi_bitlen(dev, trans->mosi_len);
-
-    spi_flash_ll_write_word(dev, trans->mosi_data);
-
-    spi_flash_ll_user_start(dev);
-    host->poll_cmd_done(host);
-    spi_flash_ll_get_buffer_data(dev, trans->miso_data, 8);
-    return ESP_OK;
-}
+#include "spi_flash_hal_common.inc"
 
 
 void spi_flash_hal_erase_chip(spi_flash_host_driver_t *host)
 void spi_flash_hal_erase_chip(spi_flash_host_driver_t *host)
 {
 {
@@ -128,37 +48,28 @@ void spi_flash_hal_program_page(spi_flash_host_driver_t *host, const void *buffe
     host->poll_cmd_done(host);
     host->poll_cmd_done(host);
 }
 }
 
 
-esp_err_t spi_flash_hal_read(spi_flash_host_driver_t *host, void *buffer, uint32_t address, uint32_t read_len)
+esp_err_t spi_flash_hal_set_write_protect(spi_flash_host_driver_t *host, bool wp)
 {
 {
     spi_dev_t *dev = get_spi_dev(host);
     spi_dev_t *dev = get_spi_dev(host);
-    //the command is already set by ``spi_flash_hal_configure_host_io_mode`` before.
-    spi_flash_ll_set_address(dev, address << 8);
-    spi_flash_ll_set_miso_bitlen(dev, read_len * 8);
-    spi_flash_ll_user_start(dev);
+    spi_flash_ll_set_write_protect(dev, wp);
     host->poll_cmd_done(host);
     host->poll_cmd_done(host);
-    spi_flash_ll_get_buffer_data(dev, buffer, read_len);
     return ESP_OK;
     return ESP_OK;
 }
 }
 
 
-
-bool spi_flash_hal_host_idle(spi_flash_host_driver_t *host)
+bool spi_flash_hal_host_idle(spi_flash_host_driver_t *chip_drv)
 {
 {
-    spi_dev_t *dev = get_spi_dev(host);
+    spi_dev_t *dev = get_spi_dev(chip_drv);
     bool idle = spi_flash_ll_host_idle(dev);
     bool idle = spi_flash_ll_host_idle(dev);
 
 
     // Not clear if this is necessary, or only necessary if
     // Not clear if this is necessary, or only necessary if
     // chip->spi == SPI1. But probably doesn't hurt...
     // chip->spi == SPI1. But probably doesn't hurt...
-    if (dev == &SPI1) {
+    if ((void*) dev == spi_flash_ll_get_hw(SPI_HOST)) {
+#if CONFIG_IDF_TARGET_ESP32
         idle &= spi_flash_ll_host_idle(&SPI0);
         idle &= spi_flash_ll_host_idle(&SPI0);
+#elif CONFIG_IDF_TARGET_ESP32S2BETA
+        idle &= spi_flash_ll_host_idle(&SPIMEM0);
+#endif
     }
     }
 
 
     return idle;
     return idle;
-}
-
-esp_err_t spi_flash_hal_set_write_protect(spi_flash_host_driver_t *host, bool wp)
-{
-    spi_dev_t *dev = get_spi_dev(host);
-    spi_flash_ll_set_write_protect(dev, wp);
-    host->poll_cmd_done(host);
-    return ESP_OK;
-}
+}

+ 5 - 7
components/spi_flash/CMakeLists.txt

@@ -1,4 +1,5 @@
 set(priv_requires bootloader_support soc)
 set(priv_requires bootloader_support soc)
+
 if(BOOTLOADER_BUILD)
 if(BOOTLOADER_BUILD)
     if (CONFIG_IDF_TARGET_ESP32)
     if (CONFIG_IDF_TARGET_ESP32)
         # ESP32 Bootloader needs SPIUnlock from this file, but doesn't
         # ESP32 Bootloader needs SPIUnlock from this file, but doesn't
@@ -33,18 +34,15 @@ else()
         "spi_flash_chip_drivers.c"
         "spi_flash_chip_drivers.c"
         "spi_flash_chip_generic.c"
         "spi_flash_chip_generic.c"
         "spi_flash_chip_issi.c"
         "spi_flash_chip_issi.c"
-        "spi_flash_chip_gd.c")
+        "spi_flash_chip_gd.c"
+        "memspi_host_driver.c")
 
 
-    if (NOT CONFIG_IDF_TARGET_ESP32S2BETA)
-        # TODO: workaround until ESP32-S2 supports new API, can be always included
-        list(APPEND srcs
-            "memspi_host_driver.c")
-        list(APPEND cache_srcs
+    list(APPEND cache_srcs
         "esp_flash_api.c"
         "esp_flash_api.c"
         "esp_flash_spi_init.c"
         "esp_flash_spi_init.c"
         "spi_flash_os_func_app.c"
         "spi_flash_os_func_app.c"
         "spi_flash_os_func_noos.c")
         "spi_flash_os_func_noos.c")
-    endif()
+
     list(APPEND srcs ${cache_srcs})
     list(APPEND srcs ${cache_srcs})
     set(priv_requires bootloader_support app_update soc)
     set(priv_requires bootloader_support app_update soc)
 endif()
 endif()

+ 0 - 9
components/spi_flash/Kconfig

@@ -77,15 +77,6 @@ menu "SPI Flash driver"
             bool "Allowed"
             bool "Allowed"
     endchoice
     endchoice
 
 
-    # Force the Legacy implementation to be used on ESP32S2Beta
-    #
-    # TODO esp32s2beta: Remove once SPI Flash HAL available on S2 Beta
-    config SPI_FLASH_FORCE_LEGACY_ESP32S2BETA
-        bool
-        default y
-        depends on IDF_TARGET_ESP32S2BETA
-        select SPI_FLASH_USE_LEGACY_IMPL
-
     config SPI_FLASH_USE_LEGACY_IMPL
     config SPI_FLASH_USE_LEGACY_IMPL
         bool "Use the legacy implementation before IDF v4.0"
         bool "Use the legacy implementation before IDF v4.0"
         default n
         default n

+ 4 - 4
components/spi_flash/esp32s2beta/flash_ops_esp32s2beta.c

@@ -16,12 +16,12 @@
 #include <sys/param.h>
 #include <sys/param.h>
 
 
 #include "esp_spi_flash.h"
 #include "esp_spi_flash.h"
-#include "esp_spi_flash_chip.h"
-#include "cache_utils.h"
 #include "soc/system_reg.h"
 #include "soc/system_reg.h"
 #include "soc/soc_memory_layout.h"
 #include "soc/soc_memory_layout.h"
 #include "esp32s2beta/rom/spi_flash.h"
 #include "esp32s2beta/rom/spi_flash.h"
 #include "esp32s2beta/rom/cache.h"
 #include "esp32s2beta/rom/cache.h"
+#include "hal/spi_flash_hal.h"
+#include "esp_flash.h"
 
 
 esp_rom_spiflash_result_t IRAM_ATTR spi_flash_write_encrypted_chip(size_t dest_addr, const void *src, size_t size)
 esp_rom_spiflash_result_t IRAM_ATTR spi_flash_write_encrypted_chip(size_t dest_addr, const void *src, size_t size)
 {
 {
@@ -48,7 +48,7 @@ esp_rom_spiflash_result_t IRAM_ATTR spi_flash_write_encrypted_chip(size_t dest_a
         return ESP_ROM_SPIFLASH_RESULT_OK;
         return ESP_ROM_SPIFLASH_RESULT_OK;
     }
     }
     else { // Already in internal memory
     else { // Already in internal memory
-        rc = spi_flash_unlock();
+        rc = esp_rom_spiflash_unlock();
         if (rc != ESP_ROM_SPIFLASH_RESULT_OK) {
         if (rc != ESP_ROM_SPIFLASH_RESULT_OK) {
             return rc;
             return rc;
         }
         }
@@ -113,7 +113,7 @@ esp_err_t spi_flash_enable_wrap(uint32_t wrap_size)
     }
     }
 }
 }
 
 
-void spi_flash_disable_wrap()
+void spi_flash_disable_wrap(void)
 {
 {
     spi_flash_wrap_set(FLASH_WRAP_MODE_DISABLE);
     spi_flash_wrap_set(FLASH_WRAP_MODE_DISABLE);
 }
 }

+ 3 - 5
components/spi_flash/esp_flash_spi_init.c

@@ -70,17 +70,15 @@ static IRAM_ATTR NOINLINE_ATTR void cs_initialize(esp_flash_t *chip, const esp_f
     int cs_io_num = config->cs_io_num;
     int cs_io_num = config->cs_io_num;
     int spics_in = spi_periph_signal[config->host_id].spics_in;
     int spics_in = spi_periph_signal[config->host_id].spics_in;
     int spics_out = spi_periph_signal[config->host_id].spics_out[config->cs_id];
     int spics_out = spi_periph_signal[config->host_id].spics_out[config->cs_id];
+    int spics_func = spi_periph_signal[config->host_id].func;
     uint32_t iomux_reg = GPIO_PIN_MUX_REG[cs_io_num];
     uint32_t iomux_reg = GPIO_PIN_MUX_REG[cs_io_num];
 
 
     //To avoid the panic caused by flash data line conflicts during cs line
     //To avoid the panic caused by flash data line conflicts during cs line
     //initialization, disable the cache temporarily
     //initialization, disable the cache temporarily
     chip->os_func->start(chip->os_func_data);
     chip->os_func->start(chip->os_func_data);
     if (use_iomux) {
     if (use_iomux) {
-        GPIO.func_in_sel_cfg[spics_in].sig_in_sel = 0;
-        PIN_INPUT_ENABLE(iomux_reg);
-        GPIO.func_out_sel_cfg[spics_out].oen_sel = 0;
-        GPIO.func_out_sel_cfg[spics_out].oen_inv_sel = false;
-        PIN_FUNC_SELECT(iomux_reg, 1);
+        gpio_iomux_in(cs_io_num, spics_in);
+        gpio_iomux_out(cs_io_num, spics_func, false);
     } else {
     } else {
         PIN_INPUT_ENABLE(iomux_reg);
         PIN_INPUT_ENABLE(iomux_reg);
         if (cs_io_num < 32) {
         if (cs_io_num < 32) {

+ 41 - 0
components/spi_flash/include/memspi_host_driver.h

@@ -99,3 +99,44 @@ esp_err_t memspi_host_read_status_hs(spi_flash_host_driver_t *driver, uint8_t *o
  * @return always ESP_OK.
  * @return always ESP_OK.
  */
  */
 esp_err_t memspi_host_flush_cache(spi_flash_host_driver_t* driver, uint32_t addr, uint32_t size);
 esp_err_t memspi_host_flush_cache(spi_flash_host_driver_t* driver, uint32_t addr, uint32_t size);
+
+/**
+ *  Erase contents of entire chip.
+ *
+ * @param driver The driver context.
+ */
+void memspi_host_erase_chip(spi_flash_host_driver_t *driver);
+
+/**
+ *  Erase a sector starting from a given address.
+ *
+ * @param driver The driver context.
+ * @param start_address Starting address of the sector.
+ */
+void memspi_host_erase_sector(spi_flash_host_driver_t *driver, uint32_t start_address);
+
+/**
+ *  Erase a block starting from a given address.
+ *
+ * @param driver The driver context.
+ * @param start_address Starting address of the block.
+ */
+void memspi_host_erase_block(spi_flash_host_driver_t *driver, uint32_t start_address);
+
+/**
+ * Program a page with contents of a buffer.
+ *
+ * @param driver The driver context.
+ * @param buffer Buffer which contains the data to be flashed.
+ * @param address Starting address of where to flash the data.
+ * @param length The number of bytes to flash.
+ */
+void memspi_host_program_page(spi_flash_host_driver_t *driver, const void *buffer, uint32_t address, uint32_t length);
+
+/**
+ * Set ability to write to chip.
+ *
+ * @param driver The driver context.
+ * @param wp Enable or disable write protect (true - enable, false - disable).
+ */
+esp_err_t memspi_host_set_write_protect(spi_flash_host_driver_t *driver, bool wp);

+ 119 - 13
components/spi_flash/memspi_host_driver.c

@@ -22,9 +22,56 @@
 static const char TAG[] = "memspi";
 static const char TAG[] = "memspi";
 static const spi_flash_host_driver_t esp_flash_default_host = ESP_FLASH_DEFAULT_HOST_DRIVER();
 static const spi_flash_host_driver_t esp_flash_default_host = ESP_FLASH_DEFAULT_HOST_DRIVER();
 
 
+#ifdef CONFIG_IDF_TARGET_ESP32S2BETA
+extern void spi_flash_hal_gpspi_poll_cmd_done(spi_flash_host_driver_t *driver);
+extern esp_err_t spi_flash_hal_gpspi_device_config(spi_flash_host_driver_t *driver);
+esp_err_t spi_flash_hal_gpspi_configure_host_io_mode(
+    spi_flash_host_driver_t *host,
+    uint32_t command,
+    uint32_t addr_bitlen,
+    int dummy_cyclelen_base,
+    esp_flash_io_mode_t io_mode);
+extern esp_err_t spi_flash_hal_gpspi_common_command(spi_flash_host_driver_t *chip_drv, spi_flash_trans_t *trans);
+extern esp_err_t spi_flash_hal_gpspi_read(spi_flash_host_driver_t *chip_drv, void *buffer, uint32_t address, uint32_t read_len);
+extern bool spi_flash_hal_gpspi_host_idle(spi_flash_host_driver_t *chip_drv);
+extern bool spi_flash_hal_gpspi_supports_direct_write(spi_flash_host_driver_t *driver, const void *p);
+extern bool spi_flash_hal_gpspi_supports_direct_read(spi_flash_host_driver_t *driver, const void *p);
+
+/** Default configuration for GPSPI */
+static const spi_flash_host_driver_t esp_flash_gpspi_host = { 
+        .dev_config = spi_flash_hal_gpspi_device_config, 
+        .common_command = spi_flash_hal_gpspi_common_command, 
+        .read_id = memspi_host_read_id_hs, 
+        .erase_chip = memspi_host_erase_chip, 
+        .erase_sector = memspi_host_erase_sector, 
+        .erase_block = memspi_host_erase_block, 
+        .read_status = memspi_host_read_status_hs, 
+        .set_write_protect = memspi_host_set_write_protect, 
+        .supports_direct_write = spi_flash_hal_gpspi_supports_direct_write, 
+        .supports_direct_read = spi_flash_hal_gpspi_supports_direct_read, 
+        .program_page = memspi_host_program_page, 
+        .max_write_bytes = SPI_FLASH_HAL_MAX_WRITE_BYTES, 
+        .read = spi_flash_hal_gpspi_read, 
+        .max_read_bytes = SPI_FLASH_HAL_MAX_READ_BYTES, 
+        .host_idle = spi_flash_hal_gpspi_host_idle, 
+        .configure_host_io_mode = spi_flash_hal_gpspi_configure_host_io_mode, 
+        .poll_cmd_done = spi_flash_hal_gpspi_poll_cmd_done, 
+        .flush_cache = NULL, 
+};
+#endif
+
 esp_err_t memspi_host_init_pointers(spi_flash_host_driver_t *host, memspi_host_data_t *data, const memspi_host_config_t *cfg)
 esp_err_t memspi_host_init_pointers(spi_flash_host_driver_t *host, memspi_host_data_t *data, const memspi_host_config_t *cfg)
 {
 {
+#ifdef CONFIG_IDF_TARGET_ESP32
     memcpy(host, &esp_flash_default_host, sizeof(spi_flash_host_driver_t));
     memcpy(host, &esp_flash_default_host, sizeof(spi_flash_host_driver_t));
+#elif CONFIG_IDF_TARGET_ESP32S2BETA
+    if (cfg->host_id == SPI_HOST)
+        memcpy(host, &esp_flash_default_host, sizeof(spi_flash_host_driver_t));
+    else {
+        memcpy(host, &esp_flash_gpspi_host, sizeof(spi_flash_host_driver_t));
+    }
+#endif
+
     esp_err_t err = spi_flash_hal_init(data, cfg);
     esp_err_t err = spi_flash_hal_init(data, cfg);
     if (err != ESP_OK) {
     if (err != ESP_OK) {
         return err;
         return err;
@@ -32,7 +79,7 @@ esp_err_t memspi_host_init_pointers(spi_flash_host_driver_t *host, memspi_host_d
 
 
     host->driver_data = data;
     host->driver_data = data;
     //some functions are not required if not SPI1
     //some functions are not required if not SPI1
-    if (data->spi != &SPI1) {
+    if ((void*)data->spi != (void*)spi_flash_ll_get_hw(SPI_HOST)) {
         host->flush_cache = NULL;
         host->flush_cache = NULL;
     }
     }
     return ESP_OK;
     return ESP_OK;
@@ -40,21 +87,20 @@ esp_err_t memspi_host_init_pointers(spi_flash_host_driver_t *host, memspi_host_d
 
 
 esp_err_t memspi_host_read_id_hs(spi_flash_host_driver_t *host, uint32_t *id)
 esp_err_t memspi_host_read_id_hs(spi_flash_host_driver_t *host, uint32_t *id)
 {
 {
-    //NOTE: we do have a read id function, however it doesn't work in high freq
+    uint32_t id_buf = 0;
     spi_flash_trans_t t = {
     spi_flash_trans_t t = {
         .command = CMD_RDID,
         .command = CMD_RDID,
-        .mosi_data = 0,
-        .mosi_len = 0,
-        .miso_len = 24
+        .miso_len = 3,
+        .miso_data = ((uint8_t*) &id_buf),
     };
     };
     host->common_command(host, &t);
     host->common_command(host, &t);
-    uint32_t raw_flash_id = t.miso_data[0];
+
+    uint32_t raw_flash_id = id_buf;
     ESP_EARLY_LOGV(TAG, "raw_chip_id: %X\n", raw_flash_id);
     ESP_EARLY_LOGV(TAG, "raw_chip_id: %X\n", raw_flash_id);
     if (raw_flash_id == 0xFFFFFF || raw_flash_id == 0) {
     if (raw_flash_id == 0xFFFFFF || raw_flash_id == 0) {
         ESP_EARLY_LOGE(TAG, "no response\n");
         ESP_EARLY_LOGE(TAG, "no response\n");
         return ESP_ERR_FLASH_NO_RESPONSE;
         return ESP_ERR_FLASH_NO_RESPONSE;
     }
     }
-
     // Byte swap the flash id as it's usually written the other way around
     // Byte swap the flash id as it's usually written the other way around
     uint8_t mfg_id = raw_flash_id & 0xFF;
     uint8_t mfg_id = raw_flash_id & 0xFF;
     uint16_t flash_id = (raw_flash_id >> 16) | (raw_flash_id & 0xFF00);
     uint16_t flash_id = (raw_flash_id >> 16) | (raw_flash_id & 0xFF00);
@@ -66,24 +112,84 @@ esp_err_t memspi_host_read_id_hs(spi_flash_host_driver_t *host, uint32_t *id)
 esp_err_t memspi_host_read_status_hs(spi_flash_host_driver_t *driver, uint8_t *out_sr)
 esp_err_t memspi_host_read_status_hs(spi_flash_host_driver_t *driver, uint8_t *out_sr)
 {
 {
     //NOTE: we do have a read id function, however it doesn't work in high freq
     //NOTE: we do have a read id function, however it doesn't work in high freq
+    uint32_t stat_buf = 0;
     spi_flash_trans_t t = {
     spi_flash_trans_t t = {
         .command = CMD_RDSR,
         .command = CMD_RDSR,
-        .mosi_data = 0,
-        .mosi_len = 0,
-        .miso_len = 8
+        .miso_data = ((uint8_t*) &stat_buf),
+        .miso_len = 1
     };
     };
     esp_err_t err = driver->common_command(driver, &t);
     esp_err_t err = driver->common_command(driver, &t);
     if (err != ESP_OK) {
     if (err != ESP_OK) {
         return err;
         return err;
     }
     }
-    *out_sr = t.miso_data[0];
+    *out_sr = stat_buf;
     return ESP_OK;
     return ESP_OK;
 }
 }
 
 
 esp_err_t memspi_host_flush_cache(spi_flash_host_driver_t* driver, uint32_t addr, uint32_t size)
 esp_err_t memspi_host_flush_cache(spi_flash_host_driver_t* driver, uint32_t addr, uint32_t size)
 {
 {
-    if (((memspi_host_data_t*)(driver->driver_data))->spi == &SPI1) {
+    if ((void*)((memspi_host_data_t*)(driver->driver_data))->spi == (void*) spi_flash_ll_get_hw(SPI_HOST)) {
         spi_flash_check_and_flush_cache(addr, size);
         spi_flash_check_and_flush_cache(addr, size);
     }
     }
     return ESP_OK;
     return ESP_OK;
-}
+}
+
+void memspi_host_erase_chip(spi_flash_host_driver_t *chip_drv)
+{
+    spi_flash_trans_t t = { 0 };
+    t.command = CMD_CHIP_ERASE;
+    chip_drv->common_command(chip_drv, &t);
+}
+
+void memspi_host_erase_sector(spi_flash_host_driver_t *chip_drv, uint32_t start_address)
+{
+    spi_flash_trans_t t = { 
+        .command = CMD_SECTOR_ERASE,
+        .address_bitlen = 24,
+        .address = start_address
+    };
+    chip_drv->common_command(chip_drv, &t);
+}
+
+void memspi_host_erase_block(spi_flash_host_driver_t *chip_drv, uint32_t start_address)
+{
+    spi_flash_trans_t t = { 
+        .command = CMD_LARGE_BLOCK_ERASE,
+        .address_bitlen = 24,
+        .address = start_address,
+    };
+    chip_drv->common_command(chip_drv, &t);
+}
+
+void memspi_host_program_page(spi_flash_host_driver_t *chip_drv, const void *buffer, uint32_t address, uint32_t length)
+{
+    spi_flash_trans_t t = { 
+        .command = CMD_PROGRAM_PAGE,
+        .address_bitlen = 24,
+        .address = address,
+        .mosi_len = length,
+        .mosi_data = buffer
+    };
+    chip_drv->common_command(chip_drv, &t);
+}
+
+esp_err_t memspi_host_read(spi_flash_host_driver_t *chip_drv, void *buffer, uint32_t address, uint32_t read_len)
+{
+    spi_flash_trans_t t = {
+        .address_bitlen = 24,
+        .address = address,
+        .miso_len = read_len,
+        .miso_data = buffer
+    };
+    chip_drv->common_command(chip_drv, &t);
+    return ESP_OK;
+}
+
+esp_err_t memspi_host_set_write_protect(spi_flash_host_driver_t *chip_drv, bool wp)
+{
+    spi_flash_trans_t t = {
+        .command = wp ? CMD_WRDI : CMD_WREN
+    };
+    chip_drv->common_command(chip_drv, &t);
+    return ESP_OK;
+}

+ 3 - 4
components/spi_flash/private_include/spi_flash_defs.h

@@ -19,8 +19,8 @@
 */
 */
 #define CMD_RDID       0x9F
 #define CMD_RDID       0x9F
 #define CMD_WRSR       0x01
 #define CMD_WRSR       0x01
-#define  SR_WIP        (1<<0) /* Status register write-in-progress bit */
-#define  SR_WREN       (1<<1) /* Status register write enable bit */
+#define  SR_WIP         (1<<0) /* Status register write-in-progress bit */
+#define  SR_WREN        (1<<1) /* Status register write enable bit */
 #define CMD_WRSR2      0x31 /* Not all SPI flash uses this command */
 #define CMD_WRSR2      0x31 /* Not all SPI flash uses this command */
 #define CMD_WREN       0x06
 #define CMD_WREN       0x06
 #define CMD_WRDI       0x04
 #define CMD_WRDI       0x04
@@ -37,8 +37,7 @@
 #define CMD_CHIP_ERASE 0xC7
 #define CMD_CHIP_ERASE 0xC7
 #define CMD_SECTOR_ERASE 0x20
 #define CMD_SECTOR_ERASE 0x20
 #define CMD_LARGE_BLOCK_ERASE 0xD8 /* 64KB block erase command */
 #define CMD_LARGE_BLOCK_ERASE 0xD8 /* 64KB block erase command */
+#define CMD_PROGRAM_PAGE 0x02
 
 
 #define CMD_RST_EN      0x66
 #define CMD_RST_EN      0x66
 #define CMD_RST_DEV     0x99
 #define CMD_RST_DEV     0x99
-
-

+ 12 - 7
components/spi_flash/spi_flash_chip_generic.c

@@ -140,7 +140,12 @@ esp_err_t spi_flash_chip_generic_read(esp_flash_t *chip, void *buffer, uint32_t
 {
 {
     esp_err_t err = ESP_OK;
     esp_err_t err = ESP_OK;
     // Configure the host, and return
     // Configure the host, and return
-    spi_flash_chip_generic_config_host_io_mode(chip);
+    err = spi_flash_chip_generic_config_host_io_mode(chip);
+
+    if (err == ESP_ERR_NOT_SUPPORTED) {
+        ESP_LOGE(TAG, "configure host io mode failed - unsupported");
+        return err;
+    }
 
 
     while (err == ESP_OK && length > 0) {
     while (err == ESP_OK && length > 0) {
         uint32_t read_len = MIN(length, chip->host->max_read_bytes);
         uint32_t read_len = MIN(length, chip->host->max_read_bytes);
@@ -386,14 +391,14 @@ const spi_flash_chip_t esp_flash_chip_generic = {
 
 
 static esp_err_t spi_flash_common_read_qe_sr(esp_flash_t *chip, uint8_t qe_rdsr_command, uint8_t qe_sr_bitwidth, uint32_t *sr)
 static esp_err_t spi_flash_common_read_qe_sr(esp_flash_t *chip, uint8_t qe_rdsr_command, uint8_t qe_sr_bitwidth, uint32_t *sr)
 {
 {
+    uint32_t sr_buf = 0;
     spi_flash_trans_t t = {
     spi_flash_trans_t t = {
         .command = qe_rdsr_command,
         .command = qe_rdsr_command,
-        .mosi_data = 0,
-        .mosi_len = 0,
-        .miso_len = qe_sr_bitwidth,
+        .miso_data = (uint8_t*) &sr_buf,
+        .miso_len = qe_sr_bitwidth / 8,
     };
     };
     esp_err_t ret = chip->host->common_command(chip->host, &t);
     esp_err_t ret = chip->host->common_command(chip->host, &t);
-    *sr = t.miso_data[0];
+    *sr = sr_buf;
     return ret;
     return ret;
 }
 }
 
 
@@ -401,8 +406,8 @@ static esp_err_t spi_flash_common_write_qe_sr(esp_flash_t *chip, uint8_t qe_wrsr
 {
 {
     spi_flash_trans_t t = {
     spi_flash_trans_t t = {
         .command = qe_wrsr_command,
         .command = qe_wrsr_command,
-        .mosi_data = qe,
-        .mosi_len = qe_sr_bitwidth,
+        .mosi_data = ((uint8_t*) &qe),
+        .mosi_len = qe_sr_bitwidth / 8,
         .miso_len = 0,
         .miso_len = 0,
     };
     };
     return chip->host->common_command(chip->host, &t);
     return chip->host->common_command(chip->host, &t);

+ 23 - 8
components/spi_flash/spi_flash_os_func_app.c

@@ -17,6 +17,7 @@
 #include "esp_spi_flash.h"   //for ``g_flash_guard_default_ops``
 #include "esp_spi_flash.h"   //for ``g_flash_guard_default_ops``
 #include "esp_flash.h"
 #include "esp_flash.h"
 #include "esp_flash_partitions.h"
 #include "esp_flash_partitions.h"
+#include "hal/spi_types.h"
 
 
 
 
 #ifdef CONFIG_IDF_TARGET_ESP32
 #ifdef CONFIG_IDF_TARGET_ESP32
@@ -99,23 +100,29 @@ static IRAM_ATTR esp_err_t main_flash_region_protected(void* arg, size_t start_a
 }
 }
 
 
 static DRAM_ATTR spi1_app_func_arg_t spi1_arg = {
 static DRAM_ATTR spi1_app_func_arg_t spi1_arg = {
-    .host_id = 0,   //for SPI1,
+    .host_id = SPI1_HOST,   //for SPI1,
     .no_protect = true,
     .no_protect = true,
 };
 };
 
 
 static DRAM_ATTR spi1_app_func_arg_t main_flash_arg = {
 static DRAM_ATTR spi1_app_func_arg_t main_flash_arg = {
-    .host_id = 0,   //for SPI1,
+    .host_id = SPI1_HOST,   //for SPI1,
     .no_protect = false,
     .no_protect = false,
 };
 };
 
 
 static app_func_arg_t spi2_arg = {
 static app_func_arg_t spi2_arg = {
-    .host_id = 1,   //for SPI2,
+    .host_id = SPI2_HOST,   //for SPI2,
 };
 };
 
 
 static app_func_arg_t spi3_arg = {
 static app_func_arg_t spi3_arg = {
-    .host_id = 2,   //for SPI3,
+    .host_id = SPI3_HOST,   //for SPI3,
 };
 };
 
 
+#ifdef CONFIG_IDF_TARGET_ESP32S2BETA
+static app_func_arg_t spi4_arg = {
+    .host_id = SPI4_HOST,   //for SPI4,
+};
+#endif
+
 //for SPI1, we have to disable the cache and interrupts before using the SPI bus
 //for SPI1, we have to disable the cache and interrupts before using the SPI bus
 const DRAM_ATTR esp_flash_os_functions_t esp_flash_spi1_default_os_functions = {
 const DRAM_ATTR esp_flash_os_functions_t esp_flash_spi1_default_os_functions = {
     .start = spi1_start,
     .start = spi1_start,
@@ -132,14 +139,22 @@ const esp_flash_os_functions_t esp_flash_spi23_default_os_functions = {
 
 
 esp_err_t esp_flash_init_os_functions(esp_flash_t *chip, int host_id)
 esp_err_t esp_flash_init_os_functions(esp_flash_t *chip, int host_id)
 {
 {
-    if (host_id == 0) {
+    if (host_id == SPI1_HOST) {
         //SPI1
         //SPI1
         chip->os_func = &esp_flash_spi1_default_os_functions;
         chip->os_func = &esp_flash_spi1_default_os_functions;
         chip->os_func_data = &spi1_arg;
         chip->os_func_data = &spi1_arg;
-    } else if (host_id == 1 || host_id == 2) {
-        //SPI2,3
+    } else if (host_id == SPI2_HOST || host_id == SPI3_HOST
+#ifdef CONFIG_IDF_TARGET_ESP32S2BETA
+        || host_id == SPI4_HOST
+#endif
+    ) {
+        //SPI2,3,4
         chip->os_func = &esp_flash_spi23_default_os_functions;
         chip->os_func = &esp_flash_spi23_default_os_functions;
-        chip->os_func_data = (host_id == 1) ? &spi2_arg : &spi3_arg;
+#if CONFIG_IDF_TARGET_ESP32
+        chip->os_func_data = (host_id == SPI2_HOST) ? &spi2_arg : &spi3_arg;
+#elif CONFIG_IDF_TARGET_ESP32S2BETA
+        chip->os_func_data = (host_id == SPI2_HOST) ? &spi2_arg : ((host_id == SPI3_HOST) ? &spi3_arg : &spi4_arg);
+#endif
     } else {
     } else {
         return ESP_ERR_INVALID_ARG;
         return ESP_ERR_INVALID_ARG;
     }
     }

+ 30 - 2
components/spi_flash/spi_flash_os_func_noos.c

@@ -17,28 +17,51 @@
 #include "esp_flash.h"
 #include "esp_flash.h"
 #include "esp_attr.h"
 #include "esp_attr.h"
 
 
-#ifdef CONFIG_IDF_TARGET_ESP32
+#if CONFIG_IDF_TARGET_ESP32
 #include "esp32/rom/ets_sys.h"
 #include "esp32/rom/ets_sys.h"
 #include "esp32/rom/cache.h"
 #include "esp32/rom/cache.h"
-#else
+#elif CONFIG_IDF_TARGET_ESP32S2BETA
 #include "esp32s2beta/rom/ets_sys.h"
 #include "esp32s2beta/rom/ets_sys.h"
 #include "esp32s2beta/rom/cache.h"
 #include "esp32s2beta/rom/cache.h"
 #endif
 #endif
 
 
+#include "esp_attr.h"
+
+#if CONFIG_IDF_TARGET_ESP32S2BETA
+typedef struct {
+    uint32_t icache_autoload;
+    uint32_t dcache_autoload;
+} spi_noos_arg_t; 
+
+static DRAM_ATTR spi_noos_arg_t spi_arg = { 0 };
+#endif
 
 
 static IRAM_ATTR esp_err_t start(void *arg)
 static IRAM_ATTR esp_err_t start(void *arg)
 {
 {
+#if CONFIG_IDF_TARGET_ESP32
     Cache_Read_Disable(0);
     Cache_Read_Disable(0);
     Cache_Read_Disable(1);
     Cache_Read_Disable(1);
+#elif CONFIG_IDF_TARGET_ESP32S2BETA
+    spi_noos_arg_t *spi_arg = arg;
+    spi_arg->icache_autoload = Cache_Suspend_ICache();
+    spi_arg->dcache_autoload = Cache_Suspend_DCache();
+#endif
     return ESP_OK;
     return ESP_OK;
 }
 }
 
 
 static IRAM_ATTR esp_err_t end(void *arg)
 static IRAM_ATTR esp_err_t end(void *arg)
 {
 {
+#if CONFIG_IDF_TARGET_ESP32
     Cache_Flush(0);
     Cache_Flush(0);
     Cache_Flush(1);
     Cache_Flush(1);
     Cache_Read_Enable(0);
     Cache_Read_Enable(0);
     Cache_Read_Enable(1);
     Cache_Read_Enable(1);
+#elif CONFIG_IDF_TARGET_ESP32S2BETA
+    spi_noos_arg_t *spi_arg = arg;
+    Cache_Invalidate_ICache_All();
+    Cache_Resume_ICache(spi_arg->icache_autoload);
+    Cache_Resume_DCache(spi_arg->dcache_autoload);
+#endif
     return ESP_OK;
     return ESP_OK;
 }
 }
 
 
@@ -58,5 +81,10 @@ const DRAM_ATTR esp_flash_os_functions_t esp_flash_noos_functions = {
 esp_err_t IRAM_ATTR esp_flash_app_disable_os_functions(esp_flash_t* chip)
 esp_err_t IRAM_ATTR esp_flash_app_disable_os_functions(esp_flash_t* chip)
 {
 {
     chip->os_func = &esp_flash_noos_functions;
     chip->os_func = &esp_flash_noos_functions;
+
+#if CONFIG_IDF_TARGET_ESP32S2BETA
+    chip->os_func_data = &spi_arg;
+#endif
+
     return ESP_OK;
     return ESP_OK;
 }
 }

+ 4 - 10
components/spi_flash/test/CMakeLists.txt

@@ -1,15 +1,9 @@
-set(src_dirs ".")
-set(exclude_srcs)
-
-if(IDF_TARGET STREQUAL "esp32")
-    list(APPEND src_dirs "esp32")
-    if(CONFIG_SPI_FLASH_USE_LEGACY_IMPL)
-        set(exclude_srcs "esp32/test_esp_flash.c" "esp32/test_partition_ext.c")
-    endif()
+if(CONFIG_SPI_FLASH_USE_LEGACY_IMPL)
+    set(exclude_srcs "test_esp_flash.c" "test_partition_ext.c")
 endif()
 endif()
 
 
-idf_component_register(SRC_DIRS ${src_dirs}
-                       EXCLUDE_SRCS ${exclude_srcs}
+idf_component_register(SRC_DIRS "."
+                       EXCLUDE_SRCS "${exclude_srcs}"
                        INCLUDE_DIRS "."
                        INCLUDE_DIRS "."
                        REQUIRES unity test_utils spi_flash bootloader_support app_update)
                        REQUIRES unity test_utils spi_flash bootloader_support app_update)
 
 

+ 132 - 32
components/spi_flash/test/esp32/test_esp_flash.c → components/spi_flash/test/test_esp_flash.c

@@ -18,27 +18,55 @@
 #include "soc/io_mux_reg.h"
 #include "soc/io_mux_reg.h"
 #include "sdkconfig.h"
 #include "sdkconfig.h"
 
 
+#include "hal/spi_flash_hal.h"
+
 #define FUNC_SPI    1
 #define FUNC_SPI    1
 
 
 static uint8_t sector_buf[4096];
 static uint8_t sector_buf[4096];
 
 
 #define TEST_SPI_SPEED      ESP_FLASH_10MHZ
 #define TEST_SPI_SPEED      ESP_FLASH_10MHZ
 #define TEST_SPI_READ_MODE  SPI_FLASH_FASTRD
 #define TEST_SPI_READ_MODE  SPI_FLASH_FASTRD
-//#define FORCE_GPIO_MATRIX
+// #define FORCE_GPIO_MATRIX
 
 
 #define EXTRA_SPI1_CLK_IO   17  //the pin which is usually used by the PSRAM clk
 #define EXTRA_SPI1_CLK_IO   17  //the pin which is usually used by the PSRAM clk
 
 
+#if CONFIG_IDF_TARGET_ESP32
 #define HSPI_PIN_NUM_MOSI   HSPI_IOMUX_PIN_NUM_MOSI
 #define HSPI_PIN_NUM_MOSI   HSPI_IOMUX_PIN_NUM_MOSI
 #define HSPI_PIN_NUM_MISO   HSPI_IOMUX_PIN_NUM_MISO
 #define HSPI_PIN_NUM_MISO   HSPI_IOMUX_PIN_NUM_MISO
 #define HSPI_PIN_NUM_CLK    HSPI_IOMUX_PIN_NUM_CLK
 #define HSPI_PIN_NUM_CLK    HSPI_IOMUX_PIN_NUM_CLK
 #define HSPI_PIN_NUM_HD     HSPI_IOMUX_PIN_NUM_HD
 #define HSPI_PIN_NUM_HD     HSPI_IOMUX_PIN_NUM_HD
 #define HSPI_PIN_NUM_WP     HSPI_IOMUX_PIN_NUM_WP
 #define HSPI_PIN_NUM_WP     HSPI_IOMUX_PIN_NUM_WP
+#define HSPI_PIN_NUM_CS     HSPI_IOMUX_PIN_NUM_CS
 
 
 #define VSPI_PIN_NUM_MOSI   VSPI_IOMUX_PIN_NUM_MOSI
 #define VSPI_PIN_NUM_MOSI   VSPI_IOMUX_PIN_NUM_MOSI
 #define VSPI_PIN_NUM_MISO   VSPI_IOMUX_PIN_NUM_MISO
 #define VSPI_PIN_NUM_MISO   VSPI_IOMUX_PIN_NUM_MISO
 #define VSPI_PIN_NUM_CLK    VSPI_IOMUX_PIN_NUM_CLK
 #define VSPI_PIN_NUM_CLK    VSPI_IOMUX_PIN_NUM_CLK
 #define VSPI_PIN_NUM_HD     VSPI_IOMUX_PIN_NUM_HD
 #define VSPI_PIN_NUM_HD     VSPI_IOMUX_PIN_NUM_HD
 #define VSPI_PIN_NUM_WP     VSPI_IOMUX_PIN_NUM_WP
 #define VSPI_PIN_NUM_WP     VSPI_IOMUX_PIN_NUM_WP
+#define VSPI_PIN_NUM_CS     VSPI_IOMUX_PIN_NUM_CS
+#elif CONFIG_IDF_TARGET_ESP32S2BETA
+#define FSPI_PIN_NUM_MOSI   FSPI_IOMUX_PIN_NUM_MOSI
+#define FSPI_PIN_NUM_MISO   FSPI_IOMUX_PIN_NUM_MISO
+#define FSPI_PIN_NUM_CLK    FSPI_IOMUX_PIN_NUM_CLK
+#define FSPI_PIN_NUM_HD     FSPI_IOMUX_PIN_NUM_HD
+#define FSPI_PIN_NUM_WP     FSPI_IOMUX_PIN_NUM_WP
+#define FSPI_PIN_NUM_CS     FSPI_IOMUX_PIN_NUM_CS
+
+// Just use the same pins for HSPI and VSPI
+#define HSPI_PIN_NUM_MOSI   FSPI_PIN_NUM_MOSI
+#define HSPI_PIN_NUM_MISO   FSPI_PIN_NUM_MISO
+#define HSPI_PIN_NUM_CLK    FSPI_PIN_NUM_CLK
+#define HSPI_PIN_NUM_HD     FSPI_PIN_NUM_HD
+#define HSPI_PIN_NUM_WP     FSPI_PIN_NUM_WP
+#define HSPI_PIN_NUM_CS     FSPI_PIN_NUM_CS
+
+#define VSPI_PIN_NUM_MOSI   FSPI_PIN_NUM_MOSI
+#define VSPI_PIN_NUM_MISO   FSPI_PIN_NUM_MISO
+#define VSPI_PIN_NUM_CLK    FSPI_PIN_NUM_CLK
+#define VSPI_PIN_NUM_HD     FSPI_PIN_NUM_HD
+#define VSPI_PIN_NUM_WP     FSPI_PIN_NUM_WP
+#define VSPI_PIN_NUM_CS     FSPI_PIN_NUM_CS
+#endif
 
 
 #define ALL_TEST_NUM (sizeof(config_list)/sizeof(flashtest_config_t))
 #define ALL_TEST_NUM (sizeof(config_list)/sizeof(flashtest_config_t))
 typedef void (*flash_test_func_t)(esp_flash_t* chip);
 typedef void (*flash_test_func_t)(esp_flash_t* chip);
@@ -50,7 +78,7 @@ typedef void (*flash_test_func_t)(esp_flash_t* chip);
 #define FLASH_TEST_CASE_3(STR, FUNCT_TO_RUN)
 #define FLASH_TEST_CASE_3(STR, FUNCT_TO_RUN)
 #else
 #else
 #define FLASH_TEST_CASE_3(STR, FUNC_TO_RUN) \
 #define FLASH_TEST_CASE_3(STR, FUNC_TO_RUN) \
-    TEST_CASE(STR", 3 chips", "[esp_flash][test_env=UT_T1_ESP_FLASH]") {flash_test_func(FUNC_TO_RUN, ALL_TEST_NUM);}
+    TEST_CASE_ESP32(STR", 3 chips", "[esp_flash][test_env=UT_T1_ESP_FLASH]") {flash_test_func(FUNC_TO_RUN, ALL_TEST_NUM);}
 #endif
 #endif
 
 
 //currently all the configs are the same with esp_flash_spi_device_config_t, no more information required
 //currently all the configs are the same with esp_flash_spi_device_config_t, no more information required
@@ -58,38 +86,68 @@ typedef esp_flash_spi_device_config_t flashtest_config_t;
 
 
 static const char TAG[] = "test_esp_flash";
 static const char TAG[] = "test_esp_flash";
 
 
+#define FLASHTEST_CONFIG_COMMON     \
+    /* 0 always reserved for main flash */ \
+    { \
+        /* no need to init */ \
+        .host_id = -1, \
+    }, \
+    { \
+        .io_mode = TEST_SPI_READ_MODE,\
+        .speed = TEST_SPI_SPEED, \
+        .host_id = SPI_HOST, \
+        .cs_id = 1, \
+        /* the pin which is usually used by the PSRAM */ \
+        .cs_io_num = 16, \
+        .input_delay_ns = 0, \
+    } 
+
+#if CONFIG_IDF_TARGET_ESP32
 flashtest_config_t config_list[] = {
 flashtest_config_t config_list[] = {
-    // 0 always reserved for main flash
-    {
-        .host_id = -1, // no need to init
-    },
-    {
-        .io_mode = TEST_SPI_READ_MODE,
-        .speed = TEST_SPI_SPEED,
-        .host_id = SPI_HOST,
-        .cs_id = 1,
-        .cs_io_num = 16, //the pin which is usually used by the PSRAM
-        .input_delay_ns = 0,
-    },
-    /* current runner doesn't have a flash on HSPI
-    {
-        .io_mode = TEST_SPI_READ_MODE,
-        .speed = TEST_SPI_SPEED,
-        .host = HSPI_HOST,
-        .cs_id = 0,
-        .cs_io_num = HSPI_IOMUX_PIN_NUM_CS,
-        .input_delay_ns = 20,
-    },
-    */
+    FLASHTEST_CONFIG_COMMON,
+    /* current runner doesn't have a flash on HSPI */
+    // {
+    //     .io_mode = TEST_SPI_READ_MODE,
+    //     .speed = TEST_SPI_SPEED,
+    //     .host_id = HSPI_HOST,
+    //     .cs_id = 0,
+    //     // uses GPIO matrix on esp32s2beta regardles if FORCE_GPIO_MATRIX
+    //     .cs_io_num = HSPI_PIN_NUM_CS, 
+    //     .input_delay_ns = 20,
+    // },
     {
     {
         .io_mode = TEST_SPI_READ_MODE,
         .io_mode = TEST_SPI_READ_MODE,
         .speed = TEST_SPI_SPEED,
         .speed = TEST_SPI_SPEED,
         .host_id = VSPI_HOST,
         .host_id = VSPI_HOST,
         .cs_id = 0,
         .cs_id = 0,
-        .cs_io_num = VSPI_IOMUX_PIN_NUM_CS,
+        .cs_io_num = VSPI_PIN_NUM_CS, 
         .input_delay_ns = 0,
         .input_delay_ns = 0,
     },
     },
 };
 };
+#elif CONFIG_IDF_TARGET_ESP32S2BETA
+flashtest_config_t config_list[] = {
+    FLASHTEST_CONFIG_COMMON,
+    /* No runners for esp32s2beta for these config yet */
+    // {
+    //     .io_mode = TEST_SPI_READ_MODE,
+    //     .speed = TEST_SPI_SPEED,
+    //     .host_id = FSPI_HOST,
+    //     .cs_id = 0,
+    //     .cs_io_num = FSPI_PIN_NUM_CS,
+    //     .input_delay_ns = 0,
+    // },
+    // /* current runner doesn't have a flash on HSPI */
+    // {
+    //     .io_mode = TEST_SPI_READ_MODE,
+    //     .speed = TEST_SPI_SPEED,
+    //     .host_id = HSPI_HOST,
+    //     .cs_id = 0,
+    //     // uses GPIO matrix on esp32s2beta regardles if FORCE_GPIO_MATRIX
+    //     .cs_io_num = HSPI_PIN_NUM_CS, 
+    //     .input_delay_ns = 20,
+    // },
+};
+#endif
 
 
 static void setup_bus(spi_host_device_t host_id)
 static void setup_bus(spi_host_device_t host_id)
 {
 {
@@ -98,10 +156,27 @@ static void setup_bus(spi_host_device_t host_id)
         //no need to initialize the bus, however the CLK may need one more output if it's on the usual place of PSRAM
         //no need to initialize the bus, however the CLK may need one more output if it's on the usual place of PSRAM
 #ifdef EXTRA_SPI1_CLK_IO
 #ifdef EXTRA_SPI1_CLK_IO
         gpio_matrix_out(EXTRA_SPI1_CLK_IO, SPICLK_OUT_IDX, 0, 0);
         gpio_matrix_out(EXTRA_SPI1_CLK_IO, SPICLK_OUT_IDX, 0, 0);
+#endif
+#if CONFIG_IDF_TARGET_ESP32S2BETA
+    } else if (host_id == FSPI_HOST) {
+        ESP_LOGI(TAG, "setup flash on SPI%d (FSPI) CS0...\n", host_id + 1);
+        spi_bus_config_t fspi_bus_cfg = {
+            .mosi_io_num = FSPI_PIN_NUM_MOSI,
+            .miso_io_num = FSPI_PIN_NUM_MISO,
+            .sclk_io_num = FSPI_PIN_NUM_CLK,
+            .quadhd_io_num = FSPI_PIN_NUM_HD,
+            .quadwp_io_num = FSPI_PIN_NUM_WP,
+            .max_transfer_sz = 64,
+        };
+#ifdef FORCE_GPIO_MATRIX
+        fspi_bus_cfg.quadhd_io_num = 5;
+#endif
+        esp_err_t ret = spi_bus_initialize(host_id, &fspi_bus_cfg, 0);
+        TEST_ESP_OK(ret);
 #endif
 #endif
         //currently the SPI bus for main flash chip is initialized through GPIO matrix
         //currently the SPI bus for main flash chip is initialized through GPIO matrix
     } else if (host_id == HSPI_HOST) {
     } else if (host_id == HSPI_HOST) {
-        ESP_LOGI(TAG, "setup flash on SPI2 (HSPI) CS0...\n");
+        ESP_LOGI(TAG, "setup flash on SPI%d (HSPI) CS0...\n", host_id + 1);
         spi_bus_config_t hspi_bus_cfg = {
         spi_bus_config_t hspi_bus_cfg = {
             .mosi_io_num = HSPI_PIN_NUM_MOSI,
             .mosi_io_num = HSPI_PIN_NUM_MOSI,
             .miso_io_num = HSPI_PIN_NUM_MISO,
             .miso_io_num = HSPI_PIN_NUM_MISO,
@@ -110,13 +185,26 @@ static void setup_bus(spi_host_device_t host_id)
             .quadwp_io_num = HSPI_PIN_NUM_WP,
             .quadwp_io_num = HSPI_PIN_NUM_WP,
             .max_transfer_sz = 64,
             .max_transfer_sz = 64,
         };
         };
+#ifdef CONFIG_IDF_TARGET_ESP32
 #ifdef FORCE_GPIO_MATRIX
 #ifdef FORCE_GPIO_MATRIX
         hspi_bus_cfg.quadhd_io_num = 23;
         hspi_bus_cfg.quadhd_io_num = 23;
+#endif
 #endif
 #endif
         esp_err_t ret = spi_bus_initialize(host_id, &hspi_bus_cfg, 0);
         esp_err_t ret = spi_bus_initialize(host_id, &hspi_bus_cfg, 0);
         TEST_ESP_OK(ret);
         TEST_ESP_OK(ret);
-    } else if (host_id == VSPI_HOST) {
-        ESP_LOGI(TAG, "setup flash on SPI3 (VSPI) CS0...\n");
+
+#ifdef CONFIG_IDF_TARGET_ESP32S2BETA
+        // HSPI have no multiline mode, use GPIO to pull those pins up
+        gpio_set_direction(HSPI_PIN_NUM_HD, GPIO_MODE_OUTPUT);
+        gpio_set_level(HSPI_PIN_NUM_HD, 1);
+
+        gpio_set_direction(HSPI_PIN_NUM_WP, GPIO_MODE_OUTPUT);
+        gpio_set_level(HSPI_PIN_NUM_WP, 1);
+#endif
+    }  
+#if CONFIG_IDF_TARGET_ESP32
+    else if (host_id == VSPI_HOST) {
+        ESP_LOGI(TAG, "setup flash on SPI%d (VSPI) CS0...\n", host_id + 1);
         spi_bus_config_t vspi_bus_cfg = {
         spi_bus_config_t vspi_bus_cfg = {
             .mosi_io_num = VSPI_PIN_NUM_MOSI,
             .mosi_io_num = VSPI_PIN_NUM_MOSI,
             .miso_io_num = VSPI_PIN_NUM_MISO,
             .miso_io_num = VSPI_PIN_NUM_MISO,
@@ -130,14 +218,20 @@ static void setup_bus(spi_host_device_t host_id)
 #endif
 #endif
         esp_err_t ret = spi_bus_initialize(host_id, &vspi_bus_cfg, 0);
         esp_err_t ret = spi_bus_initialize(host_id, &vspi_bus_cfg, 0);
         TEST_ESP_OK(ret);
         TEST_ESP_OK(ret);
-    } else {
+    } 
+#endif // CONFIG_IDF_TARGET_ESP32
+    else {
         ESP_LOGE(TAG, "invalid bus");
         ESP_LOGE(TAG, "invalid bus");
     }
     }
 }
 }
 
 
 static void release_bus(int host_id)
 static void release_bus(int host_id)
 {
 {
+#if CONFIG_IDF_TARGET_ESP32
     if (host_id == HSPI_HOST || host_id == VSPI_HOST) {
     if (host_id == HSPI_HOST || host_id == VSPI_HOST) {
+#elif CONFIG_IDF_TARGET_ESP32S2BETA
+    if (host_id == FSPI_HOST || host_id == HSPI_HOST || host_id == VSPI_HOST) {
+#endif
         spi_bus_free(host_id);
         spi_bus_free(host_id);
     }
     }
 }
 }
@@ -479,7 +573,6 @@ void test_permutations(flashtest_config_t* config)
     read_and_check(chip, part, source_buf, length);
     read_and_check(chip, part, source_buf, length);
     teardown_test_chip(chip, cfg->host_id);
     teardown_test_chip(chip, cfg->host_id);
 
 
-
     if (config->host_id != -1) {
     if (config->host_id != -1) {
         esp_flash_speed_t speed = ESP_FLASH_SPEED_MIN;
         esp_flash_speed_t speed = ESP_FLASH_SPEED_MIN;
         while (speed != ESP_FLASH_SPEED_MAX) {
         while (speed != ESP_FLASH_SPEED_MAX) {
@@ -487,10 +580,17 @@ void test_permutations(flashtest_config_t* config)
             //the io mode will switch frequently.
             //the io mode will switch frequently.
             esp_flash_io_mode_t io_mode = SPI_FLASH_READ_MODE_MIN;
             esp_flash_io_mode_t io_mode = SPI_FLASH_READ_MODE_MIN;
             while (io_mode != SPI_FLASH_READ_MODE_MAX) {
             while (io_mode != SPI_FLASH_READ_MODE_MAX) {
-                ESP_LOGI(TAG, "test flash io mode: %d, speed: %d", io_mode, speed);
                 cfg->io_mode = io_mode;
                 cfg->io_mode = io_mode;
                 cfg->speed = speed;
                 cfg->speed = speed;
                 setup_new_chip(cfg, &chip);
                 setup_new_chip(cfg, &chip);
+
+                if (io_mode > SPI_FLASH_FASTRD 
+                    && !SOC_SPI_PERIPH_SUPPORT_MULTILINE_MODE(((spi_flash_memspi_data_t *)chip->host->driver_data)->spi)) {
+                    continue;
+                }
+
+                ESP_LOGI(TAG, "test flash io mode: %d, speed: %d", io_mode, speed);
+
                 read_and_check(chip, part, source_buf, length);
                 read_and_check(chip, part, source_buf, length);
                 teardown_test_chip(chip, cfg->host_id);
                 teardown_test_chip(chip, cfg->host_id);
                 io_mode++;
                 io_mode++;
@@ -512,7 +612,7 @@ TEST_CASE("SPI flash test reading with all speed/mode permutations", "[esp_flash
 }
 }
 
 
 #ifndef CONFIG_ESP32_SPIRAM_SUPPORT
 #ifndef CONFIG_ESP32_SPIRAM_SUPPORT
-TEST_CASE("SPI flash test reading with all speed/mode permutations, 3 chips", "[esp_flash][test_env=UT_T1_ESP_FLASH]")
+TEST_CASE_ESP32("SPI flash test reading with all speed/mode permutations, 3 chips", "[esp_flash][test_env=UT_T1_ESP_FLASH]")
 {
 {
     for (int i = 0; i < ALL_TEST_NUM; i++) {
     for (int i = 0; i < ALL_TEST_NUM; i++) {
         test_permutations(&config_list[i]);
         test_permutations(&config_list[i]);

+ 1 - 1
components/spi_flash/test/esp32/test_partition_ext.c → components/spi_flash/test/test_partition_ext.c

@@ -3,7 +3,7 @@
 #include "unity.h"
 #include "unity.h"
 
 
 
 
-TEST_CASE("Basic handling of a partition in external flash", "[partition]")
+TEST_CASE_ESP32("Basic handling of a partition in external flash", "[partition]")
 {
 {
     esp_flash_t flash = {
     esp_flash_t flash = {
             .size = 1 * 1024 * 1024,
             .size = 1 * 1024 * 1024,

+ 2 - 0
examples/bluetooth/esp_ble_mesh/ble_mesh_wifi_coexist/sdkconfig.defaults

@@ -80,5 +80,7 @@ CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
 CONFIG_ESPTOOLPY_FLASHFREQ_40M=y
 CONFIG_ESPTOOLPY_FLASHFREQ_40M=y
 CONFIG_LWIP_IRAM_OPTIMIZATION=y
 CONFIG_LWIP_IRAM_OPTIMIZATION=y
 
 
+CONFIG_ESP32_WIFI_RX_IRAM_OPT=n
+
 CONFIG_PARTITION_TABLE_CUSTOM=y
 CONFIG_PARTITION_TABLE_CUSTOM=y
 CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
 CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y

+ 1 - 1
tools/ci/config/target-test.yml

@@ -460,7 +460,7 @@ UT_034:
 
 
 UT_035:
 UT_035:
   extends: .unit_test_template
   extends: .unit_test_template
-  parallel: 16
+  parallel: 38
   tags:
   tags:
     - ESP32S2BETA_IDF
     - ESP32S2BETA_IDF
     - UT_T1_1
     - UT_T1_1

+ 4 - 0
tools/unit-test-app/configs/spi_flash_legacy_s2

@@ -0,0 +1,4 @@
+TEST_COMPONENTS=spi_flash
+CONFIG_ESP32_SPIRAM_SUPPORT=y
+CONFIG_SPI_FLASH_USE_LEGACY_IMPL=y
+CONFIG_IDF_TARGET="esp32s2beta"