diff --git a/README.md b/README.md index ec001ee1..1f97464b 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,8 @@ -### Warning: Major Reformat of Source in 2.2.2 +File copy constructors and file assignment operators have been made private by +default in 2.2.3 to prevent call by value and multiple copies of file instances. -There are a huge number of changes in 2.2.2 since I decided to use clang-format -to force Google style formatting. - -I did this to avoid warnings from the static analysis programs Cppcheck and -cpplint. - -clang-format is aggressive so it may actually cause code to fail. For example -clang-format rearranges the order of includes according to the selected style. +SdFatConfig.h has options to make file constructors and assignment operators +public. UTF-8 encoded filenames are supported in v2.1.0 or later. diff --git a/doc/html.zip b/doc/html.zip index 54ffbbd7..efbd3841 100644 Binary files a/doc/html.zip and b/doc/html.zip differ diff --git a/doc/mainpage.h b/doc/mainpage.h index d172a753..19312b7b 100644 --- a/doc/mainpage.h +++ b/doc/mainpage.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2011-2021 Bill Greiman + * Copyright (c) 2011-2024 Bill Greiman * This file is part of the SdFat library for SD memory cards. * * MIT License diff --git a/examples/BufferedPrint/BufferedPrint.ino b/examples/BufferedPrint/BufferedPrint.ino index bfe0d30e..5a924eb6 100644 --- a/examples/BufferedPrint/BufferedPrint.ino +++ b/examples/BufferedPrint/BufferedPrint.ino @@ -6,7 +6,7 @@ // SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h, // 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT. -#define SD_FAT_TYPE 0 +#define SD_FAT_TYPE 3 /* Change the value of SD_CS_PIN if you are using SPI and your hardware does not use the default value, SS. diff --git a/examples/DirectoryFunctions/DirectoryFunctions.ino b/examples/DirectoryFunctions/DirectoryFunctions.ino index e102a438..498ce513 100644 --- a/examples/DirectoryFunctions/DirectoryFunctions.ino +++ b/examples/DirectoryFunctions/DirectoryFunctions.ino @@ -6,7 +6,7 @@ // SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h, // 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT. -#define SD_FAT_TYPE 0 +#define SD_FAT_TYPE 3 /* Change the value of SD_CS_PIN if you are using SPI and your hardware does not use the default value, SS. diff --git a/examples/OpenNext/OpenNext.ino b/examples/OpenNext/OpenNext.ino index 51fd4911..2e58110d 100644 --- a/examples/OpenNext/OpenNext.ino +++ b/examples/OpenNext/OpenNext.ino @@ -5,7 +5,7 @@ // SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h, // 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT. -#define SD_FAT_TYPE 0 +#define SD_FAT_TYPE 3 /* Change the value of SD_CS_PIN if you are using SPI and your hardware does not use the default value, SS. diff --git a/examples/QuickStart/QuickStart.ino b/examples/QuickStart/QuickStart.ino index 83fe99ac..eb884ab7 100644 --- a/examples/QuickStart/QuickStart.ino +++ b/examples/QuickStart/QuickStart.ino @@ -143,7 +143,7 @@ void loop() { } cout << F("\nCard successfully initialized.\n"); if (sd.vol()->fatType() == 0) { - cout << F("Can't find a valid FAT16/FAT32 partition.\n"); + cout << F("Can't find a valid FAT16/FAT32/exFAT partition.\n"); reformatMsg(); return; } @@ -163,7 +163,11 @@ void loop() { cout << F("Card size: ") << sizeMB; cout << F(" MB (MB = 1,000,000 bytes)\n"); cout << endl; - cout << F("Volume is FAT") << int(sd.vol()->fatType()); + if (sd.fatType() <= 32) { + cout << F("\nVolume is FAT") << int(sd.fatType()); + } else { + cout << F("\nVolume is exFAT"); + } cout << F(", Cluster size (bytes): ") << sd.vol()->bytesPerCluster(); cout << endl << endl; diff --git a/examples/ReadCsvFile/ReadCsvFile.ino b/examples/ReadCsvFile/ReadCsvFile.ino index 28616094..7fb61cad 100644 --- a/examples/ReadCsvFile/ReadCsvFile.ino +++ b/examples/ReadCsvFile/ReadCsvFile.ino @@ -2,7 +2,7 @@ // SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h, // 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT. -#define SD_FAT_TYPE 0 +#define SD_FAT_TYPE 3 /* Change the value of SD_CS_PIN if you are using SPI and your hardware does not use the default value, SS. diff --git a/examples/RtcTimestampTest/RtcTimestampTest.ino b/examples/RtcTimestampTest/RtcTimestampTest.ino index c0954afc..3e5e5a74 100644 --- a/examples/RtcTimestampTest/RtcTimestampTest.ino +++ b/examples/RtcTimestampTest/RtcTimestampTest.ino @@ -13,7 +13,7 @@ // SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h, // 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT. -#define SD_FAT_TYPE 0 +#define SD_FAT_TYPE 3 /* Change the value of SD_CS_PIN if you are using SPI and your hardware does not use the default value, SS. diff --git a/examples/SdInfo/SdInfo.ino b/examples/SdInfo/SdInfo.ino index 7ac7815d..a2c31623 100644 --- a/examples/SdInfo/SdInfo.ino +++ b/examples/SdInfo/SdInfo.ino @@ -1,5 +1,10 @@ /* * This program attempts to initialize an SD card and analyze its structure. + * The CID and CSD registers are also printed in HEX for use in online + * decoders like these. + * + * https://gurumeditation.org/1342/sd-memory-card-register-decoder/ + * https://archive.goughlui.com/static/multicid.htm */ #include "SdFat.h" #include "sdios.h" @@ -55,7 +60,8 @@ void cidDmp() { cout << F("Serial number: ") << hex << cid.psn() << dec << endl; cout << F("Manufacturing date: "); cout << cid.mdtMonth() << '/' << cid.mdtYear() << endl; - cout << endl; + cout << F("CID HEX: "); + hexDmp(&cid, sizeof(cid)); } //------------------------------------------------------------------------------ void clearSerialInput() { @@ -69,7 +75,7 @@ void clearSerialInput() { //------------------------------------------------------------------------------ void csdDmp() { eraseSize = csd.eraseSize(); - cout << F("cardSize: ") << 0.000512 * csd.capacity(); + cout << F("\ncardSize: ") << 0.000512 * csd.capacity(); cout << F(" MB (MB = 1,000,000 bytes)\n"); cout << F("flashEraseSize: ") << int(eraseSize) << F(" blocks\n"); @@ -85,6 +91,8 @@ void csdDmp() { } else { cout << F("zeros\n"); } + cout << F("CSD HEX: "); + hexDmp(&csd, sizeof(csd)); } //------------------------------------------------------------------------------ void errorPrint() { @@ -96,10 +104,19 @@ void errorPrint() { } } //------------------------------------------------------------------------------ +void hexDmp(void* reg, uint8_t size) { + uint8_t* u8 = reinterpret_cast(reg); + cout << hex << noshowbase; + for (size_t i = 0; i < size; i++) { + cout << setw(2) << setfill('0') << int(u8[i]); + } + cout << dec << endl; +} +//------------------------------------------------------------------------------ bool mbrDmp() { MbrSector_t mbr; bool valid = true; - if (!sd.card()->readSector(0, (uint8_t *)&mbr)) { + if (!sd.card()->readSector(0, (uint8_t*)&mbr)) { cout << F("\nread MBR failed.\n"); errorPrint(); return false; @@ -107,7 +124,7 @@ bool mbrDmp() { cout << F("\nSD Partition Table\n"); cout << F("part,boot,bgnCHS[3],type,endCHS[3],start,length\n"); for (uint8_t ip = 1; ip < 5; ip++) { - MbrPart_t *pt = &mbr.part[ip - 1]; + MbrPart_t* pt = &mbr.part[ip - 1]; if ((pt->boot != 0 && pt->boot != 0X80) || getLe32(pt->relativeSectors) > csd.capacity()) { valid = false; @@ -242,7 +259,7 @@ void loop() { printCardType(); cout << F("sdSpecVer: ") << 0.01 * scr.sdSpecVer() << endl; cout << F("HighSpeedMode: "); - if (scr.sdSpecVer() && sd.card()->cardCMD6(0X00FFFFFF, cmd6Data) && + if (scr.sdSpecVer() > 101 && sd.card()->cardCMD6(0X00FFFFFF, cmd6Data) && (2 & cmd6Data[13])) { cout << F("true\n"); } else { diff --git a/examples/SoftwareSpi/SoftwareSpi.ino b/examples/SoftwareSpi/SoftwareSpi.ino index 388bf9f2..1300cfa0 100644 --- a/examples/SoftwareSpi/SoftwareSpi.ino +++ b/examples/SoftwareSpi/SoftwareSpi.ino @@ -8,7 +8,7 @@ // SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h, // 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT. -#define SD_FAT_TYPE 0 +#define SD_FAT_TYPE 3 // // Chip select may be constant or RAM variable. const uint8_t SD_CS_PIN = 10; diff --git a/examples/SpiLoopBackTest/SpiLoopBackTest.ino b/examples/SpiLoopBackTest/SpiLoopBackTest.ino new file mode 100644 index 00000000..88101a08 --- /dev/null +++ b/examples/SpiLoopBackTest/SpiLoopBackTest.ino @@ -0,0 +1,66 @@ +// This is a simple SPI loop-back test. +// +// Connect SD_MISO to SD_MOSI +// +// Modify these defines for your configuration. +#define SD_SPI SPI +#define SD_MISO MISO +#define SD_MOSI MOSI + +#include "SPI.h" +void setup() { + uint8_t rx, tx; + Serial.begin(9600); + while (!Serial) { + yield(); + } + Serial.println(F("\nType any character to start")); + while (!Serial.available()) { + yield(); + } + Serial.print("Begin, SD_MISO: "); + Serial.print(SD_MISO), Serial.print(", SD_MOSI: "); + Serial.println(SD_MOSI); + pinMode(SD_MISO, INPUT_PULLUP); + pinMode(SD_MOSI, OUTPUT); + digitalWrite(SD_MOSI, HIGH); + if (!digitalRead(SD_MISO)) { + Serial.println("Error: SD_MISO not HIGH"); + goto fail; + } + digitalWrite(SD_MOSI, LOW); + if (digitalRead(SD_MISO)) { + Serial.println("Error: SD_MISO not LOW"); + goto fail; + } + pinMode(SD_MISO, INPUT); + pinMode(SD_MOSI, INPUT); + + // Modify if SD_SPI.begin has arguments and use this style SdFat begin call: + // sd.begin(SdSpiConfig(CS_PIN, USER_SPI_BEGIN | , &SD_SPI)); + SD_SPI.begin(); + + // Start with a 400 kHz clock. Try full speed if success for 400 kHz. + SD_SPI.beginTransaction(SPISettings(400000, MSBFIRST, SPI_MODE0)); + tx = 0; + do { + rx = SD_SPI.transfer(tx); + if (tx != rx) { + Serial.print("Error rx: 0x"); + Serial.print(rx, HEX); + Serial.print(" != tx: 0x"); + Serial.println(tx, HEX); + SD_SPI.endTransaction(); + goto fail; + } + } while (tx++ < 255); + SD_SPI.endTransaction(); + Serial.println("Success!"); + return; + +fail: + SD_SPI.endTransaction(); + Serial.println("Is SD_MISO connected to SD_MOSI?"); + Serial.println("Are SD_MISO and SD_MOSI correct?"); +} +void loop() {} \ No newline at end of file diff --git a/examples/bench/bench.ino b/examples/bench/bench.ino index 4778f44d..36a577c5 100644 --- a/examples/bench/bench.ino +++ b/examples/bench/bench.ino @@ -1,13 +1,13 @@ /* * This program is a simple binary write/read benchmark. */ -#include "FreeStack.h" #include "SdFat.h" +#include "FreeStack.h" #include "sdios.h" // SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h, // 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT. -#define SD_FAT_TYPE 0 +#define SD_FAT_TYPE 3 /* Change the value of SD_CS_PIN if you are using SPI and your hardware does not use the default value, SS. diff --git a/examples/rename/rename.ino b/examples/rename/rename.ino index 2a512340..3995fce5 100644 --- a/examples/rename/rename.ino +++ b/examples/rename/rename.ino @@ -6,7 +6,7 @@ // SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h, // 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT. -#define SD_FAT_TYPE 0 +#define SD_FAT_TYPE 3 /* Change the value of SD_CS_PIN if you are using SPI and diff --git a/extras/fmt_src.bat b/extras/fmt_src.bat new file mode 100644 index 00000000..7ddecdfe --- /dev/null +++ b/extras/fmt_src.bat @@ -0,0 +1,11 @@ +clang-format --style=Google -i *.cpp *.h +rem clang-format --style=Google -i DigitalIO/*.h +rem clang-format --style=Google -i DigitalIO/boards/*.h +clang-format --style=Google -i common/*.cpp common/*.h +clang-format --style=Google -i ExFatLib/*.cpp ExFatLib/*.h +clang-format --style=Google -i FatLib/*.cpp FatLib/*.h +clang-format --style=Google -i FsLib/*.cpp FsLib/*.h +clang-format --style=Google -i iostream/*.cpp iostream/*.h +clang-format --style=Google -i SdCard/*.cpp SdCard/*.h +clang-format --style=Google -i SpiDriver/*.cpp SpiDriver/*.h +pause diff --git a/library.properties b/library.properties index b5738f7b..12abc4f5 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=SdFat -version=2.2.2 +version=2.2.3 license=MIT author=Bill Greiman maintainer=Bill Greiman diff --git a/src/ExFatLib/ExFatFile.cpp b/src/ExFatLib/ExFatFile.cpp index 405f86fc..1301d4c0 100644 --- a/src/ExFatLib/ExFatFile.cpp +++ b/src/ExFatLib/ExFatFile.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2011-2022 Bill Greiman + * Copyright (c) 2011-2024 Bill Greiman * This file is part of the SdFat library for SD memory cards. * * MIT License @@ -223,7 +223,8 @@ bool ExFatFile::open(ExFatFile* dirFile, const char* path, oflag_t oflag) { DBG_WARN_MACRO; goto fail; } - tmpDir = *this; + // tmpDir = *this; + tmpDir.copy(this); dirFile = &tmpDir; close(); } @@ -254,7 +255,8 @@ bool ExFatFile::openCwd() { DBG_FAIL_MACRO; goto fail; } - *this = *ExFatVolume::cwv()->vwd(); + // *this = *ExFatVolume::cwv()->vwd(); + this->copy(ExFatVolume::cwv()->vwd()); rewind(); return true; diff --git a/src/ExFatLib/ExFatFile.h b/src/ExFatLib/ExFatFile.h index 5539e602..93c52510 100644 --- a/src/ExFatLib/ExFatFile.h +++ b/src/ExFatLib/ExFatFile.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2011-2022 Bill Greiman + * Copyright (c) 2011-2024 Bill Greiman * This file is part of the SdFat library for SD memory cards. * * MIT License @@ -71,12 +71,78 @@ class ExFatFile { */ ExFatFile(const char* path, oflag_t oflag) { open(path, oflag); } + /** Copy from to this. + * \param[in] from Source file. + */ + void copy(const ExFatFile* from) { + if (from != this) { +#if FILE_COPY_CONSTRUCTOR_SELECT + *this = *from; +#else // FILE_COPY_CONSTRUCTOR_SELECT + memcpy(this, from, sizeof(ExFatFile)); +#endif // FILE_COPY_CONSTRUCTOR_SELECT + } + } + /** move from to this. + * \param[in] from Source file. + */ + void move(ExFatFile* from) { + if (from != this) { + copy(from); + from->m_attributes = FILE_ATTR_CLOSED; + } + } + +#if FILE_COPY_CONSTRUCTOR_SELECT == FILE_COPY_CONSTRUCTOR_PUBLIC + /** Copy constructor. + * \param[in] from Move from file. + * + */ + ExFatFile(const ExFatFile& from) = default; + /** Copy assignment operator. + * \param[in] from Move from file. + * \return Copied file. + */ + ExFatFile& operator=(const ExFatFile& from) = default; +#elif FILE_COPY_CONSTRUCTOR_SELECT == FILE_COPY_CONSTRUCTOR_PRIVATE + + private: + ExFatFile(const ExFatFile& from) = default; + ExFatFile& operator=(const ExFatFile& from) = default; + + public: +#else // FILE_COPY_CONSTRUCTOR_SELECT + ExFatFile(const ExFatFile& from) = delete; + ExFatFile& operator=(const ExFatFile& from) = delete; +#endif // FILE_COPY_CONSTRUCTOR_SELECT + +#if FILE_MOVE_CONSTRUCTOR_SELECT + /** Move constructor. + * \param[in] from Move from file. + */ + ExFatFile(ExFatFile&& from) { move(&from); } + /** Move assignment operator. + * \param[in] from Move from file. + * \return Moved file. + */ + ExFatFile& operator=(ExFatFile&& from) { + move(&from); + return *this; + } +#else // FILE_MOVE_CONSTRUCTOR_SELECT + ExFatFile(ExFatFile&& from) = delete; + ExFatFile& operator=(ExFatFile&& from) = delete; +#endif + + /** Destructor */ #if DESTRUCTOR_CLOSES_FILE ~ExFatFile() { if (isOpen()) { close(); } } +#else // DESTRUCTOR_CLOSES_FILE + ~ExFatFile() = default; #endif // DESTRUCTOR_CLOSES_FILE /** The parenthesis operator. @@ -223,7 +289,7 @@ class ExFatFile { * * \param[out] name An array of characters for the file's name. * \param[in] size The size of the array in characters. - * \return the name length. + * \return length for success or zero for failure. */ size_t getName(char* name, size_t size) { #if USE_UTF8_LONG_NAMES diff --git a/src/ExFatLib/ExFatFileWrite.cpp b/src/ExFatLib/ExFatFileWrite.cpp index f108c224..91977e0d 100644 --- a/src/ExFatLib/ExFatFileWrite.cpp +++ b/src/ExFatLib/ExFatFileWrite.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2011-2022 Bill Greiman + * Copyright (c) 2011-2024 Bill Greiman * This file is part of the SdFat library for SD memory cards. * * MIT License @@ -179,7 +179,8 @@ bool ExFatFile::mkdir(ExFatFile* parent, const char* path, bool pFlag) { goto fail; } } - tmpDir = *this; + // tmpDir = *this; + tmpDir.copy(this); parent = &tmpDir; close(); } @@ -312,7 +313,8 @@ bool ExFatFile::rename(ExFatFile* dirFile, const char* newPath) { DBG_FAIL_MACRO; goto fail; } - oldFile = *this; + // oldFile = *this; + oldFile.copy(this); m_dirPos = file.m_dirPos; m_setCount = file.m_setCount; m_flags |= FILE_FLAG_DIR_DIRTY; @@ -463,8 +465,9 @@ bool ExFatFile::timestamp(uint8_t flags, uint16_t year, uint8_t month, uint16_t time; uint8_t ms10; - if (!isFile() || year < 1980 || year > 2107 || month < 1 || month > 12 || - day < 1 || day > 31 || hour > 23 || minute > 59 || second > 59) { + if (!isFileOrSubDir() || year < 1980 || year > 2107 || month < 1 || + month > 12 || day < 1 || day > 31 || hour > 23 || minute > 59 || + second > 59) { DBG_FAIL_MACRO; goto fail; } diff --git a/src/ExFatLib/ExFatVolume.cpp b/src/ExFatLib/ExFatVolume.cpp index 104fc0e4..10e7f9a3 100644 --- a/src/ExFatLib/ExFatVolume.cpp +++ b/src/ExFatLib/ExFatVolume.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2011-2022 Bill Greiman + * Copyright (c) 2011-2024 Bill Greiman * This file is part of the SdFat library for SD memory cards. * * MIT License @@ -37,7 +37,8 @@ bool ExFatVolume::chdir(const char* path) { DBG_FAIL_MACRO; goto fail; } - m_vwd = dir; + // m_vwd = dir; + m_vwd.copy(&dir); return true; fail: diff --git a/src/FatLib/FatFile.cpp b/src/FatLib/FatFile.cpp index 6d1fb43f..d23efeed 100644 --- a/src/FatLib/FatFile.cpp +++ b/src/FatLib/FatFile.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2011-2022 Bill Greiman + * Copyright (c) 2011-2024 Bill Greiman * This file is part of the SdFat library for SD memory cards. * * MIT License @@ -354,7 +354,8 @@ bool FatFile::mkdir(FatFile* parent, const char* path, bool pFlag) { goto fail; } } - tmpDir = *this; + // tmpDir = *this; + tmpDir.copy(this); parent = &tmpDir; close(); } @@ -477,7 +478,8 @@ bool FatFile::open(FatFile* dirFile, const char* path, oflag_t oflag) { DBG_WARN_MACRO; goto fail; } - tmpDir = *this; + // tmpDir = *this; + tmpDir.copy(this); dirFile = &tmpDir; close(); } @@ -632,7 +634,8 @@ bool FatFile::openCwd() { DBG_FAIL_MACRO; goto fail; } - *this = *FatVolume::cwv()->vwd(); + // *this = *FatVolume::cwv()->vwd(); + this->copy(FatVolume::cwv()->vwd()); rewind(); return true; @@ -965,7 +968,8 @@ bool FatFile::rename(FatFile* dirFile, const char* newPath) { } // sync() and cache directory entry sync(); - oldFile = *this; + // oldFile = *this; + oldFile.copy(this); dir = cacheDirEntry(FsCache::CACHE_FOR_READ); if (!dir) { DBG_FAIL_MACRO; @@ -1281,8 +1285,9 @@ bool FatFile::timestamp(uint8_t flags, uint16_t year, uint8_t month, uint16_t dirTime; DirFat_t* dir; - if (!isFile() || year < 1980 || year > 2107 || month < 1 || month > 12 || - day < 1 || day > 31 || hour > 23 || minute > 59 || second > 59) { + if (!isFileOrSubDir() || year < 1980 || year > 2107 || month < 1 || + month > 12 || day < 1 || day > 31 || hour > 23 || minute > 59 || + second > 59) { DBG_FAIL_MACRO; goto fail; } diff --git a/src/FatLib/FatFile.h b/src/FatLib/FatFile.h index fa34d28e..62977559 100644 --- a/src/FatLib/FatFile.h +++ b/src/FatLib/FatFile.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2011-2022 Bill Greiman + * Copyright (c) 2011-2024 Bill Greiman * This file is part of the SdFat library for SD memory cards. * * MIT License @@ -117,14 +117,80 @@ class FatFile { * OR of open flags. see FatFile::open(FatFile*, const char*, uint8_t). */ FatFile(const char* path, oflag_t oflag) { open(path, oflag); } -#if DESTRUCTOR_CLOSES_FILE + + /** Copy from to this. + * \param[in] from Source file. + */ + void copy(const FatFile* from) { + if (from != this) { +#if FILE_COPY_CONSTRUCTOR_SELECT + *this = *from; +#else // FILE_COPY_CONSTRUCTOR_SELECT + memcpy(this, from, sizeof(FatFile)); +#endif // FILE_COPY_CONSTRUCTOR_SELECT + } + } + /** move from to this. + * \param[in] from Source file. + */ + void move(FatFile* from) { + if (from != this) { + copy(from); + from->m_attributes = FILE_ATTR_CLOSED; + } + } + +#if FILE_COPY_CONSTRUCTOR_SELECT == FILE_COPY_CONSTRUCTOR_PUBLIC + /** Copy constructor. + * \param[in] from Move from file. + * + */ + FatFile(const FatFile& from) = default; + /** Copy assignment operator. + * \param[in] from Move from file. + * \return Copied file. + */ + FatFile& operator=(const FatFile& from) = default; +#elif FILE_COPY_CONSTRUCTOR_SELECT == FILE_COPY_CONSTRUCTOR_PRIVATE + + private: + FatFile(const FatFile& from) = default; + FatFile& operator=(const FatFile& from) = default; + + public: +#else // FILE_COPY_CONSTRUCTOR_SELECT + FatFile(const FatFile& from) = delete; + FatFile& operator=(const FatFile& from) = delete; +#endif // FILE_COPY_CONSTRUCTOR_SELECT + +#if FILE_MOVE_CONSTRUCTOR_SELECT + /** Move constructor. + * \param[in] from Move from file. + */ + FatFile(FatFile&& from) { move(&from); } + /** Move assignment operator. + * \param[in] from Move from file. + * \return Moved file. + */ + FatFile& operator=(FatFile&& from) { + move(&from); + return *this; + } +#else // FILE_MOVE_CONSTRUCTOR_SELECT + FatFile(FatFile&& from) = delete; + FatFile& operator=(FatFile&& from) = delete; +#endif /** Destructor */ +#if DESTRUCTOR_CLOSES_FILE ~FatFile() { if (isOpen()) { close(); } } +#else // DESTRUCTOR_CLOSES_FILE + ~FatFile() = default; #endif // DESTRUCTOR_CLOSES_FILE + /** The parenthesis operator. * * \return true if a file is open. @@ -323,8 +389,7 @@ class FatFile { * * \param[out] name An array of characters for the file's name. * \param[in] size The size of the array in bytes. The array - * must be at least 13 bytes long. The file's name will be - * truncated if the file's name is too long. + * must be at least 13 bytes long. * \return length for success or zero for failure. */ size_t getName(char* name, size_t size); @@ -333,7 +398,7 @@ class FatFile { * * \param[out] name An array of characters for the file's name. * \param[in] size The size of the array in characters. - * \return the name length. + * \return length for success or zero for failure. */ size_t getName7(char* name, size_t size); /** @@ -341,7 +406,7 @@ class FatFile { * * \param[out] name An array of characters for the file's name. * \param[in] size The size of the array in characters. - * \return the name length. + * \return length for success or zero for failure. */ size_t getName8(char* name, size_t size); #ifndef DOXYGEN_SHOULD_SKIP_THIS @@ -784,7 +849,7 @@ class FatFile { */ bool rename(FatFile* dirFile, const char* newPath); /** Set the file's current position to zero. */ - void rewind() { seekSet(0); } + void rewind() { seekSet(0UL); } /** Remove a directory file. * * The directory file will be removed only if it is empty and is not the diff --git a/src/FatLib/FatFileLFN.cpp b/src/FatLib/FatFileLFN.cpp index 54326dd4..6844a573 100644 --- a/src/FatLib/FatFileLFN.cpp +++ b/src/FatLib/FatFileLFN.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2011-2022 Bill Greiman + * Copyright (c) 2011-2024 Bill Greiman * This file is part of the SdFat library for SD memory cards. * * MIT License @@ -54,7 +54,9 @@ static void putLfnChar(DirLfn_t* ldir, uint8_t i, uint16_t c) { } //============================================================================== bool FatFile::cmpName(uint16_t index, FatLfn_t* fname, uint8_t lfnOrd) { - FatFile dir = *this; + // FatFile dir = *this; + FatFile dir; + dir.copy(this); DirLfn_t* ldir; fname->reset(); for (uint8_t order = 1; order <= lfnOrd; order++) { @@ -92,7 +94,9 @@ bool FatFile::cmpName(uint16_t index, FatLfn_t* fname, uint8_t lfnOrd) { } //------------------------------------------------------------------------------ bool FatFile::createLFN(uint16_t index, FatLfn_t* fname, uint8_t lfnOrd) { - FatFile dir = *this; + // FatFile dir = *this; + FatFile dir; + dir.copy(this); DirLfn_t* ldir; uint8_t checksum = lfnChecksum(fname->sfn); uint8_t fc = 0; @@ -376,7 +380,6 @@ bool FatFile::open(FatFile* dirFile, FatLfn_t* fname, oflag_t oflag) { if (freeFound == 0) { freeIndex = curIndex; } - while (freeFound < freeNeed) { dir = dirFile->readDirCache(); if (!dir) { diff --git a/src/FatLib/FatFileSFN.cpp b/src/FatLib/FatFileSFN.cpp index c8deef50..3a5f6934 100644 --- a/src/FatLib/FatFileSFN.cpp +++ b/src/FatLib/FatFileSFN.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2011-2022 Bill Greiman + * Copyright (c) 2011-2024 Bill Greiman * This file is part of the SdFat library for SD memory cards. * * MIT License @@ -156,7 +156,8 @@ bool FatFile::openExistingSFN(const char* path) { if (*path == 0) { return openRoot(vol); } - *this = *vol->vwd(); + // *this = *vol->vwd(); + this->copy(vol->vwd()); do { if (!parsePathName(path, &fname, &path)) { DBG_FAIL_MACRO; @@ -183,7 +184,7 @@ bool FatFile::openSFN(FatSfn_t* fname) { goto fail; } while (true) { - if (read(&dir, 32) != 32) { + if (read(&dir, sizeof(dir)) != sizeof(dir)) { DBG_FAIL_MACRO; goto fail; } @@ -192,7 +193,7 @@ bool FatFile::openSFN(FatSfn_t* fname) { goto fail; } if (isFatFileOrSubdir(&dir) && memcmp(fname->sfn, dir.name, 11) == 0) { - uint16_t saveDirIndex = (m_curPosition - 32) >> 5; + uint16_t saveDirIndex = (m_curPosition - sizeof(dir)) >> 5; uint32_t saveDirCluster = m_firstCluster; memset(this, 0, sizeof(FatFile)); m_attributes = dir.attributes & FS_ATTRIB_COPY; diff --git a/src/FatLib/FatVolume.cpp b/src/FatLib/FatVolume.cpp index 62537603..3003546a 100644 --- a/src/FatLib/FatVolume.cpp +++ b/src/FatLib/FatVolume.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2011-2022 Bill Greiman + * Copyright (c) 2011-2024 Bill Greiman * This file is part of the SdFat library for SD memory cards. * * MIT License @@ -37,7 +37,8 @@ bool FatVolume::chdir(const char* path) { DBG_FAIL_MACRO; goto fail; } - m_vwd = dir; + // m_vwd = dir; + m_vwd.copy(&dir); return true; fail: diff --git a/src/FsLib/FsFile.cpp b/src/FsLib/FsFile.cpp index bc4029d2..4ac76131 100644 --- a/src/FsLib/FsFile.cpp +++ b/src/FsLib/FsFile.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2011-2022 Bill Greiman + * Copyright (c) 2011-2024 Bill Greiman * This file is part of the SdFat library for SD memory cards. * * MIT License @@ -23,32 +23,36 @@ * DEALINGS IN THE SOFTWARE. */ #include "FsLib.h" +#if FILE_COPY_CONSTRUCTOR_SELECT //------------------------------------------------------------------------------ -FsBaseFile::FsBaseFile(const FsBaseFile& from) { - m_fFile = nullptr; - m_xFile = nullptr; - if (from.m_fFile) { - m_fFile = new (m_fileMem) FatFile; - *m_fFile = *from.m_fFile; - } else if (from.m_xFile) { - m_xFile = new (m_fileMem) ExFatFile; - *m_xFile = *from.m_xFile; - } -} +FsBaseFile::FsBaseFile(const FsBaseFile& from) { copy(&from); } //------------------------------------------------------------------------------ FsBaseFile& FsBaseFile::operator=(const FsBaseFile& from) { - if (this == &from) { - return *this; + copy(&from); + return *this; +} +#endif // FILE_COPY_CONSTRUCTOR_SELECT +//------------------------------------------------------------------------------ +void FsBaseFile::copy(const FsBaseFile* from) { + if (from != this) { + m_fFile = nullptr; + m_xFile = nullptr; + if (from->m_fFile) { + m_fFile = new (m_fileMem) FatFile; + m_fFile->copy(from->m_fFile); + } else if (from->m_xFile) { + m_xFile = new (m_fileMem) ExFatFile; + m_xFile->copy(from->m_xFile); + } } - close(); - if (from.m_fFile) { - m_fFile = new (m_fileMem) FatFile; - *m_fFile = *from.m_fFile; - } else if (from.m_xFile) { - m_xFile = new (m_fileMem) ExFatFile; - *m_xFile = *from.m_xFile; +} +//------------------------------------------------------------------------------ +void FsBaseFile::move(FsBaseFile* from) { + if (from != this) { + copy(from); + from->m_fFile = nullptr; + from->m_xFile = nullptr; } - return *this; } //------------------------------------------------------------------------------ bool FsBaseFile::close() { diff --git a/src/FsLib/FsFile.h b/src/FsLib/FsFile.h index 926294aa..c8df331e 100644 --- a/src/FsLib/FsFile.h +++ b/src/FsLib/FsFile.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2011-2022 Bill Greiman + * Copyright (c) 2011-2024 Bill Greiman * This file is part of the SdFat library for SD memory cards. * * MIT License @@ -49,9 +49,18 @@ class FsBaseFile { */ FsBaseFile(const char* path, oflag_t oflag) { open(path, oflag); } - ~FsBaseFile() { close(); } + /** Copy from to this. + * \param[in] from Source file. + */ + void copy(const FsBaseFile* from); + + /** move from to this. + * \param[in] from Source file. + */ + void move(FsBaseFile* from); + +#if FILE_COPY_CONSTRUCTOR_SELECT == FILE_COPY_CONSTRUCTOR_PUBLIC /** Copy constructor. - * * \param[in] from Object used to initialize this instance. */ FsBaseFile(const FsBaseFile& from); @@ -60,6 +69,46 @@ class FsBaseFile { * \return assigned object. */ FsBaseFile& operator=(const FsBaseFile& from); +#elif FILE_COPY_CONSTRUCTOR_SELECT == FILE_COPY_CONSTRUCTOR_PRIVATE + + private: + FsBaseFile(const FsBaseFile& from); + FsBaseFile& operator=(const FsBaseFile& from); + + public: +#else // FILE_COPY_CONSTRUCTOR_SELECT + FsBaseFile(const FsBaseFile& from) = delete; + FsBaseFile& operator=(const FsBaseFile& from) = delete; +#endif // FILE_COPY_CONSTRUCTOR_SELECT + +#if FILE_MOVE_CONSTRUCTOR_SELECT + /** Move constructor. + * \param[in] from File to move. + */ + FsBaseFile(FsBaseFile&& from) { move(&from); } + /** Move assignment operator. + * \param[in] from File to move. + * \return Assigned file. + */ + FsBaseFile& operator=(FsBaseFile&& from) { + move(&from); + return *this; + } +#else // FILE_MOVE_CONSTRUCTOR_SELECT + FsBaseFile(FsBaseFile&& from) = delete; + FsBaseFile& operator=(FsBaseFile&& from) = delete; +#endif // FILE_MOVE_CONSTRUCTOR_SELECT + +#if DESTRUCTOR_CLOSES_FILE + ~FsBaseFile() { + if (isOpen()) { + close(); + } + } +#else // DESTRUCTOR_CLOSES_FILE + ~FsBaseFile() = default; +#endif // DESTRUCTOR_CLOSES_FILE + /** The parenthesis operator. * * \return true if a file is open. @@ -752,7 +801,7 @@ class FsBaseFile { * \return true for success or false for failure. */ bool seekSet(uint64_t pos) { - return m_fFile ? pos < (1ULL << 32) && m_fFile->seekSet(pos) + return m_fFile ? pos < (1ULL << 32) && m_fFile->seekSet((uint32_t)pos) : m_xFile ? m_xFile->seekSet(pos) : false; } diff --git a/src/SdCard/SdCard.h b/src/SdCard/SdCard.h index b6ea8f0b..86697bbd 100644 --- a/src/SdCard/SdCard.h +++ b/src/SdCard/SdCard.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2011-2022 Bill Greiman + * Copyright (c) 2011-2024 Bill Greiman * This file is part of the SdFat library for SD memory cards. * * MIT License @@ -64,11 +64,10 @@ class SdCardFactory { /** Initialize SPI card. * * \param[in] config SPI configuration. - * \return generic card pointer. + * \return generic card pointer or nullptr if failure. */ SdCard* newCard(SdSpiConfig config) { - m_spiCard.begin(config); - return &m_spiCard; + return m_spiCard.begin(config) ? &m_spiCard : nullptr; } /** Initialize SDIO card. * @@ -77,8 +76,7 @@ class SdCardFactory { */ SdCard* newCard(SdioConfig config) { #if HAS_SDIO_CLASS - m_sdioCard.begin(config); - return &m_sdioCard; + return m_sdioCard.begin(config) ? &m_sdioCard : nullptr; #else // HAS_SDIO_CLASS (void)config; return nullptr; diff --git a/src/SdCard/SdCardInfo.h b/src/SdCard/SdCardInfo.h index 34387589..9ef7f75b 100644 --- a/src/SdCard/SdCardInfo.h +++ b/src/SdCard/SdCardInfo.h @@ -59,7 +59,7 @@ SD_CARD_ERROR(CMD8, "Send and check interface settings") \ SD_CARD_ERROR(CMD9, "Read CSD data") \ SD_CARD_ERROR(CMD10, "Read CID data") \ - SD_CARD_ERROR(CMD12, "Stop multiple block read") \ + SD_CARD_ERROR(CMD12, "Stop multiple block transmission") \ SD_CARD_ERROR(CMD13, "Read card status") \ SD_CARD_ERROR(CMD17, "Read single block") \ SD_CARD_ERROR(CMD18, "Read multiple blocks") \ diff --git a/src/SdCard/SdCardInterface.h b/src/SdCard/SdCardInterface.h index e24e6513..586fbdd3 100644 --- a/src/SdCard/SdCardInterface.h +++ b/src/SdCard/SdCardInterface.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2011-2022 Bill Greiman + * Copyright (c) 2011-2024 Bill Greiman * This file is part of the SdFat library for SD memory cards. * * MIT License @@ -59,6 +59,8 @@ class SdCardInterface : public FsBlockDeviceInterface { virtual bool hasDedicatedSpi() { return false; } /** \return false by default */ bool virtual isDedicatedSpi() { return false; } + /** \return false by default */ + bool virtual isSpi() { return false; } /** Set SPI sharing state * \param[in] value desired state. * \return false by default. diff --git a/src/SdCard/SdSpiCard.cpp b/src/SdCard/SdSpiCard.cpp index 9d08a3cd..e924336c 100644 --- a/src/SdCard/SdSpiCard.cpp +++ b/src/SdCard/SdSpiCard.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2011-2022 Bill Greiman + * Copyright (c) 2011-2024 Bill Greiman * This file is part of the SdFat library for SD memory cards. * * MIT License @@ -123,6 +123,8 @@ static uint16_t CRC_CCITT(const uint8_t* data, size_t n) { // SharedSpiCard member functions //------------------------------------------------------------------------------ bool SharedSpiCard::begin(SdSpiConfig spiConfig) { + uint8_t cardType; + uint32_t arg; Timeout timeout; // Restore state to creator. initSharedSpiCard(); @@ -140,7 +142,7 @@ bool SharedSpiCard::begin(SdSpiConfig spiConfig) { spiSetSckSpeed(1000UL * SD_MAX_INIT_RATE_KHZ); spiBegin(spiConfig); m_beginCalled = true; - uint32_t arg; + spiStart(); // must supply min of 74 clock cycles with CS high. @@ -169,7 +171,7 @@ bool SharedSpiCard::begin(SdSpiConfig spiConfig) { // check SD version while (true) { if (cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND) { - type(SD_CARD_TYPE_SD1); + cardType = SD_CARD_TYPE_SD1; break; } // Skip first three bytes. @@ -177,7 +179,7 @@ bool SharedSpiCard::begin(SdSpiConfig spiConfig) { m_status = spiReceive(); } if (m_status == 0XAA) { - type(SD_CARD_TYPE_SD2); + cardType = SD_CARD_TYPE_SD2; break; } if (timeout.timedOut()) { @@ -186,7 +188,7 @@ bool SharedSpiCard::begin(SdSpiConfig spiConfig) { } } // initialize card and send host supports SDHC if SD2 - arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0; + arg = cardType == SD_CARD_TYPE_SD2 ? 0X40000000 : 0; while (cardAcmd(ACMD41, arg) != R1_READY_STATE) { // check for timeout if (timeout.timedOut()) { @@ -195,13 +197,13 @@ bool SharedSpiCard::begin(SdSpiConfig spiConfig) { } } // if SD2 read OCR register to check for SDHC card - if (type() == SD_CARD_TYPE_SD2) { + if (cardType == SD_CARD_TYPE_SD2) { if (cardCommand(CMD58, 0)) { error(SD_CARD_ERROR_CMD58); goto fail; } if ((spiReceive() & 0XC0) == 0XC0) { - type(SD_CARD_TYPE_SDHC); + cardType = SD_CARD_TYPE_SDHC; } // Discard rest of ocr - contains allowed voltage range. for (uint8_t i = 0; i < 3; i++) { @@ -210,6 +212,7 @@ bool SharedSpiCard::begin(SdSpiConfig spiConfig) { } spiStop(); spiSetSckSpeed(spiConfig.maxSck); + m_type = cardType; return true; fail: @@ -307,7 +310,7 @@ bool SharedSpiCard::erase(uint32_t firstSector, uint32_t lastSector) { goto fail; } } - if (m_type != SD_CARD_TYPE_SDHC) { + if (type() != SD_CARD_TYPE_SDHC) { firstSector <<= 9; lastSector <<= 9; } diff --git a/src/SdCard/SdSpiCard.h b/src/SdCard/SdSpiCard.h index abaed59c..4b1477c3 100644 --- a/src/SdCard/SdSpiCard.h +++ b/src/SdCard/SdSpiCard.h @@ -141,6 +141,8 @@ class SharedSpiCard { bool isBusy(); /** \return false, can't be in dedicated state. */ bool isDedicatedSpi() { return false; } + /** \return true if card is on SPI bus. */ + bool isSpi() { return true; } /** * Read a card's CID register. The CID contains card identification * information such as Manufacturer ID, Product name, Product serial @@ -301,7 +303,6 @@ class SharedSpiCard { void spiStart(); void spiStop(); void spiUnselect() { sdCsWrite(m_csPin, true); } - void type(uint8_t value) { m_type = value; } bool waitReady(uint16_t ms); bool writeData(uint8_t token, const uint8_t* src); #if SPI_DRIVER_SELECT < 2 diff --git a/src/SdCard/SdioCard.h b/src/SdCard/SdioCard.h index 55859d79..eb032e4a 100644 --- a/src/SdCard/SdioCard.h +++ b/src/SdCard/SdioCard.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2011-2022 Bill Greiman + * Copyright (c) 2011-2024 Bill Greiman * This file is part of the SdFat library for SD memory cards. * * MIT License @@ -176,21 +176,11 @@ class SdioCard : public SdCardInterface { * \param[in] sector Address of first sector in sequence. * * \note This function is used with readData() and readStop() for optimized - * multiple sector reads. SPI chipSelect must be low for the entire sequence. + * multiple sector reads. * * \return true for success or false for failure. */ bool readStart(uint32_t sector); - /** Start a read multiple sectors sequence. - * - * \param[in] sector Address of first sector in sequence. - * \param[in] count Maximum sector count. - * \note This function is used with readData() and readStop() for optimized - * multiple sector reads. SPI chipSelect must be low for the entire sequence. - * - * \return true for success or false for failure. - */ - bool readStart(uint32_t sector, uint32_t count); /** End a read multiple sectors sequence. * * \return true for success or false for failure. @@ -251,16 +241,6 @@ class SdioCard : public SdCardInterface { * \return true for success or false for failure. */ bool writeStart(uint32_t sector); - /** Start a write multiple sectors sequence. - * - * \param[in] sector Address of first sector in sequence. - * \param[in] count Maximum sector count. - * \note This function is used with writeData() and writeStop() - * for optimized multiple sector writes. - * - * \return true for success or false for failure. - */ - bool writeStart(uint32_t sector, uint32_t count); /** End a write multiple sectors sequence. * diff --git a/src/SdCard/SdioTeensy.cpp b/src/SdCard/SdioTeensy.cpp index 01818236..c4b81330 100644 --- a/src/SdCard/SdioTeensy.cpp +++ b/src/SdCard/SdioTeensy.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2011-2022 Bill Greiman + * Copyright (c) 2011-2024 Bill Greiman * This file is part of the SdFat library for SD memory cards. * * MIT License @@ -764,11 +764,23 @@ bool SdioCard::begin(SdioConfig sdioConfig) { // Determine if High Speed mode is supported and set frequency. // Check status[16] for error 0XF or status[16] for new mode 0X1. uint8_t status[64]; - if (m_scr.sdSpec() > 0 && cardCMD6(0X00FFFFFF, status) && (2 & status[13]) && - cardCMD6(0X80FFFFF1, status) && (status[16] & 0XF) == 1) { - kHzSdClk = 50000; - } else { - kHzSdClk = 25000; + kHzSdClk = 25000; + if (m_scr.sdSpec() > 0) { + // card is 1.10 or greater - must support CMD6 + if (!cardCMD6(0X00FFFFFF, status)) { + return false; + } + if (2 & status[13]) { + // Card supports High Speed mode - switch mode. + if (!cardCMD6(0X80FFFFF1, status)) { + return false; + } + if ((status[16] & 0XF) == 1) { + kHzSdClk = 50000; + } else { + return sdError(SD_CARD_ERROR_CMD6); + } + } } // Disable GPIO. enableGPIO(false); @@ -1036,8 +1048,10 @@ bool SdioCard::syncDevice() { } //------------------------------------------------------------------------------ uint8_t SdioCard::type() const { - return m_version2 ? m_highCapacity ? SD_CARD_TYPE_SDHC : SD_CARD_TYPE_SD2 - : SD_CARD_TYPE_SD1; + return !m_initDone ? 0 + : !m_version2 ? SD_CARD_TYPE_SD1 + : !m_highCapacity ? SD_CARD_TYPE_SD2 + : SD_CARD_TYPE_SDHC; } //------------------------------------------------------------------------------ bool SdioCard::writeData(const uint8_t* src) { diff --git a/src/SdFat.h b/src/SdFat.h index d906ea5f..d17393df 100644 --- a/src/SdFat.h +++ b/src/SdFat.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2011-2022 Bill Greiman + * Copyright (c) 2011-2024 Bill Greiman * This file is part of the SdFat library for SD memory cards. * * MIT License @@ -38,9 +38,9 @@ #endif // INCLUDE_SDIOS //------------------------------------------------------------------------------ /** SdFat version for cpp use. */ -#define SD_FAT_VERSION 20202 +#define SD_FAT_VERSION 20203 /** SdFat version as string. */ -#define SD_FAT_VERSION_STR "2.2.2" +#define SD_FAT_VERSION_STR "2.2.3" //============================================================================== /** * \class SdBase @@ -80,7 +80,7 @@ class SdBase : public Vol { * \return true for success or false for failure. */ bool begin(SdSpiConfig spiConfig) { - return cardBegin(spiConfig) && Vol::begin(m_card); + return cardBegin(spiConfig) && volumeBegin(); } //--------------------------------------------------------------------------- /** Initialize SD card and file system for SDIO mode. @@ -89,7 +89,7 @@ class SdBase : public Vol { * \return true for success or false for failure. */ bool begin(SdioConfig sdioConfig) { - return cardBegin(sdioConfig) && Vol::begin(m_card); + return cardBegin(sdioConfig) && volumeBegin(); } //---------------------------------------------------------------------------- /** \return Pointer to SD card object. */ @@ -347,7 +347,9 @@ class SdBase : public Vol { * * \return true for success or false for failure. */ - bool volumeBegin() { return Vol::begin(m_card); } + bool volumeBegin() { + return Vol::begin(m_card) || Vol::begin(m_card, true, 0); + } #if ENABLE_ARDUINO_SERIAL /** Print error details after begin() fails. */ void initErrorPrint() { initErrorPrint(&Serial); } @@ -445,7 +447,6 @@ typedef FsBaseFile SdBaseFile; #if defined __has_include #if __has_include() #define HAS_INCLUDE_FS_H -#warning File not defined because __has_include(FS.h) #endif // __has_include() #endif // defined __has_include #ifndef HAS_INCLUDE_FS_H @@ -457,6 +458,8 @@ typedef ExFile File; #elif SDFAT_FILE_TYPE == 3 typedef FsFile File; #endif // SDFAT_FILE_TYPE +#elif !defined(DISABLE_FS_H_WARNING) +#warning File not defined because __has_include(FS.h) #endif // HAS_INCLUDE_FS_H /** * \class SdFile diff --git a/src/SdFatConfig.h b/src/SdFatConfig.h index 946bab19..353aa101 100644 --- a/src/SdFatConfig.h +++ b/src/SdFatConfig.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2011-2022 Bill Greiman + * Copyright (c) 2011-2024 Bill Greiman * This file is part of the SdFat library for SD memory cards. * * MIT License @@ -34,7 +34,7 @@ #endif // __AVR__ // // To try UTF-8 encoded filenames. -// #define USE_UTF8_LONG_NAMES 1 +// #define USE_UTF8_LONG_NAMES 1 // // For minimum flash size use these settings: // #define USE_FAT_FILE_FLAG_CONTIGUOUS 0 @@ -46,6 +46,48 @@ // Options can be set in a makefile or an IDE like platformIO // if they are in a #ifndef/#endif block below. //------------------------------------------------------------------------------ +/* + * Options for file class constructors, assignment operators and destructors. + * + * By default file copy constructors and copy assignment operators are + * private to prevent multiple copies of a instance for a file. + * + * File move constructors and move assignment operators are public to permit + * return of a file instance for compilers that aren't able to use copy elision. + * + */ +/** File copy constructors and copy assignment operators are deleted */ +#define FILE_COPY_CONSTRUCTOR_DELETED 0 +/** File copy constructors and copy assignment operators are private */ +#define FILE_COPY_CONSTRUCTOR_PRIVATE 1 +/** File copy constructors and copy assignment operators are public */ +#define FILE_COPY_CONSTRUCTOR_PUBLIC 2 + +#ifndef FILE_COPY_CONSTRUCTOR_SELECT +/** Specify kind of file copy constructors and copy assignment operators */ +#define FILE_COPY_CONSTRUCTOR_SELECT FILE_COPY_CONSTRUCTOR_PRIVATE +#endif // FILE_COPY_CONSTRUCTOR_SELECT +/** File move constructors and move assignment operators are deleted. */ +#define FILE_MOVE_CONSTRUCTOR_DELETED 0 +/** File move constructors and move assignment operators are public. */ +#define FILE_MOVE_CONSTRUCTOR_PUBLIC 1 + +#ifndef FILE_MOVE_CONSTRUCTOR_SELECT +/** Specify kind of file move constructors and move assignment operators */ +#define FILE_MOVE_CONSTRUCTOR_SELECT FILE_MOVE_CONSTRUCTOR_PUBLIC +#endif // FILE_MOVE_CONSTRUCTOR_SELECT + +#if FILE_MOVE_CONSTRUCTOR_SELECT != FILE_MOVE_CONSTRUCTOR_PUBLIC && \ + FILE_COPY_CONSTRUCTOR_SELECT != FILE_COPY_CONSTRUCTOR_PUBLIC +#error "No public move or copy assign operators" +#endif // FILE_MOVE_CONSTRUCTOR_SELECT && FILE_MOVE_CONSTRUCTOR_SELECT +/** + * Set DESTRUCTOR_CLOSES_FILE nonzero to close a file in its destructor. */ +#ifndef DESTRUCTOR_CLOSES_FILE +#define DESTRUCTOR_CLOSES_FILE 0 +#endif // DESTRUCTOR_CLOSES_FILE +//------------------------------------------------------------------------------ + /** For Debug - must be one */ #define ENABLE_ARDUINO_FEATURES 1 /** For Debug - must be one */ @@ -327,15 +369,6 @@ typedef uint8_t SdCsPin_t; #define FAT12_SUPPORT 0 #endif // FAT12_SUPPORT //------------------------------------------------------------------------------ -/** - * Set DESTRUCTOR_CLOSES_FILE nonzero to close a file in its destructor. - * - * Causes use of lots of heap in ARM. - */ -#ifndef DESTRUCTOR_CLOSES_FILE -#define DESTRUCTOR_CLOSES_FILE 0 -#endif // DESTRUCTOR_CLOSES_FILE -//------------------------------------------------------------------------------ /** * Call flush for endl if ENDL_CALLS_FLUSH is nonzero * diff --git a/src/common/CompileDateTime.h b/src/common/CompileDateTime.h index d2d6351e..7cc041eb 100644 --- a/src/common/CompileDateTime.h +++ b/src/common/CompileDateTime.h @@ -33,30 +33,25 @@ constexpr uint16_t compileYear() { return 1000 * (__DATE__[7] - '0') + 100 * (__DATE__[8] - '0') + 10 * (__DATE__[9] - '0') + (__DATE__[10] - '0'); } -/** \return true if str equals the month field of the __DATE__ macro. */ -constexpr bool compileMonthIs(const char* str) { - return __DATE__[0] == str[0] && __DATE__[1] == str[1] && - __DATE__[2] == str[2]; -} /** \return month field of the __DATE__ macro. */ constexpr uint8_t compileMonth() { - return compileMonthIs("Jan") ? 1 - : compileMonthIs("Feb") ? 2 - : compileMonthIs("Mar") ? 3 - : compileMonthIs("Apr") ? 4 - : compileMonthIs("May") ? 5 - : compileMonthIs("Jun") ? 6 - : compileMonthIs("Jul") ? 7 - : compileMonthIs("Aug") ? 8 - : compileMonthIs("Sep") ? 9 - : compileMonthIs("Oct") ? 10 - : compileMonthIs("Nov") ? 11 - : compileMonthIs("Dec") ? 12 - : 0; + return __DATE__[0] == 'J' && __DATE__[1] == 'a' && __DATE__[2] == 'n' ? 1 + : __DATE__[0] == 'F' && __DATE__[1] == 'e' && __DATE__[2] == 'b' ? 2 + : __DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'r' ? 3 + : __DATE__[0] == 'A' && __DATE__[1] == 'p' && __DATE__[2] == 'r' ? 4 + : __DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'y' ? 5 + : __DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'n' ? 6 + : __DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'l' ? 7 + : __DATE__[0] == 'A' && __DATE__[1] == 'u' && __DATE__[2] == 'g' ? 8 + : __DATE__[0] == 'S' && __DATE__[1] == 'e' && __DATE__[2] == 'p' ? 9 + : __DATE__[0] == 'O' && __DATE__[1] == 'c' && __DATE__[2] == 't' ? 10 + : __DATE__[0] == 'N' && __DATE__[1] == 'o' && __DATE__[2] == 'v' ? 11 + : __DATE__[0] == 'D' && __DATE__[1] == 'e' && __DATE__[2] == 'c' ? 12 + : 0; } /** \return day field of the __DATE__ macro. */ constexpr uint8_t compileDay() { - return 10 * (__DATE__[4] == ' ' ? 0 : __DATE__[4] - '0') + + return 10 * ((__DATE__[4] == ' ' ? '0' : __DATE__[4]) - '0') + (__DATE__[5] - '0'); } /** \return hour field of the __TIME__ macro. */ diff --git a/src/iostream/StdioStream.cpp b/src/iostream/StdioStream.cpp index ec65456d..1433e3d7 100644 --- a/src/iostream/StdioStream.cpp +++ b/src/iostream/StdioStream.cpp @@ -201,7 +201,10 @@ int StdioStream::fseek(int32_t offset, int origin) { break; case SEEK_SET: - if (!StreamBaseFile::seekSet(offset)) { + if (offset < 0) { + goto fail; + } + if (!StreamBaseFile::seekSet((uint32_t)offset)) { goto fail; } break; @@ -349,7 +352,7 @@ bool StdioStream::rewind() { return false; } } - StreamBaseFile::seekSet(0); + StreamBaseFile::seekSet(0UL); m_r = 0; return true; }