ソースを参照

Merge branch 'feature/idf-fs-profile-modifications' into 'master'

IDF fs profiling tool modifications

See merge request idf/esp-idf!2705
Angus Gratton 7 年 前
コミット
4f2fe93bc1
64 ファイル変更999 行追加689 行削除
  1. 0 4
      .gitlab-ci.yml
  2. 82 78
      components/fatfs/test_fatfs_host/Makefile
  3. 30 0
      components/fatfs/test_fatfs_host/Makefile.files
  4. 17 0
      components/fatfs/test_fatfs_host/component.mk
  5. 0 3
      components/fatfs/test_fatfs_host/sdkconfig.h
  6. 6 0
      components/fatfs/test_fatfs_host/sdkconfig/sdkconfig.h
  7. 0 4
      components/fatfs/test_fatfs_host/stubs/freertos/include/freertos/FreeRTOS.h
  8. 0 11
      components/fatfs/test_fatfs_host/stubs/freertos/include/freertos/projdefs.h
  9. 0 16
      components/fatfs/test_fatfs_host/stubs/freertos/include/freertos/semphr.h
  10. 0 45
      components/fatfs/test_fatfs_host/stubs/log/include/esp_log.h
  11. 0 20
      components/fatfs/test_fatfs_host/stubs/log/log.c
  12. 2 2
      components/fatfs/test_fatfs_host/test_fatfs.cpp
  13. 2 2
      components/fatfs/test_fatfs_host/test_utils.c
  14. 54 56
      components/spi_flash/sim/Makefile
  15. 30 0
      components/spi_flash/sim/Makefile.files
  16. 145 13
      components/spi_flash/sim/SpiFlash.cpp
  17. 31 12
      components/spi_flash/sim/SpiFlash.h
  18. 17 0
      components/spi_flash/sim/component.mk
  19. 53 7
      components/spi_flash/sim/flash_mock.cpp
  20. 2 2
      components/spi_flash/sim/flash_mock_util.c
  21. 0 0
      components/spi_flash/sim/sdkconfig/sdkconfig.h
  22. 65 0
      components/spi_flash/sim/stubs/Makefile
  23. 25 0
      components/spi_flash/sim/stubs/Makefile.files
  24. 17 0
      components/spi_flash/sim/stubs/component.mk
  25. 0 0
      components/spi_flash/sim/stubs/driver/include/driver/sdmmc_host.h
  26. 0 0
      components/spi_flash/sim/stubs/driver/include/driver/sdmmc_types.h
  27. 0 0
      components/spi_flash/sim/stubs/esp32/crc.cpp
  28. 1 1
      components/spi_flash/sim/stubs/freertos/include/freertos/FreeRTOS.h
  29. 13 2
      components/spi_flash/sim/stubs/log/include/esp_log.h
  30. 2 0
      components/spi_flash/sim/stubs/newlib/include/sys/lock.h
  31. 0 0
      components/spi_flash/sim/stubs/sdkconfig/sdkconfig.h
  32. 0 0
      components/spi_flash/sim/stubs/sdmmc/include/sdmmc_cmd.h
  33. 0 0
      components/spi_flash/sim/stubs/vfs/include/esp_vfs.h
  34. 2 0
      components/spiffs/esp_spiffs.c
  35. 1 1
      components/spiffs/spiffs_api.c
  36. 0 2
      components/spiffs/spiffs_api.h
  37. 77 76
      components/spiffs/test_spiffs_host/Makefile
  38. 33 0
      components/spiffs/test_spiffs_host/Makefile.files
  39. 17 0
      components/spiffs/test_spiffs_host/component.mk
  40. 0 0
      components/spiffs/test_spiffs_host/partition_table.csv
  41. 5 0
      components/spiffs/test_spiffs_host/sdkconfig/sdkconfig.h
  42. 0 4
      components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/FreeRTOS.h
  43. 0 11
      components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/projdefs.h
  44. 0 16
      components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/semphr.h
  45. 0 51
      components/spiffs/test_spiffs_host/stubs/log/include/esp_log.h
  46. 0 22
      components/spiffs/test_spiffs_host/stubs/log/log.c
  47. 0 10
      components/spiffs/test_spiffs_host/stubs/newlib/include/sys/lock.h
  48. 0 21
      components/spiffs/test_spiffs_host/stubs/newlib/lock.c
  49. 2 2
      components/spiffs/test_spiffs_host/test_spiffs.cpp
  50. 2 2
      components/spiffs/test_spiffs_host/test_utils.c
  51. 79 80
      components/wear_levelling/test_wl_host/Makefile
  52. 31 0
      components/wear_levelling/test_wl_host/Makefile.files
  53. 17 0
      components/wear_levelling/test_wl_host/component.mk
  54. 1 1
      components/wear_levelling/test_wl_host/partition_table.csv
  55. 0 3
      components/wear_levelling/test_wl_host/sdkconfig.h
  56. 6 0
      components/wear_levelling/test_wl_host/sdkconfig/sdkconfig.h
  57. 0 44
      components/wear_levelling/test_wl_host/stubs/log/include/esp_log.h
  58. 0 21
      components/wear_levelling/test_wl_host/stubs/log/log.c
  59. 0 16
      components/wear_levelling/test_wl_host/stubs/newlib/include/sys/lock.h
  60. 0 21
      components/wear_levelling/test_wl_host/stubs/newlib/lock.c
  61. 2 2
      components/wear_levelling/test_wl_host/test_utils.c
  62. 126 3
      components/wear_levelling/test_wl_host/test_wl.cpp
  63. 1 1
      make/component_wrapper.mk
  64. 3 1
      make/project.mk

+ 0 - 4
.gitlab-ci.yml

@@ -299,8 +299,6 @@ test_wl_on_host:
 
 test_fatfs_on_host:
   <<: *host_test_template
-  tags:
-    - wl_host_test
   script:
     - cd components/fatfs/test_fatfs_host/
     - make test
@@ -332,8 +330,6 @@ test_mdns_fuzzer_on_host:
 
 test_spiffs_on_host:
   <<: *host_test_template
-  tags:
-    - wl_host_test
   script:
     - cd components/spiffs/test_spiffs_host/
     - make test

+ 82 - 78
components/fatfs/test_fatfs_host/Makefile

@@ -1,103 +1,107 @@
-COMPONENT=fatfs
+ifndef COMPONENT
+COMPONENT := fatfs
+endif
 
-TEST_PROGRAM=test_$(COMPONENT)
+COMPONENT_LIB := lib$(COMPONENT).a
+TEST_PROGRAM := test_$(COMPONENT)
 
-#Expose as a library
-COMPONENT_LIB=lib$(COMPONENT).a
+STUBS_LIB_DIR := ../../../components/spi_flash/sim/stubs
+STUBS_LIB_BUILD_DIR := $(STUBS_LIB_DIR)/build
+STUBS_LIB := libstubs.a
 
-#Use wear levelling and flash simulation
-WEAR_LEVELLING=wear_levelling
-WEAR_LEVELLING_DIR=../../$(WEAR_LEVELLING)
-WEAR_LEVELLING_HOST_DIR=$(WEAR_LEVELLING_DIR)/test_wl_host
-WEAR_LEVELLING_LIB=lib$(WEAR_LEVELLING).a
+SPI_FLASH_SIM_DIR := ../../../components/spi_flash/sim
+SPI_FLASH_SIM_BUILD_DIR := $(SPI_FLASH_SIM_DIR)/build
+SPI_FLASH_SIM_LIB := libspi_flash.a
 
-SPI_FLASH=spi_flash
-SPI_FLASH_DIR=../../$(SPI_FLASH)
-SPI_FLASH_SIM_DIR=$(SPI_FLASH_DIR)/sim
-SPI_FLASH_LIB=lib$(SPI_FLASH).a
+WEAR_LEVELLING_DIR := ../../../components/wear_levelling/test_wl_host
+WEAR_LEVELLING_BUILD_DIR := $(WEAR_LEVELLING_DIR)/build
+WEAR_LEVELLING_LIB := libwl.a
 
-all: $(TEST_PROGRAM)
+include Makefile.files
 
-SOURCE_FILES = \
-	$(addprefix ../src/, \
-	diskio.c \
-	ff.c \
-	ffsystem.c \
-	ffunicode.c \
-	diskio_wl.c \
-	) \
-	$(addprefix ./stubs/, log/log.c)
+all: test
 
-TEST_SOURCE_FILES = \
-	test_fatfs.cpp \
-	main.cpp \
-	test_utils.c
+ifndef SDKCONFIG
+SDKCONFIG_DIR := $(dir $(realpath sdkconfig/sdkconfig.h))
+SDKCONFIG := $(SDKCONFIG_DIR)sdkconfig.h
+else
+SDKCONFIG_DIR := $(dir $(realpath $(SDKCONFIG)))
+endif
 
-INCLUDE_FLAGS = $(addprefix -I,\
-	../src \
-	. \
-	$(addprefix ./stubs/, \
-	driver/include \
-	freertos/include \
-	sdmmc/include \
-	log/include \
-	) \
-	$(SPI_FLASH_DIR)/include \
-	$(WEAR_LEVELLING_DIR)/include \
-	../../esp32/include \
-	../../../tools/catch \
-)
-
-GCOV ?= gcov
-
-CPPFLAGS += $(INCLUDE_FLAGS) -D CONFIG_LOG_DEFAULT_LEVEL -g -m32
-CFLAGS += -fprofile-arcs -ftest-coverage
-CXXFLAGS += -std=c++11 -Wall -Werror  -fprofile-arcs -ftest-coverage
-LDFLAGS += -lstdc++ -fprofile-arcs -ftest-coverage
-
-OBJ_FILES = $(filter %.o, $(SOURCE_FILES:.cpp=.o) $(SOURCE_FILES:.c=.o))
-TEST_OBJ_FILES = $(filter %.o, $(TEST_SOURCE_FILES:.cpp=.o) $(TEST_SOURCE_FILES:.c=.o))
+INCLUDE_FLAGS := $(addprefix -I, $(INCLUDE_DIRS) $(SDKCONFIG_DIR) ../../../tools/catch)
 
-$(WEAR_LEVELLING_HOST_DIR)/$(WEAR_LEVELLING_LIB): force
-	$(MAKE) -C $(WEAR_LEVELLING_HOST_DIR) lib
+CPPFLAGS += $(INCLUDE_FLAGS) -g -m32
+CXXFLAGS += $(INCLUDE_FLAGS) -std=c++11 -g -m32
 
-$(SPI_FLASH_SIM_DIR)/$(SPI_FLASH_LIB): force
-	$(MAKE) -C $(SPI_FLASH_SIM_DIR) lib
+# Build libraries that this component is dependent on
+$(STUBS_LIB_BUILD_DIR)/$(STUBS_LIB): force
+	$(MAKE) -C $(STUBS_LIB_DIR) lib SDKCONFIG=$(SDKCONFIG)
 
-force:
+$(SPI_FLASH_SIM_BUILD_DIR)/$(SPI_FLASH_SIM_LIB): force
+	$(MAKE) -C $(SPI_FLASH_SIM_DIR) lib SDKCONFIG=$(SDKCONFIG)
+
+$(WEAR_LEVELLING_BUILD_DIR)/$(WEAR_LEVELLING_LIB): force
+	$(MAKE) -C $(WEAR_LEVELLING_DIR) lib SDKCONFIG=$(SDKCONFIG)
 
-$(COMPONENT_LIB): $(OBJ_FILES)
+# Create target for building this component as a library
+CFILES := $(filter %.c, $(SOURCE_FILES))
+CPPFILES := $(filter %.cpp, $(SOURCE_FILES))
+
+CTARGET = ${2}/$(patsubst %.c,%.o,$(notdir ${1}))
+CPPTARGET = ${2}/$(patsubst %.cpp,%.o,$(notdir ${1}))
+
+ifndef BUILD_DIR
+BUILD_DIR := build
+endif
+
+OBJ_FILES := $(addprefix $(BUILD_DIR)/, $(filter %.o, $(notdir $(SOURCE_FILES:.cpp=.o) $(SOURCE_FILES:.c=.o))))
+
+define COMPILE_C
+$(call CTARGET, ${1}, $(BUILD_DIR)) : ${1} $(SDKCONFIG)
+	mkdir -p $(BUILD_DIR) 
+	$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $(call CTARGET, ${1}, $(BUILD_DIR)) ${1}
+endef
+
+define COMPILE_CPP
+$(call CPPTARGET, ${1}, $(BUILD_DIR)) : ${1} $(SDKCONFIG)
+	mkdir -p $(BUILD_DIR) 
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $(call CPPTARGET, ${1}, $(BUILD_DIR)) ${1}
+endef
+
+$(BUILD_DIR)/$(COMPONENT_LIB): $(OBJ_FILES) $(SDKCONFIG)
+	mkdir -p $(BUILD_DIR)
 	$(AR) rcs $@ $^
 
-lib: $(COMPONENT_LIB)
+lib: $(BUILD_DIR)/$(COMPONENT_LIB)
 
-partition_table.bin: partition_table.csv
-	python ../../partition_table/gen_esp32part.py $< $@
+$(foreach cfile, $(CFILES), $(eval $(call COMPILE_C, $(cfile))))
+$(foreach cxxfile, $(CPPFILES), $(eval $(call COMPILE_CPP, $(cxxfile))))
 
-$(TEST_PROGRAM): lib $(TEST_OBJ_FILES) $(SPI_FLASH_SIM_DIR)/$(SPI_FLASH_LIB) $(WEAR_LEVELLING_HOST_DIR)/$(WEAR_LEVELLING_LIB) partition_table.bin
-	g++ $(LDFLAGS) -o $(TEST_PROGRAM) $(TEST_OBJ_FILES) -L$(abspath .) -l:$(COMPONENT_LIB) -L$(SPI_FLASH_SIM_DIR) -l:$(SPI_FLASH_LIB) -L$(WEAR_LEVELLING_HOST_DIR) -l:$(WEAR_LEVELLING_LIB) -g -m32
+# Create target for building this component as a test
+TEST_SOURCE_FILES = \
+	test_fatfs.cpp \
+	main.cpp \
+	test_utils.c
 
-test: $(TEST_PROGRAM)
-	./$(TEST_PROGRAM)
+TEST_OBJ_FILES = $(filter %.o, $(TEST_SOURCE_FILES:.cpp=.o) $(TEST_SOURCE_FILES:.c=.o))
 
-COVERAGE_FILES = $(OBJ_FILES:.o=.gc*) $(TEST_OBJ_FILES:.o=.gc*)
+$(TEST_PROGRAM): lib $(TEST_OBJ_FILES) $(WEAR_LEVELLING_BUILD_DIR)/$(WEAR_LEVELLING_LIB) $(SPI_FLASH_SIM_BUILD_DIR)/$(SPI_FLASH_SIM_LIB) $(STUBS_LIB_BUILD_DIR)/$(STUBS_LIB) partition_table.bin $(SDKCONFIG)
+	g++ $(LDFLAGS) $(CXXFLAGS) -o $@  $(TEST_OBJ_FILES) -L$(BUILD_DIR) -l:$(COMPONENT_LIB) -L$(WEAR_LEVELLING_BUILD_DIR) -l:$(WEAR_LEVELLING_LIB) -L$(SPI_FLASH_SIM_BUILD_DIR) -l:$(SPI_FLASH_SIM_LIB) -L$(STUBS_LIB_BUILD_DIR) -l:$(STUBS_LIB) 
 
-$(COVERAGE_FILES): test
+test: $(TEST_PROGRAM)
+	./$(TEST_PROGRAM)
 
-coverage.info: $(COVERAGE_FILES)
-	find ../ -name "*.gcno" -exec $(GCOV) -r -pb {} +
-	lcov --capture --directory ../ --no-external --output-file coverage.info --gcov-tool $(GCOV)
+# Create other necessary targets
+partition_table.bin: partition_table.csv
+	python ../../../components/partition_table/gen_esp32part.py --verify $< $@
 
-coverage_report: coverage.info
-	genhtml coverage.info --output-directory coverage_report
-	@echo "Coverage report is in coverage_report/index.html"
+force:
 
+# Create target to cleanup files
 clean:
-	rm -f $(OBJ_FILES) $(TEST_OBJ_FILES) $(TEST_PROGRAM) $(COMPONENT_LIB) partition_table.bin
-	$(MAKE) -C $(WEAR_LEVELLING_HOST_DIR) clean
+	$(MAKE) -C $(STUBS_LIB_DIR) clean
 	$(MAKE) -C $(SPI_FLASH_SIM_DIR) clean
-	rm -f $(COVERAGE_FILES) *.gcov
-	rm -rf coverage_report/
-	rm -f coverage.info
+	$(MAKE) -C $(WEAR_LEVELLING_DIR) clean
+	rm -f $(OBJ_FILES) $(TEST_OBJ_FILES) $(TEST_PROGRAM) $(COMPONENT_LIB) partition_table.bin
 
-.PHONY: clean all test lib
+.PHONY: all lib test clean force

+ 30 - 0
components/fatfs/test_fatfs_host/Makefile.files

@@ -0,0 +1,30 @@
+SOURCE_FILES := \
+	$(addprefix ../src/, \
+	diskio.c \
+	ff.c \
+	ffsystem.c \
+	ffunicode.c \
+	diskio_wl.c \
+	) 
+
+INCLUDE_DIRS := \
+	. \
+	../src \
+	$(addprefix ../../spi_flash/sim/stubs/, \
+	app_update/include \
+	driver/include \
+	esp32/include \
+	freertos/include \
+	log/include \
+	newlib/include \
+	sdmmc/include \
+	vfs/include \
+	) \
+	$(addprefix ../../../components/, \
+	soc/esp32/include \
+	esp32/include \
+	bootloader_support/include \
+	app_update/include \
+	spi_flash/include \
+	wear_levelling/include \
+	)

+ 17 - 0
components/fatfs/test_fatfs_host/component.mk

@@ -0,0 +1,17 @@
+include $(COMPONENT_PATH)/Makefile.files
+
+COMPONENT_OWNBUILDTARGET := 1
+COMPONENT_OWNCLEANTARGET := 1
+
+COMPONENT_ADD_INCLUDEDIRS := $(INCLUDE_DIRS)
+
+.PHONY: build
+build: $(SDKCONFIG_HEADER)
+	$(MAKE) -C $(COMPONENT_PATH) lib SDKCONFIG=$(SDKCONFIG_HEADER) BUILD_DIR=$(COMPONENT_BUILD_DIR) COMPONENT=$(COMPONENT_NAME)
+
+CLEAN_FILES := component_project_vars.mk
+.PHONY: clean
+clean:
+	$(summary) RM $(CLEAN_FILES)
+	rm -f $(CLEAN_FILES)
+	$(MAKE) -C $(COMPONENT_PATH) clean SDKCONFIG=$(SDKCONFIG_HEADER) BUILD_DIR=$(COMPONENT_BUILD_DIR) COMPONENT=$(COMPONENT_NAME)

+ 0 - 3
components/fatfs/test_fatfs_host/sdkconfig.h

@@ -1,3 +0,0 @@
-# pragma once
-
-#define CONFIG_WL_SECTOR_SIZE   4096

+ 6 - 0
components/fatfs/test_fatfs_host/sdkconfig/sdkconfig.h

@@ -0,0 +1,6 @@
+# pragma once
+
+#define CONFIG_WL_SECTOR_SIZE   4096
+#define CONFIG_LOG_DEFAULT_LEVEL 3
+#define CONFIG_PARTITION_TABLE_OFFSET 0x8000
+#define CONFIG_ESPTOOLPY_FLASHSIZE "8MB"

+ 0 - 4
components/fatfs/test_fatfs_host/stubs/freertos/include/freertos/FreeRTOS.h

@@ -1,4 +0,0 @@
-#pragma once
-
-#include "projdefs.h"
-#include "semphr.h"

+ 0 - 11
components/fatfs/test_fatfs_host/stubs/freertos/include/freertos/projdefs.h

@@ -1,11 +0,0 @@
-#pragma once
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#define pdTRUE			1
-
-#if defined(__cplusplus)
-}
-#endif

+ 0 - 16
components/fatfs/test_fatfs_host/stubs/freertos/include/freertos/semphr.h

@@ -1,16 +0,0 @@
-#pragma once
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#define vSemaphoreDelete( xSemaphore )
-#define xSemaphoreCreateMutex()                     ((void*)(1))
-#define xSemaphoreGive( xSemaphore )
-#define xSemaphoreTake( xSemaphore, xBlockTime )    pdTRUE
-
-typedef void* SemaphoreHandle_t;
-
-#if defined(__cplusplus)
-}
-#endif

+ 0 - 45
components/fatfs/test_fatfs_host/stubs/log/include/esp_log.h

@@ -1,45 +0,0 @@
-#pragma once
-
-#include <stdint.h>
-#include <stdio.h>
-
-#include "sdkconfig.h"
-
-#if defined(__cplusplus)
-extern "C" {                 // Make sure we have C-declarations in C++ programs
-#endif
-
-#define LOG_LOCAL_LEVEL     ESP_LOG_DEBUG
-
-typedef enum {
-    ESP_LOG_NONE,       /*!< No log output */
-    ESP_LOG_ERROR,      /*!< Critical errors, software module can not recover on its own */
-    ESP_LOG_WARN,       /*!< Error conditions from which recovery measures have been taken */
-    ESP_LOG_INFO,       /*!< Information messages which describe normal flow of events */
-    ESP_LOG_DEBUG,      /*!< Extra information which is not necessary for normal use (values, pointers, sizes, etc). */
-    ESP_LOG_VERBOSE     /*!< Bigger chunks of debugging information, or frequent messages which can potentially flood the output. */
-} esp_log_level_t;
-
-#define LOG_COLOR_E
-#define LOG_COLOR_W
-#define LOG_COLOR_I
-#define LOG_COLOR_D
-#define LOG_COLOR_V
-#define LOG_RESET_COLOR
-
-uint32_t esp_log_timestamp(void);
-void esp_log_write(esp_log_level_t level, const char* tag, const char* format, ...) __attribute__ ((format (printf, 3, 4)));
-
-#define LOG_FORMAT(letter, format)  LOG_COLOR_ ## letter #letter " (%d) %s: " format LOG_RESET_COLOR "\n"
-
-#define ESP_LOGE( tag, format, ... )  if (LOG_LOCAL_LEVEL >= ESP_LOG_ERROR)   { esp_log_write(ESP_LOG_ERROR,   tag, LOG_FORMAT(E, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
-
-#define ESP_LOGV( tag, format, ... )  if (LOG_LOCAL_LEVEL >= ESP_LOG_VERBOSE) { esp_log_write(ESP_LOG_VERBOSE, tag, LOG_FORMAT(V, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
-
-#define ESP_LOGD( tag, format, ... )  if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG)   { esp_log_write(ESP_LOG_DEBUG,   tag, LOG_FORMAT(D, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
-
-#define ESP_LOGW( tag, format, ... )  if (LOG_LOCAL_LEVEL >= ESP_LOG_WARN)    { esp_log_write(ESP_LOG_WARN,    tag, LOG_FORMAT(W, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
-
-#if defined(__cplusplus)
-}
-#endif

+ 0 - 20
components/fatfs/test_fatfs_host/stubs/log/log.c

@@ -1,20 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-
-#include "esp_log.h"
-
-void esp_log_write(esp_log_level_t level,
-                   const char *tag,
-                   const char *format, ...)
-{
-    va_list arg;
-    va_start(arg, format);
-    vprintf(format, arg);
-    va_end(arg);
-}
-
-uint32_t esp_log_timestamp()
-{
-    return 0;
-}

+ 2 - 2
components/fatfs/test_fatfs_host/test_fatfs.cpp

@@ -9,11 +9,11 @@
 
 #include "catch.hpp"
 
-extern "C" void init_spi_flash(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin);
+extern "C" void init_spi_flash(const char* chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin);
 
 TEST_CASE("create volume, open file, write and read back data", "[fatfs]")
 {
-    init_spi_flash(0x00400000, CONFIG_WL_SECTOR_SIZE * 16, CONFIG_WL_SECTOR_SIZE, CONFIG_WL_SECTOR_SIZE, "partition_table.bin");
+    init_spi_flash(CONFIG_ESPTOOLPY_FLASHSIZE, CONFIG_WL_SECTOR_SIZE * 16, CONFIG_WL_SECTOR_SIZE, CONFIG_WL_SECTOR_SIZE, "partition_table.bin");
 
     FRESULT fr_result;
     BYTE pdrv;

+ 2 - 2
components/fatfs/test_fatfs_host/test_utils.c

@@ -1,7 +1,7 @@
 #include "esp_spi_flash.h"
 #include "esp_partition.h"
 
-void init_spi_flash(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin)
+void init_spi_flash(const char* chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin)
 {
     spi_flash_init(chip_size, block_size, sector_size, page_size, partition_bin);
-}
+}

+ 54 - 56
components/spi_flash/sim/Makefile

@@ -1,67 +1,65 @@
-COMPONENT=spi_flash
-COMPONENT_LIB=lib$(COMPONENT).a
+ifndef COMPONENT
+COMPONENT := spi_flash
+endif
+
+COMPONENT_LIB := lib$(COMPONENT).a
+
+include Makefile.files
 
 all: lib
 
-SOURCE_FILES = \
-	../partition.c \
-	../flash_ops.c \
-	SpiFlash.cpp \
-	flash_mock_util.c	\
-	flash_mock.cpp \
-	$(addprefix stubs/, \
-	newlib/lock.c \
-	app_update/esp_ota_eps.c \
-	)
-
-INCLUDE_FLAGS = $(addprefix -I,\
-	. \
-	../include \
-	../../esp32/include/ \
-	$(addprefix stubs/, \
-	newlib/include \
-	log/include \
-	freertos/include \
-	) \
-	$(addprefix ../../../components/, \
-	soc/esp32/include \
-	esp32/include \
-	bootloader_support/include \
-	app_update/include \
-	) \
-	../../../tools/catch \
-)
-
-GCOV ?= gcov
-
-CPPFLAGS += $(INCLUDE_FLAGS) -D CONFIG_LOG_DEFAULT_LEVEL -g -m32
-CFLAGS += -fprofile-arcs -ftest-coverage
-CXXFLAGS += -std=c++11 -Wall -Werror  -fprofile-arcs -ftest-coverage
-LDFLAGS += -lstdc++ -fprofile-arcs -ftest-coverage
-
-OBJ_FILES = $(filter %.o, $(SOURCE_FILES:.cpp=.o) $(SOURCE_FILES:.c=.o))
-
-$(COMPONENT_LIB): $(OBJ_FILES)
-	$(AR) rcs $@ $^
+ifndef SDKCONFIG
+SDKCONFIG_DIR := $(dir $(realpath sdkconfig/sdkconfig.h))
+SDKCONFIG := $(SDKCONFIG_DIR)sdkconfig.h
+else
+SDKCONFIG_DIR := $(dir $(realpath $(SDKCONFIG)))
+endif
+
+INCLUDE_FLAGS := $(addprefix -I, $(INCLUDE_DIRS) $(SDKCONFIG_DIR))
+
+CPPFLAGS += $(INCLUDE_FLAGS) -g -m32
+CXXFLAGS += $(INCLUDE_FLAGS) -std=c++11 -g -m32
+
+CFILES := $(filter %.c, $(SOURCE_FILES))
+CPPFILES := $(filter %.cpp, $(SOURCE_FILES))
 
-lib: $(COMPONENT_LIB)
+CTARGET = ${2}/$(patsubst %.c,%.o,$(notdir ${1}))
+CPPTARGET = ${2}/$(patsubst %.cpp,%.o,$(notdir ${1}))
 
-COVERAGE_FILES = $(OBJ_FILES:.o=.gc*)
+ifndef BUILD_DIR
+BUILD_DIR := build
+endif
 
-$(COVERAGE_FILES): lib
+OBJ_FILES := $(addprefix $(BUILD_DIR)/, $(filter %.o, $(notdir $(SOURCE_FILES:.cpp=.o) $(SOURCE_FILES:.c=.o))))
 
-coverage.info: $(COVERAGE_FILES)
-	find ../ -name "*.gcno" -exec $(GCOV) -r -pb {} +
-	lcov --capture --directory ../ --no-external --output-file coverage.info --gcov-tool $(GCOV)
+%.o : %.c $(SDKCONFIG)
+	$(CC) $(CPPFLAGS) $(CFLAGS) $< - o $@
 
-coverage_report: coverage.info
-	genhtml coverage.info --output-directory coverage_report
-	@echo "Coverage report is in coverage_report/index.html"
+%.o : %.cpp $(SDKCONFIG)
+	$(CC) $(CPPFLAGS) $(CFLAGS) $< - o $@
+
+define COMPILE_C
+$(call CTARGET, ${1}, $(BUILD_DIR)) : ${1}
+	mkdir -p $(BUILD_DIR)
+	$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $(call CTARGET, ${1}, $(BUILD_DIR)) ${1}
+endef
+
+define COMPILE_CPP
+$(call CPPTARGET, ${1}, $(BUILD_DIR)) : ${1}
+	mkdir -p $(BUILD_DIR)
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $(call CPPTARGET, ${1}, $(BUILD_DIR)) ${1}
+endef
+
+$(BUILD_DIR)/$(COMPONENT_LIB): $(OBJ_FILES) $(SDKCONFIG)
+	mkdir -p $(BUILD_DIR)
+	$(AR) rcs $@ $^
 
 clean:
-	rm -f $(OBJ_FILES) $(COMPONENT_LIB)
-	rm -f $(COVERAGE_FILES) *.gcov
-	rm -rf coverage_report/
-	rm -f coverage.info
+	rm -f $(OBJ_FILES) $(BUILD_DIR)/$(COMPONENT_LIB)
+
+lib: $(BUILD_DIR)/$(COMPONENT_LIB)
+
+$(foreach cfile, $(CFILES), $(eval $(call COMPILE_C, $(cfile))))
+$(foreach cxxfile, $(CPPFILES), $(eval $(call COMPILE_CPP, $(cxxfile))))
 
-.PHONY: clean lib all
+.PHONY: all lib clean

+ 30 - 0
components/spi_flash/sim/Makefile.files

@@ -0,0 +1,30 @@
+SOURCE_FILES := \
+	SpiFlash.cpp \
+	flash_mock.cpp \
+	flash_mock_util.c \
+	$(addprefix ../, \
+	partition.c \
+	flash_ops.c \
+	) \
+
+INCLUDE_DIRS := \
+	. \
+	../include \
+	../private_include \
+	$(addprefix stubs/, \
+	app_update/include \
+	driver/include \
+	esp32/include \
+	freertos/include \
+	log/include \
+	newlib/include \
+	sdmmc/include \
+	vfs/include \
+	) \
+	$(addprefix ../../../components/, \
+	soc/esp32/include \
+	esp32/include \
+	bootloader_support/include \
+	app_update/include \
+	spi_flash/include \
+	)

+ 145 - 13
components/spi_flash/sim/SpiFlash.cpp

@@ -27,6 +27,8 @@
 
 using namespace std;
 
+#define DIV_AND_CEIL(x, y)              ((x) / (y) + ((x) % (y) > 0))
+
 SpiFlash::SpiFlash()
 {
     return;
@@ -37,16 +39,31 @@ SpiFlash::~SpiFlash()
     deinit();
 }
 
-void SpiFlash::init(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partitions_bin)
+void SpiFlash::init(uint32_t chip_size, uint32_t block_size, uint32_t sector_size, uint32_t page_size, const char* partitions_bin)
 {
     // De-initialize first
     deinit();
 
+    // Initialize values and alloc memory
     this->chip_size = chip_size;
     this->block_size = block_size;
     this->sector_size = sector_size;
     this->page_size = page_size;
 
+    this->blocks = DIV_AND_CEIL(this->chip_size, this->block_size);
+    this->sectors = DIV_AND_CEIL(this->chip_size, this->sector_size);
+    this->pages = DIV_AND_CEIL(this->chip_size, this->page_size);
+
+    this->erase_cycles = (uint32_t*) calloc(this->sectors, sizeof(uint32_t));
+    this->erase_states = (bool*) calloc(this->sectors, sizeof(bool));
+    memset(this->erase_states, 0xFF, this->sectors * sizeof(bool));
+
+    this->total_erase_cycles_limit = 0;
+    this->erase_cycles_limit = 0;
+
+    this->total_erase_cycles = 0;
+
+    // Load partitions table bin
     this->memory = (uint8_t *) malloc(this->chip_size);
     memset(this->memory, 0xFF, this->chip_size);
 
@@ -65,31 +82,74 @@ void SpiFlash::init(size_t chip_size, size_t block_size, size_t sector_size, siz
 
 void SpiFlash::deinit()
 {
-    if(inited)
-    {
-        free(this->memory);
-    }
+    // Free all allocated memory
+    free(this->memory);
+
+    free(this->erase_cycles);
+    free(this->erase_states);
 }
 
-size_t SpiFlash::get_chip_size()
+uint32_t SpiFlash::get_chip_size()
 {
     return this->chip_size;
 }
 
-size_t SpiFlash::get_sector_size()
+uint32_t SpiFlash::get_block_size()
+{
+    return this->block_size;
+}
+
+uint32_t SpiFlash::get_sector_size()
 {
     return this->sector_size;
 }
 
+uint32_t SpiFlash::get_page_size()
+{
+    return this->page_size;
+}
+
 esp_rom_spiflash_result_t SpiFlash::erase_block(uint32_t block)
 {
-    memset(&this->memory[block * this->block_size], 0xFF, this->block_size);
+    uint32_t sectors_per_block = (this->block_size / this->sector_size);
+    uint32_t start_sector = block * sectors_per_block;
+
+    for (int i = start_sector; i < start_sector + sectors_per_block; i++) {
+        this->erase_sector(i);
+    }
+
     return ESP_ROM_SPIFLASH_RESULT_OK;
 }
 
-esp_rom_spiflash_result_t SpiFlash::erase_sector(size_t sector)
+esp_rom_spiflash_result_t SpiFlash::erase_sector(uint32_t sector)
 {
-    memset(&this->memory[sector * this->sector_size], 0xFF, this->sector_size);
+    if (this->total_erase_cycles_limit != 0 && 
+        this->total_erase_cycles >= this->total_erase_cycles_limit) {
+        return ESP_ROM_SPIFLASH_RESULT_ERR;
+    }
+
+    if (this->erase_cycles_limit != 0 && 
+        this->erase_cycles[sector] >= this->erase_cycles_limit) {
+        return ESP_ROM_SPIFLASH_RESULT_ERR;
+    }
+
+    uint32_t pages_per_sector = (this->sector_size / this->page_size);
+    uint32_t start_page = sector * pages_per_sector;
+
+    if (this->erase_states[sector]) {
+        goto out;
+    }
+
+    for (int i = start_page; i < start_page + pages_per_sector; i++) {
+        this->erase_page(i);
+    }
+
+    this->erase_cycles[sector]++;
+    this->total_erase_cycles++;
+
+    this->erase_states[sector] = true;
+
+out:
     return ESP_ROM_SPIFLASH_RESULT_OK;
 }
 
@@ -99,14 +159,36 @@ esp_rom_spiflash_result_t SpiFlash::erase_page(uint32_t page)
     return ESP_ROM_SPIFLASH_RESULT_OK;
 }
 
-esp_rom_spiflash_result_t SpiFlash::write(size_t dest_addr, const void *src, size_t size)
+esp_rom_spiflash_result_t SpiFlash::write(uint32_t dest_addr, const void *src, uint32_t size)
 {
-    // Emulate inability to set programmed bits without erasing
+    // Update reset states and check for failure
+    int start = 0;
+    int end = 0;
+
+    if (this->total_erase_cycles_limit != 0 && 
+        this->total_erase_cycles >= this->total_erase_cycles_limit) {
+        return ESP_ROM_SPIFLASH_RESULT_ERR;
+    }
+
+    start = dest_addr / this->get_sector_size();
+    end = size > 0 ? (dest_addr + size - 1) / this->get_sector_size() : start;
+
+    for (int i = start; i <= end; i++) {
+        if (this->erase_cycles_limit != 0 && 
+            this->erase_cycles[i] >= this->erase_cycles_limit) {
+            return ESP_ROM_SPIFLASH_RESULT_ERR;
+        }
+
+        this->erase_states[i] = false;
+    }
+
+    // Do the write
     for(uint32_t ctr = 0; ctr < size; ctr++)
     {
         uint8_t data = ((uint8_t*)src)[ctr];
         uint8_t written = this->memory[dest_addr + ctr];
 
+        // Emulate inability to set programmed bits without erasing
         data &= written;
 
         this->memory[dest_addr + ctr] = data;
@@ -115,8 +197,28 @@ esp_rom_spiflash_result_t SpiFlash::write(size_t dest_addr, const void *src, siz
     return ESP_ROM_SPIFLASH_RESULT_OK;
 }
 
-esp_rom_spiflash_result_t SpiFlash::read(size_t src_addr, void *dest, size_t size)
+esp_rom_spiflash_result_t SpiFlash::read(uint32_t src_addr, void *dest, uint32_t size)
 {
+    // Check for failure
+    int start = 0;
+    int end = 0;
+
+    if (this->total_erase_cycles_limit != 0 && 
+        this->total_erase_cycles >= this->total_erase_cycles_limit) {
+        return ESP_ROM_SPIFLASH_RESULT_ERR;
+    }
+
+    start = src_addr / this->get_sector_size();
+    end = size > 0 ? (src_addr + size - 1) / this->get_sector_size() : start;
+
+    for (int i = start; i <= end; i++) {
+        if (this->erase_cycles_limit != 0 && 
+            this->erase_cycles[i] >= this->erase_cycles_limit) {
+            return ESP_ROM_SPIFLASH_RESULT_ERR;
+        }
+    }
+
+    // Do the read
     memcpy(dest, &this->memory[src_addr], size);
     return ESP_ROM_SPIFLASH_RESULT_OK;
 }
@@ -124,4 +226,34 @@ esp_rom_spiflash_result_t SpiFlash::read(size_t src_addr, void *dest, size_t siz
 uint8_t* SpiFlash::get_memory_ptr(uint32_t src_address)
 {
     return &this->memory[src_address];
+}
+
+uint32_t SpiFlash::get_erase_cycles(uint32_t sector)
+{
+    return this->erase_cycles[sector];
+}
+
+uint32_t SpiFlash::get_total_erase_cycles()
+{
+    return this->total_erase_cycles;
+}
+
+void SpiFlash::set_erase_cycles_limit(uint32_t limit)
+{
+    this->erase_cycles_limit = limit;
+}
+
+void SpiFlash::set_total_erase_cycles_limit(uint32_t limit)
+{
+    this->total_erase_cycles_limit = limit;
+}
+
+void SpiFlash::reset_erase_cycles()
+{
+    memset(this->erase_cycles, 0, sizeof(this->sectors * sizeof(uint32_t)));
+}
+
+void SpiFlash::reset_total_erase_cycles()
+{
+    this->total_erase_cycles = 0;
 }

+ 31 - 12
components/spi_flash/sim/SpiFlash.h

@@ -15,6 +15,8 @@
 #ifndef _SpiFlash_H_
 #define _SpiFlash_H_
 
+#include <stdbool.h>
+
 #include "esp_err.h"
 #include "rom/spi_flash.h"
 
@@ -29,32 +31,49 @@ public:
     SpiFlash();
     ~SpiFlash();
 
-    void init(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partitions_bin);
+    void init(uint32_t chip_size, uint32_t block_size, uint32_t sector_size, uint32_t page_size, const char* partitions_bin);
+
+    uint32_t get_chip_size();
+    uint32_t get_block_size();
+    uint32_t get_sector_size();
+    uint32_t get_page_size();
 
     esp_rom_spiflash_result_t erase_block(uint32_t block);
     esp_rom_spiflash_result_t erase_sector(uint32_t sector);
     esp_rom_spiflash_result_t erase_page(uint32_t page);
 
-    esp_rom_spiflash_result_t write(size_t dest_addr, const void *src, size_t size);
-    esp_rom_spiflash_result_t read(size_t src_addr, void *dest, size_t size);
+    esp_rom_spiflash_result_t write(uint32_t dest_addr, const void *src, uint32_t size);
+    esp_rom_spiflash_result_t read(uint32_t src_addr, void *dest, uint32_t size);
 
-    size_t get_chip_size();
-    size_t get_sector_size();
+    uint32_t get_erase_cycles(uint32_t sector);
+    uint32_t get_total_erase_cycles();
+    
+    void set_erase_cycles_limit(uint32_t limit);
+    void set_total_erase_cycles_limit(uint32_t limit);
+
+    void reset_erase_cycles();
+    void reset_total_erase_cycles();
 
     uint8_t* get_memory_ptr(uint32_t src_address);
 
 private:
-    bool inited = false;
+    uint32_t chip_size;
+    uint32_t block_size;
+    uint32_t sector_size;
+    uint32_t page_size;
 
-    size_t chip_size;
-    size_t block_size;
-    size_t sector_size;
-    size_t page_size;
+    uint32_t blocks;
+    uint32_t sectors;
+    uint32_t pages;
 
     uint8_t* memory;
 
-    void* partitions;
-    uint8_t partitions_num;
+    bool* erase_states;
+
+    uint32_t* erase_cycles;
+    uint32_t erase_cycles_limit;
+    uint32_t total_erase_cycles;
+    uint32_t total_erase_cycles_limit;
 
     void deinit();
 };

+ 17 - 0
components/spi_flash/sim/component.mk

@@ -0,0 +1,17 @@
+include $(COMPONENT_PATH)/Makefile.files
+
+COMPONENT_OWNBUILDTARGET := 1
+COMPONENT_OWNCLEANTARGET := 1
+
+COMPONENT_ADD_INCLUDEDIRS := $(INCLUDE_DIRS)
+
+.PHONY: build
+build: $(SDKCONFIG_HEADER)
+	$(MAKE) -C $(COMPONENT_PATH) lib SDKCONFIG=$(SDKCONFIG_HEADER) BUILD_DIR=$(COMPONENT_BUILD_DIR) COMPONENT=$(COMPONENT_NAME)
+
+CLEAN_FILES := component_project_vars.mk
+.PHONY: clean
+clean:
+	$(summary) RM $(CLEAN_FILES)
+	rm -f $(CLEAN_FILES)
+	$(MAKE) -C $(COMPONENT_PATH) clean SDKCONFIG=$(SDKCONFIG_HEADER) BUILD_DIR=$(COMPONENT_BUILD_DIR) COMPONENT=$(COMPONENT_NAME)

+ 53 - 7
components/spi_flash/sim/flash_mock.cpp

@@ -1,26 +1,57 @@
 #include "SpiFlash.h"
 
+#include <string.h>
+#include <stdlib.h>
+
 #include "esp_spi_flash.h"
 #include "esp_partition.h"
 
 #include "esp_err.h"
 #include "rom/spi_flash.h"
 
-static SpiFlash spiflash = SpiFlash();
+SpiFlash spiflash = SpiFlash();
 
 esp_rom_spiflash_chip_t g_rom_flashchip;
 
-extern "C" void _spi_flash_init(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partitions_bin)
+size_t convert_chip_size_string(const char* chip_size_str)
+{
+    int size = 0;
+    if (strcmp(chip_size_str, "1MB") == 0) {
+        size = 0x100000;
+    }
+    else if (strcmp(chip_size_str, "2MB") == 0) {
+        size = 0x200000;
+    } 
+    else if (strcmp(chip_size_str, "4MB") == 0) {
+        size = 0x400000;
+    }
+    else if (strcmp(chip_size_str, "8MB") == 0) {
+        size = 0x800000;
+    }
+    else if (strcmp(chip_size_str, "16MB") == 0) {
+        size = 0x1000000;
+    } else {
+        size = 0;
+    }
+
+    return size;
+}
+
+extern "C" void _spi_flash_init(const char* chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partitions_bin)
 {
-    spiflash.init(chip_size, block_size, sector_size, page_size, partitions_bin);
+    size_t size = convert_chip_size_string(chip_size);
 
-    g_rom_flashchip.chip_size = chip_size;
+    assert(size != 0);
+
+    spiflash.init(size, block_size, sector_size, page_size, partitions_bin);
+
+    g_rom_flashchip.chip_size = size;
     g_rom_flashchip.block_size = block_size;
     g_rom_flashchip.sector_size = sector_size;
     g_rom_flashchip.page_size = page_size;
 }
 
-esp_err_t spi_flash_mmap(size_t src_addr, size_t size, spi_flash_mmap_memory_t memory,
+extern "C" esp_err_t spi_flash_mmap(size_t src_addr, size_t size, spi_flash_mmap_memory_t memory,
                          const void** out_ptr, spi_flash_mmap_handle_t* out_handle)
 {
     *out_handle = 0;
@@ -29,11 +60,21 @@ esp_err_t spi_flash_mmap(size_t src_addr, size_t size, spi_flash_mmap_memory_t m
     return ESP_OK;
 }
 
-void spi_flash_munmap(spi_flash_mmap_handle_t handle)
+extern "C" void spi_flash_munmap(spi_flash_mmap_handle_t handle)
 {
     return;
 }
 
+extern "C" int spi_flash_get_total_erase_cycles()
+{
+    return spiflash.get_total_erase_cycles();
+}
+
+extern "C" int spi_flash_get_erase_cycles(size_t sector)
+{
+    return spiflash.get_erase_cycles(sector);
+}
+
 esp_rom_spiflash_result_t esp_rom_spiflash_read(uint32_t target, uint32_t *dest, int32_t len)
 {
     return spiflash.read(target, dest, len);
@@ -62,4 +103,9 @@ esp_rom_spiflash_result_t esp_rom_spiflash_write(uint32_t target, const uint32_t
 esp_rom_spiflash_result_t esp_rom_spiflash_write_encrypted(uint32_t flash_addr, uint32_t *data, uint32_t len)
 {
     return spiflash.write(flash_addr, data, len);
-}
+}
+
+void *heap_caps_malloc( size_t size, uint32_t caps )
+{
+    return NULL;
+}

+ 2 - 2
components/spi_flash/sim/flash_mock_util.c

@@ -4,9 +4,9 @@
 #include "esp_err.h"
 #include "rom/spi_flash.h"
 
-extern void _spi_flash_init(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin);
+extern void _spi_flash_init(const char* chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin);
 
-void spi_flash_init(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin)
+void spi_flash_init(const char* chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin)
 {
     _spi_flash_init(chip_size, block_size, sector_size, page_size, partition_bin);
 }

+ 0 - 0
components/spi_flash/sim/sdkconfig.h → components/spi_flash/sim/sdkconfig/sdkconfig.h


+ 65 - 0
components/spi_flash/sim/stubs/Makefile

@@ -0,0 +1,65 @@
+ifndef COMPONENT
+COMPONENT := stubs
+endif
+
+COMPONENT_LIB := lib$(COMPONENT).a
+
+include Makefile.files
+
+all: lib
+
+ifndef SDKCONFIG
+SDKCONFIG_DIR := $(dir $(realpath sdkconfig/sdkconfig.h))
+SDKCONFIG := $(SDKCONFIG_DIR)sdkconfig.h
+else
+SDKCONFIG_DIR := $(dir $(realpath $(SDKCONFIG)))
+endif
+
+INCLUDE_FLAGS := $(addprefix -I, $(INCLUDE_DIRS) $(SDKCONFIG_DIR))
+
+CPPFLAGS += $(INCLUDE_FLAGS) -g -m32
+CXXFLAGS += $(INCLUDE_FLAGS) -std=c++11 -g -m32
+
+CFILES := $(filter %.c, $(SOURCE_FILES))
+CPPFILES := $(filter %.cpp, $(SOURCE_FILES))
+
+CTARGET = ${2}/$(patsubst %.c,%.o,$(notdir ${1}))
+CPPTARGET = ${2}/$(patsubst %.cpp,%.o,$(notdir ${1}))
+
+ifndef BUILD_DIR
+BUILD_DIR := build
+endif
+
+OBJ_FILES := $(addprefix $(BUILD_DIR)/, $(filter %.o, $(notdir $(SOURCE_FILES:.cpp=.o) $(SOURCE_FILES:.c=.o))))
+
+%.o : %.c $(SDKCONFIG)
+	$(CC) $(CPPFLAGS) $(CFLAGS) $< - o $@
+
+%.o : %.cpp $(SDKCONFIG)
+	$(CC) $(CPPFLAGS) $(CFLAGS) $< - o $@
+
+define COMPILE_C
+$(call CTARGET, ${1}, $(BUILD_DIR)) : ${1}
+	mkdir -p $(BUILD_DIR)
+	$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $(call CTARGET, ${1}, $(BUILD_DIR)) ${1}
+endef
+
+define COMPILE_CPP
+$(call CPPTARGET, ${1}, $(BUILD_DIR)) : ${1}
+	mkdir -p $(BUILD_DIR)
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $(call CPPTARGET, ${1}, $(BUILD_DIR)) ${1}
+endef
+
+$(BUILD_DIR)/$(COMPONENT_LIB): $(OBJ_FILES) $(SDKCONFIG)
+	mkdir -p $(BUILD_DIR)
+	$(AR) rcs $@ $^
+
+clean:
+	rm -f $(OBJ_FILES) $(BUILD_DIR)/$(COMPONENT_LIB)
+
+lib: $(BUILD_DIR)/$(COMPONENT_LIB)
+
+$(foreach cfile, $(CFILES), $(eval $(call COMPILE_C, $(cfile))))
+$(foreach cxxfile, $(CPPFILES), $(eval $(call COMPILE_CPP, $(cxxfile))))
+
+.PHONY: all lib clean

+ 25 - 0
components/spi_flash/sim/stubs/Makefile.files

@@ -0,0 +1,25 @@
+SOURCE_FILES := \
+	app_update/esp_ota_eps.c \
+	log/log.c \
+	newlib/lock.c \
+	esp32/crc.cpp
+
+INCLUDE_DIRS := \
+	../include \
+	../private_include \
+	app_update/include \
+	driver/include \
+	esp32/include \
+	freertos/include \
+	log/include \
+	newlib/include \
+	sdmmc/include \
+	vfs/include \
+	$(addprefix ../../../../components/, \
+	soc/esp32/include \
+	esp32/include \
+	bootloader_support/include \
+	app_update/include \
+	spi_flash/include \
+	)
+

+ 17 - 0
components/spi_flash/sim/stubs/component.mk

@@ -0,0 +1,17 @@
+include $(COMPONENT_PATH)/Makefile.files
+
+COMPONENT_OWNBUILDTARGET := 1
+COMPONENT_OWNCLEANTARGET := 1
+
+COMPONENT_ADD_INCLUDEDIRS := $(INCLUDE_DIRS)
+
+.PHONY: build
+build: $(SDKCONFIG_HEADER)
+	$(MAKE) -C $(COMPONENT_PATH) lib SDKCONFIG=$(SDKCONFIG_HEADER) BUILD_DIR=$(COMPONENT_BUILD_DIR) COMPONENT=$(COMPONENT_NAME)
+
+CLEAN_FILES := component_project_vars.mk
+.PHONY: clean
+clean:
+	$(summary) RM $(CLEAN_FILES)
+	rm -f $(CLEAN_FILES)
+	$(MAKE) -C $(COMPONENT_PATH) clean SDKCONFIG=$(SDKCONFIG_HEADER) BUILD_DIR=$(COMPONENT_BUILD_DIR) COMPONENT=$(COMPONENT_NAME)

+ 0 - 0
components/fatfs/test_fatfs_host/stubs/driver/include/driver/sdmmc_host.h → components/spi_flash/sim/stubs/driver/include/driver/sdmmc_host.h


+ 0 - 0
components/fatfs/test_fatfs_host/stubs/driver/include/driver/sdmmc_types.h → components/spi_flash/sim/stubs/driver/include/driver/sdmmc_types.h


+ 0 - 0
components/wear_levelling/test_wl_host/stubs/esp32/crc.cpp → components/spi_flash/sim/stubs/esp32/crc.cpp


+ 1 - 1
components/spi_flash/sim/stubs/freertos/include/freertos/FreeRTOS.h

@@ -5,4 +5,4 @@
 
 // Avoid redefinition compile error. Put here since this is included
 // in flash_ops.c.
-#define spi_flash_init()        overriden_spi_flash_init()
+#define spi_flash_init()                     overriden_spi_flash_init()

+ 13 - 2
components/spi_flash/sim/stubs/log/include/esp_log.h

@@ -3,11 +3,20 @@
 #include <stdint.h>
 #include <stdio.h>
 
+#include "sdkconfig.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#define LOG_LOCAL_LEVEL         ESP_LOG_DEBUG
+#define strlcpy(a, b, c)
+#define strlcat(a, b, c)
+
+#define heap_caps_malloc(a, b)  NULL
+#define MALLOC_CAP_INTERNAL     0
+#define MALLOC_CAP_8BIT         0
+
+#define LOG_LOCAL_LEVEL         CONFIG_LOG_DEFAULT_LEVEL
 
 typedef enum {
     ESP_LOG_NONE,       /*!< No log output */
@@ -25,6 +34,9 @@ typedef enum {
 #define LOG_COLOR_V
 #define LOG_RESET_COLOR
 
+#undef _Static_assert
+#define _Static_assert(cond, message)
+
 uint32_t esp_log_timestamp(void);
 void esp_log_write(esp_log_level_t level, const char* tag, const char* format, ...) __attribute__ ((format (printf, 3, 4)));
 
@@ -45,4 +57,3 @@ void esp_log_write(esp_log_level_t level, const char* tag, const char* format, .
 #ifdef __cplusplus
 }
 #endif
-

+ 2 - 0
components/spi_flash/sim/stubs/newlib/include/sys/lock.h

@@ -1,5 +1,7 @@
 #pragma once
 
+#include <time.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif

+ 0 - 0
components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/task.h → components/spi_flash/sim/stubs/sdkconfig/sdkconfig.h


+ 0 - 0
components/fatfs/test_fatfs_host/stubs/sdmmc/include/sdmmc_cmd.h → components/spi_flash/sim/stubs/sdmmc/include/sdmmc_cmd.h


+ 0 - 0
components/spiffs/test_spiffs_host/stubs/vfs/include/esp_vfs.h → components/spi_flash/sim/stubs/vfs/include/esp_vfs.h


+ 2 - 0
components/spiffs/esp_spiffs.c

@@ -32,6 +32,8 @@
 #include "rom/spi_flash.h"
 #include "spiffs_api.h"
 
+static const char* TAG = "SPIFFS";
+
 #ifdef CONFIG_SPIFFS_USE_MTIME
 _Static_assert(CONFIG_SPIFFS_META_LENGTH >= sizeof(time_t),
         "SPIFFS_META_LENGTH size should be >= sizeof(time_t)");

+ 1 - 1
components/spiffs/spiffs_api.c

@@ -19,7 +19,7 @@
 #include "esp_vfs.h"
 #include "spiffs_api.h"
 
-const char* TAG = "SPIFFS";
+static const char* TAG = "SPIFFS";
 
 void spiffs_api_lock(spiffs *fs)
 {

+ 0 - 2
components/spiffs/spiffs_api.h

@@ -26,8 +26,6 @@
 extern "C" {
 #endif
 
-extern const char* TAG;
-
 /**
  * @brief SPIFFS definition structure
  */

+ 77 - 76
components/spiffs/test_spiffs_host/Makefile

@@ -1,97 +1,98 @@
-COMPONENT=spiffs
+ifndef COMPONENT
+COMPONENT := spiffs
+endif
 
-TEST_PROGRAM=test_$(COMPONENT)
+COMPONENT_LIB := lib$(COMPONENT).a
+TEST_PROGRAM := test_$(COMPONENT)
 
-#Expose as a library
-COMPONENT_LIB=lib$(COMPONENT).a
+STUBS_LIB_DIR := ../../../components/spi_flash/sim/stubs
+STUBS_LIB_BUILD_DIR := $(STUBS_LIB_DIR)/build
+STUBS_LIB := libstubs.a
 
-SPI_FLASH=spi_flash
-SPI_FLASH_DIR=../../$(SPI_FLASH)
-SPI_FLASH_SIM_DIR=$(SPI_FLASH_DIR)/sim
-SPI_FLASH_LIB=lib$(SPI_FLASH).a
+SPI_FLASH_SIM_DIR := ../../../components/spi_flash/sim
+SPI_FLASH_SIM_BUILD_DIR := $(SPI_FLASH_SIM_DIR)/build
+SPI_FLASH_SIM_LIB := libspi_flash.a
 
-all: $(TEST_PROGRAM)
+include Makefile.files
 
-SOURCE_FILES = \
-	../spiffs_api.c \
-	$(addprefix ../spiffs/src/, \
-	spiffs_cache.c \
-	spiffs_check.c \
-	spiffs_gc.c \
-	spiffs_hydrogen.c \
-	spiffs_nucleus.c \
-	) \
-	$(addprefix ./stubs/, \
-	log/log.c \
-	)
+all: test
 
-TEST_SOURCE_FILES = \
-	test_spiffs.cpp \
-	main.cpp \
-	test_utils.c
+ifndef SDKCONFIG
+SDKCONFIG_DIR := $(dir $(realpath sdkconfig/sdkconfig.h))
+SDKCONFIG := $(SDKCONFIG_DIR)sdkconfig.h
+else
+SDKCONFIG_DIR := $(dir $(realpath $(SDKCONFIG)))
+endif
 
-INCLUDE_FLAGS = $(addprefix -I,\
-	. \
-	.. \
-	../spiffs/src \
-	../include \
-	$(addprefix ./stubs/, \
-	log/include \
-	freertos/include \
-	newlib/include \
-	vfs/include \
-	) \
-	../../esp32/include \
-	$(SPI_FLASH_DIR)/include \
-	../../../tools/catch \
-)
-
-GCOV ?= gcov
-
-CPPFLAGS += $(INCLUDE_FLAGS) -D CONFIG_LOG_DEFAULT_LEVEL -g -m32
-CFLAGS += -fprofile-arcs -ftest-coverage
-CXXFLAGS += -std=c++11 -Wall -Werror  -fprofile-arcs -ftest-coverage
-LDFLAGS += -lstdc++ -fprofile-arcs -ftest-coverage
-
-OBJ_FILES = $(filter %.o, $(SOURCE_FILES:.cpp=.o) $(SOURCE_FILES:.c=.o))
-TEST_OBJ_FILES = $(filter %.o, $(TEST_SOURCE_FILES:.cpp=.o) $(TEST_SOURCE_FILES:.c=.o))
-
-$(SPI_FLASH_SIM_DIR)/$(SPI_FLASH_LIB): force
-	$(MAKE) -C $(SPI_FLASH_SIM_DIR) lib
+INCLUDE_FLAGS := $(addprefix -I, $(INCLUDE_DIRS) $(SDKCONFIG_DIR) ../../../tools/catch)
 
-force:
+CPPFLAGS += $(INCLUDE_FLAGS) -g -m32
+CXXFLAGS += $(INCLUDE_FLAGS) -std=c++11 -g -m32
 
-$(COMPONENT_LIB): $(OBJ_FILES)
-	$(AR) rcs $@ $^
+# Build libraries that this component is dependent on
+$(STUBS_LIB_BUILD_DIR)/$(STUBS_LIB): force
+	$(MAKE) -C $(STUBS_LIB_DIR) lib SDKCONFIG=$(SDKCONFIG)
 
-lib: $(COMPONENT_LIB)
+$(SPI_FLASH_SIM_BUILD_DIR)/$(SPI_FLASH_SIM_LIB): force
+	$(MAKE) -C $(SPI_FLASH_SIM_DIR) lib SDKCONFIG=$(SDKCONFIG)
 
-partitions_table.bin: partitions_table.csv
-	python ../../partition_table/gen_esp32part.py $< $@
+# Create target for building this component as a library
+CFILES := $(filter %.c, $(SOURCE_FILES))
+CPPFILES := $(filter %.cpp, $(SOURCE_FILES))
 
-$(TEST_PROGRAM): lib $(TEST_OBJ_FILES) $(SPI_FLASH_SIM_DIR)/$(SPI_FLASH_LIB) partitions_table.bin
-	g++ $(LDFLAGS) -o $(TEST_PROGRAM) $(TEST_OBJ_FILES) -L$(abspath .) -l:$(COMPONENT_LIB) -L$(SPI_FLASH_SIM_DIR) -l:$(SPI_FLASH_LIB) -g -m32
+CTARGET = ${2}/$(patsubst %.c,%.o,$(notdir ${1}))
+CPPTARGET = ${2}/$(patsubst %.cpp,%.o,$(notdir ${1}))
 
-test: $(TEST_PROGRAM)
-	./$(TEST_PROGRAM)
+ifndef BUILD_DIR
+BUILD_DIR := build
+endif
 
-COVERAGE_FILES = $(OBJ_FILES:.o=.gc*) $(TEST_OBJ_FILES:.o=.gc*)
+OBJ_FILES := $(addprefix $(BUILD_DIR)/, $(filter %.o, $(notdir $(SOURCE_FILES:.cpp=.o) $(SOURCE_FILES:.c=.o))))
 
-$(COVERAGE_FILES): test
+define COMPILE_C
+$(call CTARGET, ${1}, $(BUILD_DIR)) : ${1} $(SDKCONFIG)
+	mkdir -p $(BUILD_DIR)
+	$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $(call CTARGET, ${1}, $(BUILD_DIR)) ${1}
+endef
 
-coverage.info: $(COVERAGE_FILES)
-	find ../ -name "*.gcno" -exec $(GCOV) -r -pb {} +
-	lcov --capture --directory ../ --no-external --output-file coverage.info --gcov-tool $(GCOV)
+define COMPILE_CPP
+$(call CPPTARGET, ${1}, $(BUILD_DIR)) : ${1} $(SDKCONFIG)
+	mkdir -p $(BUILD_DIR) 
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $(call CPPTARGET, ${1}, $(BUILD_DIR)) ${1}
+endef
 
-coverage_report: coverage.info
-	genhtml coverage.info --output-directory coverage_report
-	@echo "Coverage report is in coverage_report/index.html"
+$(BUILD_DIR)/$(COMPONENT_LIB): $(OBJ_FILES) $(SDKCONFIG)
+	mkdir -p $(BUILD_DIR)
+	$(AR) rcs $@ $^
 
 clean:
-	rm -f $(OBJ_FILES) $(TEST_OBJ_FILES) $(TEST_PROGRAM) $(COMPONENT_LIB) partitions_table.bin
+	$(MAKE) -C $(STUBS_LIB_DIR) clean
 	$(MAKE) -C $(SPI_FLASH_SIM_DIR) clean
-	rm -f $(COVERAGE_FILES) *.gcov
-	rm -rf coverage_report/
-	rm -f coverage.info
+	rm -f $(OBJ_FILES) $(TEST_OBJ_FILES) $(TEST_PROGRAM) $(COMPONENT_LIB) partition_table.bin
+
+lib: $(BUILD_DIR)/$(COMPONENT_LIB)
+
+$(foreach cfile, $(CFILES), $(eval $(call COMPILE_C, $(cfile))))
+$(foreach cxxfile, $(CPPFILES), $(eval $(call COMPILE_CPP, $(cxxfile))))
+
+# Create target for building this component as a test
+TEST_SOURCE_FILES = \
+	test_spiffs.cpp \
+	main.cpp \
+	test_utils.c
+
+TEST_OBJ_FILES = $(filter %.o, $(TEST_SOURCE_FILES:.cpp=.o) $(TEST_SOURCE_FILES:.c=.o))
+
+$(TEST_PROGRAM): lib $(TEST_OBJ_FILES) $(SPI_FLASH_SIM_BUILD_DIR)/$(SPI_FLASH_SIM_LIB) $(STUBS_LIB_BUILD_DIR)/$(STUBS_LIB) partition_table.bin $(SDKCONFIG)
+	g++ $(LDFLAGS) $(CXXFLAGS) -o $@  $(TEST_OBJ_FILES) -L$(BUILD_DIR) -l:$(COMPONENT_LIB) -L$(SPI_FLASH_SIM_BUILD_DIR) -l:$(SPI_FLASH_SIM_LIB) -L$(STUBS_LIB_BUILD_DIR) -l:$(STUBS_LIB)
+
+test: $(TEST_PROGRAM)
+	./$(TEST_PROGRAM)
+
+# Create other necessary targets
+partition_table.bin: partition_table.csv
+	python ../../../components/partition_table/gen_esp32part.py --verify $< $@
+
+force:
 
-.PHONY: clean all test lib
+.PHONY: all lib test clean force

+ 33 - 0
components/spiffs/test_spiffs_host/Makefile.files

@@ -0,0 +1,33 @@
+SOURCE_FILES := \
+	../spiffs_api.c \
+	$(addprefix ../spiffs/src/, \
+	spiffs_cache.c \
+	spiffs_check.c \
+	spiffs_gc.c \
+	spiffs_hydrogen.c \
+	spiffs_nucleus.c \
+	) 
+
+INCLUDE_DIRS := \
+	. \
+	.. \
+	../spiffs/src \
+	../include \
+	$(addprefix ../../spi_flash/sim/stubs/, \
+	app_update/include \
+	driver/include \
+	esp32/include \
+	freertos/include \
+	log/include \
+	newlib/include \
+	sdmmc/include \
+	vfs/include \
+	) \
+	$(addprefix ../../../components/, \
+	soc/esp32/include \
+	esp32/include \
+	bootloader_support/include \
+	app_update/include \
+	spi_flash/include \
+	wear_levelling/include \
+	)

+ 17 - 0
components/spiffs/test_spiffs_host/component.mk

@@ -0,0 +1,17 @@
+include $(COMPONENT_PATH)/Makefile.files
+
+COMPONENT_OWNBUILDTARGET := 1
+COMPONENT_OWNCLEANTARGET := 1
+
+COMPONENT_ADD_INCLUDEDIRS := $(INCLUDE_DIRS)
+
+.PHONY: build
+build: $(SDKCONFIG_HEADER)
+	$(MAKE) -C $(COMPONENT_PATH) lib SDKCONFIG=$(SDKCONFIG_HEADER) BUILD_DIR=$(COMPONENT_BUILD_DIR) COMPONENT=$(COMPONENT_NAME)
+
+CLEAN_FILES := component_project_vars.mk
+.PHONY: clean
+clean:
+	$(summary) RM $(CLEAN_FILES)
+	rm -f $(CLEAN_FILES)
+	$(MAKE) -C $(COMPONENT_PATH) clean SDKCONFIG=$(SDKCONFIG_HEADER) BUILD_DIR=$(COMPONENT_BUILD_DIR) COMPONENT=$(COMPONENT_NAME)

+ 0 - 0
components/spiffs/test_spiffs_host/partitions_table.csv → components/spiffs/test_spiffs_host/partition_table.csv


+ 5 - 0
components/spiffs/test_spiffs_host/sdkconfig.h → components/spiffs/test_spiffs_host/sdkconfig/sdkconfig.h

@@ -11,4 +11,9 @@
 #define CONFIG_SPIFFS_USE_MAGIC 1
 #define CONFIG_SPIFFS_PAGE_CHECK 1
 #define CONFIG_SPIFFS_USE_MTIME 1
+
 #define CONFIG_WL_SECTOR_SIZE 4096
+#define CONFIG_LOG_DEFAULT_LEVEL 3
+#define CONFIG_PARTITION_TABLE_OFFSET 0x8000
+
+#define CONFIG_ESPTOOLPY_FLASHSIZE "8MB"

+ 0 - 4
components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/FreeRTOS.h

@@ -1,4 +0,0 @@
-#pragma once
-
-#include "projdefs.h"
-#include "semphr.h"

+ 0 - 11
components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/projdefs.h

@@ -1,11 +0,0 @@
-#pragma once
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#define pdTRUE			1
-
-#if defined(__cplusplus)
-}
-#endif

+ 0 - 16
components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/semphr.h

@@ -1,16 +0,0 @@
-#pragma once
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#define vSemaphoreDelete( xSemaphore )
-#define xSemaphoreCreateMutex()                     ((void*)(1))
-#define xSemaphoreGive( xSemaphore )	
-#define xSemaphoreTake( xSemaphore, xBlockTime )    pdTRUE		
-
-typedef void* SemaphoreHandle_t;
-
-#if defined(__cplusplus)
-}
-#endif

+ 0 - 51
components/spiffs/test_spiffs_host/stubs/log/include/esp_log.h

@@ -1,51 +0,0 @@
-#pragma once
-
-#include <stdint.h>
-#include <stdio.h>
-
-#include "sdkconfig.h"
-
-#define strlcpy(a, b, c)
-#define strlcat(a, b, c)
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-#define LOG_LOCAL_LEVEL     ESP_LOG_DEBUG
-
-typedef enum {
-    ESP_LOG_NONE,       /*!< No log output */
-    ESP_LOG_ERROR,      /*!< Critical errors, software module can not recover on its own */
-    ESP_LOG_WARN,       /*!< Error conditions from which recovery measures have been taken */
-    ESP_LOG_INFO,       /*!< Information messages which describe normal flow of events */
-    ESP_LOG_DEBUG,      /*!< Extra information which is not necessary for normal use (values, pointers, sizes, etc). */
-    ESP_LOG_VERBOSE     /*!< Bigger chunks of debugging information, or frequent messages which can potentially flood the output. */
-} esp_log_level_t;
-
-#define LOG_COLOR_E
-#define LOG_COLOR_W
-#define LOG_COLOR_I
-#define LOG_COLOR_D
-#define LOG_COLOR_V
-#define LOG_RESET_COLOR
-
-#undef _Static_assert
-#define _Static_assert(cond, message)
-
-uint32_t esp_log_timestamp(void);
-void esp_log_write(esp_log_level_t level, const char* tag, const char* format, ...) __attribute__ ((format (printf, 3, 4)));
-
-#define LOG_FORMAT(letter, format)  LOG_COLOR_ ## letter #letter " (%d) %s: " format LOG_RESET_COLOR "\n"
-
-#define ESP_LOGE( tag, format, ... )  if (LOG_LOCAL_LEVEL >= ESP_LOG_ERROR)   { esp_log_write(ESP_LOG_ERROR,   tag, LOG_FORMAT(E, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
-
-#define ESP_LOGV( tag, format, ... )  if (LOG_LOCAL_LEVEL >= ESP_LOG_VERBOSE) { esp_log_write(ESP_LOG_VERBOSE, tag, LOG_FORMAT(V, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
-
-#define ESP_LOGD( tag, format, ... )  if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG)   { esp_log_write(ESP_LOG_DEBUG,   tag, LOG_FORMAT(D, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
-
-#define ESP_LOGW( tag, format, ... )  if (LOG_LOCAL_LEVEL >= ESP_LOG_WARN)    { esp_log_write(ESP_LOG_WARN,    tag, LOG_FORMAT(W, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
-
-#if defined(__cplusplus)
-}
-#endif

+ 0 - 22
components/spiffs/test_spiffs_host/stubs/log/log.c

@@ -1,22 +0,0 @@
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-
-#include "esp_log.h"
-
-void esp_log_write(esp_log_level_t level,
-                   const char *tag,
-                   const char *format, ...)
-{
-    va_list arg;
-    va_start(arg, format);
-    vprintf(format, arg);
-    va_end(arg);
-}
-
-uint32_t esp_log_timestamp()
-{
-    return 0;
-}
-

+ 0 - 10
components/spiffs/test_spiffs_host/stubs/newlib/include/sys/lock.h

@@ -1,10 +0,0 @@
-#pragma once
-
-#include <time.h>
-
-typedef int _lock_t;
-
-void _lock_acquire(_lock_t *lock);
-void _lock_close(_lock_t *lock);
-void _lock_init(_lock_t *lock);
-void _lock_release(_lock_t *lock);

+ 0 - 21
components/spiffs/test_spiffs_host/stubs/newlib/lock.c

@@ -1,21 +0,0 @@
-#include "sys/lock.h"
-
-void _lock_acquire(_lock_t *lock) 
-{
-    return;
-}
-
-void _lock_close(_lock_t *lock) 
-{
-    return;
-}
-
-void _lock_init(_lock_t *lock) 
-{
-    return;
-}
-
-void _lock_release(_lock_t *lock) 
-{
-    return;
-}

+ 2 - 2
components/spiffs/test_spiffs_host/test_spiffs.cpp

@@ -9,11 +9,11 @@
 
 #include "catch.hpp"
 
-extern "C" void init_spi_flash(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin);
+extern "C" void init_spi_flash(const char* chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin);
 
 TEST_CASE("format disk, open file, write and read file", "[spiffs]")
 {
-    init_spi_flash(0x00400000, CONFIG_WL_SECTOR_SIZE * 16, CONFIG_WL_SECTOR_SIZE, CONFIG_WL_SECTOR_SIZE, "partitions_table.bin");
+    init_spi_flash(CONFIG_ESPTOOLPY_FLASHSIZE, CONFIG_WL_SECTOR_SIZE * 16, CONFIG_WL_SECTOR_SIZE, CONFIG_WL_SECTOR_SIZE, "partition_table.bin");
 
     spiffs fs;
     spiffs_config cfg;

+ 2 - 2
components/spiffs/test_spiffs_host/test_utils.c

@@ -1,7 +1,7 @@
 #include "esp_spi_flash.h"
 #include "esp_partition.h"
 
-void init_spi_flash(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin)
+void init_spi_flash(const char* chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin)
 {
     spi_flash_init(chip_size, block_size, sector_size, page_size, partition_bin);
-}
+}

+ 79 - 80
components/wear_levelling/test_wl_host/Makefile

@@ -1,99 +1,98 @@
-COMPONENT=wear_levelling
-
-TEST_PROGRAM=test_$(COMPONENT)
-
-# Expose as a library for FS components that require wear_levelling
-COMPONENT_LIB=lib$(COMPONENT).a
-
-# Use simulated block device
-SPI_FLASH=spi_flash
-SPI_FLASH_DIR=../../$(SPI_FLASH)
-SPI_FLASH_SIM_DIR=$(SPI_FLASH_DIR)/sim
-SPI_FLASH_LIB=lib$(SPI_FLASH).a
-
-all: $(TEST_PROGRAM)
-
-SOURCE_FILES = \
-	$(addprefix ../, \
-	wear_levelling.cpp \
-	crc32.cpp \
-	WL_Flash.cpp \
-	Partition.cpp \
-	) \
-	$(addprefix stubs/, \
-	newlib/lock.c \
-	log/log.c \
-	esp32/crc.cpp \
-	)
+ifndef COMPONENT
+COMPONENT := wl
+endif
 
-TEST_SOURCE_FILES = \
-	test_wl.cpp \
-	main.cpp \
-	test_utils.c
+COMPONENT_LIB := lib$(COMPONENT).a
+TEST_PROGRAM := test_$(COMPONENT)
 
-INCLUDE_FLAGS = $(addprefix -I,\
-	. \
-	../ \
-	../include \
-	../private_include \
-	$(addprefix stubs/, \
-	newlib/include \
-	log/include \
-	) \
-	$(SPI_FLASH_DIR)/include \
-	../../esp32/include \
-	../../../tools/catch \
-)
-
-GCOV ?= gcov
-
-CPPFLAGS += $(INCLUDE_FLAGS) -D CONFIG_LOG_DEFAULT_LEVEL -g -m32
-CFLAGS += -fprofile-arcs -ftest-coverage
-CXXFLAGS += -std=c++11 -Wall -Werror  -fprofile-arcs -ftest-coverage
-LDFLAGS += -lstdc++ -fprofile-arcs -ftest-coverage
-
-OBJ_FILES = $(filter %.o, $(SOURCE_FILES:.cpp=.o) $(SOURCE_FILES:.c=.o))
-TEST_OBJ_FILES = $(filter %.o, $(TEST_SOURCE_FILES:.cpp=.o) $(TEST_SOURCE_FILES:.c=.o))
+STUBS_LIB_DIR := ../../../components/spi_flash/sim/stubs
+STUBS_LIB_BUILD_DIR := $(STUBS_LIB_DIR)/build
+STUBS_LIB := libstubs.a
 
-$(SPI_FLASH_SIM_DIR)/$(SPI_FLASH_LIB): force
-	$(MAKE) -C $(SPI_FLASH_SIM_DIR) lib
+SPI_FLASH_SIM_DIR := ../../../components/spi_flash/sim
+SPI_FLASH_SIM_BUILD_DIR := $(SPI_FLASH_SIM_DIR)/build
+SPI_FLASH_SIM_LIB := libspi_flash.a
 
-$(COMPONENT_LIB): $(OBJ_FILES)
-	$(AR) rcs $@ $^
+include Makefile.files
 
-force:
+all: test
 
-lib: $(COMPONENT_LIB)
+ifndef SDKCONFIG
+SDKCONFIG_DIR := $(dir $(realpath sdkconfig/sdkconfig.h))
+SDKCONFIG := $(SDKCONFIG_DIR)sdkconfig.h
+else
+SDKCONFIG_DIR := $(dir $(realpath $(SDKCONFIG)))
+endif
 
-partition_table.bin: partition_table.csv
-	python ../../../components/partition_table/gen_esp32part.py $< $@
+INCLUDE_FLAGS := $(addprefix -I, $(INCLUDE_DIRS) $(SDKCONFIG_DIR) ../../../tools/catch)
 
-$(TEST_PROGRAM): lib $(TEST_OBJ_FILES) $(SPI_FLASH_SIM_DIR)/$(SPI_FLASH_LIB) partition_table.bin
-	g++ $(LDFLAGS) -o $@  $(TEST_OBJ_FILES) -L$(abspath .) -l:$(COMPONENT_LIB) -L$(SPI_FLASH_SIM_DIR) -l:$(SPI_FLASH_LIB) -g -m32
+CPPFLAGS += $(INCLUDE_FLAGS) -g -m32
+CXXFLAGS += $(INCLUDE_FLAGS) -std=c++11 -g -m32
 
-test: $(TEST_PROGRAM)
-	./$(TEST_PROGRAM)
+# Build libraries that this component is dependent on
+$(STUBS_LIB_BUILD_DIR)/$(STUBS_LIB): force
+	$(MAKE) -C $(STUBS_LIB_DIR) lib SDKCONFIG=$(SDKCONFIG)
+
+$(SPI_FLASH_SIM_BUILD_DIR)/$(SPI_FLASH_SIM_LIB): force
+	$(MAKE) -C $(SPI_FLASH_SIM_DIR) lib SDKCONFIG=$(SDKCONFIG)
+
+# Create target for building this component as a library
+CFILES := $(filter %.c, $(SOURCE_FILES))
+CPPFILES := $(filter %.cpp, $(SOURCE_FILES))
 
-$(OUTPUT_DIR):
-	mkdir -p $(OUTPUT_DIR)
+CTARGET = ${2}/$(patsubst %.c,%.o,$(notdir ${1}))
+CPPTARGET = ${2}/$(patsubst %.cpp,%.o,$(notdir ${1}))
 
-COVERAGE_FILES = $(OBJ_FILES:.o=.gc*) $(TEST_OBJ_FILES:.o=.gc*)
+ifndef BUILD_DIR
+BUILD_DIR := build
+endif
 
-$(COVERAGE_FILES): test
+OBJ_FILES := $(addprefix $(BUILD_DIR)/, $(filter %.o, $(notdir $(SOURCE_FILES:.cpp=.o) $(SOURCE_FILES:.c=.o))))
 
-coverage.info: $(COVERAGE_FILES)
-	find ../ -name "*.gcno" -exec $(GCOV) -r -pb {} +
-	lcov --capture --directory ../ --no-external --output-file coverage.info --gcov-tool $(GCOV)
+define COMPILE_C
+$(call CTARGET, ${1}, $(BUILD_DIR)) : ${1} $(SDKCONFIG)
+	mkdir -p $(BUILD_DIR)
+	$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $(call CTARGET, ${1}, $(BUILD_DIR)) ${1}
+endef
 
-coverage_report: coverage.info
-	genhtml coverage.info --output-directory coverage_report
-	@echo "Coverage report is in coverage_report/index.html"
+define COMPILE_CPP
+$(call CPPTARGET, ${1}, $(BUILD_DIR)) : ${1} $(SDKCONFIG)
+	mkdir -p $(BUILD_DIR)
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $(call CPPTARGET, ${1}, $(BUILD_DIR)) ${1}
+endef
+
+$(BUILD_DIR)/$(COMPONENT_LIB): $(OBJ_FILES) $(SDKCONFIG)
+	mkdir -p $(BUILD_DIR)
+	$(AR) rcs $@ $^
 
 clean:
+	$(MAKE) -C $(STUBS_LIB_DIR) clean
 	$(MAKE) -C $(SPI_FLASH_SIM_DIR) clean
 	rm -f $(OBJ_FILES) $(TEST_OBJ_FILES) $(TEST_PROGRAM) $(COMPONENT_LIB) partition_table.bin
-	rm -f $(COVERAGE_FILES) *.gcov
-	rm -rf coverage_report/
-	rm -f coverage.info
 
-.PHONY: clean all test lib
+lib: $(BUILD_DIR)/$(COMPONENT_LIB)
+
+$(foreach cfile, $(CFILES), $(eval $(call COMPILE_C, $(cfile))))
+$(foreach cxxfile, $(CPPFILES), $(eval $(call COMPILE_CPP, $(cxxfile))))
+
+# Create target for building this component as a test
+TEST_SOURCE_FILES = \
+	test_wl.cpp \
+	main.cpp \
+	test_utils.c
+
+TEST_OBJ_FILES = $(filter %.o, $(TEST_SOURCE_FILES:.cpp=.o) $(TEST_SOURCE_FILES:.c=.o))
+
+$(TEST_PROGRAM): lib $(TEST_OBJ_FILES) $(SPI_FLASH_SIM_BUILD_DIR)/$(SPI_FLASH_SIM_LIB) $(STUBS_LIB_BUILD_DIR)/$(STUBS_LIB) partition_table.bin $(SDKCONFIG)
+	g++ $(LDFLAGS) $(CXXFLAGS) -o $@  $(TEST_OBJ_FILES) -L$(BUILD_DIR) -l:$(COMPONENT_LIB) -L$(SPI_FLASH_SIM_BUILD_DIR) -l:$(SPI_FLASH_SIM_LIB) -L$(STUBS_LIB_BUILD_DIR) -l:$(STUBS_LIB)
+
+test: $(TEST_PROGRAM)
+	./$(TEST_PROGRAM)
+
+# Create other necessary targets
+partition_table.bin: partition_table.csv
+	python ../../../components/partition_table/gen_esp32part.py --verify $< $@
+
+force:
+
+.PHONY: all lib test clean force

+ 31 - 0
components/wear_levelling/test_wl_host/Makefile.files

@@ -0,0 +1,31 @@
+SOURCE_FILES := \
+	$(addprefix ../, \
+	wear_levelling.cpp \
+	crc32.cpp \
+	WL_Flash.cpp \
+	Partition.cpp \
+	) 
+
+INCLUDE_DIRS := \
+	. \
+	../ \
+	../include \
+	../private_include \
+	../../spi_flash/sim \
+	$(addprefix ../../spi_flash/sim/stubs/, \
+	app_update/include \
+	driver/include \
+	esp32/include \
+	freertos/include \
+	log/include \
+	newlib/include \
+	sdmmc/include \
+	vfs/include \
+	) \
+	$(addprefix ../../../components/, \
+	soc/esp32/include \
+	esp32/include \
+	bootloader_support/include \
+	app_update/include \
+	spi_flash/include \
+	)

+ 17 - 0
components/wear_levelling/test_wl_host/component.mk

@@ -0,0 +1,17 @@
+include $(COMPONENT_PATH)/Makefile.files
+
+COMPONENT_OWNBUILDTARGET := 1
+COMPONENT_OWNCLEANTARGET := 1
+
+COMPONENT_ADD_INCLUDEDIRS := $(INCLUDE_DIRS)
+
+.PHONY: build
+build: $(SDKCONFIG_HEADER)
+	$(MAKE) -C $(COMPONENT_PATH) lib SDKCONFIG=$(SDKCONFIG_HEADER) BUILD_DIR=$(COMPONENT_BUILD_DIR) COMPONENT=$(COMPONENT_NAME)
+
+CLEAN_FILES := component_project_vars.mk
+.PHONY: clean
+clean:
+	$(summary) RM $(CLEAN_FILES)
+	rm -f $(CLEAN_FILES)
+	$(MAKE) -C $(COMPONENT_PATH) clean SDKCONFIG=$(SDKCONFIG_HEADER) BUILD_DIR=$(COMPONENT_BUILD_DIR) COMPONENT=$(COMPONENT_NAME)

+ 1 - 1
components/wear_levelling/test_wl_host/partition_table.csv

@@ -3,4 +3,4 @@
 nvs,      data, nvs,     0x9000,  0x6000,
 phy_init, data, phy,     0xf000,  0x1000,
 factory,  app,  factory, 0x10000, 1M,
-storage,  data, fat,     ,        1M,
+storage,  data, ,        ,        1M,

+ 0 - 3
components/wear_levelling/test_wl_host/sdkconfig.h

@@ -1,3 +0,0 @@
-#pragma once
-
-#define CONFIG_WL_SECTOR_SIZE 4096

+ 6 - 0
components/wear_levelling/test_wl_host/sdkconfig/sdkconfig.h

@@ -0,0 +1,6 @@
+#pragma once
+
+#define CONFIG_WL_SECTOR_SIZE 4096
+#define CONFIG_LOG_DEFAULT_LEVEL 3
+#define CONFIG_PARTITION_TABLE_OFFSET 0x8000
+#define CONFIG_ESPTOOLPY_FLASHSIZE "8MB"

+ 0 - 44
components/wear_levelling/test_wl_host/stubs/log/include/esp_log.h

@@ -1,44 +0,0 @@
-#pragma once
-
-#include <stdint.h>
-#include <stdio.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define LOG_LOCAL_LEVEL         ESP_LOG_DEBUG
-
-typedef enum {
-    ESP_LOG_NONE,       /*!< No log output */
-    ESP_LOG_ERROR,      /*!< Critical errors, software module can not recover on its own */
-    ESP_LOG_WARN,       /*!< Error conditions from which recovery measures have been taken */
-    ESP_LOG_INFO,       /*!< Information messages which describe normal flow of events */
-    ESP_LOG_DEBUG,      /*!< Extra information which is not necessary for normal use (values, pointers, sizes, etc). */
-    ESP_LOG_VERBOSE     /*!< Bigger chunks of debugging information, or frequent messages which can potentially flood the output. */
-} esp_log_level_t;
-
-#define LOG_COLOR_E
-#define LOG_COLOR_W
-#define LOG_COLOR_I
-#define LOG_COLOR_D
-#define LOG_COLOR_V
-#define LOG_RESET_COLOR
-
-uint32_t esp_log_timestamp(void);
-void esp_log_write(esp_log_level_t level, const char* tag, const char* format, ...) __attribute__ ((format (printf, 3, 4)));
-
-#define LOG_FORMAT(letter, format)  LOG_COLOR_ ## letter #letter " (%d) %s: " format LOG_RESET_COLOR "\n"
-
-#define ESP_LOGE( tag, format, ... )  if (LOG_LOCAL_LEVEL >= ESP_LOG_ERROR)   { esp_log_write(ESP_LOG_ERROR,   tag, LOG_FORMAT(E, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
-
-#define ESP_LOGV( tag, format, ... )  if (LOG_LOCAL_LEVEL >= ESP_LOG_VERBOSE) { esp_log_write(ESP_LOG_VERBOSE, tag, LOG_FORMAT(V, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
-
-#define ESP_LOGD( tag, format, ... )  if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG)   { esp_log_write(ESP_LOG_DEBUG,   tag, LOG_FORMAT(D, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
-
-#define ESP_LOGW( tag, format, ... )  if (LOG_LOCAL_LEVEL >= ESP_LOG_WARN)    { esp_log_write(ESP_LOG_WARN,    tag, LOG_FORMAT(W, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
-
-#ifdef __cplusplus
-}
-#endif
-

+ 0 - 21
components/wear_levelling/test_wl_host/stubs/log/log.c

@@ -1,21 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <time.h>
-
-#include "esp_log.h"
-
-void esp_log_write(esp_log_level_t level,
-                   const char *tag,
-                   const char *format, ...)
-{
-    va_list arg;
-    va_start(arg, format);
-    vprintf(format, arg);
-    va_end(arg);
-}
-
-uint32_t esp_log_timestamp()
-{
-    return 0;
-}

+ 0 - 16
components/wear_levelling/test_wl_host/stubs/newlib/include/sys/lock.h

@@ -1,16 +0,0 @@
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef int _lock_t;
-
-void _lock_acquire(_lock_t *lock);
-void _lock_close(_lock_t *lock);
-void _lock_init(_lock_t *lock);
-void _lock_release(_lock_t *lock);
-
-#ifdef __cplusplus
-}
-#endif

+ 0 - 21
components/wear_levelling/test_wl_host/stubs/newlib/lock.c

@@ -1,21 +0,0 @@
-#include "sys/lock.h"
-
-void _lock_acquire(_lock_t *lock)
-{
-    return;
-}
-
-void _lock_close(_lock_t *lock)
-{
-    return;
-}
-
-void _lock_init(_lock_t *lock)
-{
-    return;
-}
-
-void _lock_release(_lock_t *lock)
-{
-    return;
-}

+ 2 - 2
components/wear_levelling/test_wl_host/test_utils.c

@@ -1,7 +1,7 @@
 #include "esp_spi_flash.h"
 #include "esp_partition.h"
 
-void init_spi_flash(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin)
+void init_spi_flash(const char* chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin)
 {
     spi_flash_init(chip_size, block_size, sector_size, page_size, partition_bin);
-}
+}

+ 126 - 3
components/wear_levelling/test_wl_host/test_wl.cpp

@@ -6,22 +6,26 @@
 #include "esp_partition.h"
 #include "wear_levelling.h"
 #include "WL_Flash.h"
+#include "SpiFlash.h"
 
 #include "catch.hpp"
 
 #include "sdkconfig.h"
 
-extern "C" void init_spi_flash(size_t chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin);
+extern "C" void init_spi_flash(const char* chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin);
+extern SpiFlash spiflash;
+
+#define TEST_COUNT_MAX 100
 
 TEST_CASE("write and read back data", "[wear_levelling]")
 {
-    init_spi_flash(0x00400000, CONFIG_WL_SECTOR_SIZE * 16, CONFIG_WL_SECTOR_SIZE, CONFIG_WL_SECTOR_SIZE, "partition_table.bin");
+    init_spi_flash(CONFIG_ESPTOOLPY_FLASHSIZE, CONFIG_WL_SECTOR_SIZE * 16, CONFIG_WL_SECTOR_SIZE, CONFIG_WL_SECTOR_SIZE, "partition_table.bin");
 
     esp_err_t result;
     wl_handle_t wl_handle;
 
     int flash_handle;
-    const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, "storage");
+    const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage");
 
     // Mount wear-levelled partition
     result = wl_mount(partition, &wl_handle);
@@ -85,3 +89,122 @@ TEST_CASE("write and read back data", "[wear_levelling]")
     free(data);
     free(read);
 }
+
+TEST_CASE("power down test", "[wear_levelling]")
+{
+    init_spi_flash(CONFIG_ESPTOOLPY_FLASHSIZE, CONFIG_WL_SECTOR_SIZE * 16, CONFIG_WL_SECTOR_SIZE, CONFIG_WL_SECTOR_SIZE, "partition_table.bin");
+
+    esp_err_t result;
+    wl_handle_t wl_handle;
+
+    int flash_handle;
+    const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage");
+
+    // Mount wear-levelled partition
+    result = wl_mount(partition, &wl_handle);
+    REQUIRE(result == ESP_OK);
+
+    // Get wl partition information
+    size_t sector_size = wl_sector_size(wl_handle);
+    int32_t sectors_count = wl_size(wl_handle) / sector_size;
+
+    uint32_t add_const = 0;
+    uint32_t *sector_data = new uint32_t[sector_size / sizeof(uint32_t)];
+
+    // Fill partition with check data
+    for (int32_t i = 0; i < sectors_count; i++) {
+        REQUIRE(wl_erase_range(wl_handle, i * sector_size, sector_size) == ESP_OK);
+        for (uint32_t m = 0; m < sector_size / sizeof(uint32_t); m++) {
+            uint32_t temp_data = i * sector_size + add_const + m;
+            sector_data[m] = temp_data;
+        }
+        REQUIRE(wl_write(wl_handle, i * sector_size, sector_data, sector_size) == ESP_OK);
+    }
+
+    for (int32_t i = 0; i < sectors_count; i++) {
+        result |= wl_read(wl_handle, i * sector_size, sector_data, sector_size);
+        for (uint32_t m = 0; m < sector_size / sizeof(uint32_t); m++) {
+            uint32_t temp_data = i * sector_size + add_const + m;
+            REQUIRE(temp_data == sector_data[m]);
+            if (temp_data != sector_data[m]) {
+                printf("Error - read: %08x, expected %08x\n", sector_data[m], temp_data);
+            }
+        }
+    }
+
+    // Perform test
+    int32_t max_count = 100;
+    int32_t max_check_count = TEST_COUNT_MAX;
+    
+    printf("used_sectors_count=%d\n", max_check_count);
+
+    for (int32_t k = 0; k < max_check_count; k++) {
+
+        spiflash.set_total_erase_cycles_limit(max_count);
+
+        int32_t err_sector = -1;
+        for (int32_t i = 0; i < sectors_count; i++) {
+            result = ESP_OK;
+            result = wl_erase_range(wl_handle, i * sector_size, sector_size);
+            if (result != ESP_OK) {
+                err_sector = i;
+                break;
+            }
+            for (uint32_t m = 0; m < sector_size / sizeof(uint32_t); m++) {
+                uint32_t temp_data = i * sector_size + add_const + m;
+                sector_data[m] = temp_data;
+            }
+            result = wl_write(wl_handle, i * sector_size, sector_data, sector_size);
+            if (result != ESP_OK) {
+                err_sector = i;
+                break;
+            }
+        }
+
+        if (err_sector >= 0) {
+            max_count++;
+        } else {
+            max_count = 0;
+        }
+
+        spiflash.set_total_erase_cycles_limit(0);
+
+        result = wl_unmount(wl_handle);
+        REQUIRE(result == ESP_OK);
+
+        result = wl_mount(partition, &wl_handle);
+        REQUIRE(result == ESP_OK);
+
+        for (int32_t i = 0; i < sectors_count; i++) {
+            if (i != err_sector) {
+                result |= wl_read(wl_handle, i * sector_size, sector_data, sector_size);
+                for (uint32_t m = 0; m < sector_size / sizeof(uint32_t); m++) {
+                    uint32_t temp_data = i * sector_size + add_const + m;
+                    REQUIRE(temp_data == sector_data[m]);
+                    if (temp_data != sector_data[m]) {
+                        printf("Error - read: %08x, expected %08x, m=%i, sector=%i\n", sector_data[m], temp_data, m, i);
+                    }
+                }
+            }
+        }
+
+        if (err_sector != -1) {
+            result |= wl_erase_range(wl_handle, err_sector * sector_size, sector_size);
+            for (uint32_t m = 0; m < sector_size / sizeof(uint32_t); m++) {
+                uint32_t temp_data = err_sector * sector_size + add_const + m;
+                sector_data[m] = temp_data;
+            }
+            result |= wl_write(wl_handle, err_sector * sector_size, sector_data, sector_size);
+        }
+
+        spiflash.reset_total_erase_cycles();
+
+        printf("[%3.f%%] err_sector=%i\n", (float)k / ((float)max_check_count) * 100.0f, err_sector);
+    }
+
+    delete[] sector_data;
+
+    // Unmount
+    result = wl_unmount(wl_handle);
+    REQUIRE(result == ESP_OK);
+}

+ 1 - 1
make/component_wrapper.mk

@@ -212,7 +212,7 @@ build: $(COMPONENT_LIBRARY)
 $(COMPONENT_LIBRARY): $(COMPONENT_OBJS) $(COMPONENT_EMBED_OBJS)
 	$(summary) AR $(patsubst $(PWD)/%,%,$(CURDIR))/$@
 	rm -f $@
-	$(AR) cru $@ $^
+	$(AR) $(ARFLAGS) $@ $^
 endif
 
 # If COMPONENT_OWNCLEANTARGET is not set, define a phony clean target

+ 3 - 1
make/project.mk

@@ -345,7 +345,9 @@ else
 CXXFLAGS += -fno-exceptions
 endif
 
-export CFLAGS CPPFLAGS CXXFLAGS
+ARFLAGS := cru
+
+export CFLAGS CPPFLAGS CXXFLAGS ARFLAGS
 
 # Set default values that were not previously defined
 CC ?= gcc