From 82ef7490bc115bf450eb8030e8286b1fbb844f5b Mon Sep 17 00:00:00 2001 From: RevoluPowered Date: Sun, 9 Jun 2019 00:47:31 +0100 Subject: [PATCH 1/4] Added format if mount failed as optional argument to SD_MMC begin. SDMMC_HOST_DEFAULT is now set up as the normal SD card configuration. slot_config.width = 1 is now set too as per the documentation. --- libraries/SD_MMC/src/SD_MMC.cpp | 28 ++++++++-------------------- libraries/SD_MMC/src/SD_MMC.h | 2 +- 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/libraries/SD_MMC/src/SD_MMC.cpp b/libraries/SD_MMC/src/SD_MMC.cpp index 4de467304e5..355051f1881 100644 --- a/libraries/SD_MMC/src/SD_MMC.cpp +++ b/libraries/SD_MMC/src/SD_MMC.cpp @@ -35,41 +35,29 @@ SDMMCFS::SDMMCFS(FSImplPtr impl) : FS(impl), _card(NULL) {} -bool SDMMCFS::begin(const char * mountpoint, bool mode1bit) +bool SDMMCFS::begin(const char * mountpoint, bool mode1bit, bool format_if_mount_failed) { if(_card) { return true; } //mount sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); - sdmmc_host_t host = { - .flags = SDMMC_HOST_FLAG_4BIT, - .slot = SDMMC_HOST_SLOT_1, - .max_freq_khz = SDMMC_FREQ_DEFAULT, - .io_voltage = 3.3f, - .init = &sdmmc_host_init, - .set_bus_width = &sdmmc_host_set_bus_width, - .get_bus_width = &sdmmc_host_get_slot_width, - .set_bus_ddr_mode = &sdmmc_host_set_bus_ddr_mode, - .set_card_clk = &sdmmc_host_set_card_clk, - .do_transaction = &sdmmc_host_do_transaction, - .deinit = &sdmmc_host_deinit, - .io_int_enable = &sdmmc_host_io_int_enable, - .io_int_wait = &sdmmc_host_io_int_wait, - .command_timeout_ms = 0 - }; + sdmmc_host_t host = SDMMC_HOST_DEFAULT(); + host.max_freq_khz = SDMMC_FREQ_HIGHSPEED; #ifdef BOARD_HAS_1BIT_SDMMC mode1bit = true; #endif if(mode1bit) { - host.flags = SDMMC_HOST_FLAG_1BIT; //use 1-line SD mode + log_w("SDMMC 1 bit flag enabled"); + slot_config.flags = SDMMC_HOST_FLAG_1BIT; //use 1-line SD mode + slot_config.width = 1; } esp_vfs_fat_sdmmc_mount_config_t mount_config = { - .format_if_mount_failed = false, + .format_if_mount_failed = format_if_mount_failed, .max_files = 5, - .allocation_unit_size = 0 + .allocation_unit_size = 64 * 1024 // recommended default from ESP32 IDF examples }; esp_err_t ret = esp_vfs_fat_sdmmc_mount(mountpoint, &host, &slot_config, &mount_config, &_card); diff --git a/libraries/SD_MMC/src/SD_MMC.h b/libraries/SD_MMC/src/SD_MMC.h index e3dc15432a5..3afb1e9d638 100644 --- a/libraries/SD_MMC/src/SD_MMC.h +++ b/libraries/SD_MMC/src/SD_MMC.h @@ -28,7 +28,7 @@ class SDMMCFS : public FS public: SDMMCFS(FSImplPtr impl); - bool begin(const char * mountpoint="/sdcard", bool mode1bit=false); + bool begin(const char * mountpoint="/sdcard", bool mode1bit=false, bool format_if_mount_failed = false); void end(); sdcard_type_t cardType(); uint64_t cardSize(); From 21e3188574cbefa3b9727ec69a588f13aa3dcdb4 Mon Sep 17 00:00:00 2001 From: RevoluPowered Date: Sun, 9 Jun 2019 02:40:37 +0100 Subject: [PATCH 2/4] WIP commit for implementation of SD and FS performance increases on the ESP32 platfor --- libraries/FS.slow/library.properties | 9 + libraries/FS.slow/src/FS.cpp | 269 ++++++++++++ libraries/FS.slow/src/FS.h | 125 ++++++ libraries/{FS => FS.slow}/src/FSImpl.h | 0 libraries/{FS => FS.slow}/src/vfs_api.cpp | 13 +- libraries/{FS => FS.slow}/src/vfs_api.h | 0 libraries/FS/library.properties | 10 +- libraries/FS/src/FS.cpp | 488 +++++++++++----------- libraries/FS/src/FS.h | 31 +- libraries/SD/README.md | 42 -- 10 files changed, 675 insertions(+), 312 deletions(-) create mode 100644 libraries/FS.slow/library.properties create mode 100644 libraries/FS.slow/src/FS.cpp create mode 100644 libraries/FS.slow/src/FS.h rename libraries/{FS => FS.slow}/src/FSImpl.h (100%) rename libraries/{FS => FS.slow}/src/vfs_api.cpp (96%) rename libraries/{FS => FS.slow}/src/vfs_api.h (100%) delete mode 100644 libraries/SD/README.md diff --git a/libraries/FS.slow/library.properties b/libraries/FS.slow/library.properties new file mode 100644 index 00000000000..fb35385ba24 --- /dev/null +++ b/libraries/FS.slow/library.properties @@ -0,0 +1,9 @@ +name=FS +version=1.0 +author=Hristo Gochkov, Ivan Grokhtkov +maintainer=Hristo Gochkov +sentence=ESP32 File System +paragraph= +category=Data Storage +url= +architectures=esp32 diff --git a/libraries/FS.slow/src/FS.cpp b/libraries/FS.slow/src/FS.cpp new file mode 100644 index 00000000000..ab4f5d5289a --- /dev/null +++ b/libraries/FS.slow/src/FS.cpp @@ -0,0 +1,269 @@ +/* + 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 "FS.h" +#include "FSImpl.h" + +using namespace fs; + +size_t File::write(uint8_t c) +{ + if (!_p) { + return 0; + } + + return _p->write(&c, 1); +} + +time_t File::getLastWrite() +{ + if (!_p) { + return 0; + } + + return _p->getLastWrite(); +} + +size_t File::write(const uint8_t *buf, size_t size) +{ + if (!_p) { + return 0; + } + + return _p->write(buf, size); +} + +int File::available() +{ + if (!_p) { + return false; + } + + return _p->size() - _p->position(); +} + +int File::read() +{ + if (!_p) { + return -1; + } + + uint8_t result; + if (_p->read(&result, 1) != 1) { + return -1; + } + + return result; +} + +size_t File::read(uint8_t* buf, size_t size) +{ + if (!_p) { + return -1; + } + + return _p->read(buf, size); +} + +int File::peek() +{ + if (!_p) { + return -1; + } + + size_t curPos = _p->position(); + int result = read(); + seek(curPos, SeekSet); + return result; +} + +void File::flush() +{ + if (!_p) { + return; + } + + _p->flush(); +} + +bool File::seek(uint32_t pos, SeekMode mode) +{ + if (!_p) { + return false; + } + + return _p->seek(pos, mode); +} + +size_t File::position() const +{ + if (!_p) { + return 0; + } + + return _p->position(); +} + +size_t File::size() const +{ + if (!_p) { + return 0; + } + + return _p->size(); +} + +void File::close() +{ + if (_p) { + _p->close(); + _p = nullptr; + } +} + +File::operator bool() const +{ + return !!_p; +} + +const char* File::name() const +{ + if (!_p) { + return nullptr; + } + + return _p->name(); +} + +//to implement +boolean File::isDirectory(void) +{ + if (!_p) { + return false; + } + return _p->isDirectory(); +} + +File File::openNextFile(const char* mode) +{ + if (!_p) { + return File(); + } + return _p->openNextFile(mode); +} + +void File::rewindDirectory(void) +{ + if (!_p) { + return; + } + _p->rewindDirectory(); +} + +File FS::open(const String& path, const char* mode) +{ + return open(path.c_str(), mode); +} + +File FS::open(const char* path, const char* mode) +{ + if (!_impl) { + return File(); + } + + return File(_impl->open(path, mode)); +} + +bool FS::exists(const char* path) +{ + if (!_impl) { + return false; + } + return _impl->exists(path); +} + +bool FS::exists(const String& path) +{ + return exists(path.c_str()); +} + +bool FS::remove(const char* path) +{ + if (!_impl) { + return false; + } + return _impl->remove(path); +} + +bool FS::remove(const String& path) +{ + return remove(path.c_str()); +} + +bool FS::rename(const char* pathFrom, const char* pathTo) +{ + if (!_impl) { + return false; + } + return _impl->rename(pathFrom, pathTo); +} + +bool FS::rename(const String& pathFrom, const String& pathTo) +{ + return rename(pathFrom.c_str(), pathTo.c_str()); +} + + +bool FS::mkdir(const char *path) +{ + if (!_impl) { + return false; + } + return _impl->mkdir(path); +} + +bool FS::mkdir(const String &path) +{ + return mkdir(path.c_str()); +} + +bool FS::rmdir(const char *path) +{ + if (!_impl) { + return false; + } + return _impl->rmdir(path); +} + +bool FS::rmdir(const String &path) +{ + return rmdir(path.c_str()); +} + + +void FSImpl::mountpoint(const char * mp) +{ + _mountpoint = mp; +} + +const char * FSImpl::mountpoint() +{ + return _mountpoint; +} diff --git a/libraries/FS.slow/src/FS.h b/libraries/FS.slow/src/FS.h new file mode 100644 index 00000000000..ab02b1547c3 --- /dev/null +++ b/libraries/FS.slow/src/FS.h @@ -0,0 +1,125 @@ +/* + FS.h - 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 + */ + +#ifndef FS_H +#define FS_H + +#include +#include + +namespace fs +{ + +#define FILE_READ "r" +#define FILE_WRITE "w" +#define FILE_APPEND "a" + +class File; + +class FileImpl; +typedef std::unique_ptr FileImplPtr; +class FSImpl; +typedef std::unique_ptr FSImplPtr; + +enum SeekMode { + SeekSet = 0, + SeekCur = 1, + SeekEnd = 2 +}; + +class File : public Stream +{ +public: + File(FileImplPtr p = FileImplPtr()) : _p(p) { + _timeout = 0; + } + + size_t write(uint8_t) override; + size_t write(const uint8_t *buf, size_t size) override; + int available() override; + int read() override; + int peek() override; + void flush() override; + size_t read(uint8_t* buf, size_t size); + size_t readBytes(char *buffer, size_t length) + { + return read((uint8_t*)buffer, length); + } + + bool seek(uint32_t pos, SeekMode mode); + bool seek(uint32_t pos) + { + return seek(pos, SeekSet); + } + size_t position() const; + size_t size() const; + void close(); + operator bool() const; + time_t getLastWrite(); + const char* name() const; + + boolean isDirectory(void); + File openNextFile(const char* mode = FILE_READ); + void rewindDirectory(void); + +protected: + FileImplPtr _p; +}; + +class FS +{ +public: + FS(FSImplPtr impl) : _impl(impl) { } + + File open(const char* path, const char* mode = FILE_READ); + File open(const String& path, const char* mode = FILE_READ); + + bool exists(const char* path); + bool exists(const String& path); + + bool remove(const char* path); + bool remove(const String& path); + + bool rename(const char* pathFrom, const char* pathTo); + bool rename(const String& pathFrom, const String& pathTo); + + bool mkdir(const char *path); + bool mkdir(const String &path); + + bool rmdir(const char *path); + bool rmdir(const String &path); + + +protected: + FSImplPtr _impl; +}; + +} // namespace fs + +#ifndef FS_NO_GLOBALS +using fs::FS; +using fs::File; +using fs::SeekMode; +using fs::SeekSet; +using fs::SeekCur; +using fs::SeekEnd; +#endif //FS_NO_GLOBALS + +#endif //FS_H diff --git a/libraries/FS/src/FSImpl.h b/libraries/FS.slow/src/FSImpl.h similarity index 100% rename from libraries/FS/src/FSImpl.h rename to libraries/FS.slow/src/FSImpl.h diff --git a/libraries/FS/src/vfs_api.cpp b/libraries/FS.slow/src/vfs_api.cpp similarity index 96% rename from libraries/FS/src/vfs_api.cpp rename to libraries/FS.slow/src/vfs_api.cpp index 6502f760560..c999b0f8991 100644 --- a/libraries/FS/src/vfs_api.cpp +++ b/libraries/FS.slow/src/vfs_api.cpp @@ -41,7 +41,7 @@ FileImplPtr VFSImpl::open(const char* path, const char* mode) if(!stat(temp, &st)) { free(temp); if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)) { - return std::make_shared(this, path, mode); + return std::make_unique(this, path, mode); } log_e("%s has wrong mode 0x%08X", path, st.st_mode); return FileImplPtr(); @@ -50,7 +50,7 @@ FileImplPtr VFSImpl::open(const char* path, const char* mode) //file not found but mode permits creation if(mode && mode[0] != 'r') { free(temp); - return std::make_shared(this, path, mode); + return std::make_unique(this, path, mode); } //try to open this as directory (might be mount point) @@ -58,7 +58,7 @@ FileImplPtr VFSImpl::open(const char* path, const char* mode) if(d) { closedir(d); free(temp); - return std::make_shared(this, path, mode); + return std::make_unique(this, path, mode); } log_e("%s does not exist", temp); @@ -323,6 +323,9 @@ size_t VFSFileImpl::write(const uint8_t *buf, size_t size) } _written = true; return fwrite(buf, 1, size, _f); + + //return ::write(fileno(_f), buf, 1); + } size_t VFSFileImpl::read(uint8_t* buf, size_t size) @@ -330,7 +333,7 @@ size_t VFSFileImpl::read(uint8_t* buf, size_t size) if(_isDirectory || !_f || !buf || !size) { return 0; } - + //return ::read(fileno(_f), buf, 1); return fread(buf, 1, size, _f); } @@ -402,7 +405,7 @@ FileImplPtr VFSFileImpl::openNextFile(const char* mode) } name += fname; - return std::make_shared(_fs, name.c_str(), mode); + return std::make_unique(_fs, name.c_str(), mode); } void VFSFileImpl::rewindDirectory(void) diff --git a/libraries/FS/src/vfs_api.h b/libraries/FS.slow/src/vfs_api.h similarity index 100% rename from libraries/FS/src/vfs_api.h rename to libraries/FS.slow/src/vfs_api.h diff --git a/libraries/FS/library.properties b/libraries/FS/library.properties index fb35385ba24..e36c1e84f79 100644 --- a/libraries/FS/library.properties +++ b/libraries/FS/library.properties @@ -1,9 +1,9 @@ name=FS -version=1.0 -author=Hristo Gochkov, Ivan Grokhtkov -maintainer=Hristo Gochkov -sentence=ESP32 File System -paragraph= +version=0.1 +author=Gordon MacPherson +maintainer=Gordon MacPherson +sentence=Standard Filesystem IO for ESP32 +paragraph=Follows standard c practices as per ESP32 tool code examples to ensure fast read write speed category=Data Storage url= architectures=esp32 diff --git a/libraries/FS/src/FS.cpp b/libraries/FS/src/FS.cpp index ab4f5d5289a..a4354eac8ac 100644 --- a/libraries/FS/src/FS.cpp +++ b/libraries/FS/src/FS.cpp @@ -23,247 +23,247 @@ using namespace fs; -size_t File::write(uint8_t c) -{ - if (!_p) { - return 0; - } - - return _p->write(&c, 1); -} - -time_t File::getLastWrite() -{ - if (!_p) { - return 0; - } - - return _p->getLastWrite(); -} - -size_t File::write(const uint8_t *buf, size_t size) -{ - if (!_p) { - return 0; - } - - return _p->write(buf, size); -} - -int File::available() -{ - if (!_p) { - return false; - } - - return _p->size() - _p->position(); -} - -int File::read() -{ - if (!_p) { - return -1; - } - - uint8_t result; - if (_p->read(&result, 1) != 1) { - return -1; - } - - return result; -} - -size_t File::read(uint8_t* buf, size_t size) -{ - if (!_p) { - return -1; - } - - return _p->read(buf, size); -} - -int File::peek() -{ - if (!_p) { - return -1; - } - - size_t curPos = _p->position(); - int result = read(); - seek(curPos, SeekSet); - return result; -} - -void File::flush() -{ - if (!_p) { - return; - } - - _p->flush(); -} - -bool File::seek(uint32_t pos, SeekMode mode) -{ - if (!_p) { - return false; - } - - return _p->seek(pos, mode); -} - -size_t File::position() const -{ - if (!_p) { - return 0; - } - - return _p->position(); -} - -size_t File::size() const -{ - if (!_p) { - return 0; - } - - return _p->size(); -} - -void File::close() -{ - if (_p) { - _p->close(); - _p = nullptr; - } -} - -File::operator bool() const -{ - return !!_p; -} - -const char* File::name() const -{ - if (!_p) { - return nullptr; - } - - return _p->name(); -} - -//to implement -boolean File::isDirectory(void) -{ - if (!_p) { - return false; - } - return _p->isDirectory(); -} - -File File::openNextFile(const char* mode) -{ - if (!_p) { - return File(); - } - return _p->openNextFile(mode); -} - -void File::rewindDirectory(void) -{ - if (!_p) { - return; - } - _p->rewindDirectory(); -} - -File FS::open(const String& path, const char* mode) -{ - return open(path.c_str(), mode); -} - -File FS::open(const char* path, const char* mode) -{ - if (!_impl) { - return File(); - } - - return File(_impl->open(path, mode)); -} - -bool FS::exists(const char* path) -{ - if (!_impl) { - return false; - } - return _impl->exists(path); -} - -bool FS::exists(const String& path) -{ - return exists(path.c_str()); -} - -bool FS::remove(const char* path) -{ - if (!_impl) { - return false; - } - return _impl->remove(path); -} - -bool FS::remove(const String& path) -{ - return remove(path.c_str()); -} - -bool FS::rename(const char* pathFrom, const char* pathTo) -{ - if (!_impl) { - return false; - } - return _impl->rename(pathFrom, pathTo); -} - -bool FS::rename(const String& pathFrom, const String& pathTo) -{ - return rename(pathFrom.c_str(), pathTo.c_str()); -} - - -bool FS::mkdir(const char *path) -{ - if (!_impl) { - return false; - } - return _impl->mkdir(path); -} - -bool FS::mkdir(const String &path) -{ - return mkdir(path.c_str()); -} - -bool FS::rmdir(const char *path) -{ - if (!_impl) { - return false; - } - return _impl->rmdir(path); -} - -bool FS::rmdir(const String &path) -{ - return rmdir(path.c_str()); -} - - -void FSImpl::mountpoint(const char * mp) -{ - _mountpoint = mp; -} - -const char * FSImpl::mountpoint() -{ - return _mountpoint; -} +// size_t File::write(uint8_t c) +// { +// if (!_p) { +// return 0; +// } + +// return _p->write(&c, 1); +// } + +// time_t File::getLastWrite() +// { +// if (!_p) { +// return 0; +// } + +// return _p->getLastWrite(); +// } + +// size_t File::write(const uint8_t *buf, size_t size) +// { +// if (!_p) { +// return 0; +// } + +// return _p->write(buf, size); +// } + +// int File::available() +// { +// if (!_p) { +// return false; +// } + +// return _p->size() - _p->position(); +// } + +// int File::read() +// { +// if (!_p) { +// return -1; +// } + +// uint8_t result; +// if (_p->read(&result, 1) != 1) { +// return -1; +// } + +// return result; +// } + +// size_t File::read(uint8_t* buf, size_t size) +// { +// if (!_p) { +// return -1; +// } + +// return _p->read(buf, size); +// } + +// int File::peek() +// { +// if (!_p) { +// return -1; +// } + +// size_t curPos = _p->position(); +// int result = read(); +// seek(curPos, SeekSet); +// return result; +// } + +// void File::flush() +// { +// if (!_p) { +// return; +// } + +// _p->flush(); +// } + +// bool File::seek(uint32_t pos, SeekMode mode) +// { +// if (!_p) { +// return false; +// } + +// return _p->seek(pos, mode); +// } + +// size_t File::position() const +// { +// if (!_p) { +// return 0; +// } + +// return _p->position(); +// } + +// size_t File::size() const +// { +// if (!_p) { +// return 0; +// } + +// return _p->size(); +// } + +// void File::close() +// { +// if (_p) { +// _p->close(); +// _p = nullptr; +// } +// } + +// File::operator bool() const +// { +// return !!_p; +// } + +// const char* File::name() const +// { +// if (!_p) { +// return nullptr; +// } + +// return _p->name(); +// } + +// //to implement +// boolean File::isDirectory(void) +// { +// if (!_p) { +// return false; +// } +// return _p->isDirectory(); +// } + +// File File::openNextFile(const char* mode) +// { +// if (!_p) { +// return File(); +// } +// return _p->openNextFile(mode); +// } + +// void File::rewindDirectory(void) +// { +// if (!_p) { +// return; +// } +// _p->rewindDirectory(); +// } + +// File FS::open(const String& path, const char* mode) +// { +// return open(path.c_str(), mode); +// } + +// File FS::open(const char* path, const char* mode) +// { +// if (!_impl) { +// return File(); +// } + +// return File(_impl->open(path, mode)); +// } + +// bool FS::exists(const char* path) +// { +// if (!_impl) { +// return false; +// } +// return _impl->exists(path); +// } + +// bool FS::exists(const String& path) +// { +// return exists(path.c_str()); +// } + +// bool FS::remove(const char* path) +// { +// if (!_impl) { +// return false; +// } +// return _impl->remove(path); +// } + +// bool FS::remove(const String& path) +// { +// return remove(path.c_str()); +// } + +// bool FS::rename(const char* pathFrom, const char* pathTo) +// { +// if (!_impl) { +// return false; +// } +// return _impl->rename(pathFrom, pathTo); +// } + +// bool FS::rename(const String& pathFrom, const String& pathTo) +// { +// return rename(pathFrom.c_str(), pathTo.c_str()); +// } + + +// bool FS::mkdir(const char *path) +// { +// if (!_impl) { +// return false; +// } +// return _impl->mkdir(path); +// } + +// bool FS::mkdir(const String &path) +// { +// return mkdir(path.c_str()); +// } + +// bool FS::rmdir(const char *path) +// { +// if (!_impl) { +// return false; +// } +// return _impl->rmdir(path); +// } + +// bool FS::rmdir(const String &path) +// { +// return rmdir(path.c_str()); +// } + + +// void FSImpl::mountpoint(const char * mp) +// { +// _mountpoint = mp; +// } + +// const char * FSImpl::mountpoint() +// { +// return _mountpoint; +// } diff --git a/libraries/FS/src/FS.h b/libraries/FS/src/FS.h index d63fc5da305..3615663a749 100644 --- a/libraries/FS/src/FS.h +++ b/libraries/FS/src/FS.h @@ -21,11 +21,11 @@ #ifndef FS_H #define FS_H -#include -#include - -namespace fs -{ +extern "C" { +#include +#include +#include +} #define FILE_READ "r" #define FILE_WRITE "w" @@ -33,10 +33,6 @@ namespace fs class File; -class FileImpl; -typedef std::shared_ptr FileImplPtr; -class FSImpl; -typedef std::shared_ptr FSImplPtr; enum SeekMode { SeekSet = 0, @@ -47,7 +43,7 @@ enum SeekMode { class File : public Stream { public: - File(FileImplPtr p = FileImplPtr()) : _p(p) { + File(){ _timeout = 0; } @@ -78,15 +74,13 @@ class File : public Stream boolean isDirectory(void); File openNextFile(const char* mode = FILE_READ); void rewindDirectory(void); - -protected: - FileImplPtr _p; }; class FS { public: - FS(FSImplPtr impl) : _impl(impl) { } + FS() + {} File open(const char* path, const char* mode = FILE_READ); File open(const String& path, const char* mode = FILE_READ); @@ -106,9 +100,14 @@ class FS bool rmdir(const char *path); bool rmdir(const String &path); + FILE * _f; + DIR * _d; + char * _path; + bool _isDirectory; + mutable struct stat _stat; + mutable bool _written; -protected: - FSImplPtr _impl; + void _getStat() const; }; } // namespace fs diff --git a/libraries/SD/README.md b/libraries/SD/README.md deleted file mode 100644 index 2cc472dc809..00000000000 --- a/libraries/SD/README.md +++ /dev/null @@ -1,42 +0,0 @@ - -# SD library - -This library provides the integration of ESP32 and SD (Secure Digital) cards without additional modules. - - -## Sample wiring diagram: - - -![SD card pins](http://i.imgur.com/4CoXOuR.png) - -For others SD formats: - - -![Other SD card formats](https://upload.wikimedia.org/wikipedia/commons/thumb/a/ab/MMC-SD-miniSD-microSD-Color-Numbers-Names.gif/330px-MMC-SD-miniSD-microSD-Color-Numbers-Names.gif) - - -Image source: [Wikipedia](https://upload.wikimedia.org/wikipedia/commons/thumb/a/ab/MMC-SD-miniSD-microSD-Color-Numbers-Names.gif/330px-MMC-SD-miniSD-microSD-Color-Numbers-Names.gif) - -```diff -- Warning: Some ESP32 modules have different pinouts! -``` - - - -## FAQ: - -**Do I need any additional modules, like Arduino SD module?** - -No, just wire your SD card directly to ESP32. - - - -**What is the difference between SD and SD_MMC libraries?** - -SD runs on SPI, and SD_MMC uses the SDMMC hardware bus on the ESP32. - - - -**Can I change the CS pin?** - -Yes, just use: `SD.begin(CSpin)` From ac5ef067ae733bfda49cd05a9392edeb50c9272e Mon Sep 17 00:00:00 2001 From: RevoluPowered Date: Sun, 9 Jun 2019 20:10:27 +0100 Subject: [PATCH 3/4] WIP new template for format --- libraries/FS/src/FIleSystem.cpp | 190 +++++++++++++++++++++ libraries/FS/src/FS.cpp | 269 ------------------------------ libraries/FS/src/File.cpp | 210 +++++++++++++++++++++++ libraries/FS/src/{FS.h => File.h} | 50 +----- libraries/FS/src/FileSystem.h | 52 ++++++ 5 files changed, 453 insertions(+), 318 deletions(-) create mode 100644 libraries/FS/src/FIleSystem.cpp delete mode 100644 libraries/FS/src/FS.cpp create mode 100644 libraries/FS/src/File.cpp rename libraries/FS/src/{FS.h => File.h} (65%) create mode 100644 libraries/FS/src/FileSystem.h diff --git a/libraries/FS/src/FIleSystem.cpp b/libraries/FS/src/FIleSystem.cpp new file mode 100644 index 00000000000..a5058f112d7 --- /dev/null +++ b/libraries/FS/src/FIleSystem.cpp @@ -0,0 +1,190 @@ +#include "FileSystem.h" + +FileImplPtr VFSImpl::open(const char* path, const char* mode) +{ + if(!_mountpoint) { + log_e("File system is not mounted"); + return FileImplPtr(); + } + + if(!path || path[0] != '/') { + log_e("%s does not start with /", path); + return FileImplPtr(); + } + + char * temp = (char *)malloc(strlen(path)+strlen(_mountpoint)+2); + if(!temp) { + log_e("malloc failed"); + return FileImplPtr(); + } + + sprintf(temp,"%s%s", _mountpoint, path); + + struct stat st; + //file lound + if(!stat(temp, &st)) { + free(temp); + if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)) { + return std::make_unique(this, path, mode); + } + log_e("%s has wrong mode 0x%08X", path, st.st_mode); + return FileImplPtr(); + } + + //file not found but mode permits creation + if(mode && mode[0] != 'r') { + free(temp); + return std::make_unique(this, path, mode); + } + + //try to open this as directory (might be mount point) + DIR * d = opendir(temp); + if(d) { + closedir(d); + free(temp); + return std::make_unique(this, path, mode); + } + + log_e("%s does not exist", temp); + free(temp); + return FileImplPtr(); +} + +bool VFSImpl::exists(const char* path) +{ + if(!_mountpoint) { + log_e("File system is not mounted"); + return false; + } + + VFSFileImpl f(this, path, "r"); + if(f) { + f.close(); + return true; + } + return false; +} + +bool VFSImpl::rename(const char* pathFrom, const char* pathTo) +{ + if(!_mountpoint) { + log_e("File system is not mounted"); + return false; + } + + if(!pathFrom || pathFrom[0] != '/' || !pathTo || pathTo[0] != '/') { + log_e("bad arguments"); + return false; + } + if(!exists(pathFrom)) { + log_e("%s does not exists", pathFrom); + return false; + } + char * temp1 = (char *)malloc(strlen(pathFrom)+strlen(_mountpoint)+1); + if(!temp1) { + log_e("malloc failed"); + return false; + } + char * temp2 = (char *)malloc(strlen(pathTo)+strlen(_mountpoint)+1); + if(!temp2) { + free(temp1); + log_e("malloc failed"); + return false; + } + sprintf(temp1,"%s%s", _mountpoint, pathFrom); + sprintf(temp2,"%s%s", _mountpoint, pathTo); + auto rc = ::rename(temp1, temp2); + free(temp1); + free(temp2); + return rc == 0; +} + +bool VFSImpl::remove(const char* path) +{ + if(!_mountpoint) { + log_e("File system is not mounted"); + return false; + } + + if(!path || path[0] != '/') { + log_e("bad arguments"); + return false; + } + + VFSFileImpl f(this, path, "r"); + if(!f || f.isDirectory()) { + if(f) { + f.close(); + } + log_e("%s does not exists or is directory", path); + return false; + } + f.close(); + + char * temp = (char *)malloc(strlen(path)+strlen(_mountpoint)+1); + if(!temp) { + log_e("malloc failed"); + return false; + } + sprintf(temp,"%s%s", _mountpoint, path); + auto rc = unlink(temp); + free(temp); + return rc == 0; +} + +bool VFSImpl::mkdir(const char *path) +{ + if(!_mountpoint) { + log_e("File system is not mounted"); + return false; + } + + VFSFileImpl f(this, path, "r"); + if(f && f.isDirectory()) { + f.close(); + //log_w("%s already exists", path); + return true; + } else if(f) { + f.close(); + log_e("%s is a file", path); + return false; + } + + char * temp = (char *)malloc(strlen(path)+strlen(_mountpoint)+1); + if(!temp) { + log_e("malloc failed"); + return false; + } + sprintf(temp,"%s%s", _mountpoint, path); + auto rc = ::mkdir(temp, ACCESSPERMS); + free(temp); + return rc == 0; +} + +bool VFSImpl::rmdir(const char *path) +{ + if(!_mountpoint) { + log_e("File system is not mounted"); + return false; + } + + VFSFileImpl f(this, path, "r"); + if(!f || !f.isDirectory()) { + if(f) { + f.close(); + } + log_e("%s does not exists or is a file", path); + return false; + } + f.close(); + + char * temp = (char *)malloc(strlen(path)+strlen(_mountpoint)+1); + if(!temp) { + log_e("malloc failed"); + return false; + } + sprintf(temp,"%s%s", _mountpoint, path); + auto rc = unlink(temp); + free(temp); + return rc == 0; +} \ No newline at end of file diff --git a/libraries/FS/src/FS.cpp b/libraries/FS/src/FS.cpp deleted file mode 100644 index a4354eac8ac..00000000000 --- a/libraries/FS/src/FS.cpp +++ /dev/null @@ -1,269 +0,0 @@ -/* - 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 "FS.h" -#include "FSImpl.h" - -using namespace fs; - -// size_t File::write(uint8_t c) -// { -// if (!_p) { -// return 0; -// } - -// return _p->write(&c, 1); -// } - -// time_t File::getLastWrite() -// { -// if (!_p) { -// return 0; -// } - -// return _p->getLastWrite(); -// } - -// size_t File::write(const uint8_t *buf, size_t size) -// { -// if (!_p) { -// return 0; -// } - -// return _p->write(buf, size); -// } - -// int File::available() -// { -// if (!_p) { -// return false; -// } - -// return _p->size() - _p->position(); -// } - -// int File::read() -// { -// if (!_p) { -// return -1; -// } - -// uint8_t result; -// if (_p->read(&result, 1) != 1) { -// return -1; -// } - -// return result; -// } - -// size_t File::read(uint8_t* buf, size_t size) -// { -// if (!_p) { -// return -1; -// } - -// return _p->read(buf, size); -// } - -// int File::peek() -// { -// if (!_p) { -// return -1; -// } - -// size_t curPos = _p->position(); -// int result = read(); -// seek(curPos, SeekSet); -// return result; -// } - -// void File::flush() -// { -// if (!_p) { -// return; -// } - -// _p->flush(); -// } - -// bool File::seek(uint32_t pos, SeekMode mode) -// { -// if (!_p) { -// return false; -// } - -// return _p->seek(pos, mode); -// } - -// size_t File::position() const -// { -// if (!_p) { -// return 0; -// } - -// return _p->position(); -// } - -// size_t File::size() const -// { -// if (!_p) { -// return 0; -// } - -// return _p->size(); -// } - -// void File::close() -// { -// if (_p) { -// _p->close(); -// _p = nullptr; -// } -// } - -// File::operator bool() const -// { -// return !!_p; -// } - -// const char* File::name() const -// { -// if (!_p) { -// return nullptr; -// } - -// return _p->name(); -// } - -// //to implement -// boolean File::isDirectory(void) -// { -// if (!_p) { -// return false; -// } -// return _p->isDirectory(); -// } - -// File File::openNextFile(const char* mode) -// { -// if (!_p) { -// return File(); -// } -// return _p->openNextFile(mode); -// } - -// void File::rewindDirectory(void) -// { -// if (!_p) { -// return; -// } -// _p->rewindDirectory(); -// } - -// File FS::open(const String& path, const char* mode) -// { -// return open(path.c_str(), mode); -// } - -// File FS::open(const char* path, const char* mode) -// { -// if (!_impl) { -// return File(); -// } - -// return File(_impl->open(path, mode)); -// } - -// bool FS::exists(const char* path) -// { -// if (!_impl) { -// return false; -// } -// return _impl->exists(path); -// } - -// bool FS::exists(const String& path) -// { -// return exists(path.c_str()); -// } - -// bool FS::remove(const char* path) -// { -// if (!_impl) { -// return false; -// } -// return _impl->remove(path); -// } - -// bool FS::remove(const String& path) -// { -// return remove(path.c_str()); -// } - -// bool FS::rename(const char* pathFrom, const char* pathTo) -// { -// if (!_impl) { -// return false; -// } -// return _impl->rename(pathFrom, pathTo); -// } - -// bool FS::rename(const String& pathFrom, const String& pathTo) -// { -// return rename(pathFrom.c_str(), pathTo.c_str()); -// } - - -// bool FS::mkdir(const char *path) -// { -// if (!_impl) { -// return false; -// } -// return _impl->mkdir(path); -// } - -// bool FS::mkdir(const String &path) -// { -// return mkdir(path.c_str()); -// } - -// bool FS::rmdir(const char *path) -// { -// if (!_impl) { -// return false; -// } -// return _impl->rmdir(path); -// } - -// bool FS::rmdir(const String &path) -// { -// return rmdir(path.c_str()); -// } - - -// void FSImpl::mountpoint(const char * mp) -// { -// _mountpoint = mp; -// } - -// const char * FSImpl::mountpoint() -// { -// return _mountpoint; -// } diff --git a/libraries/FS/src/File.cpp b/libraries/FS/src/File.cpp new file mode 100644 index 00000000000..029f6394991 --- /dev/null +++ b/libraries/FS/src/File.cpp @@ -0,0 +1,210 @@ +#include "File.h" + + +File::File(const char* path, const char* mode) + , _f(NULL) + , _d(NULL) + , _path(NULL) + , _isDirectory(false) + , _written(false) +{ + _timeout = 0; + char * temp = (char *)malloc(strlen(path)+strlen(_fs->_mountpoint)+1); + if(!temp) { + return; + } + sprintf(temp,"%s%s", _fs->_mountpoint, path); + + _path = strdup(path); + if(!_path) { + log_e("strdup(%s) failed", path); + free(temp); + return; + } + + if(!stat(temp, &_stat)) { + //file found + if (S_ISREG(_stat.st_mode)) { + _isDirectory = false; + _f = fopen(temp, mode); + if(!_f) { + log_e("fopen(%s) failed", temp); + } + } else if(S_ISDIR(_stat.st_mode)) { + _isDirectory = true; + _d = opendir(temp); + if(!_d) { + log_e("opendir(%s) failed", temp); + } + } else { + log_e("Unknown type 0x%08X for file %s", ((_stat.st_mode)&_IFMT), temp); + } + } else { + //file not found + if(!mode || mode[0] == 'r') { + //try to open as directory + _d = opendir(temp); + if(_d) { + _isDirectory = true; + } else { + _isDirectory = false; + //log_w("stat(%s) failed", temp); + } + } else { + //lets create this new file + _isDirectory = false; + _f = fopen(temp, mode); + if(!_f) { + log_e("fopen(%s) failed", temp); + } + } + } + free(temp); +} + +VFSFileImpl::~VFSFileImpl() +{ + close(); +} + +void VFSFileImpl::close() +{ + if(_path) { + free(_path); + _path = NULL; + } + if(_isDirectory && _d) { + closedir(_d); + _d = NULL; + _isDirectory = false; + } else if(_f) { + fclose(_f); + _f = NULL; + } +} + +VFSFileImpl::operator bool() +{ + return (_isDirectory && _d != NULL) || _f != NULL; +} + +time_t VFSFileImpl::getLastWrite() { + _getStat() ; + return _stat.st_mtime; +} + +void VFSFileImpl::_getStat() const +{ + if(!_path) { + return; + } + char * temp = (char *)malloc(strlen(_path)+strlen(_fs->_mountpoint)+1); + if(!temp) { + return; + } + sprintf(temp,"%s%s", _fs->_mountpoint, _path); + if(!stat(temp, &_stat)) { + _written = false; + } + free(temp); +} + +size_t VFSFileImpl::write(const uint8_t *buf, size_t size) +{ + if(_isDirectory || !_f || !buf || !size) { + return 0; + } + _written = true; + return fwrite(buf, 1, size, _f); + + //return ::write(fileno(_f), buf, 1); + +} + +size_t VFSFileImpl::read(uint8_t* buf, size_t size) +{ + if(_isDirectory || !_f || !buf || !size) { + return 0; + } + //return ::read(fileno(_f), buf, 1); + return fread(buf, 1, size, _f); +} + +void VFSFileImpl::flush() +{ + if(_isDirectory || !_f) { + return; + } + fflush(_f); + // workaround for https://github.com/espressif/arduino-esp32/issues/1293 + fsync(fileno(_f)); +} + +bool VFSFileImpl::seek(uint32_t pos, SeekMode mode) +{ + if(_isDirectory || !_f) { + return false; + } + auto rc = fseek(_f, pos, mode); + return rc == 0; +} + +size_t VFSFileImpl::position() const +{ + if(_isDirectory || !_f) { + return 0; + } + return ftell(_f); +} + +size_t VFSFileImpl::size() const +{ + if(_isDirectory || !_f) { + return 0; + } + if (_written) { + _getStat(); + } + return _stat.st_size; +} + +const char* VFSFileImpl::name() const +{ + return (const char*) _path; +} + +//to implement +boolean VFSFileImpl::isDirectory(void) +{ + return _isDirectory; +} + +FileImplPtr VFSFileImpl::openNextFile(const char* mode) +{ + if(!_isDirectory || !_d) { + return FileImplPtr(); + } + struct dirent *file = readdir(_d); + if(file == NULL) { + return FileImplPtr(); + } + if(file->d_type != DT_REG && file->d_type != DT_DIR) { + return openNextFile(mode); + } + String fname = String(file->d_name); + String name = String(_path); + if(!fname.startsWith("/") && !name.endsWith("/")) { + name += "/"; + } + name += fname; + + return std::make_unique(_fs, name.c_str(), mode); +} + +void VFSFileImpl::rewindDirectory(void) +{ + if(!_isDirectory || !_d) { + return; + } + rewinddir(_d); +} diff --git a/libraries/FS/src/FS.h b/libraries/FS/src/File.h similarity index 65% rename from libraries/FS/src/FS.h rename to libraries/FS/src/File.h index 3615663a749..369dbfffa15 100644 --- a/libraries/FS/src/FS.h +++ b/libraries/FS/src/File.h @@ -20,6 +20,7 @@ #ifndef FS_H #define FS_H +#include extern "C" { #include @@ -31,7 +32,6 @@ extern "C" { #define FILE_WRITE "w" #define FILE_APPEND "a" -class File; enum SeekMode { @@ -43,10 +43,6 @@ enum SeekMode { class File : public Stream { public: - File(){ - _timeout = 0; - } - size_t write(uint8_t) override; size_t write(const uint8_t *buf, size_t size) override; int available() override; @@ -76,49 +72,5 @@ class File : public Stream void rewindDirectory(void); }; -class FS -{ -public: - FS() - {} - - File open(const char* path, const char* mode = FILE_READ); - File open(const String& path, const char* mode = FILE_READ); - - bool exists(const char* path); - bool exists(const String& path); - - bool remove(const char* path); - bool remove(const String& path); - - bool rename(const char* pathFrom, const char* pathTo); - bool rename(const String& pathFrom, const String& pathTo); - - bool mkdir(const char *path); - bool mkdir(const String &path); - - bool rmdir(const char *path); - bool rmdir(const String &path); - - FILE * _f; - DIR * _d; - char * _path; - bool _isDirectory; - mutable struct stat _stat; - mutable bool _written; - - void _getStat() const; -}; - -} // namespace fs - -#ifndef FS_NO_GLOBALS -using fs::FS; -using fs::File; -using fs::SeekMode; -using fs::SeekSet; -using fs::SeekCur; -using fs::SeekEnd; -#endif //FS_NO_GLOBALS #endif //FS_H diff --git a/libraries/FS/src/FileSystem.h b/libraries/FS/src/FileSystem.h new file mode 100644 index 00000000000..4be2bac4e97 --- /dev/null +++ b/libraries/FS/src/FileSystem.h @@ -0,0 +1,52 @@ +#ifndef FS_H +#define FS_H +#include +#include "File.h" + +extern "C" { +#include +#include +#include +} + +#define FILE_READ "r" +#define FILE_WRITE "w" +#define FILE_APPEND "a" + +class FileSystem +{ +public: + FileSystem() + {} + + File open(const char* path, const char* mode = FILE_READ); + File open(const String& path, const char* mode = FILE_READ); + + bool exists(const char* path); + bool exists(const String& path); + + bool remove(const char* path); + bool remove(const String& path); + + bool rename(const char* pathFrom, const char* pathTo); + bool rename(const String& pathFrom, const String& pathTo); + + bool mkdir(const char *path); + bool mkdir(const String &path); + + bool rmdir(const char *path); + bool rmdir(const String &path); + + FILE * _f; + DIR * _d; + char * _path; + bool _isDirectory; + mutable struct stat _stat; + mutable bool _written; + + void _getStat() const; +}; + + + +#endif // FileSystem_H \ No newline at end of file From b2f2d8aa9406c46636995c980e923b6013c2f11d Mon Sep 17 00:00:00 2001 From: RevoluPowered Date: Sun, 9 Jun 2019 23:04:18 +0100 Subject: [PATCH 4/4] Begin and End function implemented. Lots still to be done. This is the first step. SD.begin() can be called with no arguments to use the default ESP32 settings for SD Card connections. card_connection_mode can be supplied to begin to specify how the SD Card is interfaced with the ESP32 as per the ESP32-EVB or other boards which may use 1 wire mode, SPI or 4 line mode. Many functions still to be implemented and I am going to rebase these changes onto the top and remove any modifications to SD and FS because any changes made may impact other libraries and I want SD2 to be 'new' and support the default ESP32 functionality. This is intended to solve the read and write speed and be based off the standard interface provided by arduino. https://www.arduino.cc/en/Reference/SD --- libraries/SD2/src/SD.cpp | 126 +++++++++++++++++++++++++++++++++++++++ libraries/SD2/src/SD.h | 126 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 252 insertions(+) create mode 100644 libraries/SD2/src/SD.cpp create mode 100644 libraries/SD2/src/SD.h diff --git a/libraries/SD2/src/SD.cpp b/libraries/SD2/src/SD.cpp new file mode 100644 index 00000000000..99f814814d6 --- /dev/null +++ b/libraries/SD2/src/SD.cpp @@ -0,0 +1,126 @@ +#include "SD.h" + +#include +#include +#include "esp_err.h" +#include "esp_log.h" +//#include "esp_vfs_fat.h" +#include "driver/sdmmc_host.h" +#include "driver/sdspi_host.h" +//#include "sdmmc_cmd.h" + +namespace SD2 +{ + // todo: move these into class so they can be updated before begin gets called. + #define PIN_NUM_MISO 2 + #define PIN_NUM_MOSI 15 + #define PIN_NUM_CLK 14 + #define PIN_NUM_CS 13 + static const char * TAG = "SD2 library"; + + + boolean SD::begin( card_connection_mode mode, boolean auto_format_if_mount_failed ) + { + sdmmc_host_t host; + sdmmc_slot_config_t slot_config; + switch(mode) + { + case DEFAULT_PIN_MAPPING: + ESP_LOGI(TAG, "Using SDMMC peripheral"); + host = SDMMC_HOST_DEFAULT(); + + // This initializes the slot without card detect (CD) and write protect (WP) signals. + // Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals. + slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); + break; + case INTERNAL_PULLUP_MAPPING: + ESP_LOGI(TAG, "Using SDMMC peripheral with internal pullups - note external pullups still required!"); + host = SDMMC_HOST_DEFAULT(); + + // This initializes the slot without card detect (CD) and write protect (WP) signals. + // Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals. + slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); + + // GPIOs 15, 2, 4, 12, 13 should have external 10k pull-ups. + // Internal pull-ups are not sufficient. However, enabling internal pull-ups + // does make a difference some boards, so we do that here. + gpio_set_pull_mode(15, GPIO_PULLUP_ONLY); // CMD, needed in 4- and 1- line modes + gpio_set_pull_mode(2, GPIO_PULLUP_ONLY); // D0, needed in 4- and 1-line modes + gpio_set_pull_mode(4, GPIO_PULLUP_ONLY); // D1, needed in 4-line mode only + gpio_set_pull_mode(12, GPIO_PULLUP_ONLY); // D2, needed in 4-line mode only + gpio_set_pull_mode(13, GPIO_PULLUP_ONLY); // D3, needed in 4- and 1-line modes + case SPI_MAPPING: + ESP_LOGI(TAG, "Using SPI peripheral to access SD card"); + + sdmmc_host_t host = SDSPI_HOST_DEFAULT(); + sdspi_slot_config_t slot_config = SDSPI_SLOT_CONFIG_DEFAULT(); + slot_config.gpio_miso = PIN_NUM_MISO; + slot_config.gpio_mosi = PIN_NUM_MOSI; + slot_config.gpio_sck = PIN_NUM_CLK; + slot_config.gpio_cs = PIN_NUM_CS; + // This initializes the slot without card detect (CD) and write protect (WP) signals. + // Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals. + break; + case SINGLE_LINE_SDMODE: + ESP_LOGI(TAG, "Using Single line SD Mode"); + host = SDMMC_HOST_DEFAULT(); + host.flags = SDMMC_HOST_FLAG_1BIT; + + slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); + slot_config.width = 1; + + break; + default: + ESP_LOGE(TAG, "Error: configuration specified doesn't exist for SDMODE flag"); + return false; + break; + + // Options for mounting the filesystem. + // If format_if_mount_failed is set to true, SD card will be partitioned and + // formatted in case when mounting fails. + esp_vfs_fat_sdmmc_mount_config_t mount_config = { + .format_if_mount_failed = auto_format_if_mount_failed, + .max_files = 5, // todo: might need to make this configurable. + .allocation_unit_size = 16 * 1024 + }; + + // Use settings defined above to initialize SD card and mount FAT filesystem. + // Note: esp_vfs_fat_sdmmc_mount is an all-in-one convenience function. + // Please check its source code and implement error recovery when developing + // production applications. + sdmmc_card_t* card; + esp_err_t ret = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card); + + if (ret != ESP_OK) { + if (ret == ESP_FAIL) { + ESP_LOGE(TAG, "Failed to mount filesystem. " + "If you want the card to be formatted, set format_if_mount_failed = true."); + } + else { + ESP_LOGE(TAG, "Failed to initialize the card (%s). " + "Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret)); + } + return false; + } + + // Card has been initialized, print its properties + sdmmc_card_print_info(stdout, card); + status = true; + return true; + } + } + + boolean SD::end() + { + if(status) + { + esp_vfs_fat_sdmmc_unmount(); + ESP_LOGI(TAG, "Card unmounted"); + return true; + } + else + { + ESP_LOGI(TAG, "Card was never mounted so not unmounting!"); + } + } +} \ No newline at end of file diff --git a/libraries/SD2/src/SD.h b/libraries/SD2/src/SD.h new file mode 100644 index 00000000000..59632ef261a --- /dev/null +++ b/libraries/SD2/src/SD.h @@ -0,0 +1,126 @@ +/* + SD2 ESP32 SD card library designed for performance + Uses standard code designed for optimal ESP32 performance as per example code provided by Espressif. + + License: + GNU General Public License V3 + + Authored by Gordon MacPherson + + (c) Copyright GORDONITE LTD +*/ + +#ifndef __SD2_H__ +#define __SD2_H__ + +#include +#include + +namespace SD2 { + + enum card_connection_mode { + DEFAULT_PIN_MAPPING = 0, // GPIOs 15, 2, 4, 12, 13 should have external 10k pull-ups. + INTERNAL_PULLUP_MAPPING = 1, // Enables internal pullup resistors, not sufficient but makes difference on some boards. + SPI_MAPPING = 2, // GPIOs MISO(2), MOSI(15), CLK(14), CS(13) + SINGLE_LINE_SDMODE = 3 + }; + + + class SD + { + public: + // Instruct ESP32 to begin communication with the SD CARD + boolean begin( card_connection_mode mode = DEFAULT_PIN_MAPPING, boolean auto_format_if_mount_failed = false); + + // Shutdown all ESP32 SD card communication + boolean end(); // custom non standard! + + // Not implemented yet + void exists(); + void mkdir(); + void open(); + void remove(); + void rmdir(); + private: + bool status = false; + }; + + class OFile { + void name(); + void available(); + void close(); + void flush(); + void peek(); + void position(); + void print(); + void println(); + void seek(); + void size(); + void read(); + void write(); + void isDirectory(); + void openNextFile(); + void rewindDirectory(); + }; + + + class File { + File() + {}; + + virtual ~File() + { + if(filePtr != NULL) + { + fclose(filePtr); + } + } + + // Open a file + inline FILE* Open(String filePath, String mode ) + { + filePtr = fopen(filePath.c_str(), mode.c_str()); + this->filePath = filePath; + } + + // Close a file + inline FILE* Close() + { + fclose(filePtr); + filePtr = NULL; + } + + // Is the file open? + inline bool IsOpen(void) + { + return filePtr != NULL; + } + + // Return the file pointer for use in custom serialisers. + inline FILE* GetFilePtr(void) + { + return this->filePtr; + } + + inline String GetFilePath(void) + { + return this->filePath; + } + + + private: + String filePath = ""; + FILE * filePtr = NULL; + + // prevent copying file instances should always be used as a pointer if you need to pass it around, prevents multiple handles being open or pointless reallocations too + File( const File&); + File& operator=(const File&); + }; + + + + +} + + +#endif // __SD2_H__ \ No newline at end of file