From 893003357ad31d0dc8838a6652f29caa800ebfa4 Mon Sep 17 00:00:00 2001 From: Renz Bagaporo Date: Thu, 17 May 2018 18:56:52 +0800 Subject: [PATCH 1/5] wl, spi_flash: Make wl API runnable on host Makes the entirety of the wl API runnable on host. Flash emulator is separated into spi_flash component directory to be reused by other storage components. --- components/fatfs/test_fatfs_host/Makefile | 45 +++++++ .../sim}/Flash_Emulator.cpp | 0 .../sim}/Flash_Emulator.h | 4 +- components/spi_flash/sim/Makefile | 47 ++++++++ .../spi_flash/sim/include/esp_partition.h | 85 ++++++++++++++ .../spi_flash/sim/include/esp_spi_flash.h | 7 ++ components/spi_flash/sim/partition.cpp | 63 ++++++++++ components/spi_flash/sim/sdkconfig.h | 1 + components/wear_levelling/Partition.cpp | 2 + .../wear_levelling/test_wl_host/Makefile | 76 +++++++----- .../test_wl_host/TestPowerDown.cpp | 110 ------------------ .../wear_levelling/test_wl_host/sdkconfig.h | 2 + .../test_wl_host/stubs/esp32/crc.cpp | 50 ++++++++ .../stubs/esp32/include/rom/crc.h | 15 +++ .../stubs/esp32/include/rom/spi_flash.h | 13 +++ .../test_wl_host/stubs/log/include/esp_log.h | 44 +++++++ .../{esp_log_stub.cpp => stubs/log/log.c} | 5 + .../stubs/newlib/include/sys/lock.h | 17 +++ .../test_wl_host/stubs/newlib/lock.c | 21 ++++ .../wear_levelling/test_wl_host/test_wl.cpp | 94 +++++++++++++++ .../test_wl_host/wl_tests_host.cpp | 56 --------- 21 files changed, 563 insertions(+), 194 deletions(-) create mode 100644 components/fatfs/test_fatfs_host/Makefile rename components/{wear_levelling/test_wl_host => spi_flash/sim}/Flash_Emulator.cpp (100%) rename components/{wear_levelling/test_wl_host => spi_flash/sim}/Flash_Emulator.h (92%) create mode 100644 components/spi_flash/sim/Makefile create mode 100644 components/spi_flash/sim/include/esp_partition.h create mode 100644 components/spi_flash/sim/include/esp_spi_flash.h create mode 100644 components/spi_flash/sim/partition.cpp create mode 100644 components/spi_flash/sim/sdkconfig.h delete mode 100644 components/wear_levelling/test_wl_host/TestPowerDown.cpp create mode 100644 components/wear_levelling/test_wl_host/stubs/esp32/crc.cpp create mode 100644 components/wear_levelling/test_wl_host/stubs/esp32/include/rom/crc.h create mode 100644 components/wear_levelling/test_wl_host/stubs/esp32/include/rom/spi_flash.h create mode 100644 components/wear_levelling/test_wl_host/stubs/log/include/esp_log.h rename components/wear_levelling/test_wl_host/{esp_log_stub.cpp => stubs/log/log.c} (83%) create mode 100644 components/wear_levelling/test_wl_host/stubs/newlib/include/sys/lock.h create mode 100644 components/wear_levelling/test_wl_host/stubs/newlib/lock.c create mode 100644 components/wear_levelling/test_wl_host/test_wl.cpp delete mode 100644 components/wear_levelling/test_wl_host/wl_tests_host.cpp diff --git a/components/fatfs/test_fatfs_host/Makefile b/components/fatfs/test_fatfs_host/Makefile new file mode 100644 index 000000000..5b6d7a6e5 --- /dev/null +++ b/components/fatfs/test_fatfs_host/Makefile @@ -0,0 +1,45 @@ +TEST_PROGRAM=fatfs_host + +all: $(TEST_PROGRAM) + +SOURCE_FILES = \ + main.c \ + $(addprefix ../src/, \ + diskio.c \ + ff.c \ + ffsystem.c \ + ffunicode.c \ + ) + +INCLUDE_FLAGS = $(addprefix -I,\ + ../src \ + . \ + $(addprefix ./stubs/, \ + driver/include \ + freertos/include \ + sdmmc/include \ + ) \ + ../../esp32/include \ +) + +CPPFLAGS += $(INCLUDE_FLAGS) -g +CFLAGS += -fprofile-arcs -g +CXXFLAGS += -std=c++11 -Wall -Werror -fprofile-arcs -g +LDFLAGS += -lstdc++ -fprofile-arcs + +OBJ_FILES = $(SOURCE_FILES:.c=.o) +$(OBJ_FILES): %.o: %.c + +$(TEST_PROGRAM): $(OBJ_FILES) + gcc $(LDFLAGS) -o $(TEST_PROGRAM) $(OBJ_FILES) + +$(TEST_PROGRAM): $(OBJ_FILES) $(TEST_WL_DIR)/$(TEST_WL_LIB) $(TEST_PARTITION_SIM_DIR)/$(TEST_PARTITION_SIM_LIB) + g++ $(LDFLAGS) -o $(TEST_PROGRAM) $(OBJ_FILES) -L$(TEST_PARTITION_SIM_DIR) -l:$(TEST_PARTITION_SIM_LIB) -L$(TEST_WL_DIR) -l:$(TEST_WL_LIB) + +test: $(TEST_PROGRAM) + ./$(TEST_PROGRAM) + +clean: + rm -f $(OBJ_FILES) $(TEST_PROGRAM) + +.PHONY: clean all diff --git a/components/wear_levelling/test_wl_host/Flash_Emulator.cpp b/components/spi_flash/sim/Flash_Emulator.cpp similarity index 100% rename from components/wear_levelling/test_wl_host/Flash_Emulator.cpp rename to components/spi_flash/sim/Flash_Emulator.cpp diff --git a/components/wear_levelling/test_wl_host/Flash_Emulator.h b/components/spi_flash/sim/Flash_Emulator.h similarity index 92% rename from components/wear_levelling/test_wl_host/Flash_Emulator.h rename to components/spi_flash/sim/Flash_Emulator.h index 02a1be982..30b3e6ac1 100644 --- a/components/wear_levelling/test_wl_host/Flash_Emulator.h +++ b/components/spi_flash/sim/Flash_Emulator.h @@ -16,12 +16,12 @@ #define _Flash_Emulator_H_ #include "esp_err.h" -#include "Flash_Access.h" + /** * @brief This class is used to emulate flash devices. Class implements Flash_Access interface * */ -class Flash_Emulator : public Flash_Access +class Flash_Emulator { public: diff --git a/components/spi_flash/sim/Makefile b/components/spi_flash/sim/Makefile new file mode 100644 index 000000000..6a9992f08 --- /dev/null +++ b/components/spi_flash/sim/Makefile @@ -0,0 +1,47 @@ +PARTITION_SIM=partition_sim +PARTITION_SIM_LIB=lib$(PARTITION_SIM).a + +lib: $(PARTITION_SIM_LIB) + +SOURCE_FILES = \ + Flash_Emulator.cpp \ + partition.c + +INCLUDE_FLAGS = $(addprefix -I,\ + . \ + ./include \ + ../../esp32/include/ \ +) + +GCOV ?= gcov + +CPPFLAGS += $(INCLUDE_FLAGS) -D CONFIG_LOG_DEFAULT_LEVEL -g +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)) + + +$(PARTITION_SIM_LIB): $(OBJ_FILES) + $(AR) rcs $@ $^ + +COVERAGE_FILES = $(OBJ_FILES:.o=.gc*) $(OBJ_FILES:.o=.gc*) + +$(COVERAGE_FILES): $(TEST_PROGRAM) lib + +coverage.info: $(COVERAGE_FILES) + find ../ -name "*.gcno" -exec $(GCOV) -r -pb {} + + lcov --capture --directory ../ --no-external --output-file coverage.info --gcov-tool $(GCOV) + +coverage_report: coverage.info + genhtml coverage.info --output-directory coverage_report + @echo "Coverage report is in coverage_report/index.html" + +clean: + rm -f $(OBJ_FILES) $(PARTITION_SIM_LIB) + rm -f $(COVERAGE_FILES) *.gcov + rm -rf coverage_report/ + rm -f coverage.info + +.PHONY: clean lib diff --git a/components/spi_flash/sim/include/esp_partition.h b/components/spi_flash/sim/include/esp_partition.h new file mode 100644 index 000000000..c69df023d --- /dev/null +++ b/components/spi_flash/sim/include/esp_partition.h @@ -0,0 +1,85 @@ +#pragma once + +#include + +#include "esp_err.h" +#include "esp_spi_flash.h" + +/** + * @brief Partition type + * @note Keep this enum in sync with PartitionDefinition class gen_esp32part.py + */ +typedef enum { + ESP_PARTITION_TYPE_APP = 0x00, //!< Application partition type + ESP_PARTITION_TYPE_DATA = 0x01, //!< Data partition type +} esp_partition_type_t; + +/** + * @brief Partition subtype + * @note Keep this enum in sync with PartitionDefinition class gen_esp32part.py + */ +typedef enum { + ESP_PARTITION_SUBTYPE_APP_FACTORY = 0x00, //!< Factory application partition + ESP_PARTITION_SUBTYPE_APP_OTA_MIN = 0x10, //!< Base for OTA partition subtypes + ESP_PARTITION_SUBTYPE_APP_OTA_0 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 0, //!< OTA partition 0 + ESP_PARTITION_SUBTYPE_APP_OTA_1 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 1, //!< OTA partition 1 + ESP_PARTITION_SUBTYPE_APP_OTA_2 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 2, //!< OTA partition 2 + ESP_PARTITION_SUBTYPE_APP_OTA_3 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 3, //!< OTA partition 3 + ESP_PARTITION_SUBTYPE_APP_OTA_4 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 4, //!< OTA partition 4 + ESP_PARTITION_SUBTYPE_APP_OTA_5 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 5, //!< OTA partition 5 + ESP_PARTITION_SUBTYPE_APP_OTA_6 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 6, //!< OTA partition 6 + ESP_PARTITION_SUBTYPE_APP_OTA_7 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 7, //!< OTA partition 7 + ESP_PARTITION_SUBTYPE_APP_OTA_8 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 8, //!< OTA partition 8 + ESP_PARTITION_SUBTYPE_APP_OTA_9 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 9, //!< OTA partition 9 + ESP_PARTITION_SUBTYPE_APP_OTA_10 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 10,//!< OTA partition 10 + ESP_PARTITION_SUBTYPE_APP_OTA_11 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 11,//!< OTA partition 11 + ESP_PARTITION_SUBTYPE_APP_OTA_12 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 12,//!< OTA partition 12 + ESP_PARTITION_SUBTYPE_APP_OTA_13 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 13,//!< OTA partition 13 + ESP_PARTITION_SUBTYPE_APP_OTA_14 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 14,//!< OTA partition 14 + ESP_PARTITION_SUBTYPE_APP_OTA_15 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 15,//!< OTA partition 15 + ESP_PARTITION_SUBTYPE_APP_OTA_MAX = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 16,//!< Max subtype of OTA partition + ESP_PARTITION_SUBTYPE_APP_TEST = 0x20, //!< Test application partition + + ESP_PARTITION_SUBTYPE_DATA_OTA = 0x00, //!< OTA selection partition + ESP_PARTITION_SUBTYPE_DATA_PHY = 0x01, //!< PHY init data partition + ESP_PARTITION_SUBTYPE_DATA_NVS = 0x02, //!< NVS partition + ESP_PARTITION_SUBTYPE_DATA_COREDUMP = 0x03, //!< COREDUMP partition + + ESP_PARTITION_SUBTYPE_DATA_ESPHTTPD = 0x80, //!< ESPHTTPD partition + ESP_PARTITION_SUBTYPE_DATA_FAT = 0x81, //!< FAT partition + ESP_PARTITION_SUBTYPE_DATA_SPIFFS = 0x82, //!< SPIFFS partition + + ESP_PARTITION_SUBTYPE_ANY = 0xff, //!< Used to search for partitions with any subtype +} esp_partition_subtype_t; + +/** + * @brief partition information structure + * + * This is not the format in flash, that format is esp_partition_info_t. + * + * However, this is the format used by this API. + */ +typedef struct { + esp_partition_type_t type; /*!< partition type (app/data) */ + esp_partition_subtype_t subtype; /*!< partition subtype */ + uint32_t address; /*!< starting address of the partition in flash */ + uint32_t size; /*!< size of the partition, in bytes */ + char label[17]; /*!< partition label, zero-terminated ASCII string */ + bool encrypted; /*!< flag is set to true if partition is encrypted */ + + int handle; /*!< simulator handle */ +} esp_partition_t; + +esp_err_t esp_partition_write(const esp_partition_t* partition, + size_t dst_offset, const void* src, size_t size); + +esp_err_t esp_partition_erase_range(const esp_partition_t* partition, + uint32_t start_addr, uint32_t size); + +esp_err_t esp_partition_read(const esp_partition_t* partition, + size_t src_offset, void* dst, size_t size); + +esp_partition_t esp_partition_create(uint32_t size, uint32_t start); + +void esp_partition_delete(esp_partition_t partition); + diff --git a/components/spi_flash/sim/include/esp_spi_flash.h b/components/spi_flash/sim/include/esp_spi_flash.h new file mode 100644 index 000000000..9e0009d03 --- /dev/null +++ b/components/spi_flash/sim/include/esp_spi_flash.h @@ -0,0 +1,7 @@ +#pragma once + +#define CONFIG_WL_SECTOR_SIZE 4096 + +#define SPI_FLASH_SEC_SIZE CONFIG_WL_SECTOR_SIZE +#define SPI_FLASH_WRITE_SIZE 16 + diff --git a/components/spi_flash/sim/partition.cpp b/components/spi_flash/sim/partition.cpp new file mode 100644 index 000000000..e9568c0b0 --- /dev/null +++ b/components/spi_flash/sim/partition.cpp @@ -0,0 +1,63 @@ +#include + +#include "esp_partition.h" +#include "esp_spi_flash.h" +#include "Flash_Emulator.h" + +#define PARTITIONS_MAX 8 + +static Flash_Emulator* emulators[PARTITIONS_MAX]; + +esp_partition_t esp_partition_create(uint32_t size, uint32_t start) +{ + int handle = -1; + + for (int i = 0; i < PARTITIONS_MAX; i++) { + if (emulators[i] == NULL) { + emulators[i] = new Flash_Emulator(start + size, SPI_FLASH_SEC_SIZE, SPI_FLASH_WRITE_SIZE); + handle = i; + break; + } + } + + assert(handle != -1); + + esp_partition_t partition; + + // Fills partition with default values, and attaches the flash_emulator reference + // to the struct + partition.type = ESP_PARTITION_TYPE_DATA; + partition.subtype = ESP_PARTITION_SUBTYPE_DATA_FAT; + partition.address = start; + partition.size = size; + partition.handle = handle; + + return partition; +} + +void esp_partition_delete(esp_partition_t partition) +{ + delete emulators[partition.handle]; + emulators[partition.handle] = NULL; +} + +esp_err_t esp_partition_write(const esp_partition_t* partition, + size_t dst_offset, const void* src, size_t size) +{ + emulators[partition->handle]->write(dst_offset, src, size); + return ESP_OK; +} + +esp_err_t esp_partition_erase_range(const esp_partition_t* partition, + uint32_t start_addr, uint32_t size) +{ + emulators[partition->handle]->erase_range(start_addr, size); + return ESP_OK; +} + +esp_err_t esp_partition_read(const esp_partition_t* partition, + size_t src_offset, void* dst, size_t size) +{ + emulators[partition->handle]->read(src_offset, dst, size); + return ESP_OK; +} \ No newline at end of file diff --git a/components/spi_flash/sim/sdkconfig.h b/components/spi_flash/sim/sdkconfig.h new file mode 100644 index 000000000..7b9637ef9 --- /dev/null +++ b/components/spi_flash/sim/sdkconfig.h @@ -0,0 +1 @@ +#pragma once \ No newline at end of file diff --git a/components/wear_levelling/Partition.cpp b/components/wear_levelling/Partition.cpp index 63fef6ed6..e23f7fefd 100644 --- a/components/wear_levelling/Partition.cpp +++ b/components/wear_levelling/Partition.cpp @@ -31,6 +31,7 @@ esp_err_t Partition::erase_sector(size_t sector) result = erase_range(sector * SPI_FLASH_SEC_SIZE, SPI_FLASH_SEC_SIZE); return result; } + esp_err_t Partition::erase_range(size_t start_address, size_t size) { esp_err_t result = esp_partition_erase_range(this->partition, start_address, size); @@ -48,6 +49,7 @@ esp_err_t Partition::write(size_t dest_addr, const void *src, size_t size) result = esp_partition_write(this->partition, dest_addr, src, size); return result; } + esp_err_t Partition::read(size_t src_addr, void *dest, size_t size) { esp_err_t result = ESP_OK; diff --git a/components/wear_levelling/test_wl_host/Makefile b/components/wear_levelling/test_wl_host/Makefile index e71187180..dc36a97c1 100644 --- a/components/wear_levelling/test_wl_host/Makefile +++ b/components/wear_levelling/test_wl_host/Makefile @@ -1,53 +1,76 @@ TEST_PROGRAM=test_wl + +# Expose as a library for FS components that require wear_levelling +TEST_LIB=lib$(TEST_PROGRAM).a + +# Use simulated block device +TEST_PARTITION_SIM_DIR=$(IDF_PATH)/components/spi_flash/sim +TEST_PARTITION_SIM_LIB=libpartition_sim.a + all: $(TEST_PROGRAM) -SOURCE_FILES = \ - esp_error_check_stub.cpp \ - $(addprefix ../, \ - crc32.cpp \ - WL_Flash.cpp \ - ../nvs_flash/test_nvs_host/crc.cpp\ +LIB_SOURCE_FILES = \ + $(addprefix stubs/, \ + newlib/lock.c \ + log/log.c \ + esp32/crc.cpp \ ) \ - Flash_Emulator.cpp \ - wl_tests_host.cpp \ - TestPowerDown.cpp \ - esp_log_stub.cpp \ + $(addprefix ../, \ + wear_levelling.cpp \ + crc32.cpp \ + WL_Flash.cpp \ + Partition.cpp \ + ) \ + +TEST_SOURCE_FILES = \ + test_wl.cpp \ main.cpp - INCLUDE_FLAGS = $(addprefix -I,\ + . \ ../ \ ../include \ ../private_include \ + $(addprefix stubs/, \ + esp32/include \ + newlib/include \ + log/include \ + ) \ ../../esp32/include \ - ../../soc/esp32/include \ - ../../log/include \ - ../../spi_flash/include \ - ../../nvs_flash/test_nvs_host \ + ../../spi_flash/sim/include \ ../../../tools/catch \ -) +) GCOV ?= gcov -CPPFLAGS += $(INCLUDE_FLAGS) -D CONFIG_LOG_DEFAULT_LEVEL +CPPFLAGS += $(INCLUDE_FLAGS) -D CONFIG_LOG_DEFAULT_LEVEL -g CFLAGS += -fprofile-arcs -ftest-coverage CXXFLAGS += -std=c++11 -Wall -Werror -fprofile-arcs -ftest-coverage LDFLAGS += -lstdc++ -fprofile-arcs -ftest-coverage -OBJ_FILES = $(SOURCE_FILES:.cpp=.o) +LIB_OBJ_FILES = $(filter %.o, $(LIB_SOURCE_FILES:.cpp=.o) $(LIB_SOURCE_FILES:.c=.o)) +TEST_OBJ_FILES = $(filter %.o, $(TEST_SOURCE_FILES:.cpp=.o) $(TEST_SOURCE_FILES:.c=.o)) -COVERAGE_FILES = $(OBJ_FILES:.o=.gc*) +$(TEST_PARTITION_SIM_DIR)/$(TEST_PARTITION_SIM_LIB): force + $(MAKE) -C $(TEST_PARTITION_SIM_DIR) lib -$(OBJ_FILES): %.o: %.cpp +$(TEST_LIB): $(LIB_OBJ_FILES) + $(AR) rcs $@ $^ -$(TEST_PROGRAM): $(OBJ_FILES) - g++ $(LDFLAGS) -o $(TEST_PROGRAM) $(OBJ_FILES) +lib: $(TEST_LIB) + +$(TEST_PROGRAM): lib $(TEST_OBJ_FILES) $(TEST_PARTITION_SIM_DIR)/$(TEST_PARTITION_SIM_LIB) + g++ $(LDFLAGS) -o $@ $(TEST_OBJ_FILES) -L$(abspath .) -l:$(TEST_LIB) -L$(TEST_PARTITION_SIM_DIR) -l:$(TEST_PARTITION_SIM_LIB) + +force: + +test: $(TEST_PROGRAM) + ./$(TEST_PROGRAM) $(OUTPUT_DIR): mkdir -p $(OUTPUT_DIR) -test: $(TEST_PROGRAM) - ./$(TEST_PROGRAM) +COVERAGE_FILES = $(LIB_OBJ_FILES:.o=.gc*) $(TEST_OBJ_FILES:.o=.gc*) $(COVERAGE_FILES): $(TEST_PROGRAM) test @@ -60,9 +83,10 @@ coverage_report: coverage.info @echo "Coverage report is in coverage_report/index.html" clean: - rm -f $(OBJ_FILES) $(TEST_PROGRAM) + $(MAKE) -C $(TEST_PARTITION_SIM_DIR) clean + rm -f $(LIB_OBJ_FILES) $(TEST_OBJ_FILES) $(TEST_PROGRAM) $(TEST_LIB) rm -f $(COVERAGE_FILES) *.gcov rm -rf coverage_report/ rm -f coverage.info -.PHONY: clean all test +.PHONY: clean all test lib diff --git a/components/wear_levelling/test_wl_host/TestPowerDown.cpp b/components/wear_levelling/test_wl_host/TestPowerDown.cpp deleted file mode 100644 index 056d815a1..000000000 --- a/components/wear_levelling/test_wl_host/TestPowerDown.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - - -#include "WL_Config.h" -#include "WL_Flash.h" -#include "Flash_Emulator.h" -#ifdef _MSC_VER -#define CHECK(m) -#else -#include "catch.hpp" -#endif - -extern Flash_Access *s_flash; - -bool test_power_down(WL_Flash *wl_flash, Flash_Emulator *emul, uint32_t used_sectors_count) -{ - REQUIRE(wl_flash->init() == ESP_OK); - s_flash = wl_flash; - - uint32_t add_const = 0; - int32_t sectors_count = s_flash->chip_size() / s_flash->sector_size(); - esp_err_t err = ESP_OK; - uint32_t *sector_data = new uint32_t[s_flash->sector_size() / sizeof(uint32_t)]; - - for (int32_t i = 0; i < sectors_count; i++) { - REQUIRE(s_flash->erase_sector(i) == ESP_OK); - for (uint32_t m = 0; m < s_flash->sector_size() / sizeof(uint32_t); m++) { - uint32_t temp_data = i * s_flash->sector_size() + add_const + m; - sector_data[m] = temp_data; - } - REQUIRE(s_flash->write(i * s_flash->sector_size(), sector_data, s_flash->sector_size()) == ESP_OK); - } - for (int32_t i = 0; i < sectors_count; i++) { - err |= s_flash->read(i * s_flash->sector_size(), sector_data, s_flash->sector_size()); - for (uint32_t m = 0; m < s_flash->sector_size() / sizeof(uint32_t); m++) { - uint32_t temp_data = i * s_flash->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); - } - } - } - - int32_t max_count = 100; - int32_t max_check_count = used_sectors_count; - printf("used_sectors_count=%d\n", used_sectors_count); - for (int32_t k = 0; k < max_check_count; k++) { - - emul->SetResetCount(max_count); - int32_t err_sector = -1; - for (int32_t i = 0; i < sectors_count; i++) { - err = ESP_OK; - err = s_flash->erase_sector(i); - if (err != ESP_OK) { - err_sector = i; - break; - } - for (uint32_t m = 0; m < s_flash->sector_size() / sizeof(uint32_t); m++) { - uint32_t temp_data = i * s_flash->sector_size() + add_const + m; - sector_data[m] = temp_data; - } - err = s_flash->write(i * s_flash->sector_size(), sector_data, s_flash->sector_size()); - if (err != ESP_OK) { - err_sector = i; - break; - } - } - if (err_sector >= 0) { - max_count++; - } else { - max_count = 0; - } - emul->SetResetCount(INT32_MAX); - REQUIRE(wl_flash->init() == ESP_OK); - for (int32_t i = 0; i < sectors_count; i++) { - if (i != err_sector) { - err |= s_flash->read(i * s_flash->sector_size(), sector_data, s_flash->sector_size()); - for (uint32_t m = 0; m < s_flash->sector_size() / sizeof(uint32_t); m++) { - uint32_t temp_data = i * s_flash->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) { - err |= s_flash->erase_sector(err_sector); - for (uint32_t m = 0; m < s_flash->sector_size() / sizeof(uint32_t); m++) { - uint32_t temp_data = err_sector * s_flash->sector_size() + add_const + m; - sector_data[m] = temp_data; - } - err |= s_flash->write(err_sector * s_flash->sector_size(), sector_data, s_flash->sector_size()); - } - printf("[%3.f%%] err_sector=%i\n", (float)k / ((float)max_check_count) * 100.0f, err_sector); - } - delete[] sector_data; - return true; -} diff --git a/components/wear_levelling/test_wl_host/sdkconfig.h b/components/wear_levelling/test_wl_host/sdkconfig.h index e69de29bb..3f59c932d 100644 --- a/components/wear_levelling/test_wl_host/sdkconfig.h +++ b/components/wear_levelling/test_wl_host/sdkconfig.h @@ -0,0 +1,2 @@ +#pragma once + diff --git a/components/wear_levelling/test_wl_host/stubs/esp32/crc.cpp b/components/wear_levelling/test_wl_host/stubs/esp32/crc.cpp new file mode 100644 index 000000000..9e2473560 --- /dev/null +++ b/components/wear_levelling/test_wl_host/stubs/esp32/crc.cpp @@ -0,0 +1,50 @@ +#include +#include + +#include "rom/crc.h" + +static const unsigned int crc32_le_table[256] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, + 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, + 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, + 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, + 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, + 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, + 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, + 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, + 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, + 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, + 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, + 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, + 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, + + 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, + 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, + 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, + 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, + 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L, + 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, + 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, + 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, + 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, + 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, + 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, + 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, + 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL +}; + +extern "C" unsigned int crc32_le(uint32_t crc, const uint8_t* buf, size_t len) +{ + unsigned int i; + crc = ~crc; + for(i=0;i>8); + } + return ~crc; +} \ No newline at end of file diff --git a/components/wear_levelling/test_wl_host/stubs/esp32/include/rom/crc.h b/components/wear_levelling/test_wl_host/stubs/esp32/include/rom/crc.h new file mode 100644 index 000000000..41364ee5a --- /dev/null +++ b/components/wear_levelling/test_wl_host/stubs/esp32/include/rom/crc.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +uint32_t crc32_le(uint32_t crc, const uint8_t* buf, size_t len); + +#ifdef __cplusplus +} +#endif + diff --git a/components/wear_levelling/test_wl_host/stubs/esp32/include/rom/spi_flash.h b/components/wear_levelling/test_wl_host/stubs/esp32/include/rom/spi_flash.h new file mode 100644 index 000000000..b9c14ef01 --- /dev/null +++ b/components/wear_levelling/test_wl_host/stubs/esp32/include/rom/spi_flash.h @@ -0,0 +1,13 @@ +#pragma once + +#include +#include + +typedef struct { + uint32_t device_id; + uint32_t chip_size; // chip size in bytes + uint32_t block_size; + uint32_t sector_size; + uint32_t page_size; + uint32_t status_mask; +} esp_rom_spiflash_chip_t; diff --git a/components/wear_levelling/test_wl_host/stubs/log/include/esp_log.h b/components/wear_levelling/test_wl_host/stubs/log/include/esp_log.h new file mode 100644 index 000000000..a1d838d11 --- /dev/null +++ b/components/wear_levelling/test_wl_host/stubs/log/include/esp_log.h @@ -0,0 +1,44 @@ +#pragma once + +#include +#include + +#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 + diff --git a/components/wear_levelling/test_wl_host/esp_log_stub.cpp b/components/wear_levelling/test_wl_host/stubs/log/log.c similarity index 83% rename from components/wear_levelling/test_wl_host/esp_log_stub.cpp rename to components/wear_levelling/test_wl_host/stubs/log/log.c index 87dd12a90..5d606d357 100644 --- a/components/wear_levelling/test_wl_host/esp_log_stub.cpp +++ b/components/wear_levelling/test_wl_host/stubs/log/log.c @@ -1,4 +1,8 @@ #include +#include +#include +#include + #include "esp_log.h" void esp_log_write(esp_log_level_t level, @@ -15,3 +19,4 @@ uint32_t esp_log_timestamp() { return 0; } + diff --git a/components/wear_levelling/test_wl_host/stubs/newlib/include/sys/lock.h b/components/wear_levelling/test_wl_host/stubs/newlib/include/sys/lock.h new file mode 100644 index 000000000..2b5b9f59e --- /dev/null +++ b/components/wear_levelling/test_wl_host/stubs/newlib/include/sys/lock.h @@ -0,0 +1,17 @@ +#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 + diff --git a/components/wear_levelling/test_wl_host/stubs/newlib/lock.c b/components/wear_levelling/test_wl_host/stubs/newlib/lock.c new file mode 100644 index 000000000..f221fdbda --- /dev/null +++ b/components/wear_levelling/test_wl_host/stubs/newlib/lock.c @@ -0,0 +1,21 @@ +#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; +} diff --git a/components/wear_levelling/test_wl_host/test_wl.cpp b/components/wear_levelling/test_wl_host/test_wl.cpp new file mode 100644 index 000000000..b2ed120b3 --- /dev/null +++ b/components/wear_levelling/test_wl_host/test_wl.cpp @@ -0,0 +1,94 @@ +// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include +#include + +#include "esp_partition.h" +#include "wear_levelling.h" +#include "WL_Flash.h" + +#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); + +TEST_CASE("write and read back data", "[wear_levelling]") +{ + esp_err_t result; + wl_handle_t wl_handle; + + esp_partition_t partition = esp_partition_create(PARTITION_SIZE, PARTITION_START); + + // Mount wear-levelled partition + result = wl_mount(partition, &wl_handle); + REQUIRE(result == ESP_OK); + + // Get the sector size + uint32_t sector_size = wl_sector_size(wl_handle); + REQUIRE(sector_size == CONFIG_WL_SECTOR_SIZE); + + uint8_t* data = (uint8_t*) malloc(partition->size); + uint8_t* read = (uint8_t*) malloc(partition->size); + + uint32_t sectors = partition->size / sector_size; + + // Generate data + for(uint32_t sector = 0; sector < sectors; sector++) + { + uint32_t sector_address = sector * sector_size; + + for(uint32_t i = 0; i < sector_size / sizeof(i); i++) + { + ((uint32_t*) data)[i] = sector_address + i; + } + } + + // Write data + result = wl_write(wl_handle, 0, data, partition->size); + REQUIRE(result == ESP_OK); + + // Read data + result = wl_read(wl_handle, 0, read, partition->size); + REQUIRE(result == ESP_OK); + + // Verify that written and read data match + REQUIRE(memcmp(data, read, partition->size)); + + // Erase some ranges + result = wl_erase_range(wl_handle, 0, sector_size); + REQUIRE(result == ESP_OK); + result = wl_erase_range(wl_handle, 12288, sector_size * 2); + REQUIRE(result == ESP_OK); + result = wl_erase_range(wl_handle, 28672, sector_size * 3); + REQUIRE(result == ESP_OK); + + // Expected data after erasure + memset(data + 0, 0xFF, sector_size); + memset(data + 12288, 0xFF, sector_size * 2); + memset(data + 28672, 0xFF, sector_size * 3); + + // Read again, with erased ranges + result = wl_read(wl_handle, 0, read, partition->size); + REQUIRE(result == ESP_OK); + + // Verify that written and read data match + REQUIRE(memcmp(data, read, partition->size)); + + // Unmount + result = wl_unmount(wl_handle); + REQUIRE(result == ESP_OK); + + free(data); + free(read); +} \ No newline at end of file diff --git a/components/wear_levelling/test_wl_host/wl_tests_host.cpp b/components/wear_levelling/test_wl_host/wl_tests_host.cpp deleted file mode 100644 index 84bb59fea..000000000 --- a/components/wear_levelling/test_wl_host/wl_tests_host.cpp +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include "WL_Config.h" -#include "WL_Flash.h" -#include "Flash_Emulator.h" -#include "catch.hpp" - -#define FLASH_SECTOR_SIZE 512 -#define FLASH_USED_SECTOR (1024 - 3) -#define FLASH_ACCESS_SIZE (FLASH_SECTOR_SIZE*(FLASH_USED_SECTOR + 1 + 2)) -#define FLASH_START_ADDR 0x1000 -#define FLASH_PAGE_SIZE FLASH_SECTOR_SIZE*1 -#define FLASH_UPDATERATE 3 -#define FLASH_TEMP_SIZE FLASH_SECTOR_SIZE -#define FLASH_WR_BLOCK_SIZE 16 - -static const char *TAG = "wl_test_host"; -Flash_Access *s_flash; - -extern bool test_power_down(WL_Flash *wl_flash, Flash_Emulator *emul, uint32_t used_sectors_count); - -#define TEST_COUNT_MAX 100 - -TEST_CASE("flash starts with all bytes == 0xff", "[spi_flash_emu]") -{ - wl_config_t *wl = new wl_config_t(); - - wl->full_mem_size = FLASH_ACCESS_SIZE; - wl->start_addr = FLASH_START_ADDR; - wl->sector_size = FLASH_SECTOR_SIZE; - wl->page_size = FLASH_PAGE_SIZE; - wl->updaterate = FLASH_UPDATERATE; - wl->temp_buff_size = FLASH_TEMP_SIZE; - wl->wr_size = FLASH_WR_BLOCK_SIZE; - - WL_Flash *wl_flash = new WL_Flash(); - Flash_Emulator *emul = new Flash_Emulator(FLASH_ACCESS_SIZE + FLASH_START_ADDR, FLASH_SECTOR_SIZE, FLASH_WR_BLOCK_SIZE); - CHECK(wl_flash->config(wl, emul) == ESP_OK); - - test_power_down(wl_flash, emul, TEST_COUNT_MAX); -} - - From af629b35475a4676d8c4f63d8c53f66122e403d1 Mon Sep 17 00:00:00 2001 From: Renz Bagaporo Date: Thu, 17 May 2018 16:19:29 +0800 Subject: [PATCH 2/5] fatfs: Make fatfs runnable on host Makes fatfs component runnable on host. Depends on the host library build of wear levelling and flash emulator. Includes a basic sanity test of mounting a volume, opening a file, writing to the file, reading the file, closing the file and unmounting volume. --- components/fatfs/test_fatfs_host/Makefile | 80 +++++++++++++----- components/fatfs/test_fatfs_host/main.cpp | 2 + components/fatfs/test_fatfs_host/sdkconfig.h | 3 + .../stubs/driver/include/driver/sdmmc_host.h | 6 ++ .../stubs/driver/include/driver/sdmmc_types.h | 11 +++ .../freertos/include/freertos/FreeRTOS.h | 4 + .../freertos/include/freertos/projdefs.h | 11 +++ .../stubs/freertos/include/freertos/semphr.h | 16 ++++ .../stubs/log/include/esp_log.h | 45 ++++++++++ .../fatfs/test_fatfs_host/stubs/log/log.c | 20 +++++ .../stubs/sdmmc/include/sdmmc_cmd.h | 3 + .../fatfs/test_fatfs_host/test_fatfs.cpp | 83 +++++++++++++++++++ .../spi_flash/sim/include/esp_partition.h | 9 ++ components/spi_flash/sim/partition.cpp | 6 +- 14 files changed, 275 insertions(+), 24 deletions(-) create mode 100644 components/fatfs/test_fatfs_host/main.cpp create mode 100644 components/fatfs/test_fatfs_host/sdkconfig.h create mode 100644 components/fatfs/test_fatfs_host/stubs/driver/include/driver/sdmmc_host.h create mode 100644 components/fatfs/test_fatfs_host/stubs/driver/include/driver/sdmmc_types.h create mode 100644 components/fatfs/test_fatfs_host/stubs/freertos/include/freertos/FreeRTOS.h create mode 100644 components/fatfs/test_fatfs_host/stubs/freertos/include/freertos/projdefs.h create mode 100644 components/fatfs/test_fatfs_host/stubs/freertos/include/freertos/semphr.h create mode 100644 components/fatfs/test_fatfs_host/stubs/log/include/esp_log.h create mode 100644 components/fatfs/test_fatfs_host/stubs/log/log.c create mode 100644 components/fatfs/test_fatfs_host/stubs/sdmmc/include/sdmmc_cmd.h create mode 100644 components/fatfs/test_fatfs_host/test_fatfs.cpp diff --git a/components/fatfs/test_fatfs_host/Makefile b/components/fatfs/test_fatfs_host/Makefile index 5b6d7a6e5..76d75930d 100644 --- a/components/fatfs/test_fatfs_host/Makefile +++ b/components/fatfs/test_fatfs_host/Makefile @@ -1,45 +1,83 @@ -TEST_PROGRAM=fatfs_host +TEST_PROGRAM=test_fatfs + +# Use wear levelling +TEST_WL_COMPONENT=$(IDF_PATH)/components/wear_levelling +TEST_WL_DIR=$(TEST_WL_COMPONENT)/test_wl_host +TEST_WL_LIB=libtest_wl.a + +TEST_PARTITION_SIM_DIR=$(IDF_PATH)/components/spi_flash/sim +TEST_PARTITION_SIM_LIB=libpartition_sim.a all: $(TEST_PROGRAM) SOURCE_FILES = \ - main.c \ + main.cpp \ + test_fatfs.cpp \ $(addprefix ../src/, \ diskio.c \ ff.c \ ffsystem.c \ - ffunicode.c \ - ) + ffunicode.c \ + diskio_spiflash.c \ + ) \ + $(addprefix ./stubs/, log/log.c) INCLUDE_FLAGS = $(addprefix -I,\ ../src \ - . \ - $(addprefix ./stubs/, \ - driver/include \ - freertos/include \ - sdmmc/include \ - ) \ - ../../esp32/include \ + . \ + $(addprefix ./stubs/, \ + driver/include \ + freertos/include \ + sdmmc/include \ + log/include \ + ) \ + ../../esp32/include \ + $(TEST_PARTITION_SIM_DIR)/include \ + $(TEST_WL_COMPONENT)/include \ + ../../../tools/catch \ ) -CPPFLAGS += $(INCLUDE_FLAGS) -g -CFLAGS += -fprofile-arcs -g -CXXFLAGS += -std=c++11 -Wall -Werror -fprofile-arcs -g -LDFLAGS += -lstdc++ -fprofile-arcs +GCOV ?= gcov -OBJ_FILES = $(SOURCE_FILES:.c=.o) -$(OBJ_FILES): %.o: %.c +CPPFLAGS += $(INCLUDE_FLAGS) -D CONFIG_LOG_DEFAULT_LEVEL -g +CFLAGS += -fprofile-arcs -ftest-coverage +CXXFLAGS += -std=c++11 -Wall -Werror -fprofile-arcs -ftest-coverage +LDFLAGS += -lstdc++ -fprofile-arcs -ftest-coverage -$(TEST_PROGRAM): $(OBJ_FILES) - gcc $(LDFLAGS) -o $(TEST_PROGRAM) $(OBJ_FILES) +OBJ_FILES = $(filter %.o, $(SOURCE_FILES:.cpp=.o) $(SOURCE_FILES:.c=.o)) + +$(TEST_WL_DIR)/$(TEST_WL_LIB): force + $(MAKE) -C $(TEST_WL_DIR) lib + +$(TEST_PARTITION_SIM_DIR)/$(TEST_PARTITION_SIM_LIB): force + $(MAKE) -C $(TEST_PARTITION_SIM_DIR) lib + +force: $(TEST_PROGRAM): $(OBJ_FILES) $(TEST_WL_DIR)/$(TEST_WL_LIB) $(TEST_PARTITION_SIM_DIR)/$(TEST_PARTITION_SIM_LIB) g++ $(LDFLAGS) -o $(TEST_PROGRAM) $(OBJ_FILES) -L$(TEST_PARTITION_SIM_DIR) -l:$(TEST_PARTITION_SIM_LIB) -L$(TEST_WL_DIR) -l:$(TEST_WL_LIB) -test: $(TEST_PROGRAM) +run: $(TEST_PROGRAM) ./$(TEST_PROGRAM) -clean: +COVERAGE_FILES = $(OBJ_FILES:.o=.gc*) $(OBJ_FILES:.o=.gc*) + +$(COVERAGE_FILES): $(TEST_PROGRAM) lib + +coverage.info: $(COVERAGE_FILES) + find ../ -name "*.gcno" -exec $(GCOV) -r -pb {} + + lcov --capture --directory ../ --no-external --output-file coverage.info --gcov-tool $(GCOV) + +coverage_report: coverage.info + genhtml coverage.info --output-directory coverage_report + @echo "Coverage report is in coverage_report/index.html" + +clean: rm -f $(OBJ_FILES) $(TEST_PROGRAM) + $(MAKE) -C $(TEST_WL_DIR) clean + $(MAKE) -C $(TEST_PARTITION_SIM_DIR) clean + rm -f $(COVERAGE_FILES) *.gcov + rm -rf coverage_report/ + rm -f coverage.info .PHONY: clean all diff --git a/components/fatfs/test_fatfs_host/main.cpp b/components/fatfs/test_fatfs_host/main.cpp new file mode 100644 index 000000000..0c7c351f4 --- /dev/null +++ b/components/fatfs/test_fatfs_host/main.cpp @@ -0,0 +1,2 @@ +#define CATCH_CONFIG_MAIN +#include "catch.hpp" diff --git a/components/fatfs/test_fatfs_host/sdkconfig.h b/components/fatfs/test_fatfs_host/sdkconfig.h new file mode 100644 index 000000000..b61f5811d --- /dev/null +++ b/components/fatfs/test_fatfs_host/sdkconfig.h @@ -0,0 +1,3 @@ +# pragma once + +#define CONFIG_WL_SECTOR_SIZE 4096 diff --git a/components/fatfs/test_fatfs_host/stubs/driver/include/driver/sdmmc_host.h b/components/fatfs/test_fatfs_host/stubs/driver/include/driver/sdmmc_host.h new file mode 100644 index 000000000..2e6811037 --- /dev/null +++ b/components/fatfs/test_fatfs_host/stubs/driver/include/driver/sdmmc_host.h @@ -0,0 +1,6 @@ +#pragma once + +#include + +#include "sdmmc_types.h" + diff --git a/components/fatfs/test_fatfs_host/stubs/driver/include/driver/sdmmc_types.h b/components/fatfs/test_fatfs_host/stubs/driver/include/driver/sdmmc_types.h new file mode 100644 index 000000000..22df97c5c --- /dev/null +++ b/components/fatfs/test_fatfs_host/stubs/driver/include/driver/sdmmc_types.h @@ -0,0 +1,11 @@ +#pragma once + +#if defined(__cplusplus) +extern "C" { +#endif + +typedef int sdmmc_card_t; + +#if defined(__cplusplus) +} +#endif \ No newline at end of file diff --git a/components/fatfs/test_fatfs_host/stubs/freertos/include/freertos/FreeRTOS.h b/components/fatfs/test_fatfs_host/stubs/freertos/include/freertos/FreeRTOS.h new file mode 100644 index 000000000..5bafa772d --- /dev/null +++ b/components/fatfs/test_fatfs_host/stubs/freertos/include/freertos/FreeRTOS.h @@ -0,0 +1,4 @@ +#pragma once + +#include "projdefs.h" +#include "semphr.h" diff --git a/components/fatfs/test_fatfs_host/stubs/freertos/include/freertos/projdefs.h b/components/fatfs/test_fatfs_host/stubs/freertos/include/freertos/projdefs.h new file mode 100644 index 000000000..aa8c7a3de --- /dev/null +++ b/components/fatfs/test_fatfs_host/stubs/freertos/include/freertos/projdefs.h @@ -0,0 +1,11 @@ +#pragma once + +#if defined(__cplusplus) +extern "C" { +#endif + +#define pdTRUE 1 + +#if defined(__cplusplus) +} +#endif diff --git a/components/fatfs/test_fatfs_host/stubs/freertos/include/freertos/semphr.h b/components/fatfs/test_fatfs_host/stubs/freertos/include/freertos/semphr.h new file mode 100644 index 000000000..d49cafb99 --- /dev/null +++ b/components/fatfs/test_fatfs_host/stubs/freertos/include/freertos/semphr.h @@ -0,0 +1,16 @@ +#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 diff --git a/components/fatfs/test_fatfs_host/stubs/log/include/esp_log.h b/components/fatfs/test_fatfs_host/stubs/log/include/esp_log.h new file mode 100644 index 000000000..f90501430 --- /dev/null +++ b/components/fatfs/test_fatfs_host/stubs/log/include/esp_log.h @@ -0,0 +1,45 @@ +#pragma once + +#include +#include + +#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 \ No newline at end of file diff --git a/components/fatfs/test_fatfs_host/stubs/log/log.c b/components/fatfs/test_fatfs_host/stubs/log/log.c new file mode 100644 index 000000000..4f0c12bf8 --- /dev/null +++ b/components/fatfs/test_fatfs_host/stubs/log/log.c @@ -0,0 +1,20 @@ +#include +#include +#include + +#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; +} \ No newline at end of file diff --git a/components/fatfs/test_fatfs_host/stubs/sdmmc/include/sdmmc_cmd.h b/components/fatfs/test_fatfs_host/stubs/sdmmc/include/sdmmc_cmd.h new file mode 100644 index 000000000..d68711a95 --- /dev/null +++ b/components/fatfs/test_fatfs_host/stubs/sdmmc/include/sdmmc_cmd.h @@ -0,0 +1,3 @@ +#pragma once + +#include "esp_err.h" diff --git a/components/fatfs/test_fatfs_host/test_fatfs.cpp b/components/fatfs/test_fatfs_host/test_fatfs.cpp new file mode 100644 index 000000000..2c34da4f7 --- /dev/null +++ b/components/fatfs/test_fatfs_host/test_fatfs.cpp @@ -0,0 +1,83 @@ +#include +#include + +#include "ff.h" +#include "esp_partition.h" +#include "wear_levelling.h" +#include "diskio.h" +#include "diskio_spiflash.h" + +#include "catch.hpp" + +TEST_CASE("create volume, open file, write and read back data", "[fatfs]") +{ + FRESULT fr_result; + BYTE pdrv; + FATFS fs; + FIL file; + UINT bw; + + esp_err_t esp_result; + + // Create a 4MB partition + uint32_t size = 0x00400000; + int flash_handle = esp_flash_create(size, 4096, 1); + esp_partition_t partition = esp_partition_create(size, 0, flash_handle); + + // Mount wear-levelled partition + wl_handle_t wl_handle; + esp_result = wl_mount(&partition, &wl_handle); + REQUIRE(esp_result == ESP_OK); + + // Get a physical drive + esp_result = ff_diskio_get_drive(&pdrv); + REQUIRE(esp_result == ESP_OK); + + // Register physical drive as wear-levelled partition + esp_result = ff_diskio_register_wl_partition(pdrv, wl_handle); + + // Create FAT volume on the entire disk + DWORD part_list[] = {100, 0, 0, 0}; + BYTE work_area[FF_MAX_SS]; + + fr_result = f_fdisk(pdrv, part_list, work_area); + REQUIRE(fr_result == FR_OK); + fr_result = f_mkfs("", FM_ANY, 0, work_area, sizeof(work_area)); // Use default volume + + // Mount the volume + fr_result = f_mount(&fs, "", 0); + REQUIRE(fr_result == FR_OK); + + // Open, write and read data + fr_result = f_open(&file, "test.txt", FA_OPEN_ALWAYS | FA_READ | FA_WRITE); + REQUIRE(fr_result == FR_OK); + + const char data[] = "Hello, World!"; + char *read = (char*) malloc(sizeof(data)); + + fr_result = f_write(&file, data, sizeof(data), &bw); + REQUIRE(fr_result == FR_OK); + REQUIRE(bw == sizeof(data)); + + // Move to beginning of file + fr_result = f_lseek(&file, 0); + REQUIRE(fr_result == FR_OK); + + fr_result = f_read(&file, read, sizeof(data), &bw); + REQUIRE(fr_result == FR_OK); + REQUIRE(bw == sizeof(data)); + + REQUIRE(strcmp(data, read) == 0); + + // Close file + fr_result = f_close(&file); + REQUIRE(fr_result == FR_OK); + + // Unmount default volume + fr_result = f_mount(0, "", 0); + REQUIRE(fr_result == FR_OK); + + esp_partition_delete(partition); + + free(read); +} \ No newline at end of file diff --git a/components/spi_flash/sim/include/esp_partition.h b/components/spi_flash/sim/include/esp_partition.h index c69df023d..f2904e789 100644 --- a/components/spi_flash/sim/include/esp_partition.h +++ b/components/spi_flash/sim/include/esp_partition.h @@ -2,9 +2,14 @@ #include +#include "sdkconfig.h" #include "esp_err.h" #include "esp_spi_flash.h" +#if defined(__cplusplus) +extern "C" { // Make sure we have C-declarations in C++ programs +#endif + /** * @brief Partition type * @note Keep this enum in sync with PartitionDefinition class gen_esp32part.py @@ -83,3 +88,7 @@ esp_partition_t esp_partition_create(uint32_t size, uint32_t start); void esp_partition_delete(esp_partition_t partition); +#if defined(__cplusplus) +} +#endif + diff --git a/components/spi_flash/sim/partition.cpp b/components/spi_flash/sim/partition.cpp index e9568c0b0..9e9e69c38 100644 --- a/components/spi_flash/sim/partition.cpp +++ b/components/spi_flash/sim/partition.cpp @@ -4,15 +4,15 @@ #include "esp_spi_flash.h" #include "Flash_Emulator.h" -#define PARTITIONS_MAX 8 +#define EMULATORS_MAX 8 -static Flash_Emulator* emulators[PARTITIONS_MAX]; +static Flash_Emulator* emulators[EMULATORS_MAX]; esp_partition_t esp_partition_create(uint32_t size, uint32_t start) { int handle = -1; - for (int i = 0; i < PARTITIONS_MAX; i++) { + for (int i = 0; i < EMULATORS_MAX; i++) { if (emulators[i] == NULL) { emulators[i] = new Flash_Emulator(start + size, SPI_FLASH_SEC_SIZE, SPI_FLASH_WRITE_SIZE); handle = i; From e542b7a9208d410c9cba3fe71fbc0f5f2f6c3064 Mon Sep 17 00:00:00 2001 From: Renz Bagaporo Date: Tue, 22 May 2018 16:47:30 +0800 Subject: [PATCH 3/5] spiffs: Make spiffs runnable on host Makes spiffs component runnable on host. Depends on the host library build of flash emulator. Includes a basic sanity test of mounting a volume, opening a file, writing to the file, reading the file, closing the file and unmounting volume. --- components/fatfs/test_fatfs_host/Makefile | 4 +- .../fatfs/test_fatfs_host/test_fatfs.cpp | 6 +- components/spi_flash/sim/Flash_Emulator.cpp | 1 + .../spi_flash/sim/include/esp_partition.h | 6 +- components/spi_flash/sim/partition.cpp | 23 +++-- components/spiffs/component.mk | 2 +- components/spiffs/esp_spiffs.c | 98 +------------------ components/spiffs/spiffs_api.c | 93 ++++++++++++++++++ components/spiffs/spiffs_api.h | 59 +++++++++++ components/spiffs/test_spiffs_host/Makefile | 79 +++++++++++++++ components/spiffs/test_spiffs_host/main.cpp | 3 + .../spiffs/test_spiffs_host/sdkconfig.h | 14 +++ .../stubs/esp32/include/rom/spi_flash.h | 23 +++++ .../freertos/include/freertos/FreeRTOS.h | 4 + .../freertos/include/freertos/projdefs.h | 11 +++ .../stubs/freertos/include/freertos/semphr.h | 16 +++ .../stubs/freertos/include/freertos/task.h | 1 + .../stubs/log/include/esp_log.h | 51 ++++++++++ .../spiffs/test_spiffs_host/stubs/log/log.c | 22 +++++ .../stubs/newlib/include/sys/lock.h | 10 ++ .../test_spiffs_host/stubs/newlib/lock.c | 21 ++++ .../stubs/vfs/include/esp_vfs.h | 6 ++ .../spiffs/test_spiffs_host/test_spiffs.cpp | 96 ++++++++++++++++++ .../wear_levelling/test_wl_host/test_wl.cpp | 5 +- 24 files changed, 542 insertions(+), 112 deletions(-) create mode 100644 components/spiffs/spiffs_api.c create mode 100644 components/spiffs/spiffs_api.h create mode 100644 components/spiffs/test_spiffs_host/Makefile create mode 100644 components/spiffs/test_spiffs_host/main.cpp create mode 100644 components/spiffs/test_spiffs_host/sdkconfig.h create mode 100644 components/spiffs/test_spiffs_host/stubs/esp32/include/rom/spi_flash.h create mode 100644 components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/FreeRTOS.h create mode 100644 components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/projdefs.h create mode 100644 components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/semphr.h create mode 100644 components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/task.h create mode 100644 components/spiffs/test_spiffs_host/stubs/log/include/esp_log.h create mode 100644 components/spiffs/test_spiffs_host/stubs/log/log.c create mode 100644 components/spiffs/test_spiffs_host/stubs/newlib/include/sys/lock.h create mode 100644 components/spiffs/test_spiffs_host/stubs/newlib/lock.c create mode 100644 components/spiffs/test_spiffs_host/stubs/vfs/include/esp_vfs.h create mode 100644 components/spiffs/test_spiffs_host/test_spiffs.cpp diff --git a/components/fatfs/test_fatfs_host/Makefile b/components/fatfs/test_fatfs_host/Makefile index 76d75930d..abd95553b 100644 --- a/components/fatfs/test_fatfs_host/Makefile +++ b/components/fatfs/test_fatfs_host/Makefile @@ -57,7 +57,7 @@ force: $(TEST_PROGRAM): $(OBJ_FILES) $(TEST_WL_DIR)/$(TEST_WL_LIB) $(TEST_PARTITION_SIM_DIR)/$(TEST_PARTITION_SIM_LIB) g++ $(LDFLAGS) -o $(TEST_PROGRAM) $(OBJ_FILES) -L$(TEST_PARTITION_SIM_DIR) -l:$(TEST_PARTITION_SIM_LIB) -L$(TEST_WL_DIR) -l:$(TEST_WL_LIB) -run: $(TEST_PROGRAM) +test: $(TEST_PROGRAM) ./$(TEST_PROGRAM) COVERAGE_FILES = $(OBJ_FILES:.o=.gc*) $(OBJ_FILES:.o=.gc*) @@ -80,4 +80,4 @@ clean: rm -rf coverage_report/ rm -f coverage.info -.PHONY: clean all +.PHONY: clean all test diff --git a/components/fatfs/test_fatfs_host/test_fatfs.cpp b/components/fatfs/test_fatfs_host/test_fatfs.cpp index 2c34da4f7..d89ea20d9 100644 --- a/components/fatfs/test_fatfs_host/test_fatfs.cpp +++ b/components/fatfs/test_fatfs_host/test_fatfs.cpp @@ -23,7 +23,7 @@ TEST_CASE("create volume, open file, write and read back data", "[fatfs]") uint32_t size = 0x00400000; int flash_handle = esp_flash_create(size, 4096, 1); esp_partition_t partition = esp_partition_create(size, 0, flash_handle); - + // Mount wear-levelled partition wl_handle_t wl_handle; esp_result = wl_mount(&partition, &wl_handle); @@ -77,7 +77,7 @@ TEST_CASE("create volume, open file, write and read back data", "[fatfs]") fr_result = f_mount(0, "", 0); REQUIRE(fr_result == FR_OK); - esp_partition_delete(partition); + esp_flash_delete(flash_handle); free(read); -} \ No newline at end of file +} diff --git a/components/spi_flash/sim/Flash_Emulator.cpp b/components/spi_flash/sim/Flash_Emulator.cpp index 5dc69a8bb..e6e51178c 100644 --- a/components/spi_flash/sim/Flash_Emulator.cpp +++ b/components/spi_flash/sim/Flash_Emulator.cpp @@ -27,6 +27,7 @@ Flash_Emulator::Flash_Emulator(size_t size, size_t sector_sise, size_t min_size) this->buff = (uint8_t *)malloc(this->size); this->access_count = new uint32_t[this->size / this->sector_sise]; memset(this->access_count, 0, this->size / this->sector_sise * sizeof(uint32_t)); + memset(this->buff, 1, this->size); } size_t Flash_Emulator::chip_size() diff --git a/components/spi_flash/sim/include/esp_partition.h b/components/spi_flash/sim/include/esp_partition.h index f2904e789..826c40524 100644 --- a/components/spi_flash/sim/include/esp_partition.h +++ b/components/spi_flash/sim/include/esp_partition.h @@ -84,9 +84,11 @@ esp_err_t esp_partition_erase_range(const esp_partition_t* partition, esp_err_t esp_partition_read(const esp_partition_t* partition, size_t src_offset, void* dst, size_t size); -esp_partition_t esp_partition_create(uint32_t size, uint32_t start); +esp_partition_t esp_partition_create(uint32_t size, uint32_t start, int handle); -void esp_partition_delete(esp_partition_t partition); +int esp_flash_create(uint32_t size, uint32_t sector_size, uint32_t write_size); + +void esp_flash_delete(int handle); #if defined(__cplusplus) } diff --git a/components/spi_flash/sim/partition.cpp b/components/spi_flash/sim/partition.cpp index 9e9e69c38..3d2ec389f 100644 --- a/components/spi_flash/sim/partition.cpp +++ b/components/spi_flash/sim/partition.cpp @@ -8,13 +8,13 @@ static Flash_Emulator* emulators[EMULATORS_MAX]; -esp_partition_t esp_partition_create(uint32_t size, uint32_t start) -{ +int esp_flash_create(uint32_t size, uint32_t sector_size, uint32_t write_size) +{ int handle = -1; for (int i = 0; i < EMULATORS_MAX; i++) { if (emulators[i] == NULL) { - emulators[i] = new Flash_Emulator(start + size, SPI_FLASH_SEC_SIZE, SPI_FLASH_WRITE_SIZE); + emulators[i] = new Flash_Emulator(size, sector_size, write_size); handle = i; break; } @@ -22,23 +22,28 @@ esp_partition_t esp_partition_create(uint32_t size, uint32_t start) assert(handle != -1); + return handle; +} + +esp_partition_t esp_partition_create(uint32_t size, uint32_t start, int flash) +{ esp_partition_t partition; // Fills partition with default values, and attaches the flash_emulator reference // to the struct partition.type = ESP_PARTITION_TYPE_DATA; - partition.subtype = ESP_PARTITION_SUBTYPE_DATA_FAT; + partition.subtype = ESP_PARTITION_SUBTYPE_ANY; partition.address = start; partition.size = size; - partition.handle = handle; + partition.handle = flash; return partition; } -void esp_partition_delete(esp_partition_t partition) +void esp_flash_delete(int handle) { - delete emulators[partition.handle]; - emulators[partition.handle] = NULL; + delete emulators[handle]; + emulators[handle] = NULL; } esp_err_t esp_partition_write(const esp_partition_t* partition, @@ -60,4 +65,4 @@ esp_err_t esp_partition_read(const esp_partition_t* partition, { emulators[partition->handle]->read(src_offset, dst, size); return ESP_OK; -} \ No newline at end of file +} diff --git a/components/spiffs/component.mk b/components/spiffs/component.mk index 70f96dfd4..f245a57e1 100644 --- a/components/spiffs/component.mk +++ b/components/spiffs/component.mk @@ -1,5 +1,5 @@ COMPONENT_ADD_INCLUDEDIRS := include -COMPONENT_PRIV_INCLUDEDIRS := spiffs/src +COMPONENT_PRIV_INCLUDEDIRS := . spiffs/src COMPONENT_SRCDIRS := . spiffs/src COMPONENT_SUBMODULES := spiffs diff --git a/components/spiffs/esp_spiffs.c b/components/spiffs/esp_spiffs.c index d5fb18003..96233c6f9 100644 --- a/components/spiffs/esp_spiffs.c +++ b/components/spiffs/esp_spiffs.c @@ -30,29 +30,12 @@ #include "esp_vfs.h" #include "esp_err.h" #include "rom/spi_flash.h" - -static const char * TAG = "SPIFFS"; +#include "spiffs_api.h" #ifdef CONFIG_SPIFFS_USE_MTIME _Static_assert(CONFIG_SPIFFS_META_LENGTH >= sizeof(time_t), "SPIFFS_META_LENGTH size should be >= sizeof(time_t)"); #endif //CONFIG_SPIFFS_USE_MTIME -/** - * @brief SPIFFS definition structure - */ -typedef struct { - spiffs *fs; /*!< Handle to the underlying SPIFFS */ - SemaphoreHandle_t lock; /*!< FS lock */ - const esp_partition_t* partition; /*!< The partition on which SPIFFS is located */ - char base_path[ESP_VFS_PATH_MAX+1]; /*!< Mount point */ - bool by_label; /*!< Partition was mounted by label */ - spiffs_config cfg; /*!< SPIFFS Mount configuration */ - uint8_t *work; /*!< Work Buffer */ - uint8_t *fds; /*!< File Descriptor Buffer */ - uint32_t fds_sz; /*!< File Descriptor Buffer Length */ - uint8_t *cache; /*!< Cache Buffer */ - uint32_t cache_sz; /*!< Cache Buffer Length */ -} esp_spiffs_t; /** * @brief SPIFFS DIR structure @@ -89,77 +72,6 @@ static time_t vfs_spiffs_get_mtime(const spiffs_stat* s); static esp_spiffs_t * _efs[CONFIG_SPIFFS_MAX_PARTITIONS]; -void spiffs_api_lock(spiffs *fs) -{ - xSemaphoreTake(((esp_spiffs_t *)(fs->user_data))->lock, portMAX_DELAY); -} - -void spiffs_api_unlock(spiffs *fs) -{ - xSemaphoreGive(((esp_spiffs_t *)(fs->user_data))->lock); -} - -static s32_t spiffs_api_read(spiffs *fs, uint32_t addr, uint32_t size, uint8_t *dst) -{ - esp_err_t err = esp_partition_read(((esp_spiffs_t *)(fs->user_data))->partition, - addr, dst, size); - if (err) { - ESP_LOGE(TAG, "failed to read addr %08x, size %08x, err %d", addr, size, err); - return -1; - } - return 0; -} - -static s32_t spiffs_api_write(spiffs *fs, uint32_t addr, uint32_t size, uint8_t *src) -{ - esp_err_t err = esp_partition_write(((esp_spiffs_t *)(fs->user_data))->partition, - addr, src, size); - if (err) { - ESP_LOGE(TAG, "failed to write addr %08x, size %08x, err %d", addr, size, err); - return -1; - } - return 0; -} - -static s32_t spiffs_api_erase(spiffs *fs, uint32_t addr, uint32_t size) -{ - esp_err_t err = esp_partition_erase_range(((esp_spiffs_t *)(fs->user_data))->partition, - addr, size); - if (err) { - ESP_LOGE(TAG, "failed to erase addr %08x, size %08x, err %d", addr, size, err); - return -1; - } - return 0; -} - -static void spiffs_api_check(spiffs *fs, spiffs_check_type type, - spiffs_check_report report, uint32_t arg1, uint32_t arg2) -{ - static const char * spiffs_check_type_str[3] = { - "LOOKUP", - "INDEX", - "PAGE" - }; - - static const char * spiffs_check_report_str[7] = { - "PROGRESS", - "ERROR", - "FIX INDEX", - "FIX LOOKUP", - "DELETE ORPHANED INDEX", - "DELETE PAGE", - "DELETE BAD FILE" - }; - - if (report != SPIFFS_CHECK_PROGRESS) { - ESP_LOGE(TAG, "CHECK: type:%s, report:%s, %x:%x", spiffs_check_type_str[type], - spiffs_check_report_str[report], arg1, arg2); - } else { - ESP_LOGV(TAG, "CHECK PROGRESS: report:%s, %x:%x", - spiffs_check_report_str[report], arg1, arg2); - } -} - static void esp_spiffs_free(esp_spiffs_t ** efs) { esp_spiffs_t * e = *efs; @@ -232,7 +144,7 @@ static esp_err_t esp_spiffs_init(const esp_vfs_spiffs_conf_t* conf) esp_partition_subtype_t subtype = conf->partition_label ? ESP_PARTITION_SUBTYPE_ANY : ESP_PARTITION_SUBTYPE_DATA_SPIFFS; - const esp_partition_t* partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, + const esp_partition_t* partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, subtype, conf->partition_label); if (!partition) { ESP_LOGE(TAG, "spiffs partition could not be found"); @@ -310,7 +222,7 @@ static esp_err_t esp_spiffs_init(const esp_vfs_spiffs_conf_t* conf) efs->fs->user_data = (void *)efs; efs->partition = partition; - s32_t res = SPIFFS_mount(efs->fs, &efs->cfg, efs->work, efs->fds, efs->fds_sz, + s32_t res = SPIFFS_mount(efs->fs, &efs->cfg, efs->work, efs->fds, efs->fds_sz, efs->cache, efs->cache_sz, spiffs_api_check); if (conf->format_if_mount_failed && res != SPIFFS_OK) { @@ -323,7 +235,7 @@ static esp_err_t esp_spiffs_init(const esp_vfs_spiffs_conf_t* conf) esp_spiffs_free(&efs); return ESP_FAIL; } - res = SPIFFS_mount(efs->fs, &efs->cfg, efs->work, efs->fds, efs->fds_sz, + res = SPIFFS_mount(efs->fs, &efs->cfg, efs->work, efs->fds, efs->fds_sz, efs->cache, efs->cache_sz, spiffs_api_check); } if (res != SPIFFS_OK) { @@ -710,7 +622,7 @@ static struct dirent* vfs_spiffs_readdir(void* ctx, DIR* pdir) return out_dirent; } -static int vfs_spiffs_readdir_r(void* ctx, DIR* pdir, struct dirent* entry, +static int vfs_spiffs_readdir_r(void* ctx, DIR* pdir, struct dirent* entry, struct dirent** out_dirent) { assert(pdir); diff --git a/components/spiffs/spiffs_api.c b/components/spiffs/spiffs_api.c new file mode 100644 index 000000000..6dd3db963 --- /dev/null +++ b/components/spiffs/spiffs_api.c @@ -0,0 +1,93 @@ +// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "freertos/FreeRTOS.h" +#include "esp_log.h" +#include "esp_partition.h" +#include "esp_spiffs.h" +#include "esp_vfs.h" +#include "spiffs_api.h" + +const char* TAG = "SPIFFS"; + +void spiffs_api_lock(spiffs *fs) +{ + xSemaphoreTake(((esp_spiffs_t *)(fs->user_data))->lock, portMAX_DELAY); +} + +void spiffs_api_unlock(spiffs *fs) +{ + xSemaphoreGive(((esp_spiffs_t *)(fs->user_data))->lock); +} + +s32_t spiffs_api_read(spiffs *fs, uint32_t addr, uint32_t size, uint8_t *dst) +{ + esp_err_t err = esp_partition_read(((esp_spiffs_t *)(fs->user_data))->partition, + addr, dst, size); + if (err) { + ESP_LOGE(TAG, "failed to read addr %08x, size %08x, err %d", addr, size, err); + return -1; + } + return 0; +} + +s32_t spiffs_api_write(spiffs *fs, uint32_t addr, uint32_t size, uint8_t *src) +{ + esp_err_t err = esp_partition_write(((esp_spiffs_t *)(fs->user_data))->partition, + addr, src, size); + if (err) { + ESP_LOGE(TAG, "failed to write addr %08x, size %08x, err %d", addr, size, err); + return -1; + } + return 0; +} + +s32_t spiffs_api_erase(spiffs *fs, uint32_t addr, uint32_t size) +{ + esp_err_t err = esp_partition_erase_range(((esp_spiffs_t *)(fs->user_data))->partition, + addr, size); + if (err) { + ESP_LOGE(TAG, "failed to erase addr %08x, size %08x, err %d", addr, size, err); + return -1; + } + return 0; +} + +void spiffs_api_check(spiffs *fs, spiffs_check_type type, + spiffs_check_report report, uint32_t arg1, uint32_t arg2) +{ + static const char * spiffs_check_type_str[3] = { + "LOOKUP", + "INDEX", + "PAGE" + }; + + static const char * spiffs_check_report_str[7] = { + "PROGRESS", + "ERROR", + "FIX INDEX", + "FIX LOOKUP", + "DELETE ORPHANED INDEX", + "DELETE PAGE", + "DELETE BAD FILE" + }; + + if (report != SPIFFS_CHECK_PROGRESS) { + ESP_LOGE(TAG, "CHECK: type:%s, report:%s, %x:%x", spiffs_check_type_str[type], + spiffs_check_report_str[report], arg1, arg2); + } else { + ESP_LOGV(TAG, "CHECK PROGRESS: report:%s, %x:%x", + spiffs_check_report_str[report], arg1, arg2); + } +} diff --git a/components/spiffs/spiffs_api.h b/components/spiffs/spiffs_api.h new file mode 100644 index 000000000..492da7cde --- /dev/null +++ b/components/spiffs/spiffs_api.h @@ -0,0 +1,59 @@ +// Copyright 2015-2017 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 +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "spiffs.h" +#include "esp_vfs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const char* TAG; + +/** + * @brief SPIFFS definition structure + */ +typedef struct { + spiffs *fs; /*!< Handle to the underlying SPIFFS */ + SemaphoreHandle_t lock; /*!< FS lock */ + const esp_partition_t* partition; /*!< The partition on which SPIFFS is located */ + char base_path[ESP_VFS_PATH_MAX+1]; /*!< Mount point */ + bool by_label; /*!< Partition was mounted by label */ + spiffs_config cfg; /*!< SPIFFS Mount configuration */ + uint8_t *work; /*!< Work Buffer */ + uint8_t *fds; /*!< File Descriptor Buffer */ + uint32_t fds_sz; /*!< File Descriptor Buffer Length */ + uint8_t *cache; /*!< Cache Buffer */ + uint32_t cache_sz; /*!< Cache Buffer Length */ +} esp_spiffs_t; + +s32_t spiffs_api_read(spiffs *fs, uint32_t addr, uint32_t size, uint8_t *dst); + +s32_t spiffs_api_write(spiffs *fs, uint32_t addr, uint32_t size, uint8_t *src); + +s32_t spiffs_api_erase(spiffs *fs, uint32_t addr, uint32_t size); + +void spiffs_api_check(spiffs *fs, spiffs_check_type type, + spiffs_check_report report, uint32_t arg1, uint32_t arg2); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/components/spiffs/test_spiffs_host/Makefile b/components/spiffs/test_spiffs_host/Makefile new file mode 100644 index 000000000..730a7af50 --- /dev/null +++ b/components/spiffs/test_spiffs_host/Makefile @@ -0,0 +1,79 @@ +TEST_PROGRAM=test_spiffs + +TEST_PARTITION_SIM_DIR=$(IDF_PATH)/components/spi_flash/sim +TEST_PARTITION_SIM_LIB=libpartition_sim.a + +all: $(TEST_PROGRAM) + +SOURCE_FILES = \ + main.cpp \ + test_spiffs.cpp \ + ../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 \ + ) + +INCLUDE_FLAGS = $(addprefix -I,\ + . \ + .. \ + ../spiffs/src \ + ../include \ + $(addprefix ./stubs/, \ + esp32/include \ + log/include \ + freertos/include \ + newlib/include \ + vfs/include \ + ) \ + ../../esp32/include \ + $(TEST_PARTITION_SIM_DIR)/include \ + ../../../tools/catch \ +) + +GCOV ?= gcov + +CPPFLAGS += $(INCLUDE_FLAGS) -D CONFIG_LOG_DEFAULT_LEVEL -g +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_PARTITION_SIM_DIR)/$(TEST_PARTITION_SIM_LIB): force + $(MAKE) -C $(TEST_PARTITION_SIM_DIR) lib + +$(TEST_PROGRAM): $(OBJ_FILES) $(TEST_PARTITION_SIM_DIR)/$(TEST_PARTITION_SIM_LIB) + g++ $(LDFLAGS) -o $(TEST_PROGRAM) $(OBJ_FILES) -L$(TEST_PARTITION_SIM_DIR) -l:$(TEST_PARTITION_SIM_LIB) -L$(TEST_WL_DIR) -l:$(TEST_WL_LIB) + +force: + +test: $(TEST_PROGRAM) + ./$(TEST_PROGRAM) + +COVERAGE_FILES = $(OBJ_FILES:.o=.gc*) $(OBJ_FILES:.o=.gc*) + +$(COVERAGE_FILES): $(TEST_PROGRAM) lib + +coverage.info: $(COVERAGE_FILES) + find ../ -name "*.gcno" -exec $(GCOV) -r -pb {} + + lcov --capture --directory ../ --no-external --output-file coverage.info --gcov-tool $(GCOV) + +coverage_report: coverage.info + genhtml coverage.info --output-directory coverage_report + @echo "Coverage report is in coverage_report/index.html" + +clean: + rm -f $(OBJ_FILES) $(TEST_PROGRAM) $(TEST_WL_LIB) + $(MAKE) -C $(TEST_PARTITION_SIM_DIR) clean + rm -f $(COVERAGE_FILES) *.gcov + rm -rf coverage_report/ + rm -f coverage.info + +.PHONY: clean all test diff --git a/components/spiffs/test_spiffs_host/main.cpp b/components/spiffs/test_spiffs_host/main.cpp new file mode 100644 index 000000000..178916eab --- /dev/null +++ b/components/spiffs/test_spiffs_host/main.cpp @@ -0,0 +1,3 @@ +#define CATCH_CONFIG_MAIN +#include "catch.hpp" + diff --git a/components/spiffs/test_spiffs_host/sdkconfig.h b/components/spiffs/test_spiffs_host/sdkconfig.h new file mode 100644 index 000000000..7e0277fad --- /dev/null +++ b/components/spiffs/test_spiffs_host/sdkconfig.h @@ -0,0 +1,14 @@ +#pragma once + +#define CONFIG_SPIFFS_USE_MAGIC_LENGTH 1 +#define CONFIG_SPIFFS_MAX_PARTITIONS 3 +#define CONFIG_SPIFFS_OBJ_NAME_LEN 32 +#define CONFIG_SPIFFS_PAGE_SIZE 256 +#define CONFIG_SPIFFS_GC_MAX_RUNS 10 +#define CONFIG_SPIFFS_CACHE_WR 1 +#define CONFIG_SPIFFS_CACHE 1 +#define CONFIG_SPIFFS_META_LENGTH 4 +#define CONFIG_SPIFFS_USE_MAGIC 1 +#define CONFIG_SPIFFS_PAGE_CHECK 1 +#define CONFIG_SPIFFS_USE_MTIME 1 +#define CONFIG_WL_SECTOR_SIZE 4096 diff --git a/components/spiffs/test_spiffs_host/stubs/esp32/include/rom/spi_flash.h b/components/spiffs/test_spiffs_host/stubs/esp32/include/rom/spi_flash.h new file mode 100644 index 000000000..ce8e2f87b --- /dev/null +++ b/components/spiffs/test_spiffs_host/stubs/esp32/include/rom/spi_flash.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +typedef struct { + uint32_t device_id; + uint32_t chip_size; // chip size in bytes + uint32_t block_size; + uint32_t sector_size; + uint32_t page_size; + uint32_t status_mask; +} esp_rom_spiflash_chip_t; + +extern esp_rom_spiflash_chip_t g_rom_flashchip; + +#if defined(__cplusplus) +} +#endif \ No newline at end of file diff --git a/components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/FreeRTOS.h b/components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/FreeRTOS.h new file mode 100644 index 000000000..5bafa772d --- /dev/null +++ b/components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/FreeRTOS.h @@ -0,0 +1,4 @@ +#pragma once + +#include "projdefs.h" +#include "semphr.h" diff --git a/components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/projdefs.h b/components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/projdefs.h new file mode 100644 index 000000000..aa8c7a3de --- /dev/null +++ b/components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/projdefs.h @@ -0,0 +1,11 @@ +#pragma once + +#if defined(__cplusplus) +extern "C" { +#endif + +#define pdTRUE 1 + +#if defined(__cplusplus) +} +#endif diff --git a/components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/semphr.h b/components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/semphr.h new file mode 100644 index 000000000..c589795fb --- /dev/null +++ b/components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/semphr.h @@ -0,0 +1,16 @@ +#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 diff --git a/components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/task.h b/components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/task.h new file mode 100644 index 000000000..7b9637ef9 --- /dev/null +++ b/components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/task.h @@ -0,0 +1 @@ +#pragma once \ No newline at end of file diff --git a/components/spiffs/test_spiffs_host/stubs/log/include/esp_log.h b/components/spiffs/test_spiffs_host/stubs/log/include/esp_log.h new file mode 100644 index 000000000..84756cdb9 --- /dev/null +++ b/components/spiffs/test_spiffs_host/stubs/log/include/esp_log.h @@ -0,0 +1,51 @@ +#pragma once + +#include +#include + +#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 \ No newline at end of file diff --git a/components/spiffs/test_spiffs_host/stubs/log/log.c b/components/spiffs/test_spiffs_host/stubs/log/log.c new file mode 100644 index 000000000..d01a96ff4 --- /dev/null +++ b/components/spiffs/test_spiffs_host/stubs/log/log.c @@ -0,0 +1,22 @@ + +#include +#include +#include + +#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; +} + diff --git a/components/spiffs/test_spiffs_host/stubs/newlib/include/sys/lock.h b/components/spiffs/test_spiffs_host/stubs/newlib/include/sys/lock.h new file mode 100644 index 000000000..7892465ad --- /dev/null +++ b/components/spiffs/test_spiffs_host/stubs/newlib/include/sys/lock.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +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); diff --git a/components/spiffs/test_spiffs_host/stubs/newlib/lock.c b/components/spiffs/test_spiffs_host/stubs/newlib/lock.c new file mode 100644 index 000000000..697615ffd --- /dev/null +++ b/components/spiffs/test_spiffs_host/stubs/newlib/lock.c @@ -0,0 +1,21 @@ +#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; +} diff --git a/components/spiffs/test_spiffs_host/stubs/vfs/include/esp_vfs.h b/components/spiffs/test_spiffs_host/stubs/vfs/include/esp_vfs.h new file mode 100644 index 000000000..36c6384a3 --- /dev/null +++ b/components/spiffs/test_spiffs_host/stubs/vfs/include/esp_vfs.h @@ -0,0 +1,6 @@ +#pragma once + +#include "esp_err.h" + +#define ESP_VFS_FLAG_CONTEXT_PTR 1 +#define ESP_VFS_PATH_MAX 15 diff --git a/components/spiffs/test_spiffs_host/test_spiffs.cpp b/components/spiffs/test_spiffs_host/test_spiffs.cpp new file mode 100644 index 000000000..961a6c881 --- /dev/null +++ b/components/spiffs/test_spiffs_host/test_spiffs.cpp @@ -0,0 +1,96 @@ +#include +#include +#include + +#include "esp_partition.h" +#include "spiffs.h" +#include "spiffs_nucleus.h" +#include "spiffs_api.h" + +#include "catch.hpp" + +TEST_CASE("format disk, open file, write and read file", "[spiffs]") +{ + uint32_t size = 0x00400000; + + int flash_handle = esp_flash_create(size, CONFIG_WL_SECTOR_SIZE, 1); + esp_partition_t partition = esp_partition_create(size, 0, flash_handle); + + spiffs fs; + spiffs_config cfg; + + // Configure objects needed by SPIFFS + esp_spiffs_t esp_user_data; + esp_user_data.partition = &partition; + fs.user_data = (void*)&esp_user_data; + + cfg.hal_erase_f = spiffs_api_erase; + cfg.hal_read_f = spiffs_api_read; + cfg.hal_write_f = spiffs_api_write; + cfg.log_block_size = CONFIG_WL_SECTOR_SIZE; + cfg.log_page_size = CONFIG_SPIFFS_PAGE_SIZE; + cfg.phys_addr = 0; + cfg.phys_erase_block = CONFIG_WL_SECTOR_SIZE; + cfg.phys_size = partition.size; + + uint32_t max_files = 5; + + uint32_t fds_sz = max_files * sizeof(spiffs_fd); + uint32_t work_sz = cfg.log_page_size * 2; + uint32_t cache_sz = sizeof(spiffs_cache) + max_files * (sizeof(spiffs_cache_page) + + cfg.log_page_size); + + uint8_t *work = (uint8_t*) malloc(work_sz); + uint8_t *fds = (uint8_t*) malloc(fds_sz); + uint8_t *cache = (uint8_t*) malloc(cache_sz); + + s32_t spiffs_res; + + // Special mounting procedure: mount, format, mount as per + // https://github.com/pellepl/spiffs/wiki/Using-spiffs + spiffs_res = SPIFFS_mount(&fs, &cfg, work, fds, fds_sz, + cache, cache_sz, spiffs_api_check); + REQUIRE(spiffs_res == SPIFFS_ERR_NOT_A_FS); + + spiffs_res = SPIFFS_format(&fs); + REQUIRE(spiffs_res >= SPIFFS_OK); + + spiffs_res = SPIFFS_mount(&fs, &cfg, work, fds, fds_sz, + cache, cache_sz, spiffs_api_check); + REQUIRE(spiffs_res >= SPIFFS_OK); + + // Open test file + spiffs_res = SPIFFS_open(&fs, "test.txt", SPIFFS_O_CREAT | SPIFFS_O_RDWR, 0); + REQUIRE(spiffs_res >= SPIFFS_OK); + + // Write to the test file + spiffs_file file = spiffs_res; + + const char data[] = "Hello, World!"; + char *read = (char*) malloc(sizeof(data)); + + s32_t bw; + + spiffs_res = SPIFFS_write(&fs, file, (void*)data, sizeof(data)); + REQUIRE(spiffs_res >= SPIFFS_OK); + REQUIRE(spiffs_res == sizeof(data)); + + // Set the file object pointer to the beginning + spiffs_res = SPIFFS_lseek(&fs, file, 0, SPIFFS_SEEK_SET); + REQUIRE(spiffs_res >= SPIFFS_OK); + + // Set the file object pointer to the beginning + spiffs_res = SPIFFS_read(&fs, file, (void*)read, sizeof(data)); + REQUIRE(spiffs_res >= SPIFFS_OK); + REQUIRE(spiffs_res == sizeof(data)); + + // Close the test file + spiffs_res = SPIFFS_close(&fs, file); + REQUIRE(spiffs_res >= SPIFFS_OK); + + // Unmount + SPIFFS_unmount(&fs); + + esp_flash_delete(flash_handle); + free(read); +} \ No newline at end of file diff --git a/components/wear_levelling/test_wl_host/test_wl.cpp b/components/wear_levelling/test_wl_host/test_wl.cpp index b2ed120b3..019197a58 100644 --- a/components/wear_levelling/test_wl_host/test_wl.cpp +++ b/components/wear_levelling/test_wl_host/test_wl.cpp @@ -28,7 +28,8 @@ TEST_CASE("write and read back data", "[wear_levelling]") esp_err_t result; wl_handle_t wl_handle; - esp_partition_t partition = esp_partition_create(PARTITION_SIZE, PARTITION_START); + int flash_handle = esp_flash_create(PARTITION_SIZE, 4096, 16); + esp_partition_t partition = esp_partition_create(PARTITION_SIZE, PARTITION_START, flash_handle); // Mount wear-levelled partition result = wl_mount(partition, &wl_handle); @@ -91,4 +92,4 @@ TEST_CASE("write and read back data", "[wear_levelling]") free(data); free(read); -} \ No newline at end of file +} From c409666d4e76f231d2f0032e3e000dd006e311e0 Mon Sep 17 00:00:00 2001 From: Renz Bagaporo Date: Tue, 22 May 2018 18:26:19 +0800 Subject: [PATCH 4/5] ci: Add spiffs, fatfs host runs to CI Adds running the fatfs, spiffs sanity check to CI. --- .gitlab-ci.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 17feb07fb..f76a06132 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -285,6 +285,26 @@ test_wl_on_host: - cd components/wear_levelling/test_wl_host - make test +test_fatfs_on_host: + stage: test + image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG + tags: + - wl_host_test + dependencies: [] + script: + - cd components/fatfs/test_fatfs_host/ + - make test + +test_spiffs_on_host: + stage: test + image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG + tags: + - wl_host_test + dependencies: [] + script: + - cd components/spiffs/test_spiffs_host/ + - make test + test_multi_heap_on_host: stage: test image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG From 8caab13faa2120430e3e301ac2790b92d9c12d84 Mon Sep 17 00:00:00 2001 From: Renz Bagaporo Date: Sat, 26 May 2018 14:58:01 +0800 Subject: [PATCH 5/5] spi_flash: Enable flash emulation down to ROM function calls --- components/fatfs/test_fatfs_host/Makefile | 70 ++++++---- .../fatfs/test_fatfs_host/partition_table.csv | 6 + .../fatfs/test_fatfs_host/test_fatfs.cpp | 38 +++-- components/fatfs/test_fatfs_host/test_utils.c | 7 + components/spi_flash/sim/Flash_Emulator.cpp | 130 ------------------ components/spi_flash/sim/Flash_Emulator.h | 59 -------- components/spi_flash/sim/Makefile | 50 +++++-- components/spi_flash/sim/SpiFlash.cpp | 126 +++++++++++++++++ components/spi_flash/sim/SpiFlash.h | 62 +++++++++ components/spi_flash/sim/flash_mock.cpp | 65 +++++++++ components/spi_flash/sim/flash_mock_util.c | 57 ++++++++ .../spi_flash/sim/include/esp_partition.h | 96 ------------- .../spi_flash/sim/include/esp_spi_flash.h | 7 - components/spi_flash/sim/partition.cpp | 68 --------- components/spi_flash/sim/sdkconfig.h | 3 +- .../sim/stubs/app_update/esp_ota_eps.c | 13 ++ .../freertos/include/freertos/FreeRTOS.h | 8 ++ .../freertos/include/freertos/projdefs.h | 11 ++ .../stubs/freertos/include/freertos/semphr.h | 16 +++ .../stubs/freertos/include/freertos/task.h | 1 + .../spi_flash/sim/stubs/log/include/esp_log.h | 48 +++++++ components/spi_flash/sim/stubs/log/log.c | 22 +++ .../sim/stubs/newlib/include/sys/lock.h | 17 +++ components/spi_flash/sim/stubs/newlib/lock.c | 21 +++ components/spiffs/test_spiffs_host/Makefile | 54 +++++--- .../test_spiffs_host/partitions_table.csv | 6 + .../spiffs/test_spiffs_host/sdkconfig.h | 2 +- .../stubs/esp32/include/rom/spi_flash.h | 23 ---- .../spiffs/test_spiffs_host/test_spiffs.cpp | 43 +++--- .../spiffs/test_spiffs_host/test_utils.c | 7 + .../wear_levelling/doc/wl_sw_structure.rst | 3 +- .../wear_levelling/test_wl_host/Makefile | 61 ++++---- .../wear_levelling/test_wl_host/main.cpp | 2 +- .../test_wl_host/partition_table.csv | 6 + .../wear_levelling/test_wl_host/sdkconfig.h | 1 + .../test_wl_host/stubs/esp32/crc.cpp | 24 +++- .../stubs/esp32/include/rom/crc.h | 15 -- .../stubs/esp32/include/rom/spi_flash.h | 13 -- .../test_wl_host/stubs/log/log.c | 3 +- .../stubs/newlib/include/sys/lock.h | 3 +- .../test_wl_host/stubs/newlib/lock.c | 2 +- .../wear_levelling/test_wl_host/test_utils.c | 7 + .../wear_levelling/test_wl_host/test_wl.cpp | 22 +-- 43 files changed, 742 insertions(+), 556 deletions(-) create mode 100644 components/fatfs/test_fatfs_host/partition_table.csv create mode 100644 components/fatfs/test_fatfs_host/test_utils.c delete mode 100644 components/spi_flash/sim/Flash_Emulator.cpp delete mode 100644 components/spi_flash/sim/Flash_Emulator.h create mode 100644 components/spi_flash/sim/SpiFlash.cpp create mode 100644 components/spi_flash/sim/SpiFlash.h create mode 100644 components/spi_flash/sim/flash_mock.cpp create mode 100644 components/spi_flash/sim/flash_mock_util.c delete mode 100644 components/spi_flash/sim/include/esp_partition.h delete mode 100644 components/spi_flash/sim/include/esp_spi_flash.h delete mode 100644 components/spi_flash/sim/partition.cpp create mode 100644 components/spi_flash/sim/stubs/app_update/esp_ota_eps.c create mode 100644 components/spi_flash/sim/stubs/freertos/include/freertos/FreeRTOS.h create mode 100644 components/spi_flash/sim/stubs/freertos/include/freertos/projdefs.h create mode 100644 components/spi_flash/sim/stubs/freertos/include/freertos/semphr.h create mode 100644 components/spi_flash/sim/stubs/freertos/include/freertos/task.h create mode 100644 components/spi_flash/sim/stubs/log/include/esp_log.h create mode 100644 components/spi_flash/sim/stubs/log/log.c create mode 100644 components/spi_flash/sim/stubs/newlib/include/sys/lock.h create mode 100644 components/spi_flash/sim/stubs/newlib/lock.c create mode 100644 components/spiffs/test_spiffs_host/partitions_table.csv delete mode 100644 components/spiffs/test_spiffs_host/stubs/esp32/include/rom/spi_flash.h create mode 100644 components/spiffs/test_spiffs_host/test_utils.c create mode 100644 components/wear_levelling/test_wl_host/partition_table.csv delete mode 100644 components/wear_levelling/test_wl_host/stubs/esp32/include/rom/crc.h delete mode 100644 components/wear_levelling/test_wl_host/stubs/esp32/include/rom/spi_flash.h create mode 100644 components/wear_levelling/test_wl_host/test_utils.c diff --git a/components/fatfs/test_fatfs_host/Makefile b/components/fatfs/test_fatfs_host/Makefile index abd95553b..9815ed73c 100644 --- a/components/fatfs/test_fatfs_host/Makefile +++ b/components/fatfs/test_fatfs_host/Makefile @@ -1,18 +1,24 @@ -TEST_PROGRAM=test_fatfs +COMPONENT=fatfs -# Use wear levelling -TEST_WL_COMPONENT=$(IDF_PATH)/components/wear_levelling -TEST_WL_DIR=$(TEST_WL_COMPONENT)/test_wl_host -TEST_WL_LIB=libtest_wl.a +TEST_PROGRAM=test_$(COMPONENT) -TEST_PARTITION_SIM_DIR=$(IDF_PATH)/components/spi_flash/sim -TEST_PARTITION_SIM_LIB=libpartition_sim.a +#Expose as a library +COMPONENT_LIB=lib$(COMPONENT).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=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 = \ - main.cpp \ - test_fatfs.cpp \ $(addprefix ../src/, \ diskio.c \ ff.c \ @@ -22,6 +28,11 @@ SOURCE_FILES = \ ) \ $(addprefix ./stubs/, log/log.c) +TEST_SOURCE_FILES = \ + test_fatfs.cpp \ + main.cpp \ + test_utils.c + INCLUDE_FLAGS = $(addprefix -I,\ ../src \ . \ @@ -31,38 +42,47 @@ INCLUDE_FLAGS = $(addprefix -I,\ sdmmc/include \ log/include \ ) \ + $(SPI_FLASH_DIR)/include \ + $(WEAR_LEVELLING_DIR)/include \ ../../esp32/include \ - $(TEST_PARTITION_SIM_DIR)/include \ - $(TEST_WL_COMPONENT)/include \ ../../../tools/catch \ ) GCOV ?= gcov -CPPFLAGS += $(INCLUDE_FLAGS) -D CONFIG_LOG_DEFAULT_LEVEL -g +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)) -$(TEST_WL_DIR)/$(TEST_WL_LIB): force - $(MAKE) -C $(TEST_WL_DIR) lib +$(WEAR_LEVELLING_HOST_DIR)/$(WEAR_LEVELLING_LIB): force + $(MAKE) -C $(WEAR_LEVELLING_HOST_DIR) lib -$(TEST_PARTITION_SIM_DIR)/$(TEST_PARTITION_SIM_LIB): force - $(MAKE) -C $(TEST_PARTITION_SIM_DIR) lib +$(SPI_FLASH_SIM_DIR)/$(SPI_FLASH_LIB): force + $(MAKE) -C $(SPI_FLASH_SIM_DIR) lib -force: +force: -$(TEST_PROGRAM): $(OBJ_FILES) $(TEST_WL_DIR)/$(TEST_WL_LIB) $(TEST_PARTITION_SIM_DIR)/$(TEST_PARTITION_SIM_LIB) - g++ $(LDFLAGS) -o $(TEST_PROGRAM) $(OBJ_FILES) -L$(TEST_PARTITION_SIM_DIR) -l:$(TEST_PARTITION_SIM_LIB) -L$(TEST_WL_DIR) -l:$(TEST_WL_LIB) +$(COMPONENT_LIB): $(OBJ_FILES) + $(AR) rcs $@ $^ + +lib: $(COMPONENT_LIB) + +partition_table.bin: partition_table.csv + python ../../partition_table/gen_esp32part.py --verify $< $@ + +$(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 test: $(TEST_PROGRAM) ./$(TEST_PROGRAM) -COVERAGE_FILES = $(OBJ_FILES:.o=.gc*) $(OBJ_FILES:.o=.gc*) +COVERAGE_FILES = $(OBJ_FILES:.o=.gc*) $(TEST_OBJ_FILES:.o=.gc*) -$(COVERAGE_FILES): $(TEST_PROGRAM) lib +$(COVERAGE_FILES): test coverage.info: $(COVERAGE_FILES) find ../ -name "*.gcno" -exec $(GCOV) -r -pb {} + @@ -73,11 +93,11 @@ coverage_report: coverage.info @echo "Coverage report is in coverage_report/index.html" clean: - rm -f $(OBJ_FILES) $(TEST_PROGRAM) - $(MAKE) -C $(TEST_WL_DIR) clean - $(MAKE) -C $(TEST_PARTITION_SIM_DIR) clean + rm -f $(OBJ_FILES) $(TEST_OBJ_FILES) $(TEST_PROGRAM) $(COMPONENT_LIB) partition_table.bin + $(MAKE) -C $(WEAR_LEVELLING_HOST_DIR) clean + $(MAKE) -C $(SPI_FLASH_SIM_DIR) clean rm -f $(COVERAGE_FILES) *.gcov rm -rf coverage_report/ rm -f coverage.info -.PHONY: clean all test +.PHONY: clean all test lib diff --git a/components/fatfs/test_fatfs_host/partition_table.csv b/components/fatfs/test_fatfs_host/partition_table.csv new file mode 100644 index 000000000..cb7fccd87 --- /dev/null +++ b/components/fatfs/test_fatfs_host/partition_table.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags +# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild +nvs, data, nvs, 0x9000, 0x6000, +phy_init, data, phy, 0xf000, 0x1000, +factory, app, factory, 0x10000, 1M, +storage, data, fat, , 1M, \ No newline at end of file diff --git a/components/fatfs/test_fatfs_host/test_fatfs.cpp b/components/fatfs/test_fatfs_host/test_fatfs.cpp index d89ea20d9..161a8c3c5 100644 --- a/components/fatfs/test_fatfs_host/test_fatfs.cpp +++ b/components/fatfs/test_fatfs_host/test_fatfs.cpp @@ -9,8 +9,12 @@ #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); + 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"); + FRESULT fr_result; BYTE pdrv; FATFS fs; @@ -19,14 +23,11 @@ TEST_CASE("create volume, open file, write and read back data", "[fatfs]") esp_err_t esp_result; - // Create a 4MB partition - uint32_t size = 0x00400000; - int flash_handle = esp_flash_create(size, 4096, 1); - esp_partition_t partition = esp_partition_create(size, 0, flash_handle); + const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, "storage"); // Mount wear-levelled partition wl_handle_t wl_handle; - esp_result = wl_mount(&partition, &wl_handle); + esp_result = wl_mount(partition, &wl_handle); REQUIRE(esp_result == ESP_OK); // Get a physical drive @@ -52,22 +53,32 @@ TEST_CASE("create volume, open file, write and read back data", "[fatfs]") fr_result = f_open(&file, "test.txt", FA_OPEN_ALWAYS | FA_READ | FA_WRITE); REQUIRE(fr_result == FR_OK); - const char data[] = "Hello, World!"; - char *read = (char*) malloc(sizeof(data)); + // Generate data + uint32_t data_size = 100000; - fr_result = f_write(&file, data, sizeof(data), &bw); + char *data = (char*) malloc(data_size); + char *read = (char*) malloc(data_size); + + for(uint32_t i = 0; i < data_size; i += sizeof(i)) + { + *((uint32_t*)(data + i)) = i; + } + + // Write generated data + fr_result = f_write(&file, data, data_size, &bw); REQUIRE(fr_result == FR_OK); - REQUIRE(bw == sizeof(data)); + REQUIRE(bw == data_size); // Move to beginning of file fr_result = f_lseek(&file, 0); REQUIRE(fr_result == FR_OK); - fr_result = f_read(&file, read, sizeof(data), &bw); + // Read written data + fr_result = f_read(&file, read, data_size, &bw); REQUIRE(fr_result == FR_OK); - REQUIRE(bw == sizeof(data)); + REQUIRE(bw == data_size); - REQUIRE(strcmp(data, read) == 0); + REQUIRE(memcmp(data, read, data_size) == 0); // Close file fr_result = f_close(&file); @@ -77,7 +88,6 @@ TEST_CASE("create volume, open file, write and read back data", "[fatfs]") fr_result = f_mount(0, "", 0); REQUIRE(fr_result == FR_OK); - esp_flash_delete(flash_handle); - free(read); + free(data); } diff --git a/components/fatfs/test_fatfs_host/test_utils.c b/components/fatfs/test_fatfs_host/test_utils.c new file mode 100644 index 000000000..c3181ede7 --- /dev/null +++ b/components/fatfs/test_fatfs_host/test_utils.c @@ -0,0 +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) +{ + spi_flash_init(chip_size, block_size, sector_size, page_size, partition_bin); +} \ No newline at end of file diff --git a/components/spi_flash/sim/Flash_Emulator.cpp b/components/spi_flash/sim/Flash_Emulator.cpp deleted file mode 100644 index e6e51178c..000000000 --- a/components/spi_flash/sim/Flash_Emulator.cpp +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "Flash_Emulator.h" - -#include -#include -#include - -Flash_Emulator::Flash_Emulator(size_t size, size_t sector_sise, size_t min_size) -{ - this->reset_count = 0x7fffffff; - this->size = size; - this->sector_sise = sector_sise; - this->min_size = min_size; - this->buff = (uint8_t *)malloc(this->size); - this->access_count = new uint32_t[this->size / this->sector_sise]; - memset(this->access_count, 0, this->size / this->sector_sise * sizeof(uint32_t)); - memset(this->buff, 1, this->size); -} - -size_t Flash_Emulator::chip_size() -{ - return this->size; -} -size_t Flash_Emulator::sector_size() -{ - return this->sector_sise; -} - -esp_err_t Flash_Emulator::erase_sector(size_t sector) -{ - esp_err_t result = ESP_OK; - if ((this->reset_count != 0x7fffffff) && (this->reset_count != 0)) { - this->reset_count--; - } - if (this->reset_count <= 0) { - result = ESP_FAIL; - return result; - } - memset(&this->buff[sector * this->sector_sise], -1, this->sector_sise); - this->access_count[sector]++; - return result; -} - -uint32_t Flash_Emulator::get_access_minmax() -{ - uint32_t min = INT32_MAX; - uint32_t max = 0; - for (size_t i = 0; i < (this->size / this->sector_sise) - 2; i++) { - if (this->access_count[i] < min) { - min = this->access_count[i]; - } - if (this->access_count[i] > max) { - max = this->access_count[i]; - } - } - return max - min; -} - -esp_err_t Flash_Emulator::erase_range(size_t start_address, size_t size) -{ - esp_err_t result = ESP_OK; - uint32_t start_sector = start_address / this->sector_sise; - uint32_t count = (size + this->sector_sise - 1) / this->sector_sise; - for (size_t i = 0; i < count; i++) { - result |= this->erase_sector(start_sector + i); - } - return result; -} - -esp_err_t Flash_Emulator::write(size_t dest_addr, const void *src, size_t size) -{ - esp_err_t result = ESP_OK; - if ((size % this->min_size) != 0) { - result = ESP_ERR_INVALID_SIZE; - return result; - } - if ((dest_addr % this->min_size) != 0) { - result = ESP_ERR_INVALID_SIZE; - return result; - } - if ((this->reset_count != 0x7fffffff) && (this->reset_count != 0)) { - this->reset_count--; - } - if (this->reset_count <= 0) { - result = ESP_FAIL; - return result; - } - memcpy(&this->buff[dest_addr], src, size); - return result; -} - -esp_err_t Flash_Emulator::read(size_t src_addr, void *dest, size_t size) -{ - esp_err_t result = ESP_OK; - if (this->reset_count <= 0) { - result = ESP_FAIL; - return result; - } - memcpy(dest, &this->buff[src_addr], size); - return result; -} - -Flash_Emulator::~Flash_Emulator() -{ - free(this->buff); - delete this->access_count; -} - -void Flash_Emulator::SetResetCount(uint32_t count) -{ - this->reset_count = count; -} - -void Flash_Emulator::SetResetSector(size_t sector) -{ - this->reset_sector = sector; -} diff --git a/components/spi_flash/sim/Flash_Emulator.h b/components/spi_flash/sim/Flash_Emulator.h deleted file mode 100644 index 30b3e6ac1..000000000 --- a/components/spi_flash/sim/Flash_Emulator.h +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2015-2017 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. - -#ifndef _Flash_Emulator_H_ -#define _Flash_Emulator_H_ - -#include "esp_err.h" - -/** -* @brief This class is used to emulate flash devices. Class implements Flash_Access interface -* -*/ -class Flash_Emulator -{ - -public: - Flash_Emulator(size_t size, size_t sector_sise, size_t min_size); - - virtual size_t chip_size(); - - virtual esp_err_t erase_sector(size_t sector); - virtual esp_err_t erase_range(size_t start_address, size_t size); - - virtual esp_err_t write(size_t dest_addr, const void *src, size_t size); - virtual esp_err_t read(size_t src_addr, void *dest, size_t size); - - virtual size_t sector_size(); - - virtual ~Flash_Emulator(); - - uint32_t get_access_minmax(); -public: - size_t size; - size_t sector_sise; - size_t min_size; - uint8_t *buff; - - uint32_t *access_count; - -public: - uint32_t reset_count; - size_t reset_sector; - void SetResetCount(uint32_t count); - void SetResetSector(size_t sector); - -}; - -#endif // _Flash_Emulator_H_ diff --git a/components/spi_flash/sim/Makefile b/components/spi_flash/sim/Makefile index 6a9992f08..d5da7f9a6 100644 --- a/components/spi_flash/sim/Makefile +++ b/components/spi_flash/sim/Makefile @@ -1,34 +1,54 @@ -PARTITION_SIM=partition_sim -PARTITION_SIM_LIB=lib$(PARTITION_SIM).a +COMPONENT=spi_flash +COMPONENT_LIB=lib$(COMPONENT).a -lib: $(PARTITION_SIM_LIB) +all: lib SOURCE_FILES = \ - Flash_Emulator.cpp \ - partition.c + ../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 \ + ../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 +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 +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)) - -$(PARTITION_SIM_LIB): $(OBJ_FILES) +$(COMPONENT_LIB): $(OBJ_FILES) $(AR) rcs $@ $^ -COVERAGE_FILES = $(OBJ_FILES:.o=.gc*) $(OBJ_FILES:.o=.gc*) +lib: $(COMPONENT_LIB) -$(COVERAGE_FILES): $(TEST_PROGRAM) lib +COVERAGE_FILES = $(OBJ_FILES:.o=.gc*) + +$(COVERAGE_FILES): lib coverage.info: $(COVERAGE_FILES) find ../ -name "*.gcno" -exec $(GCOV) -r -pb {} + @@ -39,9 +59,9 @@ coverage_report: coverage.info @echo "Coverage report is in coverage_report/index.html" clean: - rm -f $(OBJ_FILES) $(PARTITION_SIM_LIB) + rm -f $(OBJ_FILES) $(COMPONENT_LIB) rm -f $(COVERAGE_FILES) *.gcov rm -rf coverage_report/ rm -f coverage.info -.PHONY: clean lib +.PHONY: clean lib all diff --git a/components/spi_flash/sim/SpiFlash.cpp b/components/spi_flash/sim/SpiFlash.cpp new file mode 100644 index 000000000..b8c795aff --- /dev/null +++ b/components/spi_flash/sim/SpiFlash.cpp @@ -0,0 +1,126 @@ +// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "SpiFlash.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "esp_flash_data_types.h" + +using namespace std; + +SpiFlash::SpiFlash() +{ + return; +} + +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) +{ + // De-initialize first + deinit(); + + this->chip_size = chip_size; + this->block_size = block_size; + this->sector_size = sector_size; + this->page_size = page_size; + + this->memory = (uint8_t *) malloc(this->chip_size); + memset(this->memory, 0xFF, this->chip_size); + + ifstream ifd(partitions_bin, ios::binary | ios::ate); + int size = ifd.tellg(); + + ifd.seekg(0, ios::beg); + vector buffer; + + buffer.resize(size); + + ifd.read(buffer.data(), size); + + memcpy(&this->memory[ESP_PARTITION_TABLE_ADDR], buffer.data(), buffer.size()); +} + +void SpiFlash::deinit() +{ + if(inited) + { + free(this->memory); + } +} + +size_t SpiFlash::get_chip_size() +{ + return this->chip_size; +} + +size_t SpiFlash::get_sector_size() +{ + return this->sector_size; +} + +esp_rom_spiflash_result_t SpiFlash::erase_block(uint32_t block) +{ + memset(&this->memory[block * this->block_size], 0xFF, this->block_size); + return ESP_ROM_SPIFLASH_RESULT_OK; +} + +esp_rom_spiflash_result_t SpiFlash::erase_sector(size_t sector) +{ + memset(&this->memory[sector * this->sector_size], 0xFF, this->sector_size); + return ESP_ROM_SPIFLASH_RESULT_OK; +} + +esp_rom_spiflash_result_t SpiFlash::erase_page(uint32_t page) +{ + memset(&this->memory[page * this->page_size], 0xFF, this->page_size); + return ESP_ROM_SPIFLASH_RESULT_OK; +} + +esp_rom_spiflash_result_t SpiFlash::write(size_t dest_addr, const void *src, size_t size) +{ + // Emulate inability to set programmed bits without erasing + for(uint32_t ctr = 0; ctr < size; ctr++) + { + uint8_t data = ((uint8_t*)src)[ctr]; + uint8_t written = this->memory[dest_addr + ctr]; + + data &= written; + + this->memory[dest_addr + ctr] = data; + } + + return ESP_ROM_SPIFLASH_RESULT_OK; +} + +esp_rom_spiflash_result_t SpiFlash::read(size_t src_addr, void *dest, size_t size) +{ + memcpy(dest, &this->memory[src_addr], size); + return ESP_ROM_SPIFLASH_RESULT_OK; +} + +uint8_t* SpiFlash::get_memory_ptr(uint32_t src_address) +{ + return &this->memory[src_address]; +} \ No newline at end of file diff --git a/components/spi_flash/sim/SpiFlash.h b/components/spi_flash/sim/SpiFlash.h new file mode 100644 index 000000000..ef879a966 --- /dev/null +++ b/components/spi_flash/sim/SpiFlash.h @@ -0,0 +1,62 @@ +// Copyright 2015-2017 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. + +#ifndef _SpiFlash_H_ +#define _SpiFlash_H_ + +#include "esp_err.h" +#include "rom/spi_flash.h" + +/** +* @brief This class is used to emulate flash devices. +* +*/ +class SpiFlash +{ + +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); + + 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); + + size_t get_chip_size(); + size_t get_sector_size(); + + uint8_t* get_memory_ptr(uint32_t src_address); + +private: + bool inited = false; + + size_t chip_size; + size_t block_size; + size_t sector_size; + size_t page_size; + + uint8_t* memory; + + void* partitions; + uint8_t partitions_num; + + void deinit(); +}; + +#endif // _SpiFlash_H_ diff --git a/components/spi_flash/sim/flash_mock.cpp b/components/spi_flash/sim/flash_mock.cpp new file mode 100644 index 000000000..e6a992ebc --- /dev/null +++ b/components/spi_flash/sim/flash_mock.cpp @@ -0,0 +1,65 @@ +#include "SpiFlash.h" + +#include "esp_spi_flash.h" +#include "esp_partition.h" + +#include "esp_err.h" +#include "rom/spi_flash.h" + +static 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) +{ + spiflash.init(chip_size, block_size, sector_size, page_size, partitions_bin); + + g_rom_flashchip.chip_size = chip_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, + const void** out_ptr, spi_flash_mmap_handle_t* out_handle) +{ + *out_handle = 0; + *out_ptr = (void*)spiflash.get_memory_ptr(src_addr); + + return ESP_OK; +} + +void spi_flash_munmap(spi_flash_mmap_handle_t handle) +{ + return; +} + +esp_rom_spiflash_result_t esp_rom_spiflash_read(uint32_t target, uint32_t *dest, int32_t len) +{ + return spiflash.read(target, dest, len); +} + +esp_rom_spiflash_result_t esp_rom_spiflash_erase_block(uint32_t block) +{ + return spiflash.erase_block(block); +} + +esp_rom_spiflash_result_t esp_rom_spiflash_erase_sector(uint32_t sector) +{ + return spiflash.erase_sector(sector); +} + +esp_rom_spiflash_result_t esp_rom_spiflash_erase_page(uint32_t page) +{ + return spiflash.erase_page(page); +} + +esp_rom_spiflash_result_t esp_rom_spiflash_write(uint32_t target, const uint32_t *src, int32_t len) +{ + return spiflash.write(target, src, len); +} + +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); +} \ No newline at end of file diff --git a/components/spi_flash/sim/flash_mock_util.c b/components/spi_flash/sim/flash_mock_util.c new file mode 100644 index 000000000..f12d59ac0 --- /dev/null +++ b/components/spi_flash/sim/flash_mock_util.c @@ -0,0 +1,57 @@ +#include "esp_spi_flash.h" +#include "esp_partition.h" + +#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); + +void spi_flash_init(size_t 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); +} + +void spi_flash_mark_modified_region(size_t start_addr, size_t length) +{ + return; +} + +esp_rom_spiflash_result_t esp_rom_spiflash_unlock() +{ + return ESP_ROM_SPIFLASH_RESULT_OK; +} + +void spi_flash_init_lock() +{ + return; +} + +void spi_flash_op_lock() +{ + return; +} + +void spi_flash_op_unlock() +{ + return; +} + +void spi_flash_disable_interrupts_caches_and_other_cpu() +{ + return; +} + +void spi_flash_enable_interrupts_caches_and_other_cpu() +{ + return; +} + +void spi_flash_disable_interrupts_caches_and_other_cpu_no_os() +{ + return; +} + +void spi_flash_enable_interrupts_caches_no_os() +{ + return; +} \ No newline at end of file diff --git a/components/spi_flash/sim/include/esp_partition.h b/components/spi_flash/sim/include/esp_partition.h deleted file mode 100644 index 826c40524..000000000 --- a/components/spi_flash/sim/include/esp_partition.h +++ /dev/null @@ -1,96 +0,0 @@ -#pragma once - -#include - -#include "sdkconfig.h" -#include "esp_err.h" -#include "esp_spi_flash.h" - -#if defined(__cplusplus) -extern "C" { // Make sure we have C-declarations in C++ programs -#endif - -/** - * @brief Partition type - * @note Keep this enum in sync with PartitionDefinition class gen_esp32part.py - */ -typedef enum { - ESP_PARTITION_TYPE_APP = 0x00, //!< Application partition type - ESP_PARTITION_TYPE_DATA = 0x01, //!< Data partition type -} esp_partition_type_t; - -/** - * @brief Partition subtype - * @note Keep this enum in sync with PartitionDefinition class gen_esp32part.py - */ -typedef enum { - ESP_PARTITION_SUBTYPE_APP_FACTORY = 0x00, //!< Factory application partition - ESP_PARTITION_SUBTYPE_APP_OTA_MIN = 0x10, //!< Base for OTA partition subtypes - ESP_PARTITION_SUBTYPE_APP_OTA_0 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 0, //!< OTA partition 0 - ESP_PARTITION_SUBTYPE_APP_OTA_1 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 1, //!< OTA partition 1 - ESP_PARTITION_SUBTYPE_APP_OTA_2 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 2, //!< OTA partition 2 - ESP_PARTITION_SUBTYPE_APP_OTA_3 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 3, //!< OTA partition 3 - ESP_PARTITION_SUBTYPE_APP_OTA_4 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 4, //!< OTA partition 4 - ESP_PARTITION_SUBTYPE_APP_OTA_5 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 5, //!< OTA partition 5 - ESP_PARTITION_SUBTYPE_APP_OTA_6 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 6, //!< OTA partition 6 - ESP_PARTITION_SUBTYPE_APP_OTA_7 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 7, //!< OTA partition 7 - ESP_PARTITION_SUBTYPE_APP_OTA_8 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 8, //!< OTA partition 8 - ESP_PARTITION_SUBTYPE_APP_OTA_9 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 9, //!< OTA partition 9 - ESP_PARTITION_SUBTYPE_APP_OTA_10 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 10,//!< OTA partition 10 - ESP_PARTITION_SUBTYPE_APP_OTA_11 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 11,//!< OTA partition 11 - ESP_PARTITION_SUBTYPE_APP_OTA_12 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 12,//!< OTA partition 12 - ESP_PARTITION_SUBTYPE_APP_OTA_13 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 13,//!< OTA partition 13 - ESP_PARTITION_SUBTYPE_APP_OTA_14 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 14,//!< OTA partition 14 - ESP_PARTITION_SUBTYPE_APP_OTA_15 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 15,//!< OTA partition 15 - ESP_PARTITION_SUBTYPE_APP_OTA_MAX = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 16,//!< Max subtype of OTA partition - ESP_PARTITION_SUBTYPE_APP_TEST = 0x20, //!< Test application partition - - ESP_PARTITION_SUBTYPE_DATA_OTA = 0x00, //!< OTA selection partition - ESP_PARTITION_SUBTYPE_DATA_PHY = 0x01, //!< PHY init data partition - ESP_PARTITION_SUBTYPE_DATA_NVS = 0x02, //!< NVS partition - ESP_PARTITION_SUBTYPE_DATA_COREDUMP = 0x03, //!< COREDUMP partition - - ESP_PARTITION_SUBTYPE_DATA_ESPHTTPD = 0x80, //!< ESPHTTPD partition - ESP_PARTITION_SUBTYPE_DATA_FAT = 0x81, //!< FAT partition - ESP_PARTITION_SUBTYPE_DATA_SPIFFS = 0x82, //!< SPIFFS partition - - ESP_PARTITION_SUBTYPE_ANY = 0xff, //!< Used to search for partitions with any subtype -} esp_partition_subtype_t; - -/** - * @brief partition information structure - * - * This is not the format in flash, that format is esp_partition_info_t. - * - * However, this is the format used by this API. - */ -typedef struct { - esp_partition_type_t type; /*!< partition type (app/data) */ - esp_partition_subtype_t subtype; /*!< partition subtype */ - uint32_t address; /*!< starting address of the partition in flash */ - uint32_t size; /*!< size of the partition, in bytes */ - char label[17]; /*!< partition label, zero-terminated ASCII string */ - bool encrypted; /*!< flag is set to true if partition is encrypted */ - - int handle; /*!< simulator handle */ -} esp_partition_t; - -esp_err_t esp_partition_write(const esp_partition_t* partition, - size_t dst_offset, const void* src, size_t size); - -esp_err_t esp_partition_erase_range(const esp_partition_t* partition, - uint32_t start_addr, uint32_t size); - -esp_err_t esp_partition_read(const esp_partition_t* partition, - size_t src_offset, void* dst, size_t size); - -esp_partition_t esp_partition_create(uint32_t size, uint32_t start, int handle); - -int esp_flash_create(uint32_t size, uint32_t sector_size, uint32_t write_size); - -void esp_flash_delete(int handle); - -#if defined(__cplusplus) -} -#endif - diff --git a/components/spi_flash/sim/include/esp_spi_flash.h b/components/spi_flash/sim/include/esp_spi_flash.h deleted file mode 100644 index 9e0009d03..000000000 --- a/components/spi_flash/sim/include/esp_spi_flash.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#define CONFIG_WL_SECTOR_SIZE 4096 - -#define SPI_FLASH_SEC_SIZE CONFIG_WL_SECTOR_SIZE -#define SPI_FLASH_WRITE_SIZE 16 - diff --git a/components/spi_flash/sim/partition.cpp b/components/spi_flash/sim/partition.cpp deleted file mode 100644 index 3d2ec389f..000000000 --- a/components/spi_flash/sim/partition.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include - -#include "esp_partition.h" -#include "esp_spi_flash.h" -#include "Flash_Emulator.h" - -#define EMULATORS_MAX 8 - -static Flash_Emulator* emulators[EMULATORS_MAX]; - -int esp_flash_create(uint32_t size, uint32_t sector_size, uint32_t write_size) -{ - int handle = -1; - - for (int i = 0; i < EMULATORS_MAX; i++) { - if (emulators[i] == NULL) { - emulators[i] = new Flash_Emulator(size, sector_size, write_size); - handle = i; - break; - } - } - - assert(handle != -1); - - return handle; -} - -esp_partition_t esp_partition_create(uint32_t size, uint32_t start, int flash) -{ - esp_partition_t partition; - - // Fills partition with default values, and attaches the flash_emulator reference - // to the struct - partition.type = ESP_PARTITION_TYPE_DATA; - partition.subtype = ESP_PARTITION_SUBTYPE_ANY; - partition.address = start; - partition.size = size; - partition.handle = flash; - - return partition; -} - -void esp_flash_delete(int handle) -{ - delete emulators[handle]; - emulators[handle] = NULL; -} - -esp_err_t esp_partition_write(const esp_partition_t* partition, - size_t dst_offset, const void* src, size_t size) -{ - emulators[partition->handle]->write(dst_offset, src, size); - return ESP_OK; -} - -esp_err_t esp_partition_erase_range(const esp_partition_t* partition, - uint32_t start_addr, uint32_t size) -{ - emulators[partition->handle]->erase_range(start_addr, size); - return ESP_OK; -} - -esp_err_t esp_partition_read(const esp_partition_t* partition, - size_t src_offset, void* dst, size_t size) -{ - emulators[partition->handle]->read(src_offset, dst, size); - return ESP_OK; -} diff --git a/components/spi_flash/sim/sdkconfig.h b/components/spi_flash/sim/sdkconfig.h index 7b9637ef9..3f59c932d 100644 --- a/components/spi_flash/sim/sdkconfig.h +++ b/components/spi_flash/sim/sdkconfig.h @@ -1 +1,2 @@ -#pragma once \ No newline at end of file +#pragma once + diff --git a/components/spi_flash/sim/stubs/app_update/esp_ota_eps.c b/components/spi_flash/sim/stubs/app_update/esp_ota_eps.c new file mode 100644 index 000000000..59ed6245f --- /dev/null +++ b/components/spi_flash/sim/stubs/app_update/esp_ota_eps.c @@ -0,0 +1,13 @@ +#include "esp_ota_ops.h" +#include "esp_partition.h" + +const esp_partition_t* esp_ota_get_running_partition(void) +{ + // Return first instance of an app partition + const esp_partition_t* partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, + ESP_PARTITION_SUBTYPE_ANY, + NULL); + assert(partition != NULL); + + return partition; +} diff --git a/components/spi_flash/sim/stubs/freertos/include/freertos/FreeRTOS.h b/components/spi_flash/sim/stubs/freertos/include/freertos/FreeRTOS.h new file mode 100644 index 000000000..e0dd0a7e8 --- /dev/null +++ b/components/spi_flash/sim/stubs/freertos/include/freertos/FreeRTOS.h @@ -0,0 +1,8 @@ +#pragma once + +#include "projdefs.h" +#include "semphr.h" + +// Avoid redefinition compile error. Put here since this is included +// in flash_ops.c. +#define spi_flash_init() overriden_spi_flash_init() diff --git a/components/spi_flash/sim/stubs/freertos/include/freertos/projdefs.h b/components/spi_flash/sim/stubs/freertos/include/freertos/projdefs.h new file mode 100644 index 000000000..2ec0b5f10 --- /dev/null +++ b/components/spi_flash/sim/stubs/freertos/include/freertos/projdefs.h @@ -0,0 +1,11 @@ +#pragma once + +#if defined(__cplusplus) +extern "C" { +#endif + +#define pdTRUE 1 + +#if defined(__cplusplus) +} +#endif diff --git a/components/spi_flash/sim/stubs/freertos/include/freertos/semphr.h b/components/spi_flash/sim/stubs/freertos/include/freertos/semphr.h new file mode 100644 index 000000000..d49cafb99 --- /dev/null +++ b/components/spi_flash/sim/stubs/freertos/include/freertos/semphr.h @@ -0,0 +1,16 @@ +#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 diff --git a/components/spi_flash/sim/stubs/freertos/include/freertos/task.h b/components/spi_flash/sim/stubs/freertos/include/freertos/task.h new file mode 100644 index 000000000..7b9637ef9 --- /dev/null +++ b/components/spi_flash/sim/stubs/freertos/include/freertos/task.h @@ -0,0 +1 @@ +#pragma once \ No newline at end of file diff --git a/components/spi_flash/sim/stubs/log/include/esp_log.h b/components/spi_flash/sim/stubs/log/include/esp_log.h new file mode 100644 index 000000000..a9c238000 --- /dev/null +++ b/components/spi_flash/sim/stubs/log/include/esp_log.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include + +#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__); } + +// Assume that flash encryption is not enabled. Put here since in partition.c +// esp_log.h is included later than esp_flash_encrypt.h. +#define esp_flash_encryption_enabled() false + +#ifdef __cplusplus +} +#endif + diff --git a/components/spi_flash/sim/stubs/log/log.c b/components/spi_flash/sim/stubs/log/log.c new file mode 100644 index 000000000..5d606d357 --- /dev/null +++ b/components/spi_flash/sim/stubs/log/log.c @@ -0,0 +1,22 @@ +#include +#include +#include +#include + +#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; +} + diff --git a/components/spi_flash/sim/stubs/newlib/include/sys/lock.h b/components/spi_flash/sim/stubs/newlib/include/sys/lock.h new file mode 100644 index 000000000..2b5b9f59e --- /dev/null +++ b/components/spi_flash/sim/stubs/newlib/include/sys/lock.h @@ -0,0 +1,17 @@ +#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 + diff --git a/components/spi_flash/sim/stubs/newlib/lock.c b/components/spi_flash/sim/stubs/newlib/lock.c new file mode 100644 index 000000000..f221fdbda --- /dev/null +++ b/components/spi_flash/sim/stubs/newlib/lock.c @@ -0,0 +1,21 @@ +#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; +} diff --git a/components/spiffs/test_spiffs_host/Makefile b/components/spiffs/test_spiffs_host/Makefile index 730a7af50..db94ab96f 100644 --- a/components/spiffs/test_spiffs_host/Makefile +++ b/components/spiffs/test_spiffs_host/Makefile @@ -1,13 +1,18 @@ -TEST_PROGRAM=test_spiffs +COMPONENT=spiffs -TEST_PARTITION_SIM_DIR=$(IDF_PATH)/components/spi_flash/sim -TEST_PARTITION_SIM_LIB=libpartition_sim.a +TEST_PROGRAM=test_$(COMPONENT) + +#Expose as a library +COMPONENT_LIB=lib$(COMPONENT).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 all: $(TEST_PROGRAM) SOURCE_FILES = \ - main.cpp \ - test_spiffs.cpp \ ../spiffs_api.c \ $(addprefix ../spiffs/src/, \ spiffs_cache.c \ @@ -20,46 +25,59 @@ SOURCE_FILES = \ log/log.c \ ) +TEST_SOURCE_FILES = \ + test_spiffs.cpp \ + main.cpp \ + test_utils.c + INCLUDE_FLAGS = $(addprefix -I,\ . \ .. \ ../spiffs/src \ ../include \ $(addprefix ./stubs/, \ - esp32/include \ log/include \ freertos/include \ newlib/include \ vfs/include \ ) \ ../../esp32/include \ - $(TEST_PARTITION_SIM_DIR)/include \ + $(SPI_FLASH_DIR)/include \ ../../../tools/catch \ ) GCOV ?= gcov -CPPFLAGS += $(INCLUDE_FLAGS) -D CONFIG_LOG_DEFAULT_LEVEL -g +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)) -$(TEST_PARTITION_SIM_DIR)/$(TEST_PARTITION_SIM_LIB): force - $(MAKE) -C $(TEST_PARTITION_SIM_DIR) lib - -$(TEST_PROGRAM): $(OBJ_FILES) $(TEST_PARTITION_SIM_DIR)/$(TEST_PARTITION_SIM_LIB) - g++ $(LDFLAGS) -o $(TEST_PROGRAM) $(OBJ_FILES) -L$(TEST_PARTITION_SIM_DIR) -l:$(TEST_PARTITION_SIM_LIB) -L$(TEST_WL_DIR) -l:$(TEST_WL_LIB) +$(SPI_FLASH_SIM_DIR)/$(SPI_FLASH_LIB): force + $(MAKE) -C $(SPI_FLASH_SIM_DIR) lib force: +$(COMPONENT_LIB): $(OBJ_FILES) + $(AR) rcs $@ $^ + +lib: $(COMPONENT_LIB) + +partitions_table.bin: partitions_table.csv + python ../../partition_table/gen_esp32part.py --verify $< $@ + +$(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 + test: $(TEST_PROGRAM) ./$(TEST_PROGRAM) -COVERAGE_FILES = $(OBJ_FILES:.o=.gc*) $(OBJ_FILES:.o=.gc*) +COVERAGE_FILES = $(OBJ_FILES:.o=.gc*) $(TEST_OBJ_FILES:.o=.gc*) -$(COVERAGE_FILES): $(TEST_PROGRAM) lib +$(COVERAGE_FILES): test coverage.info: $(COVERAGE_FILES) find ../ -name "*.gcno" -exec $(GCOV) -r -pb {} + @@ -70,10 +88,10 @@ coverage_report: coverage.info @echo "Coverage report is in coverage_report/index.html" clean: - rm -f $(OBJ_FILES) $(TEST_PROGRAM) $(TEST_WL_LIB) - $(MAKE) -C $(TEST_PARTITION_SIM_DIR) clean + rm -f $(OBJ_FILES) $(TEST_OBJ_FILES) $(TEST_PROGRAM) $(COMPONENT_LIB) partitions_table.bin + $(MAKE) -C $(SPI_FLASH_SIM_DIR) clean rm -f $(COVERAGE_FILES) *.gcov rm -rf coverage_report/ rm -f coverage.info -.PHONY: clean all test +.PHONY: clean all test lib diff --git a/components/spiffs/test_spiffs_host/partitions_table.csv b/components/spiffs/test_spiffs_host/partitions_table.csv new file mode 100644 index 000000000..d02771b51 --- /dev/null +++ b/components/spiffs/test_spiffs_host/partitions_table.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags +# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild +nvs, data, nvs, 0x9000, 0x6000, +phy_init, data, phy, 0xf000, 0x1000, +factory, app, factory, 0x10000, 1M, +storage, data, spiffs, , 2M, diff --git a/components/spiffs/test_spiffs_host/sdkconfig.h b/components/spiffs/test_spiffs_host/sdkconfig.h index 7e0277fad..f798d5ebc 100644 --- a/components/spiffs/test_spiffs_host/sdkconfig.h +++ b/components/spiffs/test_spiffs_host/sdkconfig.h @@ -11,4 +11,4 @@ #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_WL_SECTOR_SIZE 4096 diff --git a/components/spiffs/test_spiffs_host/stubs/esp32/include/rom/spi_flash.h b/components/spiffs/test_spiffs_host/stubs/esp32/include/rom/spi_flash.h deleted file mode 100644 index ce8e2f87b..000000000 --- a/components/spiffs/test_spiffs_host/stubs/esp32/include/rom/spi_flash.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include -#include - -#if defined(__cplusplus) -extern "C" { -#endif - -typedef struct { - uint32_t device_id; - uint32_t chip_size; // chip size in bytes - uint32_t block_size; - uint32_t sector_size; - uint32_t page_size; - uint32_t status_mask; -} esp_rom_spiflash_chip_t; - -extern esp_rom_spiflash_chip_t g_rom_flashchip; - -#if defined(__cplusplus) -} -#endif \ No newline at end of file diff --git a/components/spiffs/test_spiffs_host/test_spiffs.cpp b/components/spiffs/test_spiffs_host/test_spiffs.cpp index 961a6c881..d4a76210e 100644 --- a/components/spiffs/test_spiffs_host/test_spiffs.cpp +++ b/components/spiffs/test_spiffs_host/test_spiffs.cpp @@ -9,19 +9,20 @@ #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); + TEST_CASE("format disk, open file, write and read file", "[spiffs]") { - uint32_t size = 0x00400000; - - int flash_handle = esp_flash_create(size, CONFIG_WL_SECTOR_SIZE, 1); - esp_partition_t partition = esp_partition_create(size, 0, flash_handle); + init_spi_flash(0x00400000, CONFIG_WL_SECTOR_SIZE * 16, CONFIG_WL_SECTOR_SIZE, CONFIG_WL_SECTOR_SIZE, "partitions_table.bin"); spiffs fs; spiffs_config cfg; + const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_SPIFFS, "storage"); + // Configure objects needed by SPIFFS esp_spiffs_t esp_user_data; - esp_user_data.partition = &partition; + esp_user_data.partition = partition; fs.user_data = (void*)&esp_user_data; cfg.hal_erase_f = spiffs_api_erase; @@ -31,7 +32,7 @@ TEST_CASE("format disk, open file, write and read file", "[spiffs]") cfg.log_page_size = CONFIG_SPIFFS_PAGE_SIZE; cfg.phys_addr = 0; cfg.phys_erase_block = CONFIG_WL_SECTOR_SIZE; - cfg.phys_size = partition.size; + cfg.phys_size = partition->size; uint32_t max_files = 5; @@ -63,34 +64,44 @@ TEST_CASE("format disk, open file, write and read file", "[spiffs]") spiffs_res = SPIFFS_open(&fs, "test.txt", SPIFFS_O_CREAT | SPIFFS_O_RDWR, 0); REQUIRE(spiffs_res >= SPIFFS_OK); - // Write to the test file + // Generate data spiffs_file file = spiffs_res; - const char data[] = "Hello, World!"; - char *read = (char*) malloc(sizeof(data)); + uint32_t data_size = 100000; + + char *data = (char*) malloc(data_size); + char *read = (char*) malloc(data_size); + + for(uint32_t i = 0; i < data_size; i += sizeof(i)) + { + *((uint32_t*)(data + i)) = i; + } s32_t bw; - spiffs_res = SPIFFS_write(&fs, file, (void*)data, sizeof(data)); + // Write data to file + spiffs_res = SPIFFS_write(&fs, file, (void*)data, data_size); REQUIRE(spiffs_res >= SPIFFS_OK); - REQUIRE(spiffs_res == sizeof(data)); + REQUIRE(spiffs_res == data_size); // Set the file object pointer to the beginning spiffs_res = SPIFFS_lseek(&fs, file, 0, SPIFFS_SEEK_SET); REQUIRE(spiffs_res >= SPIFFS_OK); - // Set the file object pointer to the beginning - spiffs_res = SPIFFS_read(&fs, file, (void*)read, sizeof(data)); + // Read the file + spiffs_res = SPIFFS_read(&fs, file, (void*)read, data_size); REQUIRE(spiffs_res >= SPIFFS_OK); - REQUIRE(spiffs_res == sizeof(data)); + REQUIRE(spiffs_res == data_size); // Close the test file spiffs_res = SPIFFS_close(&fs, file); REQUIRE(spiffs_res >= SPIFFS_OK); + REQUIRE(memcmp(data, read, data_size) == 0); + // Unmount SPIFFS_unmount(&fs); - esp_flash_delete(flash_handle); free(read); -} \ No newline at end of file + free(data); +} diff --git a/components/spiffs/test_spiffs_host/test_utils.c b/components/spiffs/test_spiffs_host/test_utils.c new file mode 100644 index 000000000..c3181ede7 --- /dev/null +++ b/components/spiffs/test_spiffs_host/test_utils.c @@ -0,0 +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) +{ + spi_flash_init(chip_size, block_size, sector_size, page_size, partition_bin); +} \ No newline at end of file diff --git a/components/wear_levelling/doc/wl_sw_structure.rst b/components/wear_levelling/doc/wl_sw_structure.rst index ee897489b..e1579dbf9 100644 --- a/components/wear_levelling/doc/wl_sw_structure.rst +++ b/components/wear_levelling/doc/wl_sw_structure.rst @@ -10,10 +10,9 @@ The WLC Files ^^^^^^^^^^^^^^^ The WLC consist of few components that are implemented in different files. The list and brief description of these components written below. - - Flash_Access - memory access interface. Used to access the memory. A classes WL_Flash, Partition, SPI_Flash, Flash_Emulator are implements this interface. + - Flash_Access - memory access interface. Used to access the memory. A classes WL_Flash, Partition, SPI_Flash are implements this interface. - SPI_Flash - class implements the Flash_Access interface to provide access to the flash memory. - Partition - class implements the Flash_Access interface to provide access to the partition. - - Flash_Emulator - class implements the Flash_Access interface to provide test functionality for WLC testing. - WL_Flash - the main class that implements wear levelling functionality. - WL_State - contains state structure of the WLC. - WL_Config - contains structure to configure the WLC component at startup. diff --git a/components/wear_levelling/test_wl_host/Makefile b/components/wear_levelling/test_wl_host/Makefile index dc36a97c1..99de29942 100644 --- a/components/wear_levelling/test_wl_host/Makefile +++ b/components/wear_levelling/test_wl_host/Makefile @@ -1,30 +1,35 @@ -TEST_PROGRAM=test_wl +COMPONENT=wear_levelling + +TEST_PROGRAM=test_$(COMPONENT) # Expose as a library for FS components that require wear_levelling -TEST_LIB=lib$(TEST_PROGRAM).a +COMPONENT_LIB=lib$(COMPONENT).a # Use simulated block device -TEST_PARTITION_SIM_DIR=$(IDF_PATH)/components/spi_flash/sim -TEST_PARTITION_SIM_LIB=libpartition_sim.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 all: $(TEST_PROGRAM) -LIB_SOURCE_FILES = \ - $(addprefix stubs/, \ - newlib/lock.c \ - log/log.c \ - esp32/crc.cpp \ - ) \ +SOURCE_FILES = \ $(addprefix ../, \ wear_levelling.cpp \ crc32.cpp \ WL_Flash.cpp \ Partition.cpp \ ) \ + $(addprefix stubs/, \ + newlib/lock.c \ + log/log.c \ + esp32/crc.cpp \ + ) TEST_SOURCE_FILES = \ test_wl.cpp \ - main.cpp + main.cpp \ + test_utils.c INCLUDE_FLAGS = $(addprefix -I,\ . \ @@ -32,47 +37,49 @@ INCLUDE_FLAGS = $(addprefix -I,\ ../include \ ../private_include \ $(addprefix stubs/, \ - esp32/include \ newlib/include \ log/include \ ) \ + $(SPI_FLASH_DIR)/include \ ../../esp32/include \ - ../../spi_flash/sim/include \ ../../../tools/catch \ ) GCOV ?= gcov -CPPFLAGS += $(INCLUDE_FLAGS) -D CONFIG_LOG_DEFAULT_LEVEL -g +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 -LIB_OBJ_FILES = $(filter %.o, $(LIB_SOURCE_FILES:.cpp=.o) $(LIB_SOURCE_FILES:.c=.o)) +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)) -$(TEST_PARTITION_SIM_DIR)/$(TEST_PARTITION_SIM_LIB): force - $(MAKE) -C $(TEST_PARTITION_SIM_DIR) lib +$(SPI_FLASH_SIM_DIR)/$(SPI_FLASH_LIB): force + $(MAKE) -C $(SPI_FLASH_SIM_DIR) lib -$(TEST_LIB): $(LIB_OBJ_FILES) +$(COMPONENT_LIB): $(OBJ_FILES) $(AR) rcs $@ $^ -lib: $(TEST_LIB) - -$(TEST_PROGRAM): lib $(TEST_OBJ_FILES) $(TEST_PARTITION_SIM_DIR)/$(TEST_PARTITION_SIM_LIB) - g++ $(LDFLAGS) -o $@ $(TEST_OBJ_FILES) -L$(abspath .) -l:$(TEST_LIB) -L$(TEST_PARTITION_SIM_DIR) -l:$(TEST_PARTITION_SIM_LIB) - force: +lib: $(COMPONENT_LIB) + +partition_table.bin: partition_table.csv + python ../../../components/partition_table/gen_esp32part.py --verify $< $@ + +$(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 + test: $(TEST_PROGRAM) ./$(TEST_PROGRAM) $(OUTPUT_DIR): mkdir -p $(OUTPUT_DIR) -COVERAGE_FILES = $(LIB_OBJ_FILES:.o=.gc*) $(TEST_OBJ_FILES:.o=.gc*) +COVERAGE_FILES = $(OBJ_FILES:.o=.gc*) $(TEST_OBJ_FILES:.o=.gc*) -$(COVERAGE_FILES): $(TEST_PROGRAM) test +$(COVERAGE_FILES): test coverage.info: $(COVERAGE_FILES) find ../ -name "*.gcno" -exec $(GCOV) -r -pb {} + @@ -83,8 +90,8 @@ coverage_report: coverage.info @echo "Coverage report is in coverage_report/index.html" clean: - $(MAKE) -C $(TEST_PARTITION_SIM_DIR) clean - rm -f $(LIB_OBJ_FILES) $(TEST_OBJ_FILES) $(TEST_PROGRAM) $(TEST_LIB) + $(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 diff --git a/components/wear_levelling/test_wl_host/main.cpp b/components/wear_levelling/test_wl_host/main.cpp index 0c7c351f4..063e87874 100644 --- a/components/wear_levelling/test_wl_host/main.cpp +++ b/components/wear_levelling/test_wl_host/main.cpp @@ -1,2 +1,2 @@ #define CATCH_CONFIG_MAIN -#include "catch.hpp" +#include "catch.hpp" \ No newline at end of file diff --git a/components/wear_levelling/test_wl_host/partition_table.csv b/components/wear_levelling/test_wl_host/partition_table.csv new file mode 100644 index 000000000..cb7fccd87 --- /dev/null +++ b/components/wear_levelling/test_wl_host/partition_table.csv @@ -0,0 +1,6 @@ +# Name, Type, SubType, Offset, Size, Flags +# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild +nvs, data, nvs, 0x9000, 0x6000, +phy_init, data, phy, 0xf000, 0x1000, +factory, app, factory, 0x10000, 1M, +storage, data, fat, , 1M, \ No newline at end of file diff --git a/components/wear_levelling/test_wl_host/sdkconfig.h b/components/wear_levelling/test_wl_host/sdkconfig.h index 3f59c932d..3085b06d8 100644 --- a/components/wear_levelling/test_wl_host/sdkconfig.h +++ b/components/wear_levelling/test_wl_host/sdkconfig.h @@ -1,2 +1,3 @@ #pragma once +#define CONFIG_WL_SECTOR_SIZE 4096 \ No newline at end of file diff --git a/components/wear_levelling/test_wl_host/stubs/esp32/crc.cpp b/components/wear_levelling/test_wl_host/stubs/esp32/crc.cpp index 9e2473560..4cbb9be9e 100644 --- a/components/wear_levelling/test_wl_host/stubs/esp32/crc.cpp +++ b/components/wear_levelling/test_wl_host/stubs/esp32/crc.cpp @@ -1,8 +1,19 @@ +// 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. #include #include -#include "rom/crc.h" - static const unsigned int crc32_le_table[256] = { 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, @@ -20,7 +31,7 @@ static const unsigned int crc32_le_table[256] = { 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, - + 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, @@ -39,7 +50,9 @@ static const unsigned int crc32_le_table[256] = { 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL }; -extern "C" unsigned int crc32_le(uint32_t crc, const uint8_t* buf, size_t len) + + +extern "C" unsigned int crc32_le(unsigned int crc, unsigned char const * buf,unsigned int len) { unsigned int i; crc = ~crc; @@ -47,4 +60,5 @@ extern "C" unsigned int crc32_le(uint32_t crc, const uint8_t* buf, size_t len) crc = crc32_le_table[(crc^buf[i])&0xff]^(crc>>8); } return ~crc; -} \ No newline at end of file +} + diff --git a/components/wear_levelling/test_wl_host/stubs/esp32/include/rom/crc.h b/components/wear_levelling/test_wl_host/stubs/esp32/include/rom/crc.h deleted file mode 100644 index 41364ee5a..000000000 --- a/components/wear_levelling/test_wl_host/stubs/esp32/include/rom/crc.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -uint32_t crc32_le(uint32_t crc, const uint8_t* buf, size_t len); - -#ifdef __cplusplus -} -#endif - diff --git a/components/wear_levelling/test_wl_host/stubs/esp32/include/rom/spi_flash.h b/components/wear_levelling/test_wl_host/stubs/esp32/include/rom/spi_flash.h deleted file mode 100644 index b9c14ef01..000000000 --- a/components/wear_levelling/test_wl_host/stubs/esp32/include/rom/spi_flash.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include -#include - -typedef struct { - uint32_t device_id; - uint32_t chip_size; // chip size in bytes - uint32_t block_size; - uint32_t sector_size; - uint32_t page_size; - uint32_t status_mask; -} esp_rom_spiflash_chip_t; diff --git a/components/wear_levelling/test_wl_host/stubs/log/log.c b/components/wear_levelling/test_wl_host/stubs/log/log.c index 5d606d357..0cacb3ac7 100644 --- a/components/wear_levelling/test_wl_host/stubs/log/log.c +++ b/components/wear_levelling/test_wl_host/stubs/log/log.c @@ -18,5 +18,4 @@ void esp_log_write(esp_log_level_t level, uint32_t esp_log_timestamp() { return 0; -} - +} \ No newline at end of file diff --git a/components/wear_levelling/test_wl_host/stubs/newlib/include/sys/lock.h b/components/wear_levelling/test_wl_host/stubs/newlib/include/sys/lock.h index 2b5b9f59e..b244c9127 100644 --- a/components/wear_levelling/test_wl_host/stubs/newlib/include/sys/lock.h +++ b/components/wear_levelling/test_wl_host/stubs/newlib/include/sys/lock.h @@ -13,5 +13,4 @@ void _lock_release(_lock_t *lock); #ifdef __cplusplus } -#endif - +#endif \ No newline at end of file diff --git a/components/wear_levelling/test_wl_host/stubs/newlib/lock.c b/components/wear_levelling/test_wl_host/stubs/newlib/lock.c index f221fdbda..d13b6eaac 100644 --- a/components/wear_levelling/test_wl_host/stubs/newlib/lock.c +++ b/components/wear_levelling/test_wl_host/stubs/newlib/lock.c @@ -18,4 +18,4 @@ void _lock_init(_lock_t *lock) void _lock_release(_lock_t *lock) { return; -} +} \ No newline at end of file diff --git a/components/wear_levelling/test_wl_host/test_utils.c b/components/wear_levelling/test_wl_host/test_utils.c new file mode 100644 index 000000000..c3181ede7 --- /dev/null +++ b/components/wear_levelling/test_wl_host/test_utils.c @@ -0,0 +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) +{ + spi_flash_init(chip_size, block_size, sector_size, page_size, partition_bin); +} \ No newline at end of file diff --git a/components/wear_levelling/test_wl_host/test_wl.cpp b/components/wear_levelling/test_wl_host/test_wl.cpp index 019197a58..4b467e9d5 100644 --- a/components/wear_levelling/test_wl_host/test_wl.cpp +++ b/components/wear_levelling/test_wl_host/test_wl.cpp @@ -1,35 +1,27 @@ -// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. #include #include #include +#include "esp_spi_flash.h" #include "esp_partition.h" #include "wear_levelling.h" #include "WL_Flash.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); 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"); + esp_err_t result; wl_handle_t wl_handle; - int flash_handle = esp_flash_create(PARTITION_SIZE, 4096, 16); - esp_partition_t partition = esp_partition_create(PARTITION_SIZE, PARTITION_START, flash_handle); + int flash_handle; + const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, "storage"); // Mount wear-levelled partition result = wl_mount(partition, &wl_handle);