diff --git a/examples/OpenNext/OpenNext.ino b/examples/OpenNext/OpenNext.ino index 56329b4c..d88a49d9 100644 --- a/examples/OpenNext/OpenNext.ino +++ b/examples/OpenNext/OpenNext.ino @@ -10,6 +10,7 @@ const uint8_t chipSelect = SS; // file system object SdFat sd; +SdFile root; SdFile file; //------------------------------------------------------------------------------ void setup() { @@ -30,12 +31,13 @@ void setup() { if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) { sd.initErrorHalt(); } - - // Open next file in root. The volume working directory, vwd, is root. - // Warning, openNext starts at the current position of sd.vwd() so a - // rewind may be neccessary in your application. - sd.vwd()->rewind(); - while (file.openNext(sd.vwd(), O_RDONLY)) { + if (!root.open("/")) { + sd.errorHalt("open root failed"); + } + // Open next file in root. + // Warning, openNext starts at the current directory position + // so a rewind of the directory may be required. + while (file.openNext(&root, O_RDONLY)) { file.printFileSize(&Serial); Serial.write(' '); file.printModifyDateTime(&Serial); @@ -48,7 +50,11 @@ void setup() { Serial.println(); file.close(); } - Serial.println("Done!"); + if (root.getError()) { + Serial.println("openNext failed"); + } else { + Serial.println("Done!"); + } } //------------------------------------------------------------------------------ void loop() {} diff --git a/library.properties b/library.properties index 07088fa6..d00bcedb 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=SdFat -version=1.0.14 +version=1.0.15 author=Bill Greiman maintainer=Bill Greiman sentence=FAT16/FAT32 file system for SD cards. diff --git a/src/FatLib/FatFile.h b/src/FatLib/FatFile.h index 616959e0..0c043d5b 100644 --- a/src/FatLib/FatFile.h +++ b/src/FatLib/FatFile.h @@ -141,9 +141,11 @@ class FatFile { * LS_SIZE - %Print file size. * * LS_R - Recursive list of subdirectories. + * + * \return true for success or false if an error occurred. */ - void ls(uint8_t flags = 0) { - ls(&Serial, flags); + bool ls(uint8_t flags = 0) { + return ls(&Serial, flags); } /** %Print a directory date field. * @@ -464,8 +466,10 @@ class FatFile { * * \param[in] indent Amount of space before file name. Used for recursive * list to indicate subdirectory level. + * + * \return true for success or false if an error occurred. */ - void ls(print_t* pr, uint8_t flags = 0, uint8_t indent = 0); + bool ls(print_t* pr, uint8_t flags = 0, uint8_t indent = 0); /** Make a new directory. * * \param[in] dir An open FatFile instance for the directory that will diff --git a/src/FatLib/FatFilePrint.cpp b/src/FatLib/FatFilePrint.cpp index e5785557..5cc79e8a 100644 --- a/src/FatLib/FatFilePrint.cpp +++ b/src/FatLib/FatFilePrint.cpp @@ -96,12 +96,16 @@ void FatFile::dmpFile(print_t* pr, uint32_t pos, size_t n) { pr->write('\n'); } //------------------------------------------------------------------------------ -void FatFile::ls(print_t* pr, uint8_t flags, uint8_t indent) { +bool FatFile::ls(print_t* pr, uint8_t flags, uint8_t indent) { FatFile file; + if (!isDir() || getError()) { + DBG_FAIL_MACRO; + goto fail; + } rewind(); while (file.openNext(this, O_RDONLY)) { - // indent for dir level if (!file.isHidden() || (flags & LS_A)) { + // indent for dir level for (uint8_t i = 0; i < indent; i++) { pr->write(' '); } @@ -120,11 +124,22 @@ void FatFile::ls(print_t* pr, uint8_t flags, uint8_t indent) { pr->write('\r'); pr->write('\n'); if ((flags & LS_R) && file.isDir()) { - file.ls(pr, flags, indent + 2); + if (!file.ls(pr, flags, indent + 2)) { + DBG_FAIL_MACRO; + goto fail; + } } } file.close(); } + if (getError()) { + DBG_FAIL_MACRO; + goto fail; + } + return true; + + fail: + return false; } //------------------------------------------------------------------------------ bool FatFile::printCreateDateTime(print_t* pr) { diff --git a/src/FatLib/FatFileSystem.h b/src/FatLib/FatFileSystem.h index bc72b412..044b9cf9 100644 --- a/src/FatLib/FatFileSystem.h +++ b/src/FatLib/FatFileSystem.h @@ -61,9 +61,11 @@ class FatFileSystem : public FatVolume { * LS_SIZE - %Print file size. * * LS_R - Recursive list of subdirectories. + * + * \return true for success or false if an error occurred. */ - void ls(uint8_t flags = 0) { - ls(&Serial, flags); + bool ls(uint8_t flags = 0) { + return ls(&Serial, flags); } /** List the directory contents of a directory to Serial. * @@ -76,9 +78,11 @@ class FatFileSystem : public FatVolume { * LS_SIZE - %Print file size. * * LS_R - Recursive list of subdirectories. + * + * \return true for success or false if an error occurred. */ - void ls(const char* path, uint8_t flags = 0) { - ls(&Serial, path, flags); + bool ls(const char* path, uint8_t flags = 0) { + return ls(&Serial, path, flags); } /** open a file * @@ -194,9 +198,11 @@ class FatFileSystem : public FatVolume { * LS_SIZE - %Print file size. * * LS_R - Recursive list of subdirectories. + * + * \return true for success or false if an error occurred. */ - void ls(print_t* pr, uint8_t flags = 0) { - vwd()->ls(pr, flags); + bool ls(print_t* pr, uint8_t flags = 0) { + return vwd()->ls(pr, flags); } //---------------------------------------------------------------------------- /** List the directory contents of a directory. @@ -212,11 +218,12 @@ class FatFileSystem : public FatVolume { * LS_SIZE - %Print file size. * * LS_R - Recursive list of subdirectories. + * + * \return true for success or false if an error occurred. */ - void ls(print_t* pr, const char* path, uint8_t flags) { + bool ls(print_t* pr, const char* path, uint8_t flags) { FatFile dir; - dir.open(vwd(), path, O_RDONLY); - dir.ls(pr, flags); + return dir.open(vwd(), path, O_RDONLY) && dir.ls(pr, flags); } //---------------------------------------------------------------------------- /** Make a subdirectory in the volume working directory. diff --git a/src/SdCard/SdSpiCard.cpp b/src/SdCard/SdSpiCard.cpp index 6e20e7db..f36b59a2 100644 --- a/src/SdCard/SdSpiCard.cpp +++ b/src/SdCard/SdSpiCard.cpp @@ -30,10 +30,11 @@ #define SD_CS_DBG(m) // #define SD_CS_DBG(m) Serial.println(F(m)); -#define DBG_PROFILE_TIME 0 -#if DBG_PROFILE_TIME +#define DBG_PROFILE_STATS 0 +#if DBG_PROFILE_STATS #define DBG_TAG_LIST\ + DBG_TAG(DBG_CMD0_TIME, "CMD0 time")\ DBG_TAG(DBG_ACMD41_TIME, "ACMD41 time")\ DBG_TAG(DBG_CMD_BUSY, "cmd busy")\ DBG_TAG(DBG_ERASE_BUSY, "erase busy")\ @@ -41,7 +42,8 @@ DBG_TAG(DBG_WRITE_FLASH, "write flash")\ DBG_TAG(DBG_WRITE_BUSY, "write busy")\ DBG_TAG(DBG_WRITE_STOP, "write stop")\ - DBG_TAG(DBG_ACMD41_COUNT, "ACMD41 count") + DBG_TAG(DBG_ACMD41_COUNT, "ACMD41 count")\ + DBG_TAG(DBG_CMD0_COUNT, "CMD0 count") #define DBG_TIME_DIM DBG_ACMD41_COUNT @@ -62,6 +64,17 @@ static void dbgBeginTime(DbgTag tag) { dbgBgnTime[tag] = micros(); } //------------------------------------------------------------------------------ +static void dbgClearStats() { + for (int i = 0; i < DBG_COUNT_DIM; i++) { + dbgCount[i] = 0; + if (i < DBG_TIME_DIM) { + dbgMaxTime[i] = 0; + dbgMinTime[i] = 9999999; + dbgTotalTime[i] = 0; + } + } +} +//------------------------------------------------------------------------------ static void dbgEndTime(DbgTag tag) { uint32_t m = micros() - dbgBgnTime[tag]; dbgTotalTime[tag] += m; @@ -78,17 +91,6 @@ static void dbgEventCount(DbgTag tag) { dbgCount[tag]++; } //------------------------------------------------------------------------------ -void dbgInitTime() { - for (int i = 0; i < DBG_COUNT_DIM; i++) { - dbgCount[i] = 0; - if (i < DBG_TIME_DIM) { - dbgMaxTime[i] = 0; - dbgMinTime[i] = 9999999; - dbgTotalTime[i] = 0; - } - } -} -//------------------------------------------------------------------------------ static void dbgPrintTagText(uint8_t tag) { #define DBG_TAG(e, m) case e: Serial.print(F(m)); break; switch (tag) { @@ -97,7 +99,7 @@ static void dbgPrintTagText(uint8_t tag) { #undef DBG_TAG } //------------------------------------------------------------------------------ -void dbgPrintTime() { +static void dbgPrintStats() { Serial.println(); Serial.println(F("=======================")); Serial.println(F("item,event,min,max,avg")); @@ -125,13 +127,13 @@ void dbgPrintTime() { #define DBG_BEGIN_TIME(tag) dbgBeginTime(tag) #define DBG_END_TIME(tag) dbgEndTime(tag) #define DBG_EVENT_COUNT(tag) dbgEventCount(tag) -#else // DBG_PROFILE_TIME +#else // DBG_PROFILE_STATS #define DBG_BEGIN_TIME(tag) #define DBG_END_TIME(tag) #define DBG_EVENT_COUNT(tag) -void dbgInitTime() {} -void dbgPrintTime() {} -#endif // DBG_PROFILE_TIME +static void dbgClearStats() {} +static void dbgPrintStats() {} +#endif // DBG_PROFILE_STATS //============================================================================== #if USE_SD_CRC // CRC functions @@ -242,8 +244,13 @@ bool SdSpiCard::begin(SdSpiDriver* spi, uint8_t csPin, SPISettings settings) { } spiSelect(); + DBG_BEGIN_TIME(DBG_CMD0_TIME); // command to go idle in SPI mode - for (uint8_t i = 0; cardCommand(CMD0, 0) != R1_IDLE_STATE; i++) { + for (uint8_t i = 1;; i++) { + DBG_EVENT_COUNT(DBG_CMD0_COUNT); + if (cardCommand(CMD0, 0) == R1_IDLE_STATE) { + break; + } if (i == SD_CMD0_RETRY) { error(SD_CARD_ERROR_CMD0); goto fail; @@ -255,6 +262,7 @@ bool SdSpiCard::begin(SdSpiDriver* spi, uint8_t csPin, SPISettings settings) { spiReceive(); } } + DBG_END_TIME(DBG_CMD0_TIME); #if USE_SD_CRC if (cardCommand(CMD59, 1) != R1_IDLE_STATE) { error(SD_CARD_ERROR_CMD59); @@ -364,6 +372,10 @@ uint32_t SdSpiCard::cardSize() { return readCSD(&csd) ? sdCardCapacity(&csd) : 0; } //------------------------------------------------------------------------------ +void SdSpiCard::dbgClearStats() {::dbgClearStats();} +//------------------------------------------------------------------------------ +void SdSpiCard::dbgPrintStats() {::dbgPrintStats();} +//------------------------------------------------------------------------------ bool SdSpiCard::erase(uint32_t firstBlock, uint32_t lastBlock) { csd_t csd; if (!readCSD(&csd)) { diff --git a/src/SdCard/SdSpiCard.h b/src/SdCard/SdSpiCard.h index d8943656..bb4e83b5 100644 --- a/src/SdCard/SdSpiCard.h +++ b/src/SdCard/SdSpiCard.h @@ -60,6 +60,10 @@ class SdSpiCard { * or zero if an error occurs. */ uint32_t cardSize(); + /** Clear debug stats. */ + void dbgClearStats(); + /** Print debug stats. */ + void dbgPrintStats(); /** Erase a range of blocks. * * \param[in] firstBlock The address of the first block in the range. diff --git a/src/SdFat.h b/src/SdFat.h index 9387372f..a34c8c6f 100644 --- a/src/SdFat.h +++ b/src/SdFat.h @@ -37,7 +37,7 @@ #endif // INCLUDE_SDIOS //------------------------------------------------------------------------------ /** SdFat version */ -#define SD_FAT_VERSION "1.0.14" +#define SD_FAT_VERSION "1.0.15" //============================================================================== /** * \class SdBaseFile diff --git a/src/SpiDriver/SdSpiParticle.cpp b/src/SpiDriver/SdSpiParticle.cpp index 5d1a2289..ee75bbfb 100644 --- a/src/SpiDriver/SdSpiParticle.cpp +++ b/src/SpiDriver/SdSpiParticle.cpp @@ -44,8 +44,7 @@ void SdSpiAltDriver::activate() { */ void SdSpiAltDriver::begin(uint8_t csPin) { m_csPin = csPin; - m_spi->begin(m_csPin); - // Next line is redundant - begin(m_csPin) sets csPin to output mode. + m_spi->begin(); pinMode(m_csPin, OUTPUT); digitalWrite(m_csPin, HIGH); }