]> granicus.if.org Git - esp-idf/commitdiff
spiffs: Make spiffs runnable on host
authorRenz Bagaporo <renz@espressif.com>
Tue, 22 May 2018 08:47:30 +0000 (16:47 +0800)
committerbot <bot@espressif.com>
Wed, 6 Jun 2018 17:35:30 +0000 (17:35 +0000)
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.

24 files changed:
components/fatfs/test_fatfs_host/Makefile
components/fatfs/test_fatfs_host/test_fatfs.cpp
components/spi_flash/sim/Flash_Emulator.cpp
components/spi_flash/sim/include/esp_partition.h
components/spi_flash/sim/partition.cpp
components/spiffs/component.mk
components/spiffs/esp_spiffs.c
components/spiffs/spiffs_api.c [new file with mode: 0644]
components/spiffs/spiffs_api.h [new file with mode: 0644]
components/spiffs/test_spiffs_host/Makefile [new file with mode: 0644]
components/spiffs/test_spiffs_host/main.cpp [new file with mode: 0644]
components/spiffs/test_spiffs_host/sdkconfig.h [new file with mode: 0644]
components/spiffs/test_spiffs_host/stubs/esp32/include/rom/spi_flash.h [new file with mode: 0644]
components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/FreeRTOS.h [new file with mode: 0644]
components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/projdefs.h [new file with mode: 0644]
components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/semphr.h [new file with mode: 0644]
components/spiffs/test_spiffs_host/stubs/freertos/include/freertos/task.h [new file with mode: 0644]
components/spiffs/test_spiffs_host/stubs/log/include/esp_log.h [new file with mode: 0644]
components/spiffs/test_spiffs_host/stubs/log/log.c [new file with mode: 0644]
components/spiffs/test_spiffs_host/stubs/newlib/include/sys/lock.h [new file with mode: 0644]
components/spiffs/test_spiffs_host/stubs/newlib/lock.c [new file with mode: 0644]
components/spiffs/test_spiffs_host/stubs/vfs/include/esp_vfs.h [new file with mode: 0644]
components/spiffs/test_spiffs_host/test_spiffs.cpp [new file with mode: 0644]
components/wear_levelling/test_wl_host/test_wl.cpp

index 76d75930de1a10186273115def0aa653bfee0c26..abd95553b559edee42d4cdd1a51c254c9a354945 100644 (file)
@@ -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
index 2c34da4f71f6f1cea0f6795a9ac548475cc9588a..d89ea20d9a35be2438bbbd88412e2c06630725bb 100644 (file)
@@ -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
+}
index 5dc69a8bb4e75ce0f6eae7434daf93268ee107c4..e6e51178cd2c0d79013bde74f3af66b7bd8f0960 100644 (file)
@@ -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);\r
     this->access_count = new uint32_t[this->size / this->sector_sise];\r
     memset(this->access_count, 0, this->size / this->sector_sise * sizeof(uint32_t));\r
+    memset(this->buff, 1, this->size);\r
 }\r
 \r
 size_t Flash_Emulator::chip_size()\r
index f2904e7898c4c71498b941d10bfee5363c58ce31..826c405248423ca3434909c22b419a616bcd5fbc 100644 (file)
@@ -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)
 }
index 9e9e69c38f34d2406fb358d37418b33bbaeac2dc..3d2ec389f92541802cf71e2433506f1acd1502ce 100644 (file)
@@ -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
+}
index 70f96dfd4964ec615e1aaac153cd5be8e1dc3674..f245a57e10298a965e919c574560bc33d408d69f 100644 (file)
@@ -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
index d5fb18003813bfc564cc6d411d14dada984440ae..96233c6f9d6db5b23182f52145b80cff874c95a8 100644 (file)
 #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 (file)
index 0000000..6dd3db9
--- /dev/null
@@ -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 (file)
index 0000000..492da7c
--- /dev/null
@@ -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 <stdint.h>
+#include <stddef.h>
+#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 (file)
index 0000000..730a7af
--- /dev/null
@@ -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 (file)
index 0000000..178916e
--- /dev/null
@@ -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 (file)
index 0000000..7e0277f
--- /dev/null
@@ -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 (file)
index 0000000..ce8e2f8
--- /dev/null
@@ -0,0 +1,23 @@
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#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 (file)
index 0000000..5bafa77
--- /dev/null
@@ -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 (file)
index 0000000..aa8c7a3
--- /dev/null
@@ -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 (file)
index 0000000..c589795
--- /dev/null
@@ -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 (file)
index 0000000..7b9637e
--- /dev/null
@@ -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 (file)
index 0000000..84756cd
--- /dev/null
@@ -0,0 +1,51 @@
+#pragma once
+
+#include <stdint.h>
+#include <stdio.h>
+
+#include "sdkconfig.h"
+
+#define strlcpy(a, b, c)
+#define strlcat(a, b, c)
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define LOG_LOCAL_LEVEL     ESP_LOG_DEBUG
+
+typedef enum {
+    ESP_LOG_NONE,       /*!< No log output */
+    ESP_LOG_ERROR,      /*!< Critical errors, software module can not recover on its own */
+    ESP_LOG_WARN,       /*!< Error conditions from which recovery measures have been taken */
+    ESP_LOG_INFO,       /*!< Information messages which describe normal flow of events */
+    ESP_LOG_DEBUG,      /*!< Extra information which is not necessary for normal use (values, pointers, sizes, etc). */
+    ESP_LOG_VERBOSE     /*!< Bigger chunks of debugging information, or frequent messages which can potentially flood the output. */
+} esp_log_level_t;
+
+#define LOG_COLOR_E
+#define LOG_COLOR_W
+#define LOG_COLOR_I
+#define LOG_COLOR_D
+#define LOG_COLOR_V
+#define LOG_RESET_COLOR
+
+#undef _Static_assert
+#define _Static_assert(cond, message)
+
+uint32_t esp_log_timestamp(void);
+void esp_log_write(esp_log_level_t level, const char* tag, const char* format, ...) __attribute__ ((format (printf, 3, 4)));
+
+#define LOG_FORMAT(letter, format)  LOG_COLOR_ ## letter #letter " (%d) %s: " format LOG_RESET_COLOR "\n"
+
+#define ESP_LOGE( tag, format, ... )  if (LOG_LOCAL_LEVEL >= ESP_LOG_ERROR)   { esp_log_write(ESP_LOG_ERROR,   tag, LOG_FORMAT(E, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
+
+#define ESP_LOGV( tag, format, ... )  if (LOG_LOCAL_LEVEL >= ESP_LOG_VERBOSE) { esp_log_write(ESP_LOG_VERBOSE, tag, LOG_FORMAT(V, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
+
+#define ESP_LOGD( tag, format, ... )  if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG)   { esp_log_write(ESP_LOG_DEBUG,   tag, LOG_FORMAT(D, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
+
+#define ESP_LOGW( tag, format, ... )  if (LOG_LOCAL_LEVEL >= ESP_LOG_WARN)    { esp_log_write(ESP_LOG_WARN,    tag, LOG_FORMAT(W, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
+
+#if defined(__cplusplus)
+}
+#endif
\ 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 (file)
index 0000000..d01a96f
--- /dev/null
@@ -0,0 +1,22 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "esp_log.h"
+
+void esp_log_write(esp_log_level_t level,
+                   const char *tag,
+                   const char *format, ...)
+{
+    va_list arg;
+    va_start(arg, format);
+    vprintf(format, arg);
+    va_end(arg);
+}
+
+uint32_t esp_log_timestamp()
+{
+    return 0;
+}
+
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 (file)
index 0000000..7892465
--- /dev/null
@@ -0,0 +1,10 @@
+#pragma once
+
+#include <time.h>
+
+typedef int _lock_t;
+
+void _lock_acquire(_lock_t *lock);
+void _lock_close(_lock_t *lock);
+void _lock_init(_lock_t *lock);
+void _lock_release(_lock_t *lock);
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 (file)
index 0000000..697615f
--- /dev/null
@@ -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 (file)
index 0000000..36c6384
--- /dev/null
@@ -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 (file)
index 0000000..961a6c8
--- /dev/null
@@ -0,0 +1,96 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#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
index b2ed120b3fed4b4077e338109b5c0384d6aca525..019197a58c43608c25a7819bb8d4dee4f03659aa 100644 (file)
@@ -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
+}