From e542b7a9208d410c9cba3fe71fbc0f5f2f6c3064 Mon Sep 17 00:00:00 2001 From: Renz Bagaporo Date: Tue, 22 May 2018 16:47:30 +0800 Subject: [PATCH] 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 76d75930de..abd95553b5 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 2c34da4f71..d89ea20d9a 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 5dc69a8bb4..e6e51178cd 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 f2904e7898..826c405248 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 9e9e69c38f..3d2ec389f9 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 70f96dfd49..f245a57e10 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 d5fb180038..96233c6f9d 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 0000000000..6dd3db9637 --- /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 0000000000..492da7cde7 --- /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 0000000000..730a7af50a --- /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 0000000000..178916eab8 --- /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 0000000000..7e0277fad4 --- /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 0000000000..ce8e2f87bd --- /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 0000000000..5bafa772df --- /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 0000000000..aa8c7a3de5 --- /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 0000000000..c589795fbe --- /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 0000000000..7b9637ef9c --- /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 0000000000..84756cdb93 --- /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 0000000000..d01a96ff45 --- /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 0000000000..7892465ada --- /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 0000000000..697615ffd9 --- /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 0000000000..36c6384a3e --- /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 0000000000..961a6c8816 --- /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 b2ed120b3f..019197a58c 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 +}