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/src/FS.cpp b/libraries/FS.slow/src/FS.cpp similarity index 100% rename from libraries/FS/src/FS.cpp rename to libraries/FS.slow/src/FS.cpp diff --git a/libraries/FS/src/FS.h b/libraries/FS.slow/src/FS.h similarity index 96% rename from libraries/FS/src/FS.h rename to libraries/FS.slow/src/FS.h index d63fc5da305..ab02b1547c3 100644 --- a/libraries/FS/src/FS.h +++ b/libraries/FS.slow/src/FS.h @@ -34,9 +34,9 @@ namespace fs class File; class FileImpl; -typedef std::shared_ptr FileImplPtr; +typedef std::unique_ptr FileImplPtr; class FSImpl; -typedef std::shared_ptr FSImplPtr; +typedef std::unique_ptr FSImplPtr; enum SeekMode { SeekSet = 0, 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/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/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/File.h b/libraries/FS/src/File.h new file mode 100644 index 00000000000..369dbfffa15 --- /dev/null +++ b/libraries/FS/src/File.h @@ -0,0 +1,76 @@ +/* + 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 + +extern "C" { +#include +#include +#include +} + +#define FILE_READ "r" +#define FILE_WRITE "w" +#define FILE_APPEND "a" + + + +enum SeekMode { + SeekSet = 0, + SeekCur = 1, + SeekEnd = 2 +}; + +class File : public Stream +{ +public: + 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); +}; + + +#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 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)` 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 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();