Ver código fonte

spi_flash: mocking should be possible now

The following three headers will be mockes:
* esp_flash.h
* esp_spi_flash.h
* esp_partition.h
* counter functions live in own header
* add spi_flash sim dir for esp_err.h to Unity
* modified gen_esp_err_to_name.py to ignore
  sim/ dir in spi_flash component

Add cmock .yaml config file
Add spi hal header until soc can mock the hal
  layer as well.
Jakob Hasse 5 anos atrás
pai
commit
c233ce0449

+ 118 - 56
components/spi_flash/CMakeLists.txt

@@ -1,63 +1,125 @@
-if(BOOTLOADER_BUILD)
-    if(CONFIG_IDF_TARGET_ESP32)
-        # ESP32 Bootloader needs SPIUnlock from this file, but doesn't
-        # need other parts of this component
-        set(srcs "esp32/spi_flash_rom_patch.c")
-    elseif(CONFIG_IDF_TARGET_ESP32S2)
-        set(srcs "esp32s2/spi_flash_rom_patch.c")
-    elseif(CONFIG_IDF_TARGET_ESP32S3)
-        set(srcs "esp32s3/spi_flash_rom_patch.c")
+idf_build_get_property(spi_flash_mock CONFIG_SPI_FLASH_MOCK)
+idf_build_get_property(target IDF_TARGET)
+if(${spi_flash_mock})
+
+    message(STATUS "building SPI FLASH MOCKS")
+
+    set(IDF_PATH $ENV{IDF_PATH})
+    set(CMOCK_DIR "${IDF_PATH}/components/cmock/CMock")
+    set(MOCK_GEN_DIR "${CMAKE_CURRENT_BINARY_DIR}/mocks")
+
+    file(MAKE_DIRECTORY ${MOCK_GEN_DIR})
+
+    set(MOCK_OUTPUT
+        "${MOCK_GEN_DIR}/Mockesp_partition.c" "${MOCK_GEN_DIR}/Mockesp_partition.h"
+        "${MOCK_GEN_DIR}/Mockesp_flash.c" "${MOCK_GEN_DIR}/Mockesp_flash.h"
+        "${MOCK_GEN_DIR}/Mockesp_spi_flash.c" "${MOCK_GEN_DIR}/Mockesp_spi_flash.h")
+
+    set(MOCK_HEADERS
+        ${CMAKE_CURRENT_SOURCE_DIR}/include/esp_partition.h
+        ${CMAKE_CURRENT_SOURCE_DIR}/include/esp_flash.h
+        ${CMAKE_CURRENT_SOURCE_DIR}/include/esp_spi_flash.h
+        )
+
+    set(ENV{UNITY_DIR} "$ENV{IDF_PATH}/components/cmock/CMock")
+
+    set(include_dirs
+        "${CMAKE_CURRENT_SOURCE_DIR}/include"
+        "${MOCK_GEN_DIR}")
+
+    set(srcs "${MOCK_GEN_DIR}/Mockesp_partition.c"
+             "${MOCK_GEN_DIR}/Mockesp_spi_flash.c"
+             "${MOCK_GEN_DIR}/Mockesp_flash.c")
+
+    if(${target} STREQUAL "linux")
+        list(APPEND include_dirs
+            "${CMAKE_CURRENT_SOURCE_DIR}/../spi_flash/sim/stubs/soc/include"
+            "${CMAKE_CURRENT_SOURCE_DIR}/../spi_flash/sim/stubs/xtensa")
     endif()
-    set(cache_srcs "")
-    set(priv_requires bootloader_support soc)
+
+    idf_component_register(SRCS "${srcs}"
+                        INCLUDE_DIRS ${include_dirs}
+                        REQUIRES cmock)
+
+    # This command builds the mocks.
+    # First, environment variable UNITY_DIR is set. This is necessary to prevent unity from looking in its own submodule
+    # which doesn't work in our CI yet...
+    # The rest is a straight forward call to cmock.rb, consult cmock's documentation for more information.
+    add_custom_command(
+      OUTPUT ${MOCK_OUTPUT}
+      COMMAND ${CMAKE_COMMAND} -E env "UNITY_DIR=${IDF_PATH}/components/unity/unity"
+            ruby
+            ${CMOCK_DIR}/lib/cmock.rb
+            -o${CMAKE_CURRENT_SOURCE_DIR}/mock/mock_config.yaml
+            ${MOCK_HEADERS}
+      )
+
 else()
-    set(cache_srcs
-        "cache_utils.c"
-        "flash_mmap.c"
-        "flash_ops.c"
-        "${IDF_TARGET}/flash_ops_${IDF_TARGET}.c"
-    )
-    set(srcs
-        "partition.c")
-
-    if(CONFIG_IDF_TARGET_ESP32)
-        list(APPEND srcs
-            "esp32/spi_flash_rom_patch.c")
-    elseif(CONFIG_IDF_TARGET_ESP32S2)
-        list(APPEND srcs
-            "esp32s2/spi_flash_rom_patch.c")
-    elseif(CONFIG_IDF_TARGET_ESP32S3)
+    if(BOOTLOADER_BUILD)
+        if(CONFIG_IDF_TARGET_ESP32)
+            # ESP32 Bootloader needs SPIUnlock from this file, but doesn't
+            # need other parts of this component
+            set(srcs "esp32/spi_flash_rom_patch.c")
+        elseif(CONFIG_IDF_TARGET_ESP32S2)
+            set(srcs "esp32s2/spi_flash_rom_patch.c")
+        elseif(CONFIG_IDF_TARGET_ESP32S3)
+            set(srcs "esp32s3/spi_flash_rom_patch.c")
+        else()
+            # but on other platforms no source files are needed for bootloader
+            set(srcs)
+        endif()
+        set(cache_srcs "")
+        set(priv_requires bootloader_support soc)
+    else()
+        set(cache_srcs
+            "cache_utils.c"
+            "flash_mmap.c"
+            "flash_ops.c"
+            "${IDF_TARGET}/flash_ops_${IDF_TARGET}.c"
+        )
+        set(srcs
+            "partition.c")
+
+        if(CONFIG_IDF_TARGET_ESP32)
+            list(APPEND srcs
+                "esp32/spi_flash_rom_patch.c")
+        elseif(CONFIG_IDF_TARGET_ESP32S2)
+            list(APPEND srcs
+                "esp32s2/spi_flash_rom_patch.c")
+        elseif(CONFIG_IDF_TARGET_ESP32S3)
+            list(APPEND srcs
+                "esp32s3/spi_flash_rom_patch.c")
+        endif()
+
+        # New implementation after IDF v4.0
         list(APPEND srcs
-            "esp32s3/spi_flash_rom_patch.c")
+            "spi_flash_chip_drivers.c"
+            "spi_flash_chip_generic.c"
+            "spi_flash_chip_issi.c"
+            "spi_flash_chip_mxic.c"
+            "spi_flash_chip_gd.c"
+            "spi_flash_chip_winbond.c"
+            "memspi_host_driver.c")
+
+        list(APPEND cache_srcs
+            "esp_flash_api.c"
+            "esp_flash_spi_init.c"
+            "spi_flash_os_func_app.c"
+            "spi_flash_os_func_noos.c")
+
+        list(APPEND srcs ${cache_srcs})
+        set(priv_requires bootloader_support app_update soc esp_ipc)
     endif()
 
-    # New implementation after IDF v4.0
-    list(APPEND srcs
-        "spi_flash_chip_drivers.c"
-        "spi_flash_chip_generic.c"
-        "spi_flash_chip_issi.c"
-        "spi_flash_chip_mxic.c"
-        "spi_flash_chip_gd.c"
-        "spi_flash_chip_winbond.c"
-        "memspi_host_driver.c")
-
-    list(APPEND cache_srcs
-        "esp_flash_api.c"
-        "esp_flash_spi_init.c"
-        "spi_flash_os_func_app.c"
-        "spi_flash_os_func_noos.c")
-
-    list(APPEND srcs ${cache_srcs})
-    set(priv_requires bootloader_support app_update soc esp_ipc)
-endif()
+    idf_component_register(SRCS "${srcs}"
+                        REQUIRES hal
+                        PRIV_REQUIRES "${priv_requires}"
+                        INCLUDE_DIRS include
+                        PRIV_INCLUDE_DIRS private_include
+                        LDFRAGMENTS linker.lf)
 
-idf_component_register(SRCS "${srcs}"
-                    REQUIRES hal
-                    PRIV_REQUIRES "${priv_requires}"
-                    INCLUDE_DIRS include
-                    PRIV_INCLUDE_DIRS private_include
-                    LDFRAGMENTS linker.lf)
+    # Avoid cache miss by unexpected inlineing when built by -Os
+    set_source_files_properties(${cache_srcs} PROPERTIES COMPILE_FLAGS
+        "-fno-inline-functions -fno-inline-small-functions -fno-inline-functions-called-once")
 
-# Avoid cache miss by unexpected inlineing when built by -Os
-set_source_files_properties(${cache_srcs} PROPERTIES COMPILE_FLAGS
-    "-fno-inline-functions -fno-inline-small-functions -fno-inline-functions-called-once")
+endif()

+ 1 - 37
components/spi_flash/include/esp_spi_flash.h

@@ -20,6 +20,7 @@
 #include <stddef.h>
 #include "esp_err.h"
 #include "sdkconfig.h"
+#include "esp_spi_flash_counters.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -419,43 +420,6 @@ extern const spi_flash_guard_funcs_t g_flash_guard_default_ops;
  */
 extern const spi_flash_guard_funcs_t g_flash_guard_no_os_ops;
 
-#if CONFIG_SPI_FLASH_ENABLE_COUNTERS
-
-/**
- * Structure holding statistics for one type of operation
- */
-typedef struct {
-    uint32_t count;     // number of times operation was executed
-    uint32_t time;      // total time taken, in microseconds
-    uint32_t bytes;     // total number of bytes
-} spi_flash_counter_t;
-
-typedef struct {
-    spi_flash_counter_t read;
-    spi_flash_counter_t write;
-    spi_flash_counter_t erase;
-} spi_flash_counters_t;
-
-/**
- * @brief  Reset SPI flash operation counters
- */
-void spi_flash_reset_counters(void);
-
-/**
- * @brief  Print SPI flash operation counters
- */
-void spi_flash_dump_counters(void);
-
-/**
- * @brief  Return current SPI flash operation counters
- *
- * @return  pointer to the spi_flash_counters_t structure holding values
- *          of the operation counters
- */
-const spi_flash_counters_t* spi_flash_get_counters(void);
-
-#endif //CONFIG_SPI_FLASH_ENABLE_COUNTERS
-
 #ifdef __cplusplus
 }
 #endif

+ 66 - 0
components/spi_flash/include/esp_spi_flash_counters.h

@@ -0,0 +1,66 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "esp_err.h"
+#include "sdkconfig.h"
+
+#if CONFIG_SPI_FLASH_ENABLE_COUNTERS
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Structure holding statistics for one type of operation
+ */
+typedef struct {
+    uint32_t count;     // number of times operation was executed
+    uint32_t time;      // total time taken, in microseconds
+    uint32_t bytes;     // total number of bytes
+} spi_flash_counter_t;
+
+typedef struct {
+    spi_flash_counter_t read;
+    spi_flash_counter_t write;
+    spi_flash_counter_t erase;
+} spi_flash_counters_t;
+
+/**
+ * @brief  Reset SPI flash operation counters
+ */
+void spi_flash_reset_counters(void);
+
+/**
+ * @brief  Print SPI flash operation counters
+ */
+void spi_flash_dump_counters(void);
+
+/**
+ * @brief  Return current SPI flash operation counters
+ *
+ * @return  pointer to the spi_flash_counters_t structure holding values
+ *          of the operation counters
+ */
+const spi_flash_counters_t* spi_flash_get_counters(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //CONFIG_SPI_FLASH_ENABLE_COUNTERS
+

+ 7 - 0
components/spi_flash/mock/mock_config.yaml

@@ -0,0 +1,7 @@
+        :cmock:
+          :plugins:
+            - expect
+            - expect_any_args
+            - return_thru_ptr
+            - array
+            - callback

+ 149 - 0
components/spi_flash/sim/stubs/esp_common/esp_err.h

@@ -0,0 +1,149 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+
+#include <stdint.h>
+#include <stdio.h>
+#include <assert.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int32_t esp_err_t;
+
+/* Definitions for error constants. */
+#define ESP_OK          0       /*!< esp_err_t value indicating success (no error) */
+#define ESP_FAIL        -1      /*!< Generic esp_err_t code indicating failure */
+
+#define ESP_ERR_NO_MEM              0x101   /*!< Out of memory */
+#define ESP_ERR_INVALID_ARG         0x102   /*!< Invalid argument */
+#define ESP_ERR_INVALID_STATE       0x103   /*!< Invalid state */
+#define ESP_ERR_INVALID_SIZE        0x104   /*!< Invalid size */
+#define ESP_ERR_NOT_FOUND           0x105   /*!< Requested resource not found */
+#define ESP_ERR_NOT_SUPPORTED       0x106   /*!< Operation or feature not supported */
+#define ESP_ERR_TIMEOUT             0x107   /*!< Operation timed out */
+#define ESP_ERR_INVALID_RESPONSE    0x108   /*!< Received response was invalid */
+#define ESP_ERR_INVALID_CRC         0x109   /*!< CRC or checksum was invalid */
+#define ESP_ERR_INVALID_VERSION     0x10A   /*!< Version was invalid */
+#define ESP_ERR_INVALID_MAC         0x10B   /*!< MAC address was invalid */
+
+#define ESP_ERR_WIFI_BASE           0x3000  /*!< Starting number of WiFi error codes */
+#define ESP_ERR_MESH_BASE           0x4000  /*!< Starting number of MESH error codes */
+#define ESP_ERR_FLASH_BASE          0x6000  /*!< Starting number of flash error codes */
+
+/**
+  * @brief Returns string for esp_err_t error codes
+  *
+  * This function finds the error code in a pre-generated lookup-table and
+  * returns its string representation.
+  *
+  * The function is generated by the Python script
+  * tools/gen_esp_err_to_name.py which should be run each time an esp_err_t
+  * error is modified, created or removed from the IDF project.
+  *
+  * @param code esp_err_t error code
+  * @return string error message
+  */
+const char *esp_err_to_name(esp_err_t code);
+
+/**
+  * @brief Returns string for esp_err_t and system error codes
+  *
+  * This function finds the error code in a pre-generated lookup-table of
+  * esp_err_t errors and returns its string representation. If the error code
+  * is not found then it is attempted to be found among system errors.
+  *
+  * The function is generated by the Python script
+  * tools/gen_esp_err_to_name.py which should be run each time an esp_err_t
+  * error is modified, created or removed from the IDF project.
+  *
+  * @param code esp_err_t error code
+  * @param[out] buf buffer where the error message should be written
+  * @param buflen Size of buffer buf. At most buflen bytes are written into the buf buffer (including the terminating null byte).
+  * @return buf containing the string error message
+  */
+const char *esp_err_to_name_r(esp_err_t code, char *buf, size_t buflen);
+
+/** @cond */
+void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression) __attribute__((noreturn));
+
+/** @cond */
+void _esp_error_check_failed_without_abort(esp_err_t rc, const char *file, int line, const char *function, const char *expression);
+
+#ifndef __ASSERT_FUNC
+/* This won't happen on IDF, which defines __ASSERT_FUNC in assert.h, but it does happen when building on the host which
+   uses /usr/include/assert.h or equivalent.
+*/
+#ifdef __ASSERT_FUNCTION
+#define __ASSERT_FUNC __ASSERT_FUNCTION /* used in glibc assert.h */
+#else
+#define __ASSERT_FUNC "??"
+#endif
+#endif
+/** @endcond */
+
+/**
+ * Macro which can be used to check the error code,
+ * and terminate the program in case the code is not ESP_OK.
+ * Prints the error code, error location, and the failed statement to serial output.
+ *
+ * Disabled if assertions are disabled.
+ */
+#ifdef NDEBUG
+#define ESP_ERROR_CHECK(x) do {                                         \
+        esp_err_t __err_rc = (x);                                       \
+        (void) sizeof(__err_rc);                                        \
+    } while(0)
+#elif defined(CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT)
+#define ESP_ERROR_CHECK(x) do {                                         \
+        esp_err_t __err_rc = (x);                                       \
+        if (__err_rc != ESP_OK) {                                       \
+            abort();                                                    \
+        }                                                               \
+    } while(0)
+#else
+#define ESP_ERROR_CHECK(x) do {                                         \
+        esp_err_t __err_rc = (x);                                       \
+        if (__err_rc != ESP_OK) {                                       \
+            _esp_error_check_failed(__err_rc, __FILE__, __LINE__,       \
+                                    __ASSERT_FUNC, #x);                 \
+        }                                                               \
+    } while(0)
+#endif
+
+/**
+ * Macro which can be used to check the error code. Prints the error code, error location, and the failed statement to
+ * serial output.
+ * In comparison with ESP_ERROR_CHECK(), this prints the same error message but isn't terminating the program.
+ */
+#ifdef NDEBUG
+#define ESP_ERROR_CHECK_WITHOUT_ABORT(x) ({                                         \
+        esp_err_t __err_rc = (x);                                                   \
+        __err_rc;                                                                   \
+    })
+#else
+#define ESP_ERROR_CHECK_WITHOUT_ABORT(x) ({                                         \
+        esp_err_t __err_rc = (x);                                                   \
+        if (__err_rc != ESP_OK) {                                                   \
+            _esp_error_check_failed_without_abort(__err_rc, __FILE__, __LINE__,     \
+                                    __ASSERT_FUNC, #x);                             \
+        }                                                                           \
+        __err_rc;                                                                   \
+    })
+#endif //NDEBUG
+
+#ifdef __cplusplus
+}
+#endif

+ 148 - 0
components/spi_flash/sim/stubs/soc/include/hal/spi_flash_types.h

@@ -0,0 +1,148 @@
+// Copyright 2010-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.
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Definition of a common transaction. Also holds the return value. */
+typedef struct {
+    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;
+
+/** @brief Mode used for reading from SPI flash */
+typedef enum {
+    SPI_FLASH_SLOWRD = 0, ///< Data read using single I/O, some limits on speed
+    SPI_FLASH_FASTRD, ///< Data read using single I/O, no limit on speed
+    SPI_FLASH_DOUT,   ///< Data read using dual I/O
+    SPI_FLASH_DIO,    ///< Both address & data transferred using dual I/O
+    SPI_FLASH_QOUT,   ///< Data read using quad I/O
+    SPI_FLASH_QIO,    ///< Both address & data transferred using quad I/O
+
+    SPI_FLASH_READ_MODE_MAX,    ///< The fastest io mode supported by the host is ``ESP_FLASH_READ_MODE_MAX-1``.
+} esp_flash_io_mode_t;
+
+struct spi_flash_host_driver_s;
+typedef struct spi_flash_host_driver_s spi_flash_host_driver_t;
+
+/** SPI Flash Host driver instance */
+typedef struct {
+    const struct spi_flash_host_driver_s* driver;  ///< Pointer to the implementation function table
+    // Implementations can wrap this structure into their own ones, and append other data here
+} spi_flash_host_inst_t ;
+
+/** Host driver configuration and context structure. */
+struct spi_flash_host_driver_s {
+    /**
+     * Configure the device-related register before transactions. This saves
+     * some time to re-configure those registers when we send continuously
+     */
+    esp_err_t (*dev_config)(spi_flash_host_inst_t *host);
+    /**
+     * Send an user-defined spi transaction to the device.
+     */
+    esp_err_t (*common_command)(spi_flash_host_inst_t *host, spi_flash_trans_t *t);
+    /**
+     * Read flash ID.
+     */
+    esp_err_t (*read_id)(spi_flash_host_inst_t *host, uint32_t *id);
+    /**
+     * Erase whole flash chip.
+     */
+    void (*erase_chip)(spi_flash_host_inst_t *host);
+    /**
+     * Erase a specific sector by its start address.
+     */
+    void (*erase_sector)(spi_flash_host_inst_t *host, uint32_t start_address);
+    /**
+     * Erase a specific block by its start address.
+     */
+    void (*erase_block)(spi_flash_host_inst_t *host, uint32_t start_address);
+    /**
+     * Read the status of the flash chip.
+     */
+    esp_err_t (*read_status)(spi_flash_host_inst_t *host, uint8_t *out_sr);
+    /**
+     * Disable write protection.
+     */
+    esp_err_t (*set_write_protect)(spi_flash_host_inst_t *host, bool wp);
+    /**
+     * Program a page of the flash. Check ``max_write_bytes`` for the maximum allowed writing length.
+     */
+    void (*program_page)(spi_flash_host_inst_t *host, const void *buffer, uint32_t address, uint32_t length);
+    /** Check whether given buffer can be directly used to write */
+    bool (*supports_direct_write)(spi_flash_host_inst_t *host, const void *p);
+    /**
+     * Slicer for write data. The `program_page` should be called iteratively with the return value
+     * of this function.
+     *
+     * @param address Beginning flash address to write
+     * @param len Length request to write
+     * @param align_addr Output of the aligned address to write to
+     * @param page_size Physical page size of the flash chip
+     * @return Length that can be actually written in one `program_page` call
+     */
+    int (*write_data_slicer)(spi_flash_host_inst_t *host, uint32_t address, uint32_t len, uint32_t *align_addr,
+                             uint32_t page_size);
+    /**
+     * Read data from the flash. Check ``max_read_bytes`` for the maximum allowed reading length.
+     */
+    esp_err_t (*read)(spi_flash_host_inst_t *host, void *buffer, uint32_t address, uint32_t read_len);
+    /** Check whether given buffer can be directly used to read */
+    bool (*supports_direct_read)(spi_flash_host_inst_t *host, const void *p);
+    /**
+     * Slicer for read data. The `read` should be called iteratively with the return value
+     * of this function.
+     *
+     * @param address Beginning flash address to read
+     * @param len Length request to read
+     * @param align_addr Output of the aligned address to read
+     * @param page_size Physical page size of the flash chip
+     * @return Length that can be actually read in one `read` call
+     */
+    int (*read_data_slicer)(spi_flash_host_inst_t *host, uint32_t address, uint32_t len, uint32_t *align_addr, uint32_t page_size);
+    /**
+     * Check whether the host is idle to perform new operations.
+     */
+    bool (*host_idle)(spi_flash_host_inst_t *host);
+    /**
+     * Configure the host to work at different read mode. Responsible to compensate the timing and set IO mode.
+     */
+    esp_err_t (*configure_host_io_mode)(spi_flash_host_inst_t *host, uint32_t command,
+                                        uint32_t addr_bitlen, int dummy_bitlen_base,
+                                        esp_flash_io_mode_t io_mode);
+    /**
+     *  Internal use, poll the HW until the last operation is done.
+     */
+    void (*poll_cmd_done)(spi_flash_host_inst_t *host);
+    /**
+     * For some host (SPI1), they are shared with a cache. When the data is
+     * modified, the cache needs to be flushed. Left NULL if not supported.
+     */
+    esp_err_t (*flush_cache)(spi_flash_host_inst_t* host, uint32_t addr, uint32_t size);
+};
+///Slowest io mode supported by ESP32, currently SlowRd
+#define SPI_FLASH_READ_MODE_MIN SPI_FLASH_SLOWRD
+
+#ifdef __cplusplus
+}
+#endif

+ 1 - 1
components/unity/CMakeLists.txt

@@ -27,7 +27,7 @@ else()
 endif()
 
 idf_component_register(SRCS "${srcs}"
-                    INCLUDE_DIRS "include" "unity/src" "unity/extras/fixture/src")
+                    INCLUDE_DIRS ${includes})
 
 if(NOT ${IDF_TARGET} STREQUAL "linux")
     target_compile_definitions(${COMPONENT_LIB} PUBLIC

+ 3 - 1
tools/gen_esp_err_to_name.py

@@ -46,7 +46,9 @@ ignore_files = [os.path.join('components', 'mdns', 'test_afl_fuzz_host', 'esp32_
                 ]
 
 # add directories here which should not be parsed, this is a tuple since it will be used with *.startswith()
-ignore_dirs = (os.path.join('examples'), os.path.join('components', 'cmock', 'CMock', 'test'))
+ignore_dirs = (os.path.join('examples'),
+               os.path.join('components', 'cmock', 'CMock', 'test'),
+               os.path.join('components', 'spi_flash', 'sim'))
 
 # macros from here have higher priorities in case of collisions
 priority_headers = [os.path.join('components', 'esp_common', 'include', 'esp_err.h')]