From f671dc2f107c5ff90916f70db212e5ce14f468d5 Mon Sep 17 00:00:00 2001 From: Larry Bernstone Date: Mon, 27 Aug 2018 12:05:07 -0600 Subject: [PATCH 1/7] First commit of FFat library --- boards.txt | 117 +++++------ .../FFat/examples/FFat_Test/FFat_Test.ino | 183 ++++++++++++++++++ libraries/FFat/library.properties | 9 + libraries/FFat/src/FFat.cpp | 132 +++++++++++++ libraries/FFat/src/FFat.h | 47 +++++ .../examples/FSBrowser/FSBrowser.ino | 32 +-- tools/partitions/ffat.csv | 7 + 7 files changed, 459 insertions(+), 68 deletions(-) create mode 100644 libraries/FFat/examples/FFat_Test/FFat_Test.ino create mode 100644 libraries/FFat/library.properties create mode 100644 libraries/FFat/src/FFat.cpp create mode 100644 libraries/FFat/src/FFat.h create mode 100644 tools/partitions/ffat.csv diff --git a/boards.txt b/boards.txt index 185b0a9afd6..6e397d0c152 100644 --- a/boards.txt +++ b/boards.txt @@ -8,62 +8,6 @@ menu.PSRAM=PSRAM ############################################################## -ttgo-lora32-v1.name=TTGO LoRa32-OLED V1 - -ttgo-lora32-v1.upload.tool=esptool -ttgo-lora32-v1.upload.maximum_size=1310720 -ttgo-lora32-v1.upload.maximum_data_size=294912 -ttgo-lora32-v1.upload.wait_for_upload_port=true - -ttgo-lora32-v1.serial.disableDTR=true -ttgo-lora32-v1.serial.disableRTS=true - -ttgo-lora32-v1.build.mcu=esp32 -ttgo-lora32-v1.build.core=esp32 -ttgo-lora32-v1.build.variant=ttgo-lora32-v1 -ttgo-lora32-v1.build.board=TTGO_LoRa32_V1 - -ttgo-lora32-v1.build.f_cpu=240000000L -ttgo-lora32-v1.build.flash_mode=dio -ttgo-lora32-v1.build.flash_size=4MB -ttgo-lora32-v1.build.boot=dio -ttgo-lora32-v1.build.partitions=default - -ttgo-lora32-v1.menu.FlashFreq.80=80MHz -ttgo-lora32-v1.menu.FlashFreq.80.build.flash_freq=80m -ttgo-lora32-v1.menu.FlashFreq.40=40MHz -ttgo-lora32-v1.menu.FlashFreq.40.build.flash_freq=40m - -ttgo-lora32-v1.menu.UploadSpeed.921600=921600 -ttgo-lora32-v1.menu.UploadSpeed.921600.upload.speed=921600 -ttgo-lora32-v1.menu.UploadSpeed.115200=115200 -ttgo-lora32-v1.menu.UploadSpeed.115200.upload.speed=115200 -ttgo-lora32-v1.menu.UploadSpeed.256000.windows=256000 -ttgo-lora32-v1.menu.UploadSpeed.256000.upload.speed=256000 -ttgo-lora32-v1.menu.UploadSpeed.230400.windows.upload.speed=256000 -ttgo-lora32-v1.menu.UploadSpeed.230400=230400 -ttgo-lora32-v1.menu.UploadSpeed.230400.upload.speed=230400 -ttgo-lora32-v1.menu.UploadSpeed.460800.linux=460800 -ttgo-lora32-v1.menu.UploadSpeed.460800.macosx=460800 -ttgo-lora32-v1.menu.UploadSpeed.460800.upload.speed=460800 -ttgo-lora32-v1.menu.UploadSpeed.512000.windows=512000 -ttgo-lora32-v1.menu.UploadSpeed.512000.upload.speed=512000 - -ttgo-lora32-v1.menu.DebugLevel.none=None -ttgo-lora32-v1.menu.DebugLevel.none.build.code_debug=0 -ttgo-lora32-v1.menu.DebugLevel.error=Error -ttgo-lora32-v1.menu.DebugLevel.error.build.code_debug=1 -ttgo-lora32-v1.menu.DebugLevel.warn=Warn -ttgo-lora32-v1.menu.DebugLevel.warn.build.code_debug=2 -ttgo-lora32-v1.menu.DebugLevel.info=Info -ttgo-lora32-v1.menu.DebugLevel.info.build.code_debug=3 -ttgo-lora32-v1.menu.DebugLevel.debug=Debug -ttgo-lora32-v1.menu.DebugLevel.debug.build.code_debug=4 -ttgo-lora32-v1.menu.DebugLevel.verbose=Verbose -ttgo-lora32-v1.menu.DebugLevel.verbose.build.code_debug=5 - -############################################################## - esp32.name=ESP32 Dev Module esp32.upload.tool=esptool @@ -102,6 +46,8 @@ esp32.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 esp32.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (Large APPS with OTA) esp32.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs esp32.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 +esp32.menu.PartitionScheme.fatflash=16M Fat +esp32.menu.PartitionScheme.fatflash.build.partitions=ffat esp32.menu.FlashMode.qio=QIO esp32.menu.FlashMode.qio.build.flash_mode=dio @@ -126,6 +72,9 @@ esp32.menu.FlashSize.4M.build.flash_size=4MB esp32.menu.FlashSize.2M=2MB (16Mb) esp32.menu.FlashSize.2M.build.flash_size=2MB esp32.menu.FlashSize.2M.build.partitions=minimal +esp32.menu.FlashSize.16M=16MB (128Mb) +esp32.menu.FlashSize.16M.build.flash_size=16MB +esp32.menu.FlashSize.2M.build.partitions=ffat esp32.menu.UploadSpeed.921600=921600 esp32.menu.UploadSpeed.921600.upload.speed=921600 @@ -157,6 +106,62 @@ esp32.menu.DebugLevel.verbose.build.code_debug=5 ############################################################## +ttgo-lora32-v1.name=TTGO LoRa32-OLED V1 + +ttgo-lora32-v1.upload.tool=esptool +ttgo-lora32-v1.upload.maximum_size=1310720 +ttgo-lora32-v1.upload.maximum_data_size=294912 +ttgo-lora32-v1.upload.wait_for_upload_port=true + +ttgo-lora32-v1.serial.disableDTR=true +ttgo-lora32-v1.serial.disableRTS=true + +ttgo-lora32-v1.build.mcu=esp32 +ttgo-lora32-v1.build.core=esp32 +ttgo-lora32-v1.build.variant=ttgo-lora32-v1 +ttgo-lora32-v1.build.board=TTGO_LoRa32_V1 + +ttgo-lora32-v1.build.f_cpu=240000000L +ttgo-lora32-v1.build.flash_mode=dio +ttgo-lora32-v1.build.flash_size=4MB +ttgo-lora32-v1.build.boot=dio +ttgo-lora32-v1.build.partitions=default + +ttgo-lora32-v1.menu.FlashFreq.80=80MHz +ttgo-lora32-v1.menu.FlashFreq.80.build.flash_freq=80m +ttgo-lora32-v1.menu.FlashFreq.40=40MHz +ttgo-lora32-v1.menu.FlashFreq.40.build.flash_freq=40m + +ttgo-lora32-v1.menu.UploadSpeed.921600=921600 +ttgo-lora32-v1.menu.UploadSpeed.921600.upload.speed=921600 +ttgo-lora32-v1.menu.UploadSpeed.115200=115200 +ttgo-lora32-v1.menu.UploadSpeed.115200.upload.speed=115200 +ttgo-lora32-v1.menu.UploadSpeed.256000.windows=256000 +ttgo-lora32-v1.menu.UploadSpeed.256000.upload.speed=256000 +ttgo-lora32-v1.menu.UploadSpeed.230400.windows.upload.speed=256000 +ttgo-lora32-v1.menu.UploadSpeed.230400=230400 +ttgo-lora32-v1.menu.UploadSpeed.230400.upload.speed=230400 +ttgo-lora32-v1.menu.UploadSpeed.460800.linux=460800 +ttgo-lora32-v1.menu.UploadSpeed.460800.macosx=460800 +ttgo-lora32-v1.menu.UploadSpeed.460800.upload.speed=460800 +ttgo-lora32-v1.menu.UploadSpeed.512000.windows=512000 +ttgo-lora32-v1.menu.UploadSpeed.512000.upload.speed=512000 + +ttgo-lora32-v1.menu.DebugLevel.none=None +ttgo-lora32-v1.menu.DebugLevel.none.build.code_debug=0 +ttgo-lora32-v1.menu.DebugLevel.error=Error +ttgo-lora32-v1.menu.DebugLevel.error.build.code_debug=1 +ttgo-lora32-v1.menu.DebugLevel.warn=Warn +ttgo-lora32-v1.menu.DebugLevel.warn.build.code_debug=2 +ttgo-lora32-v1.menu.DebugLevel.info=Info +ttgo-lora32-v1.menu.DebugLevel.info.build.code_debug=3 +ttgo-lora32-v1.menu.DebugLevel.debug=Debug +ttgo-lora32-v1.menu.DebugLevel.debug.build.code_debug=4 +ttgo-lora32-v1.menu.DebugLevel.verbose=Verbose +ttgo-lora32-v1.menu.DebugLevel.verbose.build.code_debug=5 + +############################################################## + cw02.name=XinaBox CW02 cw02.upload.tool=esptool diff --git a/libraries/FFat/examples/FFat_Test/FFat_Test.ino b/libraries/FFat/examples/FFat_Test/FFat_Test.ino new file mode 100644 index 00000000000..84c2e1ca888 --- /dev/null +++ b/libraries/FFat/examples/FFat_Test/FFat_Test.ino @@ -0,0 +1,183 @@ +#include "FS.h" +#include "FFat.h" + +/* You only need to format FFat the first time you run a + test or else use the FFat plugin to create a partition + https://github.com/me-no-dev/arduino-esp32fs-plugin */ +#define FORMAT_FFAT true + +void listDir(fs::FS &fs, const char * dirname, uint8_t levels){ + Serial.printf("Listing directory: %s\r\n", dirname); + + File root = fs.open(dirname); + if(!root){ + Serial.println("- failed to open directory"); + return; + } + if(!root.isDirectory()){ + Serial.println(" - not a directory"); + return; + } + + File file = root.openNextFile(); + while(file){ + if(file.isDirectory()){ + Serial.print(" DIR : "); + Serial.println(file.name()); + if(levels){ + listDir(fs, file.name(), levels -1); + } + } else { + Serial.print(" FILE: "); + Serial.print(file.name()); + Serial.print("\tSIZE: "); + Serial.println(file.size()); + } + file = root.openNextFile(); + } +} + +void readFile(fs::FS &fs, const char * path){ + Serial.printf("Reading file: %s\r\n", path); + + File file = fs.open(path); + if(!file || file.isDirectory()){ + Serial.println("- failed to open file for reading"); + return; + } + + Serial.println("- read from file:"); + while(file.available()){ + Serial.write(file.read()); + } +} + +void writeFile(fs::FS &fs, const char * path, const char * message){ + Serial.printf("Writing file: %s\r\n", path); + + File file = fs.open(path, FILE_WRITE); + if(!file){ + Serial.println("- failed to open file for writing"); + return; + } + if(file.print(message)){ + Serial.println("- file written"); + } else { + Serial.println("- frite failed"); + } +} + +void appendFile(fs::FS &fs, const char * path, const char * message){ + Serial.printf("Appending to file: %s\r\n", path); + + File file = fs.open(path, FILE_APPEND); + if(!file){ + Serial.println("- failed to open file for appending"); + return; + } + if(file.print(message)){ + Serial.println("- message appended"); + } else { + Serial.println("- append failed"); + } +} + +void renameFile(fs::FS &fs, const char * path1, const char * path2){ + Serial.printf("Renaming file %s to %s\r\n", path1, path2); + if (fs.rename(path1, path2)) { + Serial.println("- file renamed"); + } else { + Serial.println("- rename failed"); + } +} + +void deleteFile(fs::FS &fs, const char * path){ + Serial.printf("Deleting file: %s\r\n", path); + if(fs.remove(path)){ + Serial.println("- file deleted"); + } else { + Serial.println("- delete failed"); + } +} + +void testFileIO(fs::FS &fs, const char * path){ + Serial.printf("Testing file I/O with %s\r\n", path); + + static uint8_t buf[512]; + size_t len = 0; + File file = fs.open(path, FILE_WRITE); + if(!file){ + Serial.println("- failed to open file for writing"); + return; + } + + size_t i; + Serial.print("- writing" ); + uint32_t start = millis(); + for(i=0; i<2048; i++){ + if ((i & 0x001F) == 0x001F){ + Serial.print("."); + } + file.write(buf, 512); + } + Serial.println(""); + uint32_t end = millis() - start; + Serial.printf(" - %u bytes written in %u ms\r\n", 2048 * 512, end); + file.close(); + + file = fs.open(path); + start = millis(); + end = start; + i = 0; + if(file && !file.isDirectory()){ + len = file.size(); + size_t flen = len; + start = millis(); + Serial.print("- reading" ); + while(len){ + size_t toRead = len; + if(toRead > 512){ + toRead = 512; + } + file.read(buf, toRead); + if ((i++ & 0x001F) == 0x001F){ + Serial.print("."); + } + len -= toRead; + } + Serial.println(""); + end = millis() - start; + Serial.printf("- %u bytes read in %u ms\r\n", flen, end); + file.close(); + } else { + Serial.println("- failed to open file for reading"); + } +} + +void setup(){ + Serial.begin(115200); + Serial.setDebugOutput(true); + if (FORMAT_FFAT) FFat.format(); + if(!FFat.begin()){ + Serial.println("FFat Mount Failed"); + return; + } + + Serial.printf("Total space: %10lu\n", FFat.totalBytes()); + Serial.printf("Free space: %10lu\n", FFat.freeBytes()); + listDir(FFat, "/", 0); + writeFile(FFat, "/hello.txt", "Hello "); + appendFile(FFat, "/hello.txt", "World!\r\n"); + readFile(FFat, "/hello.txt"); + renameFile(FFat, "/hello.txt", "/foo.txt"); + readFile(FFat, "/foo.txt"); + deleteFile(FFat, "/foo.txt"); + testFileIO(FFat, "/test.txt"); + Serial.printf("Free space: %10lu\n", FFat.freeBytes()); + deleteFile(FFat, "/test.txt"); + Serial.println( "Test complete" ); +} + +void loop(){ + +} diff --git a/libraries/FFat/library.properties b/libraries/FFat/library.properties new file mode 100644 index 00000000000..aebca39d950 --- /dev/null +++ b/libraries/FFat/library.properties @@ -0,0 +1,9 @@ +name=FFat +version=1.0 +author=Hristo Gochkov, Ivan Grokhtkov, Larry Bernstone +maintainer=Hristo Gochkov +sentence=ESP32 FAT on Flash File System +paragraph= +category=Data Storage +url= +architectures=esp32 diff --git a/libraries/FFat/src/FFat.cpp b/libraries/FFat/src/FFat.cpp new file mode 100644 index 00000000000..ac1130130e4 --- /dev/null +++ b/libraries/FFat/src/FFat.cpp @@ -0,0 +1,132 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "vfs_api.h" + +extern "C" { +#include +#include +#include +#include "esp_vfs_fat.h" +#include "diskio.h" +#include "diskio_wl.h" +#include "vfs_fat_internal.h" +} +#include "FFat.h" + +using namespace fs; + +F_Fat::F_Fat(FSImplPtr impl) + : FS(impl) +{} + +bool F_Fat::begin(bool formatOnFail, const char * basePath, uint8_t maxOpenFiles, const char * partitionLabel) +{ + if(_wl_handle){ + log_w("Already Mounted!"); + return true; + } + esp_vfs_fat_mount_config_t conf = { + .format_if_mount_failed = formatOnFail, + .max_files = maxOpenFiles + }; + + esp_err_t err = esp_vfs_fat_spiflash_mount(basePath, partitionLabel, &conf, &_wl_handle); + if(err){ + log_e("Mounting FatFlash failed! Error: %d", err); + return false; + } + _impl->mountpoint(basePath); + return true; +} + +void F_Fat::end() +{ + if(_wl_handle){ + esp_err_t err = esp_vfs_fat_spiflash_unmount(_impl->mountpoint(), _wl_handle); + if(err){ + log_e("Unmounting FatFlash failed! Error: %d", err); + return; + } + _wl_handle = NULL; + _impl->mountpoint(NULL); + } +} + +bool F_Fat::format(bool full_wipe, char* partitionLabel) +{ + esp_err_t result; + wl_handle_t temp_handle; + esp_vfs_fat_mount_config_t conf = { + .format_if_mount_failed = false, + .max_files = 1 + }; +// Attempt to mount to see if there is already data + esp_partition_subtype_t subtype = ESP_PARTITION_SUBTYPE_DATA_FAT; + const esp_partition_t *ffat_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, subtype, partitionLabel); + result = wl_mount(ffat_partition, &temp_handle); + + if (result == ESP_OK) { +// Wipe disk- quick just wipes the FAT. Full zeroes the whole disk + //result = esp_vfs_fat_spiflash_mount("/format_ffat", partitionLabel, &conf, &temp_handle); + uint32_t wipe_size = full_wipe ? wl_size(temp_handle) : 16384; + wl_erase_range(temp_handle, 0, wipe_size); + esp_vfs_fat_spiflash_unmount("/format_ffat", temp_handle); + } + conf.format_if_mount_failed = true; + result = esp_vfs_fat_spiflash_mount("/format_ffat", partitionLabel, &conf, &temp_handle); + esp_vfs_fat_spiflash_unmount("/format_ffat", temp_handle); + return result; +} + +size_t F_Fat::totalBytes() +{ + FATFS *fs; + DWORD free_clust, tot_sect, sect_size; + + BYTE pdrv = ff_diskio_get_pdrv_wl(_wl_handle); + char drv[3] = {(char)'0' + pdrv, ':', 0}; + FRESULT res = f_getfree(drv, &free_clust, &fs); + tot_sect = (fs->n_fatent - 2) * fs->csize; + sect_size=CONFIG_WL_SECTOR_SIZE; + return tot_sect * sect_size; +} + +size_t F_Fat::freeBytes() +{ + + FATFS *fs; + DWORD free_clust, free_sect, sect_size; + + BYTE pdrv = ff_diskio_get_pdrv_wl(_wl_handle); + char drv[3] = {(char)'0' + pdrv, ':', 0}; + FRESULT res = f_getfree(drv, &free_clust, &fs); + free_sect = free_clust * fs->csize; + sect_size=CONFIG_WL_SECTOR_SIZE; + return free_sect * sect_size; +} + +bool F_Fat::exists(const char* path) +{ + File f = open(path, "r"); + return (f == true) && !f.isDirectory(); +} + +bool F_Fat::exists(const String& path) +{ + return exists(path.c_str()); +} + + +F_Fat FFat = F_Fat(FSImplPtr(new VFSImpl())); diff --git a/libraries/FFat/src/FFat.h b/libraries/FFat/src/FFat.h new file mode 100644 index 00000000000..4d670efafb9 --- /dev/null +++ b/libraries/FFat/src/FFat.h @@ -0,0 +1,47 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _FFAT_H_ +#define _FFAT_H_ + +#include "FS.h" +#include "wear_levelling.h" + +#define FFAT_WIPE_QUICK 0 +#define FFAT_WIPE_FULL 1 +#define FFAT_PARTITION_LABEL "ffat" + +namespace fs +{ + +class F_Fat : public FS +{ +public: + F_Fat(FSImplPtr impl); + bool begin(bool formatOnFail=false, const char * basePath="/ffat", uint8_t maxOpenFiles=10, const char * partitionLabel = FFAT_PARTITION_LABEL); + bool format(bool full_wipe = FFAT_WIPE_QUICK, char* partitionLabel = FFAT_PARTITION_LABEL); + size_t totalBytes(); + size_t freeBytes(); + void end(); + bool exists(const char* path); + bool exists(const String& path); + +private: + wl_handle_t _wl_handle; +}; + +} + +extern fs::F_Fat FFat; + +#endif /* _FAT_FLASH_H_ */ diff --git a/libraries/WebServer/examples/FSBrowser/FSBrowser.ino b/libraries/WebServer/examples/FSBrowser/FSBrowser.ino index 9683d76aca3..45d9110a178 100644 --- a/libraries/WebServer/examples/FSBrowser/FSBrowser.ino +++ b/libraries/WebServer/examples/FSBrowser/FSBrowser.ino @@ -1,5 +1,5 @@ /* - FSWebServer - Example WebServer with SPIFFS backend for esp8266 + FSWebServer - Example WebServer with FS backend for esp8266/esp32 Copyright (c) 2015 Hristo Gochkov. All rights reserved. This file is part of the WebServer library for Arduino environment. @@ -26,14 +26,21 @@ #include #include #include -#include +#define FILESYSTEM SPIFFS +#define FORMAT_FILESYSTEM true #define DBG_OUTPUT_PORT Serial +#if FILESYSTEM == FFat +#include +#endif +#if FILESYSTEM == SPIFFS +#include +#endif + const char* ssid = "wifi-ssid"; const char* password = "wifi-password"; const char* host = "esp32fs"; - WebServer server(80); //holds the current upload File fsUploadFile; @@ -84,7 +91,7 @@ String getContentType(String filename) { bool exists(String path){ bool yes = false; - File file = SPIFFS.open(path, "r"); + File file = FILESYSTEM.open(path, "r"); if(!file.isDirectory()){ yes = true; } @@ -103,7 +110,7 @@ bool handleFileRead(String path) { if (exists(pathWithGz)) { path += ".gz"; } - File file = SPIFFS.open(path, "r"); + File file = FILESYSTEM.open(path, "r"); server.streamFile(file, contentType); file.close(); return true; @@ -122,7 +129,7 @@ void handleFileUpload() { filename = "/" + filename; } DBG_OUTPUT_PORT.print("handleFileUpload Name: "); DBG_OUTPUT_PORT.println(filename); - fsUploadFile = SPIFFS.open(filename, "w"); + fsUploadFile = FILESYSTEM.open(filename, "w"); filename = String(); } else if (upload.status == UPLOAD_FILE_WRITE) { //DBG_OUTPUT_PORT.print("handleFileUpload Data: "); DBG_OUTPUT_PORT.println(upload.currentSize); @@ -149,7 +156,7 @@ void handleFileDelete() { if (!exists(path)) { return server.send(404, "text/plain", "FileNotFound"); } - SPIFFS.remove(path); + FILESYSTEM.remove(path); server.send(200, "text/plain", ""); path = String(); } @@ -166,7 +173,7 @@ void handleFileCreate() { if (exists(path)) { return server.send(500, "text/plain", "FILE EXISTS"); } - File file = SPIFFS.open(path, "w"); + File file = FILESYSTEM.open(path, "w"); if (file) { file.close(); } else { @@ -186,7 +193,7 @@ void handleFileList() { DBG_OUTPUT_PORT.println("handleFileList: " + path); - File root = SPIFFS.open(path); + File root = FILESYSTEM.open(path); path = String(); String output = "["; @@ -212,9 +219,10 @@ void setup(void) { DBG_OUTPUT_PORT.begin(115200); DBG_OUTPUT_PORT.print("\n"); DBG_OUTPUT_PORT.setDebugOutput(true); - SPIFFS.begin(); + if (FORMAT_FILESYSTEM) FILESYSTEM.format(); + FILESYSTEM.begin(); { - File root = SPIFFS.open("/"); + File root = FILESYSTEM.open("/"); File file = root.openNextFile(); while(file){ String fileName = file.name(); @@ -267,7 +275,7 @@ void setup(void) { }, handleFileUpload); //called when the url is not defined here - //use it to load content from SPIFFS + //use it to load content from FILESYSTEM server.onNotFound([]() { if (!handleFileRead(server.uri())) { server.send(404, "text/plain", "FileNotFound"); diff --git a/tools/partitions/ffat.csv b/tools/partitions/ffat.csv new file mode 100644 index 00000000000..43e26fbc08f --- /dev/null +++ b/tools/partitions/ffat.csv @@ -0,0 +1,7 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +otadata, data, ota, 0xe000, 0x2000, +app0, app, ota_0, 0x10000, 0x200000, +app1, app, ota_1, 0x210000,0x200000, +eeprom, data, 0x99, 0x410000,0x1000, +ffat, data, fat, 0x411000,0xBEE000, From 297ce448e99e6ebdd14b8c707e1b1b610c7792db Mon Sep 17 00:00:00 2001 From: Larry Bernstone Date: Mon, 27 Aug 2018 12:52:31 -0600 Subject: [PATCH 2/7] Fixed reboot loops if no fat present. Added CMakeLists --- CMakeLists.txt | 2 ++ libraries/FFat/src/FFat.cpp | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e0d89a796b..5b33b4b829d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,6 +40,7 @@ set(LIBRARY_SRCS libraries/DNSServer/src/DNSServer.cpp libraries/EEPROM/EEPROM.cpp libraries/ESPmDNS/src/ESPmDNS.cpp + libraries/FFat/src/FFat.cpp libraries/FS/src/FS.cpp libraries/FS/src/vfs_api.cpp libraries/HTTPClient/src/HTTPClient.cpp @@ -175,6 +176,7 @@ set(COMPONENT_ADD_INCLUDEDIRS libraries/DNSServer/src libraries/ESP32/src libraries/ESPmDNS/src + libraries/FFat/src libraries/FS/src libraries/HTTPClient/src libraries/NetBIOS/src diff --git a/libraries/FFat/src/FFat.cpp b/libraries/FFat/src/FFat.cpp index ac1130130e4..b25695899dc 100644 --- a/libraries/FFat/src/FFat.cpp +++ b/libraries/FFat/src/FFat.cpp @@ -37,6 +37,14 @@ bool F_Fat::begin(bool formatOnFail, const char * basePath, uint8_t maxOpenFiles log_w("Already Mounted!"); return true; } + + esp_partition_subtype_t subtype = ESP_PARTITION_SUBTYPE_DATA_FAT; + const esp_partition_t *ffat_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, subtype, partitionLabel); + if (!ffat_partition) { + log_e("No FAT partition found with label %s",partitionLabel); + return false; + } + esp_vfs_fat_mount_config_t conf = { .format_if_mount_failed = formatOnFail, .max_files = maxOpenFiles @@ -75,6 +83,10 @@ bool F_Fat::format(bool full_wipe, char* partitionLabel) // Attempt to mount to see if there is already data esp_partition_subtype_t subtype = ESP_PARTITION_SUBTYPE_DATA_FAT; const esp_partition_t *ffat_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, subtype, partitionLabel); + if (!ffat_partition) { + log_e("No FAT partition found with label %s",partitionLabel); + return false; + } result = wl_mount(ffat_partition, &temp_handle); if (result == ESP_OK) { From 27a88e1557d6118b920324e002f2dc5fbb33b127 Mon Sep 17 00:00:00 2001 From: Larry Bernstone Date: Mon, 27 Aug 2018 17:34:35 -0600 Subject: [PATCH 3/7] Functionalize the partition checks --- libraries/FFat/src/FFat.cpp | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/libraries/FFat/src/FFat.cpp b/libraries/FFat/src/FFat.cpp index b25695899dc..30749ca3893 100644 --- a/libraries/FFat/src/FFat.cpp +++ b/libraries/FFat/src/FFat.cpp @@ -31,6 +31,17 @@ F_Fat::F_Fat(FSImplPtr impl) : FS(impl) {} +const esp_partition_t *check_partition(const char* label) +{ + const esp_partition_t* ck_part = esp_partition_find_first( + ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, label); + if (!ck_part) { + log_e("No FAT partition found with label %s", label); + return false; + } + return ck_part; +} + bool F_Fat::begin(bool formatOnFail, const char * basePath, uint8_t maxOpenFiles, const char * partitionLabel) { if(_wl_handle){ @@ -38,12 +49,7 @@ bool F_Fat::begin(bool formatOnFail, const char * basePath, uint8_t maxOpenFiles return true; } - esp_partition_subtype_t subtype = ESP_PARTITION_SUBTYPE_DATA_FAT; - const esp_partition_t *ffat_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, subtype, partitionLabel); - if (!ffat_partition) { - log_e("No FAT partition found with label %s",partitionLabel); - return false; - } + if (!check_partition(partitionLabel)) return false; esp_vfs_fat_mount_config_t conf = { .format_if_mount_failed = formatOnFail, @@ -81,12 +87,8 @@ bool F_Fat::format(bool full_wipe, char* partitionLabel) .max_files = 1 }; // Attempt to mount to see if there is already data - esp_partition_subtype_t subtype = ESP_PARTITION_SUBTYPE_DATA_FAT; - const esp_partition_t *ffat_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, subtype, partitionLabel); - if (!ffat_partition) { - log_e("No FAT partition found with label %s",partitionLabel); - return false; - } + const esp_partition_t *ffat_partition = check_partition(partitionLabel); + if (!ffat_partition) return false; result = wl_mount(ffat_partition, &temp_handle); if (result == ESP_OK) { From ef549b586a7ab4f12e6976629f1d9730760c6d51 Mon Sep 17 00:00:00 2001 From: Larry Bernstone Date: Mon, 27 Aug 2018 19:24:10 -0600 Subject: [PATCH 4/7] Cleanup, especially in format --- libraries/FFat/src/FFat.cpp | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/libraries/FFat/src/FFat.cpp b/libraries/FFat/src/FFat.cpp index 30749ca3893..8ffac3b55c0 100644 --- a/libraries/FFat/src/FFat.cpp +++ b/libraries/FFat/src/FFat.cpp @@ -13,11 +13,7 @@ // limitations under the License. #include "vfs_api.h" - extern "C" { -#include -#include -#include #include "esp_vfs_fat.h" #include "diskio.h" #include "diskio_wl.h" @@ -31,7 +27,7 @@ F_Fat::F_Fat(FSImplPtr impl) : FS(impl) {} -const esp_partition_t *check_partition(const char* label) +const esp_partition_t *check_ffat_partition(const char* label) { const esp_partition_t* ck_part = esp_partition_find_first( ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, label); @@ -49,13 +45,12 @@ bool F_Fat::begin(bool formatOnFail, const char * basePath, uint8_t maxOpenFiles return true; } - if (!check_partition(partitionLabel)) return false; + if (!check_ffat_partition(partitionLabel)) return false; esp_vfs_fat_mount_config_t conf = { .format_if_mount_failed = formatOnFail, .max_files = maxOpenFiles }; - esp_err_t err = esp_vfs_fat_spiflash_mount(basePath, partitionLabel, &conf, &_wl_handle); if(err){ log_e("Mounting FatFlash failed! Error: %d", err); @@ -82,23 +77,22 @@ bool F_Fat::format(bool full_wipe, char* partitionLabel) { esp_err_t result; wl_handle_t temp_handle; - esp_vfs_fat_mount_config_t conf = { - .format_if_mount_failed = false, - .max_files = 1 - }; // Attempt to mount to see if there is already data - const esp_partition_t *ffat_partition = check_partition(partitionLabel); + const esp_partition_t *ffat_partition = check_ffat_partition(partitionLabel); if (!ffat_partition) return false; result = wl_mount(ffat_partition, &temp_handle); if (result == ESP_OK) { // Wipe disk- quick just wipes the FAT. Full zeroes the whole disk - //result = esp_vfs_fat_spiflash_mount("/format_ffat", partitionLabel, &conf, &temp_handle); uint32_t wipe_size = full_wipe ? wl_size(temp_handle) : 16384; wl_erase_range(temp_handle, 0, wipe_size); - esp_vfs_fat_spiflash_unmount("/format_ffat", temp_handle); + wl_unmount(temp_handle); } - conf.format_if_mount_failed = true; +// Now do a mount with format_if_fail (which it will) + esp_vfs_fat_mount_config_t conf = { + .format_if_mount_failed = true, + .max_files = 1 + }; result = esp_vfs_fat_spiflash_mount("/format_ffat", partitionLabel, &conf, &temp_handle); esp_vfs_fat_spiflash_unmount("/format_ffat", temp_handle); return result; From 4cfbccc7b0bc905907d509c2f60187a01afa9084 Mon Sep 17 00:00:00 2001 From: Larry Bernstone Date: Fri, 31 Aug 2018 10:10:03 -0600 Subject: [PATCH 5/7] Dont format if mounted. More wording cleanup --- libraries/FFat/examples/FFat_Test/FFat_Test.ino | 4 +--- libraries/FFat/src/FFat.cpp | 12 ++++++++---- libraries/FFat/src/FFat.h | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/libraries/FFat/examples/FFat_Test/FFat_Test.ino b/libraries/FFat/examples/FFat_Test/FFat_Test.ino index 84c2e1ca888..1206da76b94 100644 --- a/libraries/FFat/examples/FFat_Test/FFat_Test.ino +++ b/libraries/FFat/examples/FFat_Test/FFat_Test.ino @@ -1,9 +1,7 @@ #include "FS.h" #include "FFat.h" -/* You only need to format FFat the first time you run a - test or else use the FFat plugin to create a partition - https://github.com/me-no-dev/arduino-esp32fs-plugin */ +// You only need to format FFat the first time you run a test #define FORMAT_FFAT true void listDir(fs::FS &fs, const char * dirname, uint8_t levels){ diff --git a/libraries/FFat/src/FFat.cpp b/libraries/FFat/src/FFat.cpp index 8ffac3b55c0..cb8dc6d41b4 100644 --- a/libraries/FFat/src/FFat.cpp +++ b/libraries/FFat/src/FFat.cpp @@ -53,7 +53,7 @@ bool F_Fat::begin(bool formatOnFail, const char * basePath, uint8_t maxOpenFiles }; esp_err_t err = esp_vfs_fat_spiflash_mount(basePath, partitionLabel, &conf, &_wl_handle); if(err){ - log_e("Mounting FatFlash failed! Error: %d", err); + log_e("Mounting FFat partition failed! Error: %d", err); return false; } _impl->mountpoint(basePath); @@ -65,7 +65,7 @@ void F_Fat::end() if(_wl_handle){ esp_err_t err = esp_vfs_fat_spiflash_unmount(_impl->mountpoint(), _wl_handle); if(err){ - log_e("Unmounting FatFlash failed! Error: %d", err); + log_e("Unmounting FFat partition failed! Error: %d", err); return; } _wl_handle = NULL; @@ -76,6 +76,10 @@ void F_Fat::end() bool F_Fat::format(bool full_wipe, char* partitionLabel) { esp_err_t result; + if(_wl_handle){ + log_w("Already Mounted!"); + return false; + } wl_handle_t temp_handle; // Attempt to mount to see if there is already data const esp_partition_t *ffat_partition = check_ffat_partition(partitionLabel); @@ -107,7 +111,7 @@ size_t F_Fat::totalBytes() char drv[3] = {(char)'0' + pdrv, ':', 0}; FRESULT res = f_getfree(drv, &free_clust, &fs); tot_sect = (fs->n_fatent - 2) * fs->csize; - sect_size=CONFIG_WL_SECTOR_SIZE; + sect_size = CONFIG_WL_SECTOR_SIZE; return tot_sect * sect_size; } @@ -121,7 +125,7 @@ size_t F_Fat::freeBytes() char drv[3] = {(char)'0' + pdrv, ':', 0}; FRESULT res = f_getfree(drv, &free_clust, &fs); free_sect = free_clust * fs->csize; - sect_size=CONFIG_WL_SECTOR_SIZE; + sect_size = CONFIG_WL_SECTOR_SIZE; return free_sect * sect_size; } diff --git a/libraries/FFat/src/FFat.h b/libraries/FFat/src/FFat.h index 4d670efafb9..bcc8e47248d 100644 --- a/libraries/FFat/src/FFat.h +++ b/libraries/FFat/src/FFat.h @@ -44,4 +44,4 @@ class F_Fat : public FS extern fs::F_Fat FFat; -#endif /* _FAT_FLASH_H_ */ +#endif /* _FFAT_H_ */ From 7b8f8a4c35dfeb6a4798ba0f047a5689090e5d04 Mon Sep 17 00:00:00 2001 From: Larry Bernstone Date: Tue, 4 Sep 2018 15:42:13 -0600 Subject: [PATCH 6/7] 16M ffat should only be on 16M board --- boards.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards.txt b/boards.txt index 6e397d0c152..a4b4ec02a4c 100644 --- a/boards.txt +++ b/boards.txt @@ -74,7 +74,7 @@ esp32.menu.FlashSize.2M.build.flash_size=2MB esp32.menu.FlashSize.2M.build.partitions=minimal esp32.menu.FlashSize.16M=16MB (128Mb) esp32.menu.FlashSize.16M.build.flash_size=16MB -esp32.menu.FlashSize.2M.build.partitions=ffat +esp32.menu.FlashSize.16M.build.partitions=ffat esp32.menu.UploadSpeed.921600=921600 esp32.menu.UploadSpeed.921600.upload.speed=921600 From 5c9511dbba37ec8a60d4941ca6c489a26e7de34e Mon Sep 17 00:00:00 2001 From: Larry Bernstone Date: Mon, 10 Sep 2018 20:08:17 -0600 Subject: [PATCH 7/7] Fix some casting issues that trip up the compiler when building as ESP-IDF component --- libraries/FFat/src/FFat.cpp | 6 +++--- libraries/FFat/src/FFat.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/FFat/src/FFat.cpp b/libraries/FFat/src/FFat.cpp index cb8dc6d41b4..a7a03ac2de1 100644 --- a/libraries/FFat/src/FFat.cpp +++ b/libraries/FFat/src/FFat.cpp @@ -33,7 +33,7 @@ const esp_partition_t *check_ffat_partition(const char* label) ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, label); if (!ck_part) { log_e("No FAT partition found with label %s", label); - return false; + return NULL; } return ck_part; } @@ -108,7 +108,7 @@ size_t F_Fat::totalBytes() DWORD free_clust, tot_sect, sect_size; BYTE pdrv = ff_diskio_get_pdrv_wl(_wl_handle); - char drv[3] = {(char)'0' + pdrv, ':', 0}; + char drv[3] = {(char)(48+pdrv), ':', 0}; FRESULT res = f_getfree(drv, &free_clust, &fs); tot_sect = (fs->n_fatent - 2) * fs->csize; sect_size = CONFIG_WL_SECTOR_SIZE; @@ -122,7 +122,7 @@ size_t F_Fat::freeBytes() DWORD free_clust, free_sect, sect_size; BYTE pdrv = ff_diskio_get_pdrv_wl(_wl_handle); - char drv[3] = {(char)'0' + pdrv, ':', 0}; + char drv[3] = {(char)(48+pdrv), ':', 0}; FRESULT res = f_getfree(drv, &free_clust, &fs); free_sect = free_clust * fs->csize; sect_size = CONFIG_WL_SECTOR_SIZE; diff --git a/libraries/FFat/src/FFat.h b/libraries/FFat/src/FFat.h index bcc8e47248d..7a5499efacb 100644 --- a/libraries/FFat/src/FFat.h +++ b/libraries/FFat/src/FFat.h @@ -28,8 +28,8 @@ class F_Fat : public FS { public: F_Fat(FSImplPtr impl); - bool begin(bool formatOnFail=false, const char * basePath="/ffat", uint8_t maxOpenFiles=10, const char * partitionLabel = FFAT_PARTITION_LABEL); - bool format(bool full_wipe = FFAT_WIPE_QUICK, char* partitionLabel = FFAT_PARTITION_LABEL); + bool begin(bool formatOnFail=false, const char * basePath="/ffat", uint8_t maxOpenFiles=10, const char * partitionLabel = (char*)FFAT_PARTITION_LABEL); + bool format(bool full_wipe = FFAT_WIPE_QUICK, char* partitionLabel = (char*)FFAT_PARTITION_LABEL); size_t totalBytes(); size_t freeBytes(); void end();