From 3d313dc978dc7e3d48077d80a0a63c65c9edf270 Mon Sep 17 00:00:00 2001 From: fvanroie Date: Sun, 10 May 2020 15:11:44 +0200 Subject: [PATCH] Add STM32Spiffs --- include/hasp_conf.h | 15 +- lib/STM32Spiffs/src/STM32Spiffs.cpp | 207 ++++++++++ lib/STM32Spiffs/src/STM32Spiffs.h | 180 ++++++++ lib/STM32Spiffs/src/params_test.h | 93 +++++ lib/STM32Spiffs/src/spiffs_config.h | 383 ++++++++++++++++++ platformio.ini | 10 + src/hasp.cpp | 2 +- src/hasp_config.cpp | 22 +- src/hasp_gui.cpp | 19 +- src/hasp_http.cpp | 22 +- src/hasp_spiffs.cpp | 12 +- .../stm32f4xx/stm32f407-black_ili9341.ini | 8 +- .../stm32f4xx/stm32f407-devebox_ili9341.ini | 17 +- 13 files changed, 943 insertions(+), 47 deletions(-) create mode 100644 lib/STM32Spiffs/src/STM32Spiffs.cpp create mode 100644 lib/STM32Spiffs/src/STM32Spiffs.h create mode 100644 lib/STM32Spiffs/src/params_test.h create mode 100644 lib/STM32Spiffs/src/spiffs_config.h diff --git a/include/hasp_conf.h b/include/hasp_conf.h index 28260cbd..f8d2e79f 100644 --- a/include/hasp_conf.h +++ b/include/hasp_conf.h @@ -46,7 +46,7 @@ #define HASP_HAS_FILESYSTEM (ARDUINO_ARCH_ESP32 > 0 || ARDUINO_ARCH_ESP8266 > 0) #ifndef HASP_USE_SPIFFS -#define HASP_USE_SPIFFS (HASP_HAS_FILESYSTEM) +#define HASP_USE_SPIFFS 1 //(HASP_HAS_FILESYSTEM) #endif #ifndef HASP_USE_EEPROM @@ -87,15 +87,26 @@ /* Includes */ #if HASP_USE_SPIFFS > 0 + +#if defined(STM32F4xx) +#include "STM32Spiffs.h" // Include the SPIFFS library +#endif + #if defined(ARDUINO_ARCH_ESP32) #include "SPIFFS.h" -#endif #include // Include the SPIFFS library +#endif + +#if defined(ARDUINO_ARCH_ESP8266) +#include // Include the SPIFFS library +#endif + #include "hasp_spiffs.h" #if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) //#include "lv_zifont.h" #endif + #endif // SPIFFS #if HASP_USE_EEPROM > 0 diff --git a/lib/STM32Spiffs/src/STM32Spiffs.cpp b/lib/STM32Spiffs/src/STM32Spiffs.cpp new file mode 100644 index 00000000..0ee82cdb --- /dev/null +++ b/lib/STM32Spiffs/src/STM32Spiffs.cpp @@ -0,0 +1,207 @@ +/* + FS.cpp - file system wrapper + Copyright (c) 2015 Ivan Grokhotkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include "spiffs.h" +#include "STM32Spiffs.h" + +namespace SpiffsLib +{ + +File::File(spiffs_file f, spiffs *fs) +{ + _file = f; + _fs = fs; +} + +File::File(void) +{ + _file = 0; + _fs = nullptr; +} + +int File::read() +{ + u8_t ch; + SPIFFS_read(_fs, _file, (u8_t *)&ch, 1); + return ch; +} +int File::peek() { return 0; } +int File::availableForWrite() { return 0; } +int File::available() { return 0; } +int File::read(void *buf, uint16_t nbyte) +{ + return SPIFFS_read(_fs, _file, (u8_t *)buf, nbyte); +} + +bool File::seek(uint32_t pos) +{ + return SPIFFS_lseek(_fs, _file, pos, SPIFFS_SEEK_SET) >= 0; +} + +uint32_t File::position() +{ + return SPIFFS_tell(_fs, _file); +} + +void File::flush() +{ + SPIFFS_fflush(_fs, _file); +} + +size_t File::write(uint8_t ch) +{ + int res = SPIFFS_write(_fs, _file, (u8_t *)&ch, 1); + return res; +} +size_t File::write(const uint8_t *buf, size_t size) +{ + int res = SPIFFS_write(_fs, _file, (u8_t *)buf, size); + return res; +} + +void File::close() +{ + SPIFFS_close(_fs, _file); +} + +File::~File(void) +{ + Serial.print("File destructor called!"); +} + +SPIFlash *SpiffsClass::flash; +spiffs SpiffsClass::my_fs; +u8_t SpiffsClass::spiffs_work_buf[LOG_PAGE_SIZE * 2]; +u8_t SpiffsClass::spiffs_fds[32 * 4]; +u8_t SpiffsClass::spiffs_cache_buf[(LOG_PAGE_SIZE + 32) * 4]; + +s32_t SpiffsClass::my_spiffs_read(u32_t addr, u32_t size, u8_t *dst) +{ + flash->readByteArray(addr, dst, size); + // Serial.print("Reading "); + // Serial.println(*dst); + return SPIFFS_OK; +} + +s32_t SpiffsClass::my_spiffs_write(u32_t addr, u32_t size, u8_t *src) +{ + flash->writeByteArray(addr, src, size); + Serial.print("Writing "); + Serial.println(size); + return SPIFFS_OK; +} + +s32_t SpiffsClass::my_spiffs_erase(u32_t addr, u32_t size) +{ + flash->eraseSection(addr, size); + Serial.print("Erasing "); + Serial.print(addr, HEX); + Serial.print(" - "); + Serial.println(size); + return SPIFFS_OK; +} + +int SpiffsClass::mount() +{ + spiffs_config cfg; +#if SPIFFS_SINGLETON == 0 + cfg.phys_size = flash->GetCapacity(); // use all spi flash + cfg.phys_addr = 0; // start spiffs at start of spi flash + cfg.phys_erase_block = 65536; // according to datasheet + cfg.log_block_size = 65536; // let us not complicate things + cfg.log_page_size = LOG_PAGE_SIZE; // as we said +#endif + + cfg.hal_read_f = my_spiffs_read; + cfg.hal_write_f = my_spiffs_write; + cfg.hal_erase_f = my_spiffs_erase; + + int res = SPIFFS_mount(&my_fs, + &cfg, + spiffs_work_buf, + spiffs_fds, + sizeof(spiffs_fds), + spiffs_cache_buf, + sizeof(spiffs_cache_buf), + 0); + Serial.print("mount result: "); + Serial.println(res); + + return res; +} + +bool SpiffsClass::begin(uint8_t cs) +{ + if (!flash) + { + flash = new SPIFlash(cs); + } + flash->begin(); + + Serial.println(F("Mount Spiffs")); + int res = mount(); + Serial.println(res); + + if (res == SPIFFS_ERR_NOT_A_FS) + { + Serial.println(F("**************** Spiffs Format ******************")); + res = SPIFFS_format(&my_fs); + Serial.println(res); + + Serial.println(F("Mount Spiffs again")); + res = mount(); + Serial.println(res); + } + return res == SPIFFS_OK; +} + +File SpiffsClass::open(const char *filename, uint8_t mode) +{ + spiffs_file fh = SPIFFS_open(&my_fs, filename, mode, 0); + File f(fh, &my_fs); + return f; +}; + +bool SpiffsClass::exists(const char *filepath) +{ + spiffs_DIR d; + struct spiffs_dirent e; + struct spiffs_dirent *pe = &e; + int res; + + spiffs_file fd = -1; + + SPIFFS_opendir(&my_fs, "/", &d); + while ((pe = SPIFFS_readdir(&d, pe))) + { + if (0 == strncmp(filepath, (char *)pe->name, strlen(filepath))) + { + return true; + } + } + SPIFFS_closedir(&d); + + return false; +} + +bool SpiffsClass::rename(const char *oldPath, const char *newPath) +{ + return SPIFFS_rename(&my_fs, oldPath, newPath) == SPIFFS_OK; +} + +} // namespace SpiffsLib \ No newline at end of file diff --git a/lib/STM32Spiffs/src/STM32Spiffs.h b/lib/STM32Spiffs/src/STM32Spiffs.h new file mode 100644 index 00000000..b3415d29 --- /dev/null +++ b/lib/STM32Spiffs/src/STM32Spiffs.h @@ -0,0 +1,180 @@ +#ifndef STM32SPIFFS_H +#define STM32SPIFFS_H + +#define FLASH_CHIP_SELECT_PIN PA15 + +// these are declared in params_test.h +// typedef signed int32_t s32_t; +// typedef unsigned int u32_t; +// typedef signed short s16_t; +// typedef unsigned short u16_t; +// typedef signed char s8_t; +// typedef unsigned char u8_t; + +#include +#include +#include "SPIMemory.h" +#include "spiffs.h" + +//#define FILE_READ "r" +//#define FILE_WRITE "w" +//#define FILE_APPEND "a" + +#define FILE_READ (SPIFFS_CREAT | SPIFFS_RDONLY ) +#define FILE_WRITE (SPIFFS_CREAT | SPIFFS_RDWR | SPIFFS_TRUNC) +#define FILE_APPEND (SPIFFS_CREAT | SPIFFS_RDWR | SPIFFS_APPEND) + +namespace SpiffsLib +{ + +class File : public Stream +{ +private: + spiffs_file _file; // file handle + spiffs *_fs; // file system + +public: + File(spiffs_file f, spiffs *fs); // wraps an underlying spiffs_file + File(void); // 'empty' constructor + ~File(); + size_t write(uint8_t); + size_t write(const uint8_t *buf, size_t size); + int availableForWrite(); + int available(); + int read(); + int peek(); + void flush(); + int read(void *buf, uint16_t nbyte); + bool seek(uint32_t pos); + uint32_t position(); + uint32_t size(); + void close(); + operator bool(); + char *name(); + + // bool isDirectory(void); + // File openNextFile(uint8_t mode = FILE_READ); + // void rewindDirectory(void); + + using Print::write; +}; + +class SpiffsClass +{ + +private: + // my quick&dirty iterator, should be replaced + spiffs_file getParentDir(const char *filepath, int *indx); + +public: + // These are required for initialisation and use of spiffs + static SPIFlash *flash; + static spiffs my_fs; + spiffs_file root; + + // This needs to be called to set up the connection to the SD card + // before other methods are used. + bool begin(uint8_t csPin = FLASH_CHIP_SELECT_PIN); + bool begin(uint32_t clock, uint8_t csPin); + + //call this when a card is removed. It will allow you to insert and initialise a new card. + void end(); + + // Open the specified file/directory with the supplied mode (e.g. read or + // write, etc). Returns a File object for interacting with the file. + // Note that currently only one file can be open at a time. + File open(const char *filename, uint8_t mode = FILE_READ); + File open(const String &filename, uint8_t mode = FILE_READ) + { + return open(filename.c_str(), mode); + } + + // Methods to determine if the requested file path exists. + bool exists(const char *filepath); + bool exists(const String &filepath) + { + return exists(filepath.c_str()); + } + + // Create the requested directory heirarchy--if intermediate directories + // do not exist they will be created. + bool mkdir(const char *filepath); + bool mkdir(const String &filepath) + { + return mkdir(filepath.c_str()); + } + + // Delete the file. + bool remove(const char *filepath); + bool remove(const String &filepath) + { + return remove(filepath.c_str()); + } + + bool rmdir(const char *filepath); + bool rmdir(const String &filepath) + { + return rmdir(filepath.c_str()); + } + + bool rename(const char *oldPath, const char *newPath); + +private: + // This is used to determine the mode used to open a file + // it's here because it's the easiest place to pass the + // information through the directory walking function. But + // it's probably not the best place for it. + // It shouldn't be set directly--it is set via the parameters to `open`. + int fileOpenMode; + + friend class File; + friend bool callback_openPath(spiffs_file &, const char *, bool, void *); + + static u8_t spiffs_work_buf[LOG_PAGE_SIZE * 2]; + static u8_t spiffs_fds[32 * 4]; + static u8_t spiffs_cache_buf[(LOG_PAGE_SIZE + 32) * 4]; + + int mount(); + static s32_t my_spiffs_read(u32_t addr, u32_t size, u8_t *dst); + static s32_t my_spiffs_write(u32_t addr, u32_t size, u8_t *src); + static s32_t my_spiffs_erase(u32_t addr, u32_t size); +}; + +/* +class SPIFFS +{ +public: + static SPIFlash *flash; + static spiffs my_fs; + + SPIFFS(); + int mount(); + bool begin(uint8_t cs); + spiffs_file open(const char *path, const char *mode); + +private: + static u8_t spiffs_work_buf[LOG_PAGE_SIZE * 2]; + static u8_t spiffs_fds[32 * 4]; + static u8_t spiffs_cache_buf[(LOG_PAGE_SIZE + 32) * 4]; + + static s32_t my_spiffs_read(u32_t addr, u32_t size, u8_t *dst); + static s32_t my_spiffs_write(u32_t addr, u32_t size, u8_t *src); + static s32_t my_spiffs_erase(u32_t addr, u32_t size); +};*/ + +enum SeekMode +{ + SeekSet = 0, + SeekCur = 1, + SeekEnd = 2 +}; + +extern SpiffsClass SPIFFS; + +}; // namespace SpiffsLib + +typedef SpiffsLib::File File; +typedef SpiffsLib::SpiffsClass SpiffsFS; +static SpiffsFS SPIFFS; + +#endif //FS_H \ No newline at end of file diff --git a/lib/STM32Spiffs/src/params_test.h b/lib/STM32Spiffs/src/params_test.h new file mode 100644 index 00000000..df5d1a33 --- /dev/null +++ b/lib/STM32Spiffs/src/params_test.h @@ -0,0 +1,93 @@ +/* + * params_test.h + * + * Created on: May 26, 2013 + * Author: petera + */ + +#ifndef PARAMS_TEST_H_ +#define PARAMS_TEST_H_ + +#include + +//////////////// TEST PARAMS //////////////// + +// default test total emulated spi flash size +#define PHYS_FLASH_SIZE (16 * 1024 * 1024) +// default test spiffs file system size +#define SPIFFS_FLASH_SIZE (2 * 1024 * 1024) +// default test spiffs file system offset in emulated spi flash +#define SPIFFS_PHYS_ADDR (4 * 1024 * 1024) +// default test sector size +#define SECTOR_SIZE 65536 +// default test logical block size +#define LOG_BLOCK (SECTOR_SIZE * 2) +// default test logical page size +#define LOG_PAGE (SECTOR_SIZE / 256) +// default test number of filedescs +#define DEFAULT_NUM_FD 16 +// default test number of cache pages +#define DEFAULT_NUM_CACHE_PAGES 8 + +// When testing, test bench create reference files for comparison on +// the actual hard drive. By default, put these on ram drive for speed. +#define TEST_PATH "/dev/shm/spiffs/test-data/" + +#define ASSERT(c, m) real_assert((c), (m), __FILE__, __LINE__); +void real_assert(int c, const char * n, const char * file, int l); + +/////////// SPIFFS BUILD CONFIG //////////// + +// test using filesystem magic +#ifndef SPIFFS_USE_MAGIC +#define SPIFFS_USE_MAGIC 1 +#endif +// test using filesystem magic length +#ifndef SPIFFS_USE_MAGIC_LENGTH +#define SPIFFS_USE_MAGIC_LENGTH 1 +#endif +// test using extra param in callback +#ifndef SPIFFS_HAL_CALLBACK_EXTRA +#define SPIFFS_HAL_CALLBACK_EXTRA 1 +#endif +// test using filehandle offset +#ifndef SPIFFS_FILEHDL_OFFSET +#define SPIFFS_FILEHDL_OFFSET 1 +// use this offset +#define TEST_SPIFFS_FILEHDL_OFFSET 0x1000 +#endif + +#ifdef NO_TEST +#define SPIFFS_LOCK(fs) +#define SPIFFS_UNLOCK(fs) +#else +struct spiffs_t; +extern void test_lock(struct spiffs_t * fs); +extern void test_unlock(struct spiffs_t * fs); +#define SPIFFS_LOCK(fs) test_lock(fs) +#define SPIFFS_UNLOCK(fs) test_unlock(fs) +#endif + +// dbg output +#define SPIFFS_DBG(_f, ...) // printf("\x1b[32m" _f "\x1b[0m", ## __VA_ARGS__) +#define SPIFFS_API_DBG(_f, ...) // printf("\n\x1b[1m\x1b[7m" _f "\x1b[0m", ## __VA_ARGS__) +#define SPIFFS_GC_DBG(_f, ...) // printf("\x1b[36m" _f "\x1b[0m", ## __VA_ARGS__) +#define SPIFFS_CACHE_DBG(_f, ...) // printf("\x1b[33m" _f "\x1b[0m", ## __VA_ARGS__) +#define SPIFFS_CHECK_DBG(_f, ...) // printf("\x1b[31m" _f "\x1b[0m", ## __VA_ARGS__) + +// needed types +// typedef signed int s32_t; +// typedef unsigned int u32_t; +// typedef signed short s16_t; +// typedef unsigned short u16_t; +// typedef signed char s8_t; +// typedef unsigned char u8_t; + +typedef uint8_t u8_t; +typedef int8_t s8_t; +typedef uint16_t u16_t; +typedef int16_t s16_t; +typedef uint32_t u32_t; +typedef int32_t s32_t; + +#endif /* PARAMS_TEST_H_ */ diff --git a/lib/STM32Spiffs/src/spiffs_config.h b/lib/STM32Spiffs/src/spiffs_config.h new file mode 100644 index 00000000..c16c73ad --- /dev/null +++ b/lib/STM32Spiffs/src/spiffs_config.h @@ -0,0 +1,383 @@ +/* + * spiffs_config.h + * + * Created on: Jul 3, 2013 + * Author: petera + */ + +#ifndef SPIFFS_CONFIG_H_ +#define SPIFFS_CONFIG_H_ + +// ----------- 8< ------------ +// Following includes are for the linux test build of spiffs +// These may/should/must be removed/altered/replaced in your target +#include "params_test.h" +#include +#include +#include +#include +#include +#ifdef _SPIFFS_TEST +#include "testrunner.h" +#endif +// ----------- >8 ------------ + +// compile time switches + +// Set generic spiffs debug output call. +#ifndef SPIFFS_DBG +#define SPIFFS_DBG(_f, ...) printf(_f, ## __VA_ARGS__) +#endif +// Set spiffs debug output call for garbage collecting. +#ifndef SPIFFS_GC_DBG +#define SPIFFS_GC_DBG(_f, ...) printf(_f, ## __VA_ARGS__) +#endif +// Set spiffs debug output call for caching. +#ifndef SPIFFS_CACHE_DBG +#define SPIFFS_CACHE_DBG(_f, ...) printf(_f, ## __VA_ARGS__) +#endif +// Set spiffs debug output call for system consistency checks. +#ifndef SPIFFS_CHECK_DBG +#define SPIFFS_CHECK_DBG(_f, ...) printf(_f, ## __VA_ARGS__) +#endif +// Set spiffs debug output call for all api invocations. +#ifndef SPIFFS_API_DBG +#define SPIFFS_API_DBG(_f, ...) printf(_f, ## __VA_ARGS__) +#endif + + + +// Defines spiffs debug print formatters +// some general signed number +#ifndef _SPIPRIi +#define _SPIPRIi "%d" +#endif +// address +#ifndef _SPIPRIad +#define _SPIPRIad "%08x" +#endif +// block +#ifndef _SPIPRIbl +#define _SPIPRIbl "%04x" +#endif +// page +#ifndef _SPIPRIpg +#define _SPIPRIpg "%04x" +#endif +// span index +#ifndef _SPIPRIsp +#define _SPIPRIsp "%04x" +#endif +// file descriptor +#ifndef _SPIPRIfd +#define _SPIPRIfd "%d" +#endif +// file object id +#ifndef _SPIPRIid +#define _SPIPRIid "%04x" +#endif +// file flags +#ifndef _SPIPRIfl +#define _SPIPRIfl "%02x" +#endif + + +// Enable/disable API functions to determine exact number of bytes +// for filedescriptor and cache buffers. Once decided for a configuration, +// this can be disabled to reduce flash. +#ifndef SPIFFS_BUFFER_HELP +#define SPIFFS_BUFFER_HELP 0 +#endif + +// Enables/disable memory read caching of nucleus file system operations. +// If enabled, memory area must be provided for cache in SPIFFS_mount. +#ifndef SPIFFS_CACHE +#define SPIFFS_CACHE 1 +#endif +#if SPIFFS_CACHE +// Enables memory write caching for file descriptors in hydrogen +#ifndef SPIFFS_CACHE_WR +#define SPIFFS_CACHE_WR 1 +#endif + +// Enable/disable statistics on caching. Debug/test purpose only. +#ifndef SPIFFS_CACHE_STATS +#define SPIFFS_CACHE_STATS 1 +#endif +#endif + +// Always check header of each accessed page to ensure consistent state. +// If enabled it will increase number of reads, will increase flash. +#ifndef SPIFFS_PAGE_CHECK +#define SPIFFS_PAGE_CHECK 1 +#endif + +// Define maximum number of gc runs to perform to reach desired free pages. +#ifndef SPIFFS_GC_MAX_RUNS +#define SPIFFS_GC_MAX_RUNS 5 +#endif + +// Enable/disable statistics on gc. Debug/test purpose only. +#ifndef SPIFFS_GC_STATS +#define SPIFFS_GC_STATS 1 +#endif + +// Garbage collecting examines all pages in a block which and sums up +// to a block score. Deleted pages normally gives positive score and +// used pages normally gives a negative score (as these must be moved). +// To have a fair wear-leveling, the erase age is also included in score, +// whose factor normally is the most positive. +// The larger the score, the more likely it is that the block will +// picked for garbage collection. + +// Garbage collecting heuristics - weight used for deleted pages. +#ifndef SPIFFS_GC_HEUR_W_DELET +#define SPIFFS_GC_HEUR_W_DELET (5) +#endif +// Garbage collecting heuristics - weight used for used pages. +#ifndef SPIFFS_GC_HEUR_W_USED +#define SPIFFS_GC_HEUR_W_USED (-1) +#endif +// Garbage collecting heuristics - weight used for time between +// last erased and erase of this block. +#ifndef SPIFFS_GC_HEUR_W_ERASE_AGE +#define SPIFFS_GC_HEUR_W_ERASE_AGE (50) +#endif + +// Object name maximum length. Note that this length include the +// zero-termination character, meaning maximum string of characters +// can at most be SPIFFS_OBJ_NAME_LEN - 1. +#ifndef SPIFFS_OBJ_NAME_LEN +#define SPIFFS_OBJ_NAME_LEN (32) +#endif + +// Maximum length of the metadata associated with an object. +// Setting to non-zero value enables metadata-related API but also +// changes the on-disk format, so the change is not backward-compatible. +// +// Do note: the meta length must never exceed +// logical_page_size - (SPIFFS_OBJ_NAME_LEN + 64) +// +// This is derived from following: +// logical_page_size - (SPIFFS_OBJ_NAME_LEN + sizeof(spiffs_page_header) + +// spiffs_object_ix_header fields + at least some LUT entries) +#ifndef SPIFFS_OBJ_META_LEN +#define SPIFFS_OBJ_META_LEN (0) +#endif + +// Size of buffer allocated on stack used when copying data. +// Lower value generates more read/writes. No meaning having it bigger +// than logical page size. +#ifndef SPIFFS_COPY_BUFFER_STACK +#define SPIFFS_COPY_BUFFER_STACK (64) +#endif + +// Enable this to have an identifiable spiffs filesystem. This will look for +// a magic in all sectors to determine if this is a valid spiffs system or +// not on mount point. If not, SPIFFS_format must be called prior to mounting +// again. +#ifndef SPIFFS_USE_MAGIC +#define SPIFFS_USE_MAGIC (0) +#endif + +#if SPIFFS_USE_MAGIC +// Only valid when SPIFFS_USE_MAGIC is enabled. If SPIFFS_USE_MAGIC_LENGTH is +// enabled, the magic will also be dependent on the length of the filesystem. +// For example, a filesystem configured and formatted for 4 megabytes will not +// be accepted for mounting with a configuration defining the filesystem as 2 +// megabytes. +#ifndef SPIFFS_USE_MAGIC_LENGTH +#define SPIFFS_USE_MAGIC_LENGTH (0) +#endif +#endif + +// SPIFFS_LOCK and SPIFFS_UNLOCK protects spiffs from reentrancy on api level +// These should be defined on a multithreaded system + +// define this to enter a mutex if you're running on a multithreaded system +#ifndef SPIFFS_LOCK +#define SPIFFS_LOCK(fs) +#endif +// define this to exit a mutex if you're running on a multithreaded system +#ifndef SPIFFS_UNLOCK +#define SPIFFS_UNLOCK(fs) +#endif + +// Enable if only one spiffs instance with constant configuration will exist +// on the target. This will reduce calculations, flash and memory accesses. +// Parts of configuration must be defined below instead of at time of mount. +#ifndef SPIFFS_SINGLETON +#define SPIFFS_SINGLETON 1 +#endif + +#if SPIFFS_SINGLETON +// Instead of giving parameters in config struct, singleton build must +// give parameters in defines below. +#ifndef SPIFFS_CFG_PHYS_SZ +#define SPIFFS_CFG_PHYS_SZ(ignore) (1024*1024*2) +#endif +#ifndef SPIFFS_CFG_PHYS_ERASE_SZ +#define SPIFFS_CFG_PHYS_ERASE_SZ(ignore) (65536) +#endif +#ifndef SPIFFS_CFG_PHYS_ADDR +#define SPIFFS_CFG_PHYS_ADDR(ignore) (0) +#endif +#ifndef SPIFFS_CFG_LOG_PAGE_SZ +#define SPIFFS_CFG_LOG_PAGE_SZ(ignore) (256) +#endif +#ifndef SPIFFS_CFG_LOG_BLOCK_SZ +#define SPIFFS_CFG_LOG_BLOCK_SZ(ignore) (65536) +#endif +#endif + +// Enable this if your target needs aligned data for index tables +#ifndef SPIFFS_ALIGNED_OBJECT_INDEX_TABLES +#define SPIFFS_ALIGNED_OBJECT_INDEX_TABLES 0 +#endif + +// Enable this if you want the HAL callbacks to be called with the spiffs struct +#ifndef SPIFFS_HAL_CALLBACK_EXTRA +#define SPIFFS_HAL_CALLBACK_EXTRA 0 +#endif + +// Enable this if you want to add an integer offset to all file handles +// (spiffs_file). This is useful if running multiple instances of spiffs on +// same target, in order to recognise to what spiffs instance a file handle +// belongs. +// NB: This adds config field fh_ix_offset in the configuration struct when +// mounting, which must be defined. +#ifndef SPIFFS_FILEHDL_OFFSET +#define SPIFFS_FILEHDL_OFFSET 0 +#endif + +// Enable this to compile a read only version of spiffs. +// This will reduce binary size of spiffs. All code comprising modification +// of the file system will not be compiled. Some config will be ignored. +// HAL functions for erasing and writing to spi-flash may be null. Cache +// can be disabled for even further binary size reduction (and ram savings). +// Functions modifying the fs will return SPIFFS_ERR_RO_NOT_IMPL. +// If the file system cannot be mounted due to aborted erase operation and +// SPIFFS_USE_MAGIC is enabled, SPIFFS_ERR_RO_ABORTED_OPERATION will be +// returned. +// Might be useful for e.g. bootloaders and such. +#ifndef SPIFFS_READ_ONLY +#define SPIFFS_READ_ONLY 0 +#endif + +// Enable this to add a temporal file cache using the fd buffer. +// The effects of the cache is that SPIFFS_open will find the file faster in +// certain cases. It will make it a lot easier for spiffs to find files +// opened frequently, reducing number of readings from the spi flash for +// finding those files. +// This will grow each fd by 6 bytes. If your files are opened in patterns +// with a degree of temporal locality, the system is optimized. +// Examples can be letting spiffs serve web content, where one file is the css. +// The css is accessed for each html file that is opened, meaning it is +// accessed almost every second time a file is opened. Another example could be +// a log file that is often opened, written, and closed. +// The size of the cache is number of given file descriptors, as it piggybacks +// on the fd update mechanism. The cache lives in the closed file descriptors. +// When closed, the fd know the whereabouts of the file. Instead of forgetting +// this, the temporal cache will keep handling updates to that file even if the +// fd is closed. If the file is opened again, the location of the file is found +// directly. If all available descriptors become opened, all cache memory is +// lost. +#ifndef SPIFFS_TEMPORAL_FD_CACHE +#define SPIFFS_TEMPORAL_FD_CACHE 1 +#endif + +// Temporal file cache hit score. Each time a file is opened, all cached files +// will lose one point. If the opened file is found in cache, that entry will +// gain SPIFFS_TEMPORAL_CACHE_HIT_SCORE points. One can experiment with this +// value for the specific access patterns of the application. However, it must +// be between 1 (no gain for hitting a cached entry often) and 255. +#ifndef SPIFFS_TEMPORAL_CACHE_HIT_SCORE +#define SPIFFS_TEMPORAL_CACHE_HIT_SCORE 4 +#endif + +// Enable to be able to map object indices to memory. +// This allows for faster and more deterministic reading if cases of reading +// large files and when changing file offset by seeking around a lot. +// When mapping a file's index, the file system will be scanned for index pages +// and the info will be put in memory provided by user. When reading, the +// memory map can be looked up instead of searching for index pages on the +// medium. This way, user can trade memory against performance. +// Whole, parts of, or future parts not being written yet can be mapped. The +// memory array will be owned by spiffs and updated accordingly during garbage +// collecting or when modifying the indices. The latter is invoked by when the +// file is modified in some way. The index buffer is tied to the file +// descriptor. +#ifndef SPIFFS_IX_MAP +#define SPIFFS_IX_MAP 1 +#endif + +// By default SPIFFS in some cases relies on the property of NOR flash that bits +// cannot be set from 0 to 1 by writing and that controllers will ignore such +// bit changes. This results in fewer reads as SPIFFS can in some cases perform +// blind writes, with all bits set to 1 and only those it needs reset set to 0. +// Most of the chips and controllers allow this behavior, so the default is to +// use this technique. If your controller is one of the rare ones that don't, +// turn this option on and SPIFFS will perform a read-modify-write instead. +#ifndef SPIFFS_NO_BLIND_WRITES +#define SPIFFS_NO_BLIND_WRITES 0 +#endif + +// Set SPIFFS_TEST_VISUALISATION to non-zero to enable SPIFFS_vis function +// in the api. This function will visualize all filesystem using given printf +// function. +#ifndef SPIFFS_TEST_VISUALISATION +#define SPIFFS_TEST_VISUALISATION 1 +#endif +#if SPIFFS_TEST_VISUALISATION +#ifndef spiffs_printf +#define spiffs_printf(...) printf(__VA_ARGS__) +#endif +// spiffs_printf argument for a free page +#ifndef SPIFFS_TEST_VIS_FREE_STR +#define SPIFFS_TEST_VIS_FREE_STR "_" +#endif +// spiffs_printf argument for a deleted page +#ifndef SPIFFS_TEST_VIS_DELE_STR +#define SPIFFS_TEST_VIS_DELE_STR "/" +#endif +// spiffs_printf argument for an index page for given object id +#ifndef SPIFFS_TEST_VIS_INDX_STR +#define SPIFFS_TEST_VIS_INDX_STR(id) "i" +#endif +// spiffs_printf argument for a data page for given object id +#ifndef SPIFFS_TEST_VIS_DATA_STR +#define SPIFFS_TEST_VIS_DATA_STR(id) "d" +#endif +#endif + +#ifndef SPIFFS_SECURE_ERASE +#define SPIFFS_SECURE_ERASE 0 +#endif + +// Types depending on configuration such as the amount of flash bytes +// given to spiffs file system in total (spiffs_file_system_size), +// the logical block size (log_block_size), and the logical page size +// (log_page_size) +// +// Set SPIFFS_TYPES_OVERRIDE if you wish to have your own +// definitions for these types (for example, if you want them +// to be u32_t) + +#ifndef SPIFFS_TYPES_OVERRIDE +// Block index type. Make sure the size of this type can hold +// the highest number of all blocks - i.e. spiffs_file_system_size / log_block_size +typedef u16_t spiffs_block_ix; +// Page index type. Make sure the size of this type can hold +// the highest page number of all pages - i.e. spiffs_file_system_size / log_page_size +typedef u16_t spiffs_page_ix; +// Object id type - most significant bit is reserved for index flag. Make sure the +// size of this type can hold the highest object id on a full system, +// i.e. 2 + (spiffs_file_system_size / (2*log_page_size))*2 +typedef u16_t spiffs_obj_id; +// Object span index type. Make sure the size of this type can +// hold the largest possible span index on the system - +// i.e. (spiffs_file_system_size / log_page_size) - 1 +typedef u16_t spiffs_span_ix; +#endif + +#endif /* SPIFFS_CONFIG_H_ */ diff --git a/platformio.ini b/platformio.ini index 8a971a18..9cfe2119 100644 --- a/platformio.ini +++ b/platformio.ini @@ -93,11 +93,21 @@ esp32_flags= stm32_flags= ${env.build_flags} + -I include/stm32f4 -D IRAM_ATTR= ; No IRAM_ATTR available on STM32 -D STM32 -D STREAMUTILS_USE_EEPROM_UPDATE=1 ; update cell only when changed -D MQTT_MAX_PACKET_SIZE=2048 ; longer PubSubClient messages +[libs] +stm32_deps= + ${env.lib_deps} + SPIMemory@^3.4.0 + Ticker@^3.1.5 + ; STM32duino LwIP@^2.1.2 + https://github.com/stm32duino/LwIP.git + https://github.com/khoih-prog/EthernetWebServer_STM32 + ; -- By default there are no ${override.build_flags} set ; -- to use it, copy platformio_override.ini from the template [override] diff --git a/src/hasp.cpp b/src/hasp.cpp index fc983b0c..f8b8a4ae 100644 --- a/src/hasp.cpp +++ b/src/hasp.cpp @@ -953,7 +953,7 @@ void haspLoadPage(const char * pages) Log.notice(F("HASP: Loading file %s"), pages); - File file = SPIFFS.open(pages, "r"); + File file = SPIFFS.open(pages, FILE_READ); dispatchJsonl(file); file.close(); diff --git a/src/hasp_config.cpp b/src/hasp_config.cpp index c2da806a..604c3e12 100644 --- a/src/hasp_config.cpp +++ b/src/hasp_config.cpp @@ -14,15 +14,15 @@ #include "hasp_conf.h" -#if HASP_USE_SPIFFS > 0 -#include // Include the SPIFFS library -#if defined(ARDUINO_ARCH_ESP32) -#include "SPIFFS.h" -#endif -#endif -#if HASP_USE_EEPROM > 0 -#include "EEPROM.h" -#endif +// #if HASP_USE_SPIFFS > 0 +// #include // Include the SPIFFS library +// #if defined(ARDUINO_ARCH_ESP32) +// #include "SPIFFS.h" +// #endif +// #endif +// #if HASP_USE_EEPROM > 0 +// #include "EEPROM.h" +// #endif void confDebugSet(const char * name) { @@ -94,7 +94,7 @@ void configGetConfig(JsonDocument & settings, bool setupdebug = false) DeserializationError error; #if HASP_USE_SPIFFS > 0 - File file = SPIFFS.open(configFile, "r"); + File file = SPIFFS.open(configFile, FILE_READ); if(file) { size_t size = file.size(); @@ -268,7 +268,7 @@ void configWriteConfig() if(writefile) { #if HASP_USE_SPIFFS > 0 - File file = SPIFFS.open(configFile, "w"); + File file = SPIFFS.open(configFile, FILE_WRITE); if(file) { Log.notice(F("CONF: Writing %s"), configFile.c_str()); size_t size = serializeJson(doc, file); diff --git a/src/hasp_gui.cpp b/src/hasp_gui.cpp index 7c33af36..84b1f07b 100644 --- a/src/hasp_gui.cpp +++ b/src/hasp_gui.cpp @@ -14,6 +14,7 @@ #include "hasp_gui.h" #include "hasp_oobe.h" #include "hasp.h" +#include "hasp_conf.h" //#include "lv_ex_conf.h" //#include "tpcal.h" @@ -26,17 +27,19 @@ #define TOUCH_DRIVER 0 #endif -#if HASP_USE_SPIFFS > 0 -#if defined(ARDUINO_ARCH_ESP32) -#include "SPIFFS.h" -#endif -#include // Include the SPIFFS library -#endif +// #if HASP_USE_SPIFFS > 0 +// #if defined(ARDUINO_ARCH_ESP32) +// #include "SPIFFS.h" +// #include // Include the SPIFFS library +// #elif defined(ARDUINO_ARCH_ESP8266) +// #include // Include the SPIFFS library +// #endif +// #endif #define BACKLIGHT_CHANNEL 15 // pwm channek 0-15 /* ---------- Screenshot Variables ---------- */ -#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) +#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)|| defined(STM32F4xx) File pFileOut; #endif uint8_t guiSnapshot = 0; @@ -1095,7 +1098,7 @@ static void guiSendBmpHeader() #if HASP_USE_SPIFFS > 0 void guiTakeScreenshot(const char * pFileName) { - pFileOut = SPIFFS.open(pFileName, "w"); + pFileOut = SPIFFS.open(pFileName, FILE_WRITE); if(pFileOut == 0) { Log.warning(F("GUI: %s cannot be opened"), pFileName); diff --git a/src/hasp_http.cpp b/src/hasp_http.cpp index 3cb7e0fc..c490852b 100644 --- a/src/hasp_http.cpp +++ b/src/hasp_http.cpp @@ -23,11 +23,12 @@ #if defined(ARDUINO_ARCH_ESP32) #include "SPIFFS.h" #include -#include #include #elif defined(ARDUINO_ARCH_ESP8266) #include #include +#elif defined(STM32F4xx) +#include "STM32Spiffs.h" #endif #if HASP_USE_HTTP > 0 @@ -39,6 +40,9 @@ uint16_t httpPort = 80; #if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) FS * filesystem = &SPIFFS; File fsUploadFile; +#elif defined(STM32F4xx) +SpiffsFS * filesystem = &SPIFFS; +File fsUploadFile; #endif char httpUser[32] = ""; @@ -684,7 +688,7 @@ bool handleFileRead(String path) if(filesystem->exists(pathWithGz) || filesystem->exists(path)) { if(filesystem->exists(pathWithGz)) path += F(".gz"); - File file = filesystem->open(path, "r"); + File file = filesystem->open(path, FILE_READ); String contentType = getContentType(path); if(path == F("/edit.htm.gz")) { contentType = F("text/html"); @@ -712,7 +716,7 @@ void handleFileUpload() filename += upload->filename; } if(filename.length() < 32) { - fsUploadFile = filesystem->open(filename, "w"); + fsUploadFile = filesystem->open(filename, FILE_WRITE); Log.notice(F("handleFileUpload Name: %s"), filename.c_str()); } else { Log.error(F("Filename %s is too long"), filename.c_str()); @@ -777,14 +781,14 @@ void handleFileCreate() if(filesystem->exists(path)) { return webServer.send(500, PSTR("text/plain"), PSTR("FILE EXISTS")); } - File file = filesystem->open(path, "w"); + File file = filesystem->open(path, FILE_WRITE); if(file) { file.close(); } else { return webServer.send(500, PSTR("text/plain"), PSTR("CREATE FAILED")); } webServer.send(200, PSTR("text/plain"), ""); - path.clear(); + // path.clear(); } void handleFileList() @@ -796,9 +800,11 @@ void handleFileList() return; } - String path = webServer.arg(F("dir")); - Log.verbose(F("handleFileList: %s"), path.c_str()); - path.clear(); + { + String path = webServer.arg(F("dir")); + Log.verbose(F("handleFileList: %s"), path.c_str()); + // path.clear(); + } #if defined(ARDUINO_ARCH_ESP32) File root = SPIFFS.open("/"); diff --git a/src/hasp_spiffs.cpp b/src/hasp_spiffs.cpp index b916b07a..bbb4969a 100644 --- a/src/hasp_spiffs.cpp +++ b/src/hasp_spiffs.cpp @@ -5,12 +5,12 @@ #include "hasp_conf.h" #include "hasp_spiffs.h" -#if HASP_USE_SPIFFS>0 -#if defined(ARDUINO_ARCH_ESP32) -#include "SPIFFS.h" -#endif -#include -#endif +// #if HASP_USE_SPIFFS>0 +// #if defined(ARDUINO_ARCH_ESP32) +// #include "SPIFFS.h" +// #endif +// #include +// #endif void spiffsInfo() { // Get all information of your SPIFFS diff --git a/user_setups/stm32f4xx/stm32f407-black_ili9341.ini b/user_setups/stm32f4xx/stm32f407-black_ili9341.ini index 8f96fa44..66a38fee 100644 --- a/user_setups/stm32f4xx/stm32f407-black_ili9341.ini +++ b/user_setups/stm32f4xx/stm32f407-black_ili9341.ini @@ -14,7 +14,6 @@ monitor_port = COM7 ; To change the port, use platform_override.ini build_flags = ${env.build_flags} ${flags.stm32_flags} - -I include/stm32f4 ; -- TFT_eSPI build options ------------------------ ${lcd.lolin24} ;-D TFT_MISO=PB4 ;Default @@ -27,16 +26,17 @@ build_flags = -D TFT_RST=-1 ;D4 -D HASP_OUTPUT_PIN=PE0 ; User LED D2 on DevEBox board -D HASP_INPUT_PIN=PD15 ; User Button K1 on DevEBox board - -D STM32_SERIAL1 ; Set this option to use Serial1 as default sersial port, leave out if using Serial2 - ;-D HAL_ETH_MODULE_ENABLED=1 ; enable ethernet support - ;-D LAN8742A_PHY_ADDRESS=0x01U ; set LAN8720 PHY address + -D STM32_SERIAL1 ; Set this option to use Serial1 as default serial port, leave out if using Serial2 -D HASP_USE_TASMOTA_SLAVE=1 +; -- W5500 Ethernet configuration ------------------ -D HASP_USE_ETHERNET=1 -D W5500_MOSI=PB15 ;SPI2 MOSI -D W5500_MISO=PB14 ;SPI2 MISO -D W5500_SCLK=PB13 ;SPI2 SCLK -D W5500_CS=PB6 ;SPI2 CS -D W5500_RST=PD1 ;SPI2 CS + ;-D HAL_ETH_MODULE_ENABLED=1 ; enable ethernet support + ;-D LAN8742A_PHY_ADDRESS=0x01U ; set LAN8720 PHY address lib_deps = ${env.lib_deps} diff --git a/user_setups/stm32f4xx/stm32f407-devebox_ili9341.ini b/user_setups/stm32f4xx/stm32f407-devebox_ili9341.ini index 43b5d65c..997e0046 100644 --- a/user_setups/stm32f4xx/stm32f407-devebox_ili9341.ini +++ b/user_setups/stm32f4xx/stm32f407-devebox_ili9341.ini @@ -16,7 +16,6 @@ monitor_port = COM19 ; To change the port, use platform_override.ini build_flags = ${env.build_flags} ${flags.stm32_flags} - -I include/stm32f4 ; -- TFT_eSPI build options ------------------------ ${lcd.lolin24} ;-D TFT_MISO=PB4 ;Default @@ -34,19 +33,23 @@ build_flags = -D HASP_OUTPUT_PIN=PA1 ; User LED D2 on DevEBox board -D HASP_INPUT_PIN=PA0 ; User Button K1 on DevEBox board -D STM32_SERIAL1 ; Set this option to use Serial1 as default sersial port, leave out if using Serial2 +; -- LAN8720 Ethernet configuration ------------------ -D HASP_USE_ETHERNET=1 -D USE_BUILTIN_ETHERNET=1 -D HAL_ETH_MODULE_ENABLED=1 ; -D LAN8742A_PHY_ADDRESS=0x01U ; moved to include\stm32f4\hal_conf_custom.h ; -D DP83848_PHY_ADDRESS=0x01U - +; -- Spiffs Configuration + -D ARCH_STM32=1 + -D LOG_PAGE_SIZE=256 + -D SPIFFS_HAL_CALLBACK_EXTRA=0 + -D NO_TEST=1 + lib_deps = - ${env.lib_deps} - Ticker@^3.1.5 - ; STM32duino LwIP@^2.1.2 + ${libs.stm32_deps} ; STM32duino STM32Ethernet@^1.0.5 - https://github.com/stm32duino/LwIP.git https://github.com/stm32duino/STM32Ethernet.git - https://github.com/khoih-prog/EthernetWebServer_STM32 + STM32Spiffs + https://github.com/pellepl/spiffs.git src_filter = +<*> -<.git/> -<.svn/> - - - - - +