浏览代码

Fix SdInfo example and file.timestamp. Remove Syscall::yield and SysCall::halt

Fix SdInfo example and file.timestamp. Remove Syscall::yield and SysCall::halt.

Major restructuring for future portability to RTOS systems and RPI Pico.
Bill Greiman 3 年之前
父节点
当前提交
fb7415151b
共有 100 个文件被更改,包括 1024 次插入1024 次删除
  1. 1 1
      README.md
  2. 311 144
      doc/Doxyfile
  3. 二进制
      doc/html.zip
  4. 8 4
      doc/mainpage.h
  5. 3 6
      examples/AvrAdcLogger/AvrAdcLogger.ino
  6. 2 2
      examples/DirectoryFunctions/DirectoryFunctions.ino
  7. 2 2
      examples/ExFatLogger/ExFatLogger.ino
  8. 58 0
      examples/MinimumSizeSdReader/MinimumSizeSdReader.ino
  9. 2 2
      examples/OpenNext/OpenNext.ino
  10. 3 3
      examples/QuickStart/QuickStart.ino
  11. 0 175
      examples/STM32Test/STM32Test.ino
  12. 5 5
      examples/SdFormatter/SdFormatter.ino
  13. 3 3
      examples/SdInfo/SdInfo.ino
  14. 2 2
      examples/SoftwareSpi/SoftwareSpi.ino
  15. 1 1
      examples/TeensySdioLogger/TeensySdioLogger.ino
  16. 3 3
      examples/UserChipSelectFunction/UserChipSelectFunction.ino
  17. 2 2
      examples/bench/bench.ino
  18. 4 4
      examples/examplesV1/#attic/AnalogLogger/AnalogLogger.ino
  19. 4 4
      examples/examplesV1/#attic/BaseExtCaseTest/BaseExtCaseTest.ino
  20. 2 2
      examples/examplesV1/#attic/HelloWorld/HelloWorld.ino
  21. 3 3
      examples/examplesV1/#attic/PrintBenchmarkSD/PrintBenchmarkSD.ino
  22. 2 2
      examples/examplesV1/#attic/SD_Size/SD_Size.ino
  23. 4 4
      examples/examplesV1/#attic/SdFatSize/SdFatSize.ino
  24. 2 2
      examples/examplesV1/#attic/StreamParseInt/StreamParseInt.ino
  25. 4 4
      examples/examplesV1/#attic/append/append.ino
  26. 4 4
      examples/examplesV1/#attic/average/average.ino
  27. 3 3
      examples/examplesV1/#attic/benchSD/benchSD.ino
  28. 3 3
      examples/examplesV1/#attic/bufstream/bufstream.ino
  29. 2 2
      examples/examplesV1/#attic/cin_cout/cin_cout.ino
  30. 3 3
      examples/examplesV1/#attic/eventlog/eventlog.ino
  31. 4 4
      examples/examplesV1/#attic/fgetsRewrite/fgetsRewrite.ino
  32. 3 3
      examples/examplesV1/#attic/readlog/readlog.ino
  33. 1 1
      examples/examplesV1/AnalogBinLogger/AnalogBinLogger.ino
  34. 1 1
      examples/examplesV1/DirectoryFunctions/DirectoryFunctions.ino
  35. 1 1
      examples/examplesV1/LongFileName/LongFileName.ino
  36. 6 6
      examples/examplesV1/LowLatencyLogger/LowLatencyLogger.ino
  37. 6 6
      examples/examplesV1/LowLatencyLoggerADXL345/LowLatencyLogger.ino
  38. 4 4
      examples/examplesV1/LowLatencyLoggerADXL345/UserFunctions.cpp
  39. 6 6
      examples/examplesV1/LowLatencyLoggerMPU6050/LowLatencyLogger.ino
  40. 2 2
      examples/examplesV1/LowLatencyLoggerMPU6050/UserFunctions.cpp
  41. 5 5
      examples/examplesV1/OpenNext/OpenNext.ino
  42. 3 3
      examples/examplesV1/PrintBenchmark/PrintBenchmark.ino
  43. 3 3
      examples/examplesV1/QuickStart/QuickStart.ino
  44. 6 6
      examples/examplesV1/RawWrite/RawWrite.ino
  45. 7 7
      examples/examplesV1/ReadCsv/ReadCsv.ino
  46. 8 8
      examples/examplesV1/ReadCsvArray/ReadCsvArray.ino
  47. 4 4
      examples/examplesV1/ReadCsvStream/ReadCsvStream.ino
  48. 2 2
      examples/examplesV1/STM32Test/STM32Test.ino
  49. 12 12
      examples/examplesV1/SdFormatter/SdFormatter.ino
  50. 8 8
      examples/examplesV1/SdInfo/SdInfo.ino
  51. 4 4
      examples/examplesV1/SoftwareSpi/SoftwareSpi.ino
  52. 5 5
      examples/examplesV1/StdioBench/StdioBench.ino
  53. 12 12
      examples/examplesV1/TeensySdioDemo/TeensySdioDemo.ino
  54. 3 3
      examples/examplesV1/Timestamp/Timestamp.ino
  55. 4 4
      examples/examplesV1/TwoCards/TwoCards.ino
  56. 2 2
      examples/examplesV1/VolumeFreeSpace/VolumeFreeSpace.ino
  57. 2 2
      examples/examplesV1/bench/bench.ino
  58. 6 6
      examples/examplesV1/dataLogger/dataLogger.ino
  59. 4 4
      examples/examplesV1/fgets/fgets.ino
  60. 2 2
      examples/examplesV1/formatting/formatting.ino
  61. 4 4
      examples/examplesV1/getline/getline.ino
  62. 2 2
      examples/examplesV1/rename/rename.ino
  63. 0 66
      examples/examplesV1/v1v2.txt
  64. 5 5
      examples/examplesV1/wipe/wipe.ino
  65. 2 2
      examples/rename/rename.ino
  66. 1 2
      extras/attic/PrintBasic.h
  67. 1 1
      library.properties
  68. 1 1
      src/BufferedPrint.h
  69. 1 1
      src/ExFatLib/ExFatConfig.h
  70. 14 14
      src/ExFatLib/ExFatDbg.cpp
  71. 14 15
      src/ExFatLib/ExFatFile.cpp
  72. 15 5
      src/ExFatLib/ExFatFile.h
  73. 3 3
      src/ExFatLib/ExFatFilePrint.cpp
  74. 12 16
      src/ExFatLib/ExFatFileWrite.cpp
  75. 3 4
      src/ExFatLib/ExFatFormatter.cpp
  76. 1 3
      src/ExFatLib/ExFatFormatter.h
  77. 1 2
      src/ExFatLib/ExFatLib.h
  78. 3 2
      src/ExFatLib/ExFatName.cpp
  79. 14 12
      src/ExFatLib/ExFatPartition.cpp
  80. 22 10
      src/ExFatLib/ExFatPartition.h
  81. 0 55
      src/ExFatLib/ExFatTypes.h
  82. 2 2
      src/ExFatLib/ExFatVolume.cpp
  83. 1 2
      src/ExFatLib/ExFatVolume.h
  84. 59 10
      src/FatLib/FatDbg.cpp
  85. 40 43
      src/FatLib/FatFile.cpp
  86. 44 37
      src/FatLib/FatFile.h
  87. 13 15
      src/FatLib/FatFileLFN.cpp
  88. 3 52
      src/FatLib/FatFilePrint.cpp
  89. 92 20
      src/FatLib/FatFileSFN.cpp
  90. 2 2
      src/FatLib/FatFormatter.cpp
  91. 2 4
      src/FatLib/FatFormatter.h
  92. 1 1
      src/FatLib/FatLib.h
  93. 2 4
      src/FatLib/FatName.cpp
  94. 36 34
      src/FatLib/FatPartition.cpp
  95. 19 34
      src/FatLib/FatPartition.h
  96. 2 2
      src/FatLib/FatVolume.cpp
  97. 1 2
      src/FatLib/FatVolume.h
  98. 2 2
      src/FreeStack.cpp
  99. 1 1
      src/FreeStack.h
  100. 1 1
      src/FsLib/FsFile.cpp

+ 1 - 1
README.md

@@ -4,7 +4,7 @@ Earlier releases of Version 1 are here:
 
 https://github.com/greiman/SdFat/releases
 
-###### UTF-8 encoded filenames are supported in v2.1.0.
+UTF-8 encoded filenames are supported in v2.1.0 or later.
 
 Try the UnicodeFilenames example.  Here is output from ls:
 <pre>

文件差异内容过多而无法显示
+ 311 - 144
doc/Doxyfile


二进制
doc/html.zip


+ 8 - 4
doc/mainpage.h

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License
@@ -249,11 +249,9 @@ DirectoryFunctions - Use of chdir(), ls(), mkdir(), and rmdir().
 
 examplesV1 folder - Examples from SdFat V1 for compatibility tests.
 
-%ExFatFormatter - Produces optimal exFAT format for smaller SD cards.
-
 ExFatLogger - A data-logger optimized for exFAT features.
 
-ExFatUnicodeTest - Test program for Unicode file names.
+MinimumSizeSdReader - Example of small file reader for FAT16/FAT32.
 
 OpenNext - Open all files in the root dir and print their filename.
 
@@ -275,10 +273,16 @@ SoftwareSpi - Demo of limited Software SPI support in SdFat V2.
 
 STM32Test - Example use of two SPI ports on an STM32 board.
 
+TeensyDmaAdcLogger - Fast logger using DMA ADC.
+
 TeensyRtcTimestamp - %File timestamps for Teensy3.
 
 TeensySdioDemo - Demo of SDIO and SPI modes for the Teensy 3.5/3.6 built-in SD.
 
+TeensySdioLogger -  Fast logger using a ring buffer.
+
+UnicodeFilenames - Test program for Unicode file names.
+
 UserChipSelectFunction - Useful for port expanders or replacement of the standard GPIO functions.
 
 UserSPIDriver - An example of an external SPI driver.

+ 3 - 6
examples/AvrAdcLogger/AvrAdcLogger.ino

@@ -34,9 +34,6 @@ MinimumSerial MinSerial;
 //------------------------------------------------------------------------------
 // This example was designed for exFAT but will support FAT16/FAT32.
 //
-// If an exFAT SD is required, the ExFatFormatter example will format
-// smaller cards with an exFAT file system.
-//
 // Note: Uno will not support SD_FAT_TYPE = 3.
 // 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.
@@ -152,9 +149,9 @@ const uint16_t ISR_TIMER0 = 160;
 //==============================================================================
 const uint32_t MAX_FILE_SIZE = MAX_FILE_SIZE_MiB << 20;
 
-// Select fastest interface.  Max SPI rate for AVR is 10 MHx.
+// Max SPI rate for AVR is 10 MHz for F_CPU 20 MHz, 8 MHz for F_CPU 16 MHz.
 #define SPI_CLOCK SD_SCK_MHZ(10)
-
+// Select fastest interface.
 #if ENABLE_DEDICATED_SPI
 #define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
 #else  // ENABLE_DEDICATED_SPI
@@ -868,7 +865,7 @@ void loop(void) {
   Serial.println(F("r - record ADC data"));
 
   while(!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
   char c = tolower(Serial.read());
   Serial.println();

+ 2 - 2
examples/DirectoryFunctions/DirectoryFunctions.ino

@@ -66,12 +66,12 @@ void setup() {
 
   // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   delay(1000);
   cout << F("Type any character to start\n");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
 
   // Initialize the SD card.

+ 2 - 2
examples/ExFatLogger/ExFatLogger.ino

@@ -516,7 +516,7 @@ void setup() {
 
   // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   delay(1000);
   Serial.println(F("Type any character to begin"));
@@ -568,7 +568,7 @@ void loop() {
   Serial.println(F("r - record data"));
   Serial.println(F("t - test without logging"));
   while(!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
   char c = tolower(Serial.read());
   Serial.println();

+ 58 - 0
examples/MinimumSizeSdReader/MinimumSizeSdReader.ino

@@ -0,0 +1,58 @@
+// Create a text file on the SD with this path using short 8.3 names.
+#define SFN_PATH "/DIR/TEST.TXT"
+
+// Modify CS_PIN for your chip select pin.
+#define CS_PIN SS
+
+// Set USE_SD_H to one for SD.h or zero for SdFat.
+#define USE_SD_H 0
+
+#if USE_SD_H
+#include "SD.h"
+File file;
+#else
+#include "SdFat.h"
+// Setting ENABLE_DEDICATED_SPI to zero saves over 200 more bytes.
+#if ENABLE_DEDICATED_SPI
+#warning "Set ENABLE_DEDICATED_SPI zero in SdFat/src/SdFatConfig.h for minimum size"
+#endif  // ENABLE_DEDICATED_SPI
+// Insure FAT16/FAT32 only.
+SdFat32 SD;
+// FatFile does not support Stream functions, just simple read/write.
+FatFile file;
+#endif
+
+void error(const char* msg) {
+  Serial.println(msg);
+  while(true);
+}
+
+void setup() {
+  int n;
+  char buf[4];
+
+  Serial.begin(9600);
+  while (!Serial) {}
+  Serial.println("Type any character to begin");
+  while (!Serial.available()) {}
+
+  if (!SD.begin(CS_PIN)) error("SD.begin");
+
+#if USE_SD_H
+  file = SD.open(SFN_PATH);
+  if (!file) error("open");
+#else
+  // Open existing file with a path of 8.3 names.
+  // Directories will be opened O_RDONLY files O_RDWR.
+  if (!file.openExistingSFN(SFN_PATH)) error("open");
+#endif
+  while ((n = file.read(buf, sizeof(buf)))) {
+   Serial.write(buf, n);
+  }
+// close() is only needed if you write to the file. For example, read
+// config data, modify the data, rewind the file and write the data.
+// file.close();
+}
+
+void loop() {
+}

+ 2 - 2
examples/OpenNext/OpenNext.ino

@@ -63,12 +63,12 @@ void setup() {
 
   // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
 
   Serial.println("Type any character to start");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
 
   // Initialize the SD.

+ 3 - 3
examples/QuickStart/QuickStart.ino

@@ -68,7 +68,7 @@ void setup() {
 
   // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   cout << F("\nSPI pins:\n");
   cout << F("MISO: ") << int(MISO) << endl;
@@ -106,7 +106,7 @@ void loop() {
 
   cout << F("\nEnter the chip select pin number: ");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
   cin.readline();
   if (cin >> chipSelect) {
@@ -182,6 +182,6 @@ void loop() {
 
   cout << F("\nSuccess!  Type any character to restart.\n");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
 }

+ 0 - 175
examples/STM32Test/STM32Test.ino

@@ -1,175 +0,0 @@
-/* This example is for https://github.com/rogerclarkmelbourne/Arduino_STM32
- *
- * Example use of two SPI ports on an STM32 board.
- * Note SPI speed is limited to 18 MHz.
- */
-#include <SPI.h>
-#include "SdFat.h"
-#include "FreeStack.h"
-
-// Chip select PA4, shared SPI, 18 MHz, port 1.
-#define SD1_CONFIG SdSpiConfig(PA4, SHARED_SPI, SD_SCK_MHZ(18), &SPI)
-SdFs sd1;
-FsFile file1;
-
-// Use mySPI2 since SPI2 is used in SPI.h as a different type.
-static SPIClass mySPI2(2);
-// Chip select PB12, dedicated SPI, 18 MHz, port 2.
-#if ENABLE_DEDICATED_SPI
-#define SD2_CONFIG SdSpiConfig(PB12, DEDICATED_SPI, SD_SCK_MHZ(18), &mySPI2)
-#else  // ENABLE_DEDICATED_SPI
-#define SD2_CONFIG SdSpiConfig(PB12, SHARED_SPI, SD_SCK_MHZ(18), &mySPI2)
-#endif  // ENABLE_DEDICATED_SPI
-
-SdFs sd2;
-FsFile file2;
-
-const uint8_t BUF_DIM = 100;
-uint8_t buf[BUF_DIM];
-
-const uint32_t FILE_SIZE = 1000000;
-const uint32_t NWRITE = FILE_SIZE/BUF_DIM;
-//------------------------------------------------------------------------------
-// print error msg, any SD error codes, and halt.
-// store messages in flash
-#define error(msg) {Serial.println(msg); errorHalt();}
-void errorHalt() {
-  if (sd1.sdErrorCode()) {
-    sd1.errorHalt();
-  }
-  sd2.errorHalt();
-}
-//------------------------------------------------------------------------------
-void setup() {
-  Serial.begin(9600);
-  // Wait for USB Serial
-  while (!Serial) {
-    SysCall::yield();
-  }
-  Serial.print(F("FreeStack: "));
-  Serial.println(FreeStack());
-
-  // fill buffer with known data
-  for (size_t i = 0; i < sizeof(buf); i++) {
-    buf[i] = i;
-  }
-
-  Serial.println(F("type any character to start"));
-  while (!Serial.available()) {
-    SysCall::yield();
-  }
-
-  // initialize the first card
-  if (!sd1.begin(SD1_CONFIG)) {
-    error("sd1.begin");
-  }
-  // create Dir1 on sd1 if it does not exist
-  if (!sd1.exists("/Dir1")) {
-    if (!sd1.mkdir("/Dir1")) {
-      error("sd1.mkdir");
-    }
-  }
-  // Make Dir1 the working directory on sd1.
-  if (!sd1.chdir("Dir1")) {
-     error("dsd1.chdir");
-  }
-  // initialize the second card
-  if (!sd2.begin(SD2_CONFIG)) {
-    error("sd2.begin");
-  }
-// create Dir2 on sd2 if it does not exist
-  if (!sd2.exists("/Dir2")) {
-    if (!sd2.mkdir("/Dir2")) {
-      error("sd2.mkdir");
-    }
-  }
-  // Make Dir2 the working directory on sd2.
-  if (!sd2.chdir("Dir2")) {
-     error("sd2.chdir");
-  }
-  // remove test.bin from /Dir1 directory of sd1
-  if (sd1.exists("test.bin")) {
-    if (!sd1.remove("test.bin")) {
-      error("remove test.bin");
-    }
-  }
-  // remove rename.bin from /Dir2 directory of sd2
-  if (sd2.exists("rename.bin")) {
-    if (!sd2.remove("rename.bin")) {
-      error("remove rename.bin");
-    }
-  }
-  // list directories.
-  Serial.println(F("------sd1 Dir1-------"));
-  sd1.ls("/", LS_R | LS_SIZE);
-  Serial.println(F("------sd2 Dir2-------"));
-  sd2.ls("/", LS_R | LS_SIZE);
-  Serial.println(F("---------------------"));
-
-  // create or open /Dir1/test.bin and truncate it to zero length
-  if (!file1.open(&sd1, "test.bin", O_RDWR | O_CREAT | O_TRUNC)) {
-    error("file1.open");
-  }
-  Serial.println(F("Writing test.bin to sd1"));
-
-  // write data to /Dir1/test.bin on sd1
-  for (uint32_t i = 0; i < NWRITE; i++) {
-    if (file1.write(buf, sizeof(buf)) != sizeof(buf)) {
-      error("file1.write");
-    }
-  }
-
-  // create or open /Dir2/copy.bin and truncate it to zero length
-  if (!file2.open(&sd2, "copy.bin", O_WRONLY | O_CREAT | O_TRUNC)) {
-    error("file2.open");
-  }
-  Serial.println(F("Copying test.bin to copy.bin"));
-
-  // copy file1 to file2
-  file1.rewind();
-  uint32_t t = millis();
-
-  while (1) {
-    int n = file1.read(buf, sizeof(buf));
-    if (n < 0) {
-      error("file1.read");
-    }
-    if (n == 0) {
-      break;
-    }
-    if ((int)file2.write(buf, n) != n) {
-      error("file2.write");
-    }
-  }
-  t = millis() - t;
-  Serial.print(F("File size: "));
-  Serial.println(file2.fileSize());
-  Serial.print(F("Copy time: "));
-  Serial.print(t);
-  Serial.println(F(" millis"));
-  // close test.bin
-  file1.close();
-  // sync copy.bin so ls works.
-  file2.close();
-  // list directories.
-  Serial.println(F("------sd1 -------"));
-  sd1.ls("/", LS_R | LS_SIZE);
-  Serial.println(F("------sd2 -------"));
-  sd2.ls("/", LS_R | LS_SIZE);
-  Serial.println(F("---------------------"));
-  Serial.println(F("Renaming copy.bin"));
-  // Rename copy.bin. The renamed file will be in Dir2.
-  if (!sd2.rename("copy.bin", "rename.bin")) {
-    error("rename copy.bin");
-  }
-  file2.close();
-  // list directories.
-  Serial.println(F("------sd1 -------"));
-  sd1.ls("/", LS_R | LS_SIZE);
-  Serial.println(F("------sd2 -------"));
-  sd2.ls("/", LS_R | LS_SIZE);
-  Serial.println(F("---------------------"));
-  Serial.println(F("Done"));
-}
-//------------------------------------------------------------------------------
-void loop() {}

+ 5 - 5
examples/SdFormatter/SdFormatter.ino

@@ -73,7 +73,7 @@ void sdErrorHalt() {
     cout << F(" = ") << int(m_card->errorCode()) << endl;
     cout << F("SD errorData = ") << int(m_card->errorData()) << endl;
   }
-  SysCall::halt();
+  while (true) {}
 }
 //------------------------------------------------------------------------------
 void clearSerialInput() {
@@ -158,12 +158,12 @@ void setup() {
   Serial.begin(9600);
   // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   printConfig(SD_CONFIG);
   cout << F("\nType any character to start\n");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
   // Discard any extra characters.
   clearSerialInput();
@@ -183,7 +183,7 @@ void setup() {
          "Warning, all data on the card will be erased.\n"
          "Enter 'Y' to continue: ");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
   c = Serial.read();
   cout << c << endl;
@@ -230,7 +230,7 @@ void setup() {
          "Enter option: ");
 
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
   c = Serial.read();
   cout << c << endl;

+ 3 - 3
examples/SdInfo/SdInfo.ino

@@ -54,7 +54,7 @@ bool cidDmp() {
   cout << F("Serial number: ") << hex << m_cid.psn << dec << endl;
   cout << F("Manufacturing date: ");
   cout << int(m_cid.mdt_month) << '/';
-  cout << (2000 + m_cid.mdt_year_low + 10 * m_cid.mdt_year_high) << endl;
+  cout << (2000 + 16*m_cid.mdt_year_high + m_cid.mdt_year_low) << endl;
   cout << endl;
   return true;
 }
@@ -206,7 +206,7 @@ void setup() {
   Serial.begin(9600);
   // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   cout << F("SdFat version: ") << SD_FAT_VERSION_STR << endl;
   printConfig(SD_CONFIG);
@@ -220,7 +220,7 @@ void loop() {
   // F stores strings in flash to save RAM
   cout << F("\ntype any character to start\n");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
   uint32_t t = millis();
   if (!sd.cardBegin(SD_CONFIG)) {

+ 2 - 2
examples/SoftwareSpi/SoftwareSpi.ino

@@ -47,11 +47,11 @@ void setup() {
   Serial.begin(9600);
   // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   Serial.println("Type any character to start");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
 
   if (!sd.begin(SD_CONFIG)) {

+ 1 - 1
examples/TeensySdioLogger/TeensySdioLogger.ino

@@ -62,7 +62,7 @@ void logData() {
     // Amount of data in ringBuf.
     size_t n = rb.bytesUsed();
     if ((n + file.curPosition()) > (LOG_FILE_SIZE - 20)) {
-      Serial.println("File full - quiting.");
+      Serial.println("File full - quitting.");
       break;
     }
     if (n > maxUsed) {

+ 3 - 3
examples/UserChipSelectFunction/UserChipSelectFunction.ino

@@ -5,7 +5,7 @@
 
 // SD_CHIP_SELECT_MODE must be set to one or two in SdFat/SdFatConfig.h.
 // A value of one allows optional replacement and two requires replacement.
-#if SD_CHIP_SELECT_MODE == 1 || SD_CHIP_SELECT_MODE == 2  
+#if SD_CHIP_SELECT_MODE == 1 || SD_CHIP_SELECT_MODE == 2
 
 // SD chip select pin.
 #define SD_CS_PIN SS
@@ -34,11 +34,11 @@ void setup() {
     sd.initErrorHalt(&Serial);
   }
   sd.ls(&Serial, LS_SIZE);
-  
+
   Serial.print(F("sdCsInit calls: "));
   Serial.println(initCalls);
   Serial.print(F("sdCsWrite calls: "));
-  Serial.println(writeCalls); 
+  Serial.println(writeCalls);
 }
 //------------------------------------------------------------------------------
 void loop() {}

+ 2 - 2
examples/bench/bench.ino

@@ -122,7 +122,7 @@ void setup() {
 
   // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   delay(1000);
   cout << F("\nUse a freshly formatted SD for best performance.\n");
@@ -149,7 +149,7 @@ void loop() {
   // F() stores strings in flash to save RAM
   cout << F("Type any character to start\n");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
 #if HAS_UNUSED_STACK
   cout << F("FreeStack: ") << FreeStack() << endl;

+ 4 - 4
examples/examplesV1/#attic/AnalogLogger/AnalogLogger.ino

@@ -66,10 +66,10 @@ ostream& operator << (ostream& os, DateTime& dt) {
 //------------------------------------------------------------------------------
 void setup() {
   Serial.begin(9600);
-  
+
   // Wait for USB Serial.
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   // F() stores strings in flash to save RAM
   cout << endl << F("FreeStack: ") << FreeStack() << endl;
@@ -77,7 +77,7 @@ void setup() {
 #if WAIT_TO_START
   cout << F("Type any character to start\n");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
   // Discard input.
   do {
@@ -193,5 +193,5 @@ void loop() {
   }
   logfile.close();
   cout << F("Done!");
-  SysCall::halt();
+  while (true) {}
 }

+ 4 - 4
examples/examplesV1/#attic/BaseExtCaseTest/BaseExtCaseTest.ino

@@ -17,14 +17,14 @@ const char* name[] = {
 //------------------------------------------------------------------------------
 void setup() {
   Serial.begin(9600);
-  
-  // Wait for USB Serial 
+
+  // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   Serial.println("type any character to start");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
   if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) {
     Serial.println("begin failed");

+ 2 - 2
examples/examplesV1/#attic/HelloWorld/HelloWorld.ino

@@ -8,9 +8,9 @@ ArduinoOutStream cout(Serial);
 void setup() {
   Serial.begin(9600);
 
-  // Wait for USB Serial 
+  // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   delay(2000);
 

+ 3 - 3
examples/examplesV1/#attic/PrintBenchmarkSD/PrintBenchmarkSD.ino

@@ -24,8 +24,8 @@ void error(const char* s) {
 //------------------------------------------------------------------------------
 void setup() {
   Serial.begin(9600);
-  
-  // Wait for USB Serial 
+
+  // Wait for USB Serial
   while (!Serial) {
     yield();
   }
@@ -51,7 +51,7 @@ void loop() {
   if (!SD.begin(chipSelect)) {
     error("begin");
   }
-  
+
   Serial.println(F("Starting print test.  Please wait.\n"));
 
   // do write test

+ 2 - 2
examples/examplesV1/#attic/SD_Size/SD_Size.ino

@@ -9,8 +9,8 @@ File file;
 //------------------------------------------------------------------------------
 void setup() {
   Serial.begin(9600);
-  
-  // Wait for USB Serial 
+
+  // Wait for USB Serial
   while (!Serial) {
     yield();
   }

+ 4 - 4
examples/examplesV1/#attic/SdFatSize/SdFatSize.ino

@@ -12,12 +12,12 @@ SdFile file;
 //------------------------------------------------------------------------------
 void setup() {
   Serial.begin(9600);
-  
-  // Wait for USB Serial 
+
+  // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
-  
+
   if (!sd.begin()) {
     Serial.println("begin failed");
     return;

+ 2 - 2
examples/examplesV1/#attic/StreamParseInt/StreamParseInt.ino

@@ -13,11 +13,11 @@ void setup() {
   Serial.begin(9600);
   // Wait for USB Serial.
   while(!Serial) {
-    SysCall::yield();
+    yield();
   }
   Serial.println(F("Type any character to start"));
   while (!Serial.available()) {
-    SysCall::yield(); 
+    yield();
   }
   // Initialize the SD.
   if (!SD.begin(csPin)) {

+ 4 - 4
examples/examplesV1/#attic/append/append.ino

@@ -26,15 +26,15 @@ void setup() {
   char name[] = "append.txt";
 
   Serial.begin(9600);
-  
-  // Wait for USB Serial 
+
+  // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   // F() stores strings in flash to save RAM
   cout << endl << F("Type any character to start\n");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
 
   // Initialize at the highest speed supported by the board that is

+ 4 - 4
examples/examplesV1/#attic/average/average.ino

@@ -55,15 +55,15 @@ void calcAverage() {
 //------------------------------------------------------------------------------
 void setup() {
   Serial.begin(9600);
-  
-  // Wait for USB Serial 
+
+  // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   // F() stores strings in flash to save RAM
   cout << F("Type any character to start\n");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
 
   // Initialize at the highest speed supported by the board that is

+ 3 - 3
examples/examplesV1/#attic/benchSD/benchSD.ino

@@ -27,8 +27,8 @@ void error(const char* s) {
 //------------------------------------------------------------------------------
 void setup() {
   Serial.begin(9600);
-  
-  // Wait for USB Serial 
+
+  // Wait for USB Serial
   while (!Serial) {
     yield();
   }
@@ -46,7 +46,7 @@ void loop() {
 
   // F() stores strings in flash to save RAM
   Serial.println(F("Type any character to start"));
-  
+
   while (!Serial.available()) {
     yield();
   }

+ 3 - 3
examples/examplesV1/#attic/bufstream/bufstream.ino

@@ -13,10 +13,10 @@ void setup() {
   int i, j, k;    // values from parsed line
 
   Serial.begin(9600);
-  
-  // Wait for USB Serial 
+
+  // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   delay(2000);
 

+ 2 - 2
examples/examplesV1/#attic/cin_cout/cin_cout.ino

@@ -16,9 +16,9 @@ ArduinoInStream cin(Serial, cinBuf, sizeof(cinBuf));
 //------------------------------------------------------------------------------
 void setup() {
   Serial.begin(9600);
-  // Wait for USB Serial 
+  // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
 }
 //------------------------------------------------------------------------------

+ 3 - 3
examples/examplesV1/#attic/eventlog/eventlog.ino

@@ -36,14 +36,14 @@ void logEvent(const char *msg) {
 //------------------------------------------------------------------------------
 void setup() {
   Serial.begin(9600);
-  // Wait for USB Serial 
+  // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   // F() stores strings in flash to save RAM
   cout << F("Type any character to start\n");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
   delay(400);  // catch Due reset problem
 

+ 4 - 4
examples/examplesV1/#attic/fgetsRewrite/fgetsRewrite.ino

@@ -86,14 +86,14 @@ void makeTestFile() {
 //------------------------------------------------------------------------------
 void setup() {
   Serial.begin(9600);
-  
-  // Wait for USB Serial 
+
+  // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   cout << F("Type any character to start\n");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
 
   // Initialize at the highest speed supported by the board that is

+ 3 - 3
examples/examplesV1/#attic/readlog/readlog.ino

@@ -18,10 +18,10 @@ ArduinoOutStream cout(Serial);
 void setup() {
   int c;
   Serial.begin(9600);
-  
-  // Wait for USB Serial 
+
+  // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   // Initialize at the highest speed supported by the board that is
   // not over 50 MHz. Try a lower speed if SPI errors occur.

+ 1 - 1
examples/examplesV1/AnalogBinLogger/AnalogBinLogger.ino

@@ -798,7 +798,7 @@ void loop(void) {
   Serial.println(F("r - record ADC data"));
 
   while(!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
   char c = tolower(Serial.read());
   if (ERROR_LED_PIN >= 0) {

+ 1 - 1
examples/examplesV1/DirectoryFunctions/DirectoryFunctions.ino

@@ -34,7 +34,7 @@ void setup() {
 
   // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   delay(1000);
 

+ 1 - 1
examples/examplesV1/LongFileName/LongFileName.ino

@@ -72,7 +72,7 @@ void loop() {
   Serial.print(F("\r\nEnter File Number: "));
 
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
   c = Serial.read();
   uint8_t i = c - '0';

+ 6 - 6
examples/examplesV1/LowLatencyLogger/LowLatencyLogger.ino

@@ -123,7 +123,7 @@ struct block_t {
 //
 void fatalBlink() {
   while (true) {
-    SysCall::yield();
+    yield();
     if (ERROR_LED_PIN >= 0) {
       digitalWrite(ERROR_LED_PIN, HIGH);
       delay(200);
@@ -321,7 +321,7 @@ void openBinFile() {
   Serial.write(name, BASE_NAME_SIZE);
   for (int i = 0; i < 2; i++) {
     while (!Serial.available()) {
-     SysCall::yield();
+     yield();
     }
     char c = Serial.read();
     Serial.write(c);
@@ -566,7 +566,7 @@ void setup(void) {
 
   // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   Serial.print(F("\nFreeStack: "));
   Serial.println(FreeStack());
@@ -592,7 +592,7 @@ void setup(void) {
   if (sd.exists(TMP_FILE_NAME)) {
     Serial.println(F("\nType 'Y' to recover existing tmp file " TMP_FILE_NAME));
     while (!Serial.available()) {
-      SysCall::yield();
+      yield();
     }
     if (Serial.read() == 'Y') {
       recoverTmpFile();
@@ -617,11 +617,11 @@ void loop(void) {
   Serial.println(F("r - record data"));
   Serial.println(F("t - test without logging"));
   while(!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
 #if WDT_YIELD_TIME_MICROS
   Serial.println(F("LowLatencyLogger can not run with watchdog timer"));
-  SysCall::halt();
+  while (true) {}
 #endif
 
   char c = tolower(Serial.read());

+ 6 - 6
examples/examplesV1/LowLatencyLoggerADXL345/LowLatencyLogger.ino

@@ -123,7 +123,7 @@ struct block_t {
 //
 void fatalBlink() {
   while (true) {
-    SysCall::yield();
+    yield();
     if (ERROR_LED_PIN >= 0) {
       digitalWrite(ERROR_LED_PIN, HIGH);
       delay(200);
@@ -321,7 +321,7 @@ void openBinFile() {
   Serial.write(name, BASE_NAME_SIZE);
   for (int i = 0; i < 2; i++) {
     while (!Serial.available()) {
-     SysCall::yield();
+     yield();
     }
     char c = Serial.read();
     Serial.write(c);
@@ -566,7 +566,7 @@ void setup(void) {
 
   // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   Serial.print(F("\nFreeStack: "));
   Serial.println(FreeStack());
@@ -592,7 +592,7 @@ void setup(void) {
   if (sd.exists(TMP_FILE_NAME)) {
     Serial.println(F("\nType 'Y' to recover existing tmp file " TMP_FILE_NAME));
     while (!Serial.available()) {
-      SysCall::yield();
+      yield();
     }
     if (Serial.read() == 'Y') {
       recoverTmpFile();
@@ -617,11 +617,11 @@ void loop(void) {
   Serial.println(F("r - record data"));
   Serial.println(F("t - test without logging"));
   while(!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
 #if WDT_YIELD_TIME_MICROS
   Serial.println(F("LowLatencyLogger can not run with watchdog timer"));
-  SysCall::halt();
+  while (true) {}
 #endif
 
   char c = tolower(Serial.read());

+ 4 - 4
examples/examplesV1/LowLatencyLoggerADXL345/UserFunctions.cpp

@@ -17,12 +17,12 @@ const uint8_t DATAZ1 = 0x37; //Z-Axis Data 1
 
 void writeADXL345Register(const uint8_t registerAddress, const uint8_t value) {
   // Max SPI clock frequency is 5 MHz with CPOL = 1 and CPHA = 1.
-  SPI.beginTransaction(SPISettings(5000000, MSBFIRST, SPI_MODE3));  
+  SPI.beginTransaction(SPISettings(5000000, MSBFIRST, SPI_MODE3));
   digitalWrite(ADXL345_CS, LOW);
   SPI.transfer(registerAddress);
   SPI.transfer(value);
   digitalWrite(ADXL345_CS, HIGH);
-  SPI.endTransaction();  
+  SPI.endTransaction();
 }
 
 void userSetup() {
@@ -32,7 +32,7 @@ void userSetup() {
   //Put the ADXL345 into +/- 4G range by writing the value 0x01 to the DATA_FORMAT register.
   writeADXL345Register(DATA_FORMAT, 0x01);
   //Put the ADXL345 into Measurement Mode by writing 0x08 to the POWER_CTL register.
-  writeADXL345Register(POWER_CTL, 0x08);  //Measurement mode  
+  writeADXL345Register(POWER_CTL, 0x08);  //Measurement mode
 }
 
 // Acquire a data record.
@@ -45,7 +45,7 @@ void acquireData(data_t* data) {
   SPI.transfer(DATAX0 | 0XC0);
   data->accel[0] = SPI.transfer(0) | (SPI.transfer(0) << 8);
   data->accel[1] = SPI.transfer(0) | (SPI.transfer(0) << 8);
-  data->accel[2] = SPI.transfer(0) | (SPI.transfer(0) << 8); 
+  data->accel[2] = SPI.transfer(0) | (SPI.transfer(0) << 8);
   digitalWrite(ADXL345_CS, HIGH);
   SPI.endTransaction();
 }

+ 6 - 6
examples/examplesV1/LowLatencyLoggerMPU6050/LowLatencyLogger.ino

@@ -123,7 +123,7 @@ struct block_t {
 //
 void fatalBlink() {
   while (true) {
-    SysCall::yield();
+    yield();
     if (ERROR_LED_PIN >= 0) {
       digitalWrite(ERROR_LED_PIN, HIGH);
       delay(200);
@@ -321,7 +321,7 @@ void openBinFile() {
   Serial.write(name, BASE_NAME_SIZE);
   for (int i = 0; i < 2; i++) {
     while (!Serial.available()) {
-     SysCall::yield();
+     yield();
     }
     char c = Serial.read();
     Serial.write(c);
@@ -566,7 +566,7 @@ void setup(void) {
 
   // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   Serial.print(F("\nFreeStack: "));
   Serial.println(FreeStack());
@@ -592,7 +592,7 @@ void setup(void) {
   if (sd.exists(TMP_FILE_NAME)) {
     Serial.println(F("\nType 'Y' to recover existing tmp file " TMP_FILE_NAME));
     while (!Serial.available()) {
-      SysCall::yield();
+      yield();
     }
     if (Serial.read() == 'Y') {
       recoverTmpFile();
@@ -617,11 +617,11 @@ void loop(void) {
   Serial.println(F("r - record data"));
   Serial.println(F("t - test without logging"));
   while(!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
 #if WDT_YIELD_TIME_MICROS
   Serial.println(F("LowLatencyLogger can not run with watchdog timer"));
-  SysCall::halt();
+  while (true) {}
 #endif
 
   char c = tolower(Serial.read());

+ 2 - 2
examples/examplesV1/LowLatencyLoggerMPU6050/UserFunctions.cpp

@@ -9,7 +9,7 @@ static uint32_t startMicros;
 // Acquire a data record.
 void acquireData(data_t* data) {
   data->time = micros();
-  mpu.getMotion6(&data->ax, &data->ay, &data->az, 
+  mpu.getMotion6(&data->ax, &data->ay, &data->az,
                  &data->gx, &data->gy, &data->gz);
 }
 
@@ -21,7 +21,7 @@ void userSetup() {
 #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
   Fastwire::setup(400, true);
 #endif
-  mpu.initialize();  
+  mpu.initialize();
 }
 
 // Print a data record.

+ 5 - 5
examples/examplesV1/OpenNext/OpenNext.ino

@@ -15,15 +15,15 @@ SdFile file;
 //------------------------------------------------------------------------------
 void setup() {
   Serial.begin(9600);
-  
-  // Wait for USB Serial 
+
+  // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
-  
+
   Serial.println("Type any character to start");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
 
   // Initialize at the highest speed supported by the board that is

+ 3 - 3
examples/examplesV1/PrintBenchmark/PrintBenchmark.ino

@@ -26,9 +26,9 @@ ArduinoOutStream cout(Serial);
 //------------------------------------------------------------------------------
 void setup() {
   Serial.begin(9600);
-  // Wait for USB Serial 
+  // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
 }
 //------------------------------------------------------------------------------
@@ -44,7 +44,7 @@ void loop() {
   // F stores strings in flash to save RAM
   cout << F("Type any character to start\n");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
   delay(400);  // catch Due reset problem
 

+ 3 - 3
examples/examplesV1/QuickStart/QuickStart.ino

@@ -43,7 +43,7 @@ void setup() {
 
   // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   cout << F("\nSPI pins:\n");
   cout << F("MISO: ") << int(MISO) << endl;
@@ -80,7 +80,7 @@ void loop() {
 
   cout << F("\nEnter the chip select pin number: ");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
   cin.readline();
   if (cin >> chipSelect) {
@@ -156,6 +156,6 @@ void loop() {
   } while (Serial.available() && Serial.read() >= 0);
   cout << F("\nSuccess!  Type any character to restart.\n");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
 }

+ 6 - 6
examples/examplesV1/RawWrite/RawWrite.ino

@@ -45,10 +45,10 @@ ArduinoOutStream cout(Serial);
 //------------------------------------------------------------------------------
 void setup(void) {
   Serial.begin(9600);
-  
-  // Wait for USB Serial 
+
+  // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
 }
 //------------------------------------------------------------------------------
@@ -60,7 +60,7 @@ void loop(void) {
   // F stores strings in flash to save RAM
   cout << F("Type any character to start\n");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
 
   cout << F("FreeStack: ") << FreeStack() << endl;
@@ -101,7 +101,7 @@ void loop(void) {
   cout << F("Start raw write of ") << file.fileSize()/1000UL << F(" KB\n");
   cout << F("Target rate: ") << RATE_KB_PER_SEC << F(" KB/sec\n");
   cout << F("Target time: ") << TEST_TIME_SEC << F(" seconds\n");
-  
+
   // tell card to setup for multiple block write with pre-erase
   if (!sd.card()->writeStart(bgnBlock, BLOCK_COUNT)) {
     error("writeStart failed");
@@ -173,7 +173,7 @@ void loop(void) {
   cout << F(" seconds\n");
   cout << F("Min block write time: ") << minWriteTime << F(" micros\n");
   cout << F("Max block write time: ") << maxWriteTime << F(" micros\n");
-  cout << F("Avg block write time: ") << avgWriteTime << F(" micros\n");  
+  cout << F("Avg block write time: ") << avgWriteTime << F(" micros\n");
   // close file for next pass of loop
   file.close();
   Serial.println();

+ 7 - 7
examples/examplesV1/ReadCsv/ReadCsv.ino

@@ -30,7 +30,7 @@ File file;
  * delim - csv delimiter.
  *
  * return - negative value for failure.
- *          delimiter, '\n' or zero(EOF) for success.           
+ *          delimiter, '\n' or zero(EOF) for success.
  */
 int csvReadText(File* file, char* str, size_t size, char delim) {
   char ch;
@@ -129,8 +129,8 @@ int csvReadFloat(File* file, float* num, char delim) {
 //------------------------------------------------------------------------------
 void setup() {
   Serial.begin(9600);
-  
-  // Wait for USB Serial 
+
+  // Wait for USB Serial
   while (!Serial) {
     yield();
   }
@@ -144,8 +144,8 @@ void setup() {
     return;
   }
   // Remove existing file.
-   SD.remove("READTEST.TXT"); 
-   
+   SD.remove("READTEST.TXT");
+
   // Create the file.
   file = SD.open("READTEST.TXT", FILE_WRITE);
   if (!file) {
@@ -169,7 +169,7 @@ void setup() {
   file.seek(0);
 
   // Read the file and print fields.
-  int16_t tcalc; 
+  int16_t tcalc;
   float t1, t2, h1, h2;
   // Must be dim 9 to allow for zero byte.
   char timeS[9], dateS[9];
@@ -188,7 +188,7 @@ void setup() {
       while ((ch = file.read()) > 0 && nr++ < 100) {
         Serial.write(ch);
       }
-      break;            
+      break;
     }
     Serial.print(tcalc);
     Serial.print(CSV_DELIM);

+ 8 - 8
examples/examplesV1/ReadCsvArray/ReadCsvArray.ino

@@ -47,23 +47,23 @@ size_t readField(File* file, char* str, size_t size, const char* delim) {
   return n;
 }
 //------------------------------------------------------------------------------
-#define errorHalt(msg) {Serial.println(F(msg)); SysCall::halt();}
+#define errorHalt(msg) {Serial.println(F(msg)); while (true) {}}
 //------------------------------------------------------------------------------
 void setup() {
   Serial.begin(9600);
-  
-  // Wait for USB Serial 
+
+  // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   Serial.println("Type any character to start");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
   // Initialize the SD.
   if (!SD.begin(CS_PIN)) {
     errorHalt("begin failed");
-  } 
+  }
   // Create or open the file.
   file = SD.open("READNUM.TXT", FILE_WRITE);
   if (!file) {
@@ -93,7 +93,7 @@ void setup() {
   char *ptr;     // Test for valid field.
 
   // Read the file and store the data.
-  
+
   for (i = 0; i < ROW_DIM; i++) {
     for (j = 0; j < COL_DIM; j++) {
       n = readField(&file, str, sizeof(str), ",\n");
@@ -117,7 +117,7 @@ void setup() {
     // Allow missing endl at eof.
     if (str[n-1] != '\n' && file.available()) {
       errorHalt("missing endl");
-    }    
+    }
   }
 
   // Print the array.

+ 4 - 4
examples/examplesV1/ReadCsvStream/ReadCsvStream.ino

@@ -92,14 +92,14 @@ void writeFile() {
 //------------------------------------------------------------------------------
 void setup() {
   Serial.begin(9600);
-  
-  // Wait for USB Serial 
+
+  // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   cout << F("Type any character to start\n");
   while (!Serial.available()) {
-    SysCall::yield();  
+    yield();
   }
 
   // Initialize at the highest speed supported by the board that is

+ 2 - 2
examples/examplesV1/STM32Test/STM32Test.ino

@@ -33,7 +33,7 @@ const uint16_t NWRITE = FILE_SIZE/BUF_DIM;
 //------------------------------------------------------------------------------
 void setup() {
   Serial.begin(9600);
-  // Wait for USB Serial 
+  // Wait for USB Serial
   while (!Serial) {
   }
 
@@ -151,7 +151,7 @@ void setup() {
   Serial.println(F(" millis"));
   // close test.bin
   file1.close();
-  file2.close(); 
+  file2.close();
   // list current directory on both cards
   Serial.println(F("------sd1 -------"));
   sd1.ls("/", LS_R | LS_DATE | LS_SIZE);

+ 12 - 12
examples/examplesV1/SdFormatter/SdFormatter.ino

@@ -12,7 +12,7 @@
  * and SDFormatter uses FAT12.
  */
 #error  use new Version 2 SdFormatter
-// Set USE_SDIO to zero for SPI card access. 
+// Set USE_SDIO to zero for SPI card access.
 #define USE_SDIO 0
 //
 // Change the value of chipSelect if your hardware does
@@ -45,7 +45,7 @@ SdioCardEX card;
 #else  // USE_SDIO
 Sd2Card card;
 #endif  // USE_SDIO
- 
+
 uint32_t cardSizeBlocks;
 uint32_t cardCapacityMB;
 
@@ -84,7 +84,7 @@ void sdErrorHalt() {
     cout << F("SD error: ") << hex << int(card.errorCode());
     cout << ',' << int(card.errorData()) << dec << endl;
   }
-  SysCall::halt();
+  while (true) {}
 }
 //------------------------------------------------------------------------------
 #if DEBUG_PRINT
@@ -171,10 +171,10 @@ void clearFatDir(uint32_t bgn, uint32_t count) {
   for (uint32_t i = 0; i < count; i++) {
     if (!card.writeBlock(bgn + i, cache.data)) {
        sdError("Clear FAT/DIR writeBlock failed");
-    }     
+    }
     if ((i & 0XFF) == 0) {
       cout << '.';
-    }    
+    }
   }
 #else  // USE_SDIO
   if (!card.writeStart(bgn, count)) {
@@ -461,13 +461,13 @@ void formatCard() {
 void setup() {
   char c;
   Serial.begin(9600);
-  // Wait for USB Serial 
+  // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   cout << F("Type any character to start\n");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
   // Discard any extra characters.
   do {
@@ -487,7 +487,7 @@ void setup() {
          "Warning, all data on the card will be erased.\n"
          "Enter 'Y' to continue: ");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
 
   c = Serial.read();
@@ -511,7 +511,7 @@ void setup() {
          "Enter option: ");
 
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
   c = Serial.read();
   cout << c << endl;
@@ -521,7 +521,7 @@ void setup() {
   }
 #if USE_SDIO
   if (!card.begin()) {
-    sdError("card.begin failed");  
+    sdError("card.begin failed");
   }
 #else  // USE_SDIO
   if (!card.begin(chipSelect, SPI_SPEED)) {
@@ -531,7 +531,7 @@ void setup() {
            "Is chip select correct at the top of this program?\n");
     sdError("card.begin failed");
   }
-#endif  
+#endif
   cardSizeBlocks = card.cardSize();
   if (cardSizeBlocks == 0) {
     sdError("cardSize");

+ 8 - 8
examples/examplesV1/SdInfo/SdInfo.ino

@@ -5,7 +5,7 @@
 #include "SdFat.h"
 #include "sdios.h"
 #error Use new Version 2 SdInfo
-// Set USE_SDIO to zero for SPI card access. 
+// Set USE_SDIO to zero for SPI card access.
 #define USE_SDIO 0
 /*
  * SD chip select pin.  Common values are:
@@ -143,10 +143,10 @@ void volDmp() {
 //------------------------------------------------------------------------------
 void setup() {
   Serial.begin(9600);
-  
-  // Wait for USB Serial 
+
+  // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
 
   // use uppercase in hex and use 0X base prefix
@@ -154,7 +154,7 @@ void setup() {
 
   // F stores strings in flash to save RAM
   cout << F("SdFat version: ") << SD_FAT_VERSION << endl;
-#if !USE_SDIO  
+#if !USE_SDIO
   if (DISABLE_CHIP_SELECT < 0) {
     cout << F(
            "\nAssuming the SD is the only SPI device.\n"
@@ -167,7 +167,7 @@ void setup() {
   }
   cout << F("\nAssuming the SD chip select pin is: ") <<int(SD_CHIP_SELECT);
   cout << F("\nEdit SD_CHIP_SELECT to change the SD chip select pin.\n");
-#endif  // !USE_SDIO  
+#endif  // !USE_SDIO
 }
 //------------------------------------------------------------------------------
 void loop() {
@@ -179,7 +179,7 @@ void loop() {
   // F stores strings in flash to save RAM
   cout << F("\ntype any character to start\n");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
 
   uint32_t t = millis();
@@ -195,7 +195,7 @@ void loop() {
     sdErrorMsg("cardBegin failed");
     return;
   }
- #endif  // USE_SDIO 
+ #endif  // USE_SDIO
   t = millis() - t;
 
   cardSize = sd.card()->cardSize();

+ 4 - 4
examples/examplesV1/SoftwareSpi/SoftwareSpi.ino

@@ -24,13 +24,13 @@ SdFile file;
 
 void setup() {
   Serial.begin(9600);
-  // Wait for USB Serial 
+  // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   Serial.println("Type any character to start");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
 
   if (!sd.begin(SD_CHIP_SELECT_PIN)) {
@@ -43,7 +43,7 @@ void setup() {
   file.println(F("This line was printed using software SPI."));
 
   file.rewind();
-  
+
   while (file.available()) {
     Serial.write(file.read());
   }

+ 5 - 5
examples/examplesV1/StdioBench/StdioBench.ino

@@ -32,17 +32,17 @@ void setup() {
 
   Serial.begin(9600);
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
 
   Serial.println(F("Type any character to start"));
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
   Serial.println(F("Starting test"));
 
   // Initialize at the highest speed supported by the board that is
-  // not over 50 MHz. Try a lower speed if SPI errors occur.  
+  // not over 50 MHz. Try a lower speed if SPI errors occur.
   if (!sd.begin(SD_CS_PIN, SD_SCK_MHZ(50))) {
     sd.errorHalt();
   }
@@ -146,7 +146,7 @@ void setup() {
             stdioFile.printField(n, '\n');
 #else  // PRINT_FIELD
             stdioFile.println(n);
-#endif  // PRINT_FIELD      
+#endif  // PRINT_FIELD
           }
           break;
 
@@ -157,7 +157,7 @@ void setup() {
               stdioFile.printField(f[i], '\n', 4);
 #else  // PRINT_FIELD
               stdioFile.println(f[i], 4);
-#endif  // PRINT_FIELD                            
+#endif  // PRINT_FIELD
             }
           }
           break;

+ 12 - 12
examples/examplesV1/TeensySdioDemo/TeensySdioDemo.ino

@@ -1,7 +1,7 @@
 // Simple performance test for Teensy 3.5/3.6 SDHC.
 // Demonstrates yield() efficiency.
 
-// Warning SdFatSdio and SdFatSdioEX normally should 
+// Warning SdFatSdio and SdFatSdioEX normally should
 // not both be used in a program.
 // Each has its own cache and member variables.
 
@@ -48,8 +48,8 @@ void errorHalt(const char* msg) {
 }
 //------------------------------------------------------------------------------
 uint32_t kHzSdClk() {
-  return useEx ? sdEx.card()->kHzSdClk() : sd.card()->kHzSdClk(); 
-}  
+  return useEx ? sdEx.card()->kHzSdClk() : sd.card()->kHzSdClk();
+}
 //------------------------------------------------------------------------------
 // Replace "weak" system yield() function.
 void yield() {
@@ -74,7 +74,7 @@ void runTest() {
   totalMicros = 0;
   yieldMicros = 0;
   yieldCalls = 0;
-  yieldMaxUsec = 0; 
+  yieldMaxUsec = 0;
   if (!file.open("TeensyDemo.bin", O_RDWR | O_CREAT)) {
     errorHalt("open failed");
   }
@@ -100,19 +100,19 @@ void runTest() {
     Serial.print(',');
     file.rewind();
     t = micros();
-    
+
     for (uint32_t n = 0; n < nRdWr; n++) {
       if ((int)nb != file.read(buf, nb)) {
         errorHalt("read failed");
       }
-      // crude check of data.     
+      // crude check of data.
       if (buf32[0] != n || buf32[nb/4 - 1] != n) {
         errorHalt("data check");
       }
     }
     t = micros() - t;
-    totalMicros += t;   
-    Serial.println(1000.0*FILE_SIZE/t);    
+    totalMicros += t;
+    Serial.println(1000.0*FILE_SIZE/t);
   }
   file.close();
   Serial.print("\ntotalMicros  ");
@@ -122,7 +122,7 @@ void runTest() {
   Serial.print("yieldCalls   ");
   Serial.println(yieldCalls);
   Serial.print("yieldMaxUsec ");
-  Serial.println(yieldMaxUsec); 
+  Serial.println(yieldMaxUsec);
   Serial.print("kHzSdClk     ");
   Serial.println(kHzSdClk());
   Serial.println("Done");
@@ -133,8 +133,8 @@ void setup() {
   while (!Serial) {
   }
   Serial.println("SdFatSdioEX uses extended multi-block transfers without DMA.");
-  Serial.println("SdFatSdio uses a traditional DMA SDIO implementation."); 
-  Serial.println("Note the difference is speed and busy yield time.\n"); 
+  Serial.println("SdFatSdio uses a traditional DMA SDIO implementation.");
+  Serial.println("Note the difference is speed and busy yield time.\n");
 }
 //-----------------------------------------------------------------------------
 void loop() {
@@ -163,7 +163,7 @@ void loop() {
       sd.initErrorHalt("SdFatSdio begin() failed");
     }
     // make sd the current volume.
-    sd.chvol();  
+    sd.chvol();
   }
   runTest();
 }

+ 3 - 3
examples/examplesV1/Timestamp/Timestamp.ino

@@ -53,7 +53,7 @@ void dateTime(uint16_t* date, uint16_t* time) {
 void printTimestamps(SdFile& f) {
   cout << F("Creation: ");
   f.printCreateDateTime(&Serial);
-  cout << endl << F("Modify: ");  
+  cout << endl << F("Modify: ");
   f.printModifyDateTime(&Serial);
   cout << endl << F("Access: ");
   f.printAccessDateTime(&Serial);
@@ -64,11 +64,11 @@ void setup(void) {
   Serial.begin(9600);
   // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   cout << F("Type any character to start\n");
   while (!Serial.available()) {
-    SysCall::yield();  
+    yield();
   }
   // Initialize at the highest speed supported by the board that is
   // not over 50 MHz. Try a lower speed if SPI errors occur.

+ 4 - 4
examples/examplesV1/TwoCards/TwoCards.ino

@@ -25,9 +25,9 @@ const uint32_t NWRITE = FILE_SIZE/BUF_DIM;
 //------------------------------------------------------------------------------
 void setup() {
   Serial.begin(9600);
-  // Wait for USB Serial 
+  // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   Serial.print(F("FreeStack: "));
 
@@ -40,7 +40,7 @@ void setup() {
 
   Serial.println(F("type any character to start"));
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
 
   // disable sd2 while initializing sd1
@@ -146,7 +146,7 @@ void setup() {
   Serial.println(F(" millis"));
   // close test.bin
   file1.close();
-  file2.close(); 
+  file2.close();
   // list current directory on both cards
   Serial.println(F("------sd1 -------"));
   sd1.ls("/", LS_R | LS_DATE | LS_SIZE);

+ 2 - 2
examples/examplesV1/VolumeFreeSpace/VolumeFreeSpace.ino

@@ -38,7 +38,7 @@ void setup() {
   Serial.begin(9600);
   // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   if (!MAINTAIN_FREE_CLUSTER_COUNT) {
     cout << F("Please edit SdFatConfig.h and set\n");
@@ -48,7 +48,7 @@ void setup() {
   // F stores strings in flash to save RAM
   cout << F("Type any character to start\n");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
   // Initialize at the highest speed supported by the board that is
   // not over 50 MHz. Try a lower speed if SPI errors occur.

+ 2 - 2
examples/examplesV1/bench/bench.ino

@@ -84,7 +84,7 @@ void setup() {
 
   // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   delay(1000);
   cout << F("\nUse a freshly formatted SD for best performance.\n");
@@ -108,7 +108,7 @@ void loop() {
   // F( stores strings in flash to save RAM
   cout << F("Type any character to start\n");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
   cout << F("chipSelect: ") << int(chipSelect) << endl;
   cout << F("FreeStack: ") << FreeStack() << endl;

+ 6 - 6
examples/examplesV1/dataLogger/dataLogger.ino

@@ -67,18 +67,18 @@ void setup() {
   char fileName[13] = FILE_BASE_NAME "00.csv";
 
   Serial.begin(9600);
-  
-  // Wait for USB Serial 
+
+  // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   delay(1000);
 
   Serial.println(F("Type any character to start"));
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
-  
+
   // Initialize at the highest speed supported by the board that is
   // not over 50 MHz. Try a lower speed if SPI errors occur.
   if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) {
@@ -145,6 +145,6 @@ void loop() {
     // Close file and stop.
     file.close();
     Serial.println(F("Done"));
-    SysCall::halt();
+    while (true) {}
   }
 }

+ 4 - 4
examples/examplesV1/fgets/fgets.ino

@@ -61,15 +61,15 @@ void makeTestFile() {
 //------------------------------------------------------------------------------
 void setup(void) {
   Serial.begin(9600);
-  
-  // Wait for USB Serial 
+
+  // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
 
   cout << F("Type any character to start\n");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
   delay(400);  // catch Due reset problem
 

+ 2 - 2
examples/examplesV1/formatting/formatting.ino

@@ -43,9 +43,9 @@ void showDate(int m, int d, int y) {
 void setup(void) {
   Serial.begin(9600);
 
-  // Wait for USB Serial 
+  // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   delay(2000);
 

+ 4 - 4
examples/examplesV1/getline/getline.ino

@@ -55,16 +55,16 @@ void testGetline() {
 //------------------------------------------------------------------------------
 void setup(void) {
   Serial.begin(9600);
-  
-  // Wait for USB Serial 
+
+  // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
 
   // F stores strings in flash to save RAM
   cout << F("Type any character to start\n");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
 
   // Initialize at the highest speed supported by the board that is

+ 2 - 2
examples/examplesV1/rename/rename.ino

@@ -23,11 +23,11 @@ void setup() {
 
   // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   cout << F("Insert an empty SD.  Type any character to start.") << endl;
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
 
   // Initialize at the highest speed supported by the board that is

+ 0 - 66
examples/examplesV1/v1v2.txt

@@ -1,66 +0,0 @@
-diff -rb "C:\\Users\\bill\\Documents\\Arduino\\libraries\\SdFat\\examples/STM32Test/STM32Test.ino" "C:\\Users\\bill\\Documents\\ArduinoSdFat\\libraries\\SdFat\\examples\\examplesV1/STM32Test/STM32Test.ino"
-8c8
-< 
----
-> #error See new Version 2 STM32 example
-diff -rb "C:\\Users\\bill\\Documents\\Arduino\\libraries\\SdFat\\examples/SdFormatter/SdFormatter.ino" "C:\\Users\\bill\\Documents\\ArduinoSdFat\\libraries\\SdFat\\examples\\examplesV1/SdFormatter/SdFormatter.ino"
-14c14
-< 
----
-> #error  use new Version 2 SdFormatter
-diff -rb "C:\\Users\\bill\\Documents\\Arduino\\libraries\\SdFat\\examples/SdInfo/SdInfo.ino" "C:\\Users\\bill\\Documents\\ArduinoSdFat\\libraries\\SdFat\\examples\\examplesV1/SdInfo/SdInfo.ino"
-7c7
-< 
----
-> #error Use new Version 2 SdInfo
-diff -rb "C:\\Users\\bill\\Documents\\Arduino\\libraries\\SdFat\\examples/SoftwareSpi/SoftwareSpi.ino" "C:\\Users\\bill\\Documents\\ArduinoSdFat\\libraries\\SdFat\\examples\\examplesV1/SoftwareSpi/SoftwareSpi.ino"
-7a8
-> #error See Version 2 software SPI example
-diff -rb "C:\\Users\\bill\\Documents\\Arduino\\libraries\\SdFat\\examples/StdioBench/StdioBench.ino" "C:\\Users\\bill\\Documents\\ArduinoSdFat\\libraries\\SdFat\\examples\\examplesV1/StdioBench/StdioBench.ino"
-3a4
-> #include "sdios.h"
-27c28
-<   uint32_t printSize;
----
->   uint32_t printSize = 0;
-29c30
-<   uint32_t printTime;
----
->   uint32_t printTime = 0;
-diff -rb "C:\\Users\\bill\\Documents\\Arduino\\libraries\\SdFat\\examples/TeensySdioDemo/TeensySdioDemo.ino" "C:\\Users\\bill\\Documents\\ArduinoSdFat\\libraries\\SdFat\\examples\\examplesV1/TeensySdioDemo/TeensySdioDemo.ino"
-9c9
-< 
----
-> #error See Version 2 SDIO example
-diff -rb "C:\\Users\\bill\\Documents\\Arduino\\libraries\\SdFat\\examples/Timestamp/Timestamp.ino" "C:\\Users\\bill\\Documents\\ArduinoSdFat\\libraries\\SdFat\\examples\\examplesV1/Timestamp/Timestamp.ino"
-8d7
-< 
-55,59d53
-<   dir_t d;
-<   if (!f.dirEntry(&d)) {
-<     error("f.dirEntry failed");
-<   }
-< 
-61,73c55,59
-<   f.printFatDate(d.creationDate);
-<   cout << ' ';
-<   f.printFatTime(d.creationTime);
-<   cout << endl;
-< 
-<   cout << F("Modify: ");
-<   f.printFatDate(d.lastWriteDate);
-<   cout <<' ';
-<   f.printFatTime(d.lastWriteTime);
-<   cout << endl;
-< 
-<   cout << F("Access: ");
-<   f.printFatDate(d.lastAccessDate);
----
->   f.printCreateDateTime(&Serial);
->   cout << endl << F("Modify: ");  
->   f.printModifyDateTime(&Serial);
->   cout << endl << F("Access: ");
->   f.printAccessDateTime(&Serial);
-diff -rb "C:\\Users\\bill\\Documents\\Arduino\\libraries\\SdFat\\examples/wipe/wipe.ino" "C:\\Users\\bill\\Documents\\ArduinoSdFat\\libraries\\SdFat\\examples\\examplesV1/wipe/wipe.ino"
-1a2
-> #error wipe is not supported in SdFat V2. Use bool format(print_t* pr = nullptr).

+ 5 - 5
examples/examplesV1/wipe/wipe.ino

@@ -9,20 +9,20 @@ SdFat sd;
 void setup() {
   int c;
   Serial.begin(9600);
-  // Wait for USB Serial 
+  // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   Serial.println("Type 'Y' to wipe all data.");
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
   c = Serial.read();
   if (c != 'Y') {
     sd.errorHalt("Quitting, you did not type 'Y'.");
   }
   // Initialize at the highest speed supported by the board that is
-  // not over 50 MHz. Try a lower speed if SPI errors occur. 
+  // not over 50 MHz. Try a lower speed if SPI errors occur.
   if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) {
     sd.initErrorHalt();
   }
@@ -32,7 +32,7 @@ void setup() {
   }
   // Must reinitialize after wipe.
   // Initialize at the highest speed supported by the board that is
-  // not over 50 MHz. Try a lower speed if SPI errors occur.  
+  // not over 50 MHz. Try a lower speed if SPI errors occur.
   if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) {
     sd.errorHalt("Second init failed.");
   }

+ 2 - 2
examples/rename/rename.ino

@@ -64,11 +64,11 @@ void setup() {
 
   // Wait for USB Serial
   while (!Serial) {
-    SysCall::yield();
+    yield();
   }
   cout << F("Insert an empty SD.  Type any character to start.") << endl;
   while (!Serial.available()) {
-    SysCall::yield();
+    yield();
   }
 
   // Initialize at the highest speed supported by the board that is

+ 1 - 2
extras/attic/PrintBasic.h

@@ -32,12 +32,11 @@
 #include <stddef.h>
 #include <string.h>
 
-class __FlashStringHelper;
-
 #ifdef F
 #warning F() macro defined for non Arduino System
 #elif defined(__AVR__)
 #include <avr/pgmspace.h>
+class __FlashStringHelper;
 #define F(str) (reinterpret_cast<const __FlashStringHelper *>(PSTR(str)))
 #else  // F
 #define F(str) (str)

+ 1 - 1
library.properties

@@ -1,5 +1,5 @@
 name=SdFat
-version=2.1.0
+version=2.1.1
 license=MIT
 author=Bill Greiman <fat16lib@sbcglobal.net>
 maintainer=Bill Greiman <fat16lib@sbcglobal.net>

+ 1 - 1
src/BufferedPrint.h

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License

+ 1 - 1
src/ExFatLib/ExFatConfig.h

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License

+ 14 - 14
src/ExFatLib/ExFatDbg.cpp

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License
@@ -24,7 +24,7 @@
  */
 #include "ExFatVolume.h"
 #include "../common/upcase.h"
-#include "ExFatFile.h"
+#include "ExFatLib.h"
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
 //------------------------------------------------------------------------------
 static void printHex(print_t* pr, uint8_t h);
@@ -294,7 +294,7 @@ void ExFatPartition::checkUpcase(print_t* pr) {
   uint8_t* upcase = nullptr;
   uint32_t size = 0;
   uint32_t sector = clusterStartSector(m_rootDirectoryCluster);
-  uint8_t* cache = dataCacheGet(sector, FsCache::CACHE_FOR_READ);
+  uint8_t* cache = dataCachePrepare(sector, FsCache::CACHE_FOR_READ);
   if (!cache) {
     pr->println(F("read root failed"));
     return;
@@ -315,7 +315,7 @@ void ExFatPartition::checkUpcase(print_t* pr) {
   }
   for (size_t i = 0; i < size/2; i++) {
     if ((i%256) == 0) {
-      upcase = dataCacheGet(sector++, FsCache::CACHE_FOR_READ);
+      upcase = dataCachePrepare(sector++, FsCache::CACHE_FOR_READ);
       if (!upcase) {
         pr->println(F("read upcase failed"));
         return;
@@ -378,7 +378,7 @@ void ExFatPartition::dmpFat(print_t* pr, uint32_t start, uint32_t count) {
   uint32_t cluster = 128*start;
   pr->println(F("FAT:"));
   for (uint32_t i = 0; i < count; i++) {
-    uint8_t* cache = dataCacheGet(sector + i, FsCache::CACHE_FOR_READ);
+    uint8_t* cache = dataCachePrepare(sector + i, FsCache::CACHE_FOR_READ);
     if (!cache) {
       pr->println(F("cache read failed"));
       return;
@@ -400,12 +400,12 @@ void ExFatPartition::dmpFat(print_t* pr, uint32_t start, uint32_t count) {
 }
 //------------------------------------------------------------------------------
 void ExFatPartition::dmpSector(print_t* pr, uint32_t sector) {
-  uint8_t* cache = dataCacheGet(sector, FsCache::CACHE_FOR_READ);
+  uint8_t* cache = dataCachePrepare(sector, FsCache::CACHE_FOR_READ);
   if (!cache) {
     pr->println(F("dmpSector failed"));
     return;
   }
-  for (uint16_t i = 0; i < 512; i++) {
+  for (uint16_t i = 0; i < m_bytesPerSector; i++) {
     if (i%32 == 0) {
       if (i) {
         pr->println();
@@ -434,8 +434,8 @@ bool ExFatPartition::printDir(print_t* pr, ExFatFile* file) {
 #define RAW_ROOT
 #ifndef RAW_ROOT
   while (1) {
-    uint8_t buf[32];
-    if (file->read(buf, 32) != 32) {
+    uint8_t buf[FS_DIR_SIZE];
+    if (file->read(buf, FS_DIR_SIZE) != FS_DIR_SIZE) {
       break;
     }
     dir = reinterpret_cast<DirGeneric_t*>(buf);
@@ -446,7 +446,7 @@ bool ExFatPartition::printDir(print_t* pr, ExFatFile* file) {
   for (uint32_t iDir = 0; iDir < nDir; iDir++) {
     size_t i = iDir%16;
     if (i == 0) {
-      uint8_t* cache = dataCacheGet(sector++, FsCache::CACHE_FOR_READ);
+      uint8_t* cache = dataCachePrepare(sector++, FsCache::CACHE_FOR_READ);
       if (!cache) {
         return false;
       }
@@ -556,7 +556,7 @@ void ExFatPartition::printUpcase(print_t* pr) {
   uint32_t checksum = 0;
   DirUpcase_t* dir;
   sector = clusterStartSector(m_rootDirectoryCluster);
-  upcase = dataCacheGet(sector, FsCache::CACHE_FOR_READ);
+  upcase = dataCachePrepare(sector, FsCache::CACHE_FOR_READ);
   dir = reinterpret_cast<DirUpcase_t*>(upcase);
   if (!dir) {
     pr->println(F("read root dir failed"));
@@ -575,7 +575,7 @@ void ExFatPartition::printUpcase(print_t* pr) {
   }
   for (uint16_t i = 0; i < size/2; i++) {
     if ((i%256) == 0) {
-      upcase = dataCacheGet(sector++, FsCache::CACHE_FOR_READ);
+      upcase = dataCachePrepare(sector++, FsCache::CACHE_FOR_READ);
       if (!upcase) {
         pr->println(F("read upcase failed"));
         return;
@@ -597,7 +597,7 @@ void ExFatPartition::printUpcase(print_t* pr) {
 }
 //------------------------------------------------------------------------------
 bool ExFatPartition::printVolInfo(print_t* pr) {
-  uint8_t* cache = dataCacheGet(0, FsCache::CACHE_FOR_READ);
+  uint8_t* cache = dataCachePrepare(0, FsCache::CACHE_FOR_READ);
   if (!cache) {
     pr->println(F("read mbr failed"));
     return false;
@@ -610,7 +610,7 @@ bool ExFatPartition::printVolInfo(print_t* pr) {
     pr->print(F("bad partition size"));
     return false;
   }
-  cache = dataCacheGet(volStart, FsCache::CACHE_FOR_READ);
+  cache = dataCachePrepare(volStart, FsCache::CACHE_FOR_READ);
   if (!cache) {
     pr->println(F("read pbs failed"));
     return false;

+ 14 - 15
src/ExFatLib/ExFatFile.cpp

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License
@@ -25,8 +25,7 @@
 #define DBG_FILE "ExFatFile.cpp"
 #include "../common/DebugMacros.h"
 #include "../common/FsUtf.h"
-#include "ExFatFile.h"
-#include "ExFatVolume.h"
+#include "ExFatLib.h"
 //------------------------------------------------------------------------------
 /** test for legal character.
  *
@@ -44,7 +43,7 @@ inline bool lfnLegalChar(uint8_t c) {
 //------------------------------------------------------------------------------
 uint8_t* ExFatFile::dirCache(uint8_t set, uint8_t options) {
   DirPos_t pos = m_dirPos;
-  if (m_vol->dirSeek(&pos, 32*set) != 1) {
+  if (m_vol->dirSeek(&pos, FS_DIR_SIZE*set) != 1) {
     return nullptr;
   }
   return m_vol->dirCache(&pos, options);
@@ -214,7 +213,7 @@ bool ExFatFile::open(ExFatFile* dirFile, const char* path, oflag_t oflag) {
 }
 //------------------------------------------------------------------------------
 bool ExFatFile::open(ExFatFile* dirFile, uint32_t index, oflag_t oflag) {
-  if (dirFile->seekSet(32*index) && openNext(dirFile, oflag)) {
+  if (dirFile->seekSet(FS_DIR_SIZE*index) && openNext(dirFile, oflag)) {
     if (dirIndex() == index) {
       return true;
     }
@@ -245,7 +244,7 @@ bool ExFatFile::openPrivate(ExFatFile* dir, ExName_t* fname, oflag_t oflag) {
   DirFile_t*   dirFile;
   DirStream_t* dirStream;
   DirName_t*   dirName;
-  uint8_t buf[32];
+  uint8_t buf[FS_DIR_SIZE];
   uint8_t freeCount = 0;
   uint8_t freeNeed = 3;
   bool inSet = false;
@@ -278,18 +277,18 @@ bool ExFatFile::openPrivate(ExFatFile* dir, ExName_t* fname, oflag_t oflag) {
   }
 
   while (1) {
-    n = dir->read(buf, 32);
+    n = dir->read(buf, FS_DIR_SIZE);
     if (n == 0) {
       goto create;
     }
-    if (n != 32) {
+    if (n != FS_DIR_SIZE) {
       DBG_FAIL_MACRO;
       goto fail;
     }
     if (!(buf[0] & 0x80)) {
       // Unused entry.
       if (freeCount == 0) {
-        freePos.position = dir->curPosition() - 32;
+        freePos.position = dir->curPosition() - FS_DIR_SIZE;
         freePos.cluster = dir->curCluster();
       }
       if (freeCount < freeNeed) {
@@ -321,7 +320,7 @@ bool ExFatFile::openPrivate(ExFatFile* dir, ExName_t* fname, oflag_t oflag) {
       }
       m_vol = dir->volume();
       m_dirPos.cluster = dir->curCluster();
-      m_dirPos.position = dir->curPosition() - 32;
+      m_dirPos.position = dir->curPosition() - FS_DIR_SIZE;
       m_dirPos.isContiguous = dir->isContiguous();
     } else if (buf[0] == EXFAT_TYPE_STREAM) {
       dirStream = reinterpret_cast<DirStream_t*>(buf);
@@ -396,7 +395,7 @@ bool ExFatFile::openPrivate(ExFatFile* dir, ExName_t* fname, oflag_t oflag) {
     goto fail;
   }
   while (freeCount < freeNeed) {
-    n = dir->read(buf, 32);
+    n = dir->read(buf, FS_DIR_SIZE);
     if (n == 0) {
       curCluster = dir->m_curCluster;
       if (!dir->addDirCluster()) {
@@ -406,12 +405,12 @@ bool ExFatFile::openPrivate(ExFatFile* dir, ExName_t* fname, oflag_t oflag) {
       dir->m_curCluster = curCluster;
       continue;
     }
-    if (n != 32) {
+    if (n != FS_DIR_SIZE) {
       DBG_FAIL_MACRO;
       goto fail;
     }
     if (freeCount == 0) {
-      freePos.position = dir->curPosition() - 32;
+      freePos.position = dir->curPosition() - FS_DIR_SIZE;
       freePos.cluster = dir->curCluster();
     }
     freeCount++;
@@ -428,7 +427,7 @@ bool ExFatFile::openPrivate(ExFatFile* dir, ExName_t* fname, oflag_t oflag) {
       DBG_FAIL_MACRO;
       goto fail;
     }
-    memset(cache, 0 , 32);
+    memset(cache, 0 , FS_DIR_SIZE);
     if (i == 0) {
       dirFile = reinterpret_cast<DirFile_t*>(cache);
       dirFile->type = EXFAT_TYPE_FILE;
@@ -586,7 +585,7 @@ int ExFatFile::read(void* buf, size_t count) {
         n = toRead;
       }
       // read sector to cache and copy data to caller
-      cache = m_vol->dataCacheGet(sector, FsCache::CACHE_FOR_READ);
+      cache = m_vol->dataCachePrepare(sector, FsCache::CACHE_FOR_READ);
       if (!cache) {
         DBG_FAIL_MACRO;
         goto fail;

+ 15 - 5
src/ExFatLib/ExFatFile.h

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License
@@ -30,12 +30,10 @@
  */
 #include <limits.h>
 #include <string.h>
-#include "ExFatConfig.h"
 #include "../common/FsDateTime.h"
-#include "../common/FsStructs.h"
 #include "../common/FsApiConstants.h"
 #include "../common/FmtNumber.h"
-#include "ExFatTypes.h"
+#include "../common/FsName.h"
 #include "ExFatPartition.h"
 
 class ExFatVolume;
@@ -43,6 +41,18 @@ class ExFatVolume;
 /** Expression for path name separator. */
 #define isDirSeparator(c) ((c) == '/')
 //------------------------------------------------------------------------------
+/**
+ * \class ExName_t
+ * \brief Internal type for file name - do not use in user apps.
+ */
+class ExName_t : public FsName {
+ public:
+  /** Length of UTF-16 name */
+  size_t nameLength;
+  /** Hash for UTF-16 name */
+  uint16_t nameHash;
+};
+//------------------------------------------------------------------------------
 /**
  * \class ExFatFile
  * \brief Basic file class.
@@ -125,7 +135,7 @@ class ExFatFile {
   /** \return Total data length for file. */
   uint64_t dataLength() const {return m_dataLength;}
   /** \return Directory entry index. */
-  uint32_t dirIndex() const {return m_dirPos.position/32;}
+  uint32_t dirIndex() const {return m_dirPos.position/FS_DIR_SIZE;}
   /** Test for the existence of a file in a directory
    *
    * \param[in] path Path of the file to be tested for.

+ 3 - 3
src/ExFatLib/ExFatFilePrint.cpp

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License
@@ -24,8 +24,8 @@
  */
 #define DBG_FILE "ExFatFilePrint.cpp"
 #include "../common/DebugMacros.h"
-#include "ExFatFile.h"
-#include "ExFatVolume.h"
+#include "ExFatLib.h"
+#include "../common/FsUtf.h"
 //------------------------------------------------------------------------------
 bool ExFatFile::ls(print_t* pr) {
   ExFatFile file;

+ 12 - 16
src/ExFatLib/ExFatFileWrite.cpp

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License
@@ -24,8 +24,7 @@
  */
 #define DBG_FILE "ExFatFileWrite.cpp"
 #include "../common/DebugMacros.h"
-#include "ExFatFile.h"
-#include "ExFatVolume.h"
+#include "ExFatLib.h"
 //==============================================================================
 #if READ_ONLY
 bool ExFatFile::mkdir(ExFatFile* parent, const char* path, bool pFlag) {
@@ -131,18 +130,15 @@ bool ExFatFile::addDirCluster() {
     DBG_FAIL_MACRO;
     goto fail;
   }
-  cache =  m_vol->cacheClear();
-  if (!cache) {
-    DBG_FAIL_MACRO;
-    goto fail;
-  }
-  memset(cache, 0, m_vol->bytesPerSector());
   sector = m_vol->clusterStartSector(m_curCluster);
-  for (uint32_t i = 0; i < m_vol->sectorsPerCluster(); i++) {
-    if (!m_vol->writeSector(sector + i, cache)) {
+  for (uint32_t i = 0; i  < m_vol->sectorsPerCluster(); i++) {
+    cache = m_vol->dataCachePrepare(sector + i,
+                                    FsCache::CACHE_RESERVE_FOR_WRITE);
+    if (!cache) {
       DBG_FAIL_MACRO;
       goto fail;
     }
+    memset(cache, 0, m_vol->bytesPerSector());
   }
   if (!isRoot()) {
     m_flags |= FILE_FLAG_DIR_DIRTY;
@@ -340,7 +336,7 @@ bool ExFatFile::rename(ExFatFile* dirFile, const char* newPath) {
 //------------------------------------------------------------------------------
 bool ExFatFile::rmdir() {
   int n;
-  uint8_t dir[32];
+  uint8_t dir[FS_DIR_SIZE];
   // must be open subdirectory
   if (!isSubDir()) {
     DBG_FAIL_MACRO;
@@ -350,11 +346,11 @@ bool ExFatFile::rmdir() {
 
   // make sure directory is empty
   while (1) {
-    n = read(dir, 32);
+    n = read(dir, FS_DIR_SIZE);
     if (n == 0) {
       break;
     }
-    if (n != 32 || dir[0] & 0X80) {
+    if (n != FS_DIR_SIZE || dir[0] & 0X80) {
       DBG_FAIL_MACRO;
       goto fail;
     }
@@ -493,7 +489,7 @@ bool ExFatFile::timestamp(uint8_t flags, uint16_t year, uint8_t month,
   time = FS_TIME(hour, minute, second);
   ms10 = second & 1 ? 100 : 0;
 
-  for (uint8_t is = 0;; is++) {
+  for (uint8_t is = 0; is <= m_setCount; is++) {
     cache = dirCache(is, FsCache::CACHE_FOR_READ);
     if (!cache) {
       DBG_FAIL_MACRO;
@@ -697,7 +693,7 @@ size_t ExFatFile::write(const void* buf, size_t nbyte) {
         // rewrite part of sector
         cacheOption = FsCache::CACHE_FOR_WRITE;
       }
-      cache = m_vol->dataCacheGet(sector, cacheOption);
+      cache = m_vol->dataCachePrepare(sector, cacheOption);
       if (!cache) {
         DBG_FAIL_MACRO;
         goto fail;

+ 3 - 4
src/ExFatLib/ExFatFormatter.cpp

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License
@@ -25,8 +25,7 @@
 #define DBG_FILE "ExFatFormatter.cpp"
 #include "../common/DebugMacros.h"
 #include "../common/upcase.h"
-#include "../common/FsStructs.h"
-#include "ExFatFormatter.h"
+#include "ExFatLib.h"
 //------------------------------------------------------------------------------
 // Formatter assumes 512 byte sectors.
 const uint32_t BOOT_BACKUP_OFFSET = 12;
@@ -266,7 +265,7 @@ bool ExFatFormatter::format(BlockDevice* dev, uint8_t* secBuf, print_t* pr) {
   setLe64(dbm->size, bitmapSize);
 
   // upcase directory entry.
-  dup = reinterpret_cast<DirUpcase_t*>(secBuf +64);
+  dup = reinterpret_cast<DirUpcase_t*>(secBuf + 64);
   dup->type = EXFAT_TYPE_UPCASE;
   setLe32(dup->checksum, m_upcaseChecksum);
   setLe32(dup->firstCluster, UPCASE_CLUSTER);

+ 1 - 3
src/ExFatLib/ExFatFormatter.h

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License
@@ -24,8 +24,6 @@
  */
 #ifndef ExFatFormatter_h
 #define ExFatFormatter_h
-#include "ExFatConfig.h"
-#include "../common/SysCall.h"
 #include "../common/BlockDevice.h"
 /**
  * \class ExFatFormatter

+ 1 - 2
src/ExFatLib/ExFatLib.h

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License
@@ -25,6 +25,5 @@
 #ifndef ExFatLib_h
 #define ExFatLib_h
 #include "ExFatVolume.h"
-#include "ExFatFile.h"
 #include "ExFatFormatter.h"
 #endif  // ExFatLib_h

+ 3 - 2
src/ExFatLib/ExFatName.cpp

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License
@@ -25,7 +25,8 @@
 #define DBG_FILE "ExFatName.cpp"
 #include "../common/DebugMacros.h"
 #include "../common/upcase.h"
-#include "ExFatFile.h"
+#include "../common/FsUtf.h"
+#include "ExFatLib.h"
 //------------------------------------------------------------------------------
 static char toUpper(char c) {
   return 'a' <= c && c <= 'z' ? c - 'a' + 'A' : c;

+ 14 - 12
src/ExFatLib/ExFatPartition.cpp

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License
@@ -24,8 +24,7 @@
  */
 #define DBG_FILE "ExFatPartition.cpp"
 #include "../common/DebugMacros.h"
-#include "ExFatVolume.h"
-#include "../common/FsStructs.h"
+#include "ExFatLib.h"
 //------------------------------------------------------------------------------
 // return 0 if error, 1 if no space, else start cluster.
 uint32_t ExFatPartition::bitmapFind(uint32_t cluster, uint32_t count) {
@@ -42,7 +41,7 @@ uint32_t ExFatPartition::bitmapFind(uint32_t cluster, uint32_t count) {
   while (true) {
     uint32_t sector = m_clusterHeapStartSector +
                      (endAlloc >> (m_bytesPerSectorShift + 3));
-    cache = bitmapCacheGet(sector, FsCache::CACHE_FOR_READ);
+    cache = bitmapCachePrepare(sector, FsCache::CACHE_FOR_READ);
     if (!cache) {
       return 0;
     }
@@ -102,7 +101,7 @@ bool ExFatPartition::bitmapModify(uint32_t cluster,
                    (start >> (m_bytesPerSectorShift + 3));
   i = (start >> 3) & m_sectorMask;
   while (true) {
-    cache = bitmapCacheGet(sector++, FsCache::CACHE_FOR_WRITE);
+    cache = bitmapCachePrepare(sector++, FsCache::CACHE_FOR_WRITE);
     if (!cache) {
       DBG_FAIL_MACRO;
       goto fail;
@@ -141,7 +140,7 @@ uint32_t ExFatPartition::chainSize(uint32_t cluster) {
 uint8_t* ExFatPartition::dirCache(DirPos_t* pos, uint8_t options) {
   uint32_t sector = clusterStartSector(pos->cluster);
   sector += (m_clusterMask & pos->position) >> m_bytesPerSectorShift;
-  uint8_t* cache = dataCacheGet(sector, options);
+  uint8_t* cache = dataCachePrepare(sector, options);
   return cache ? cache + (pos->position & m_sectorMask) : nullptr;
 }
 //------------------------------------------------------------------------------
@@ -176,13 +175,16 @@ int8_t ExFatPartition::fatGet(uint32_t cluster, uint32_t* value) {
   }
   sector = m_fatStartSector + (cluster >> (m_bytesPerSectorShift - 2));
 
-  cache = dataCacheGet(sector, FsCache::CACHE_FOR_READ);
+  cache = dataCachePrepare(sector, FsCache::CACHE_FOR_READ);
   if (!cache) {
     return -1;
   }
   next = getLe32(cache + ((cluster << 2) & m_sectorMask));
+  if (next == EXFAT_EOC) {
+    return 0;
+  }
   *value = next;
-  return next == EXFAT_EOC ? 0 : 1;
+  return 1;
 }
 //------------------------------------------------------------------------------
 bool ExFatPartition::fatPut(uint32_t cluster, uint32_t value) {
@@ -193,7 +195,7 @@ bool ExFatPartition::fatPut(uint32_t cluster, uint32_t value) {
     goto fail;
   }
   sector = m_fatStartSector + (cluster >> (m_bytesPerSectorShift - 2));
-  cache = dataCacheGet(sector, FsCache::CACHE_FOR_WRITE);
+  cache = dataCachePrepare(sector, FsCache::CACHE_FOR_WRITE);
   if (!cache) {
     DBG_FAIL_MACRO;
     goto fail;
@@ -242,7 +244,7 @@ uint32_t ExFatPartition::freeClusterCount() {
   uint8_t* cache;
 
   while (true) {
-    cache = dataCacheGet(sector++, FsCache::CACHE_FOR_READ);
+    cache = dataCachePrepare(sector++, FsCache::CACHE_FOR_READ);
     if (!cache) {
       return 0;
     }
@@ -275,7 +277,7 @@ bool ExFatPartition::init(BlockDevice* dev, uint8_t part) {
   m_fatType = 0;
   m_blockDev = dev;
   cacheInit(m_blockDev);
-  cache = dataCacheGet(0, FsCache::CACHE_FOR_READ);
+  cache = dataCachePrepare(0, FsCache::CACHE_FOR_READ);
   if (part > 4 || !cache) {
     DBG_FAIL_MACRO;
     goto fail;
@@ -288,7 +290,7 @@ bool ExFatPartition::init(BlockDevice* dev, uint8_t part) {
       goto fail;
     }
     volStart = getLe32(mp->relativeSectors);
-    cache = dataCacheGet(volStart, FsCache::CACHE_FOR_READ);
+    cache = dataCachePrepare(volStart, FsCache::CACHE_FOR_READ);
     if (!cache) {
       DBG_FAIL_MACRO;
       goto fail;

+ 22 - 10
src/ExFatLib/ExFatPartition.h

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License
@@ -31,13 +31,25 @@
 #include "../common/SysCall.h"
 #include "../common/BlockDevice.h"
 #include "../common/FsCache.h"
+#include "../common/FsStructs.h"
 #include "ExFatConfig.h"
-#include "ExFatTypes.h"
 /** Type for exFAT partition */
 const uint8_t FAT_TYPE_EXFAT = 64;
 
 class ExFatFile;
-
+//------------------------------------------------------------------------------
+/**
+ * \struct DirPos_t
+ * \brief Internal type for position in directory file.
+ */
+struct DirPos_t {
+  /** current cluster */
+  uint32_t cluster;
+  /** offset */
+  uint32_t position;
+  /** directory is contiguous */
+  bool     isContiguous;
+};
 //==============================================================================
 /**
  * \class ExFatPartition
@@ -123,11 +135,11 @@ class ExFatPartition {
   bool bitmapModify(uint32_t cluster, uint32_t count, bool value);
   //----------------------------------------------------------------------------
   // Cache functions.
-  uint8_t* bitmapCacheGet(uint32_t sector, uint8_t option) {
+  uint8_t* bitmapCachePrepare(uint32_t sector, uint8_t option) {
 #if USE_EXFAT_BITMAP_CACHE
-    return m_bitmapCache.get(sector, option);
+    return m_bitmapCache.prepare(sector, option);
 #else  // USE_EXFAT_BITMAP_CACHE
-    return m_dataCache.get(sector, option);
+    return m_dataCache.prepare(sector, option);
 #endif  // USE_EXFAT_BITMAP_CACHE
   }
   void cacheInit(BlockDevice* dev) {
@@ -145,8 +157,8 @@ class ExFatPartition {
   }
   void dataCacheDirty() {m_dataCache.dirty();}
   void dataCacheInvalidate() {m_dataCache.invalidate();}
-  uint8_t* dataCacheGet(uint32_t sector, uint8_t option) {
-    return m_dataCache.get(sector, option);
+  uint8_t* dataCachePrepare(uint32_t sector, uint8_t option) {
+    return m_dataCache.prepare(sector, option);
   }
   uint32_t dataCacheSector() {return m_dataCache.sector();}
   bool dataCacheSync() {return m_dataCache.sync();}
@@ -186,8 +198,8 @@ class ExFatPartition {
   }
   //----------------------------------------------------------------------------
   static const uint8_t  m_bytesPerSectorShift = 9;
-  static const uint16_t m_bytesPerSector = 512;
-  static const uint16_t m_sectorMask = 0x1FF;
+  static const uint16_t m_bytesPerSector = 1 << m_bytesPerSectorShift;
+  static const uint16_t m_sectorMask = m_bytesPerSector - 1;
   //----------------------------------------------------------------------------
 #if USE_EXFAT_BITMAP_CACHE
   FsCache  m_bitmapCache;

+ 0 - 55
src/ExFatLib/ExFatTypes.h

@@ -1,55 +0,0 @@
-/**
- * Copyright (c) 2011-2020 Bill Greiman
- * This file is part of the SdFat library for SD memory cards.
- *
- * MIT License
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-#ifndef ExFatTypes_h
-#define ExFatTypes_h
-#include "ExFatConfig.h"
-#include "../common/FsUtf.h"
-#include "../common/FsName.h"
-//------------------------------------------------------------------------------
-/**
- * \struct DirPos_t
- * \brief Internal type for position in directory file.
- */
-struct DirPos_t {
-  /** current cluster */
-  uint32_t cluster;
-  /** offset */
-  uint32_t position;
-  /** directory is contiguous */
-  bool     isContiguous;
-};
-//------------------------------------------------------------------------------
-/**
- * \class ExName_t
- * \brief Internal type for file name - do not use in user apps.
- */
-class ExName_t : public FsName {
- public:
-  /** Length of UTF-16 name */
-  size_t nameLength;
-  /** Hash for UTF-16 name */
-  uint16_t nameHash;
-};
-#endif  // ExFatTypes_h

+ 2 - 2
src/ExFatLib/ExFatVolume.cpp

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License
@@ -24,7 +24,7 @@
  */
 #define DBG_FILE "ExFatVolume.cpp"
 #include "../common/DebugMacros.h"
-#include "ExFatVolume.h"
+#include "ExFatLib.h"
 ExFatVolume* ExFatVolume::m_cwv = nullptr;
 //-----------------------------------------------------------------------------
 bool ExFatVolume::chdir(const char* path) {

+ 1 - 2
src/ExFatLib/ExFatVolume.h

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License
@@ -24,7 +24,6 @@
  */
 #ifndef ExFatVolume_h
 #define ExFatVolume_h
-#include "ExFatPartition.h"
 #include "ExFatFile.h"
 //==============================================================================
 /**

+ 59 - 10
src/FatLib/FatDbg.cpp

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License
@@ -22,8 +22,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
-#include "FatVolume.h"
-#include "FatFile.h"
+#include "FatLib.h"
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
 //------------------------------------------------------------------------------
 static uint16_t getLfnChar(DirLfn_t* ldir, uint8_t i) {
@@ -44,6 +43,18 @@ static void printHex(print_t* pr, uint8_t h) {
   pr->print(h, HEX);
 }
 //------------------------------------------------------------------------------
+static void printHex(print_t* pr, uint8_t w, uint16_t h) {
+  char buf[5];
+  char* ptr = buf + sizeof(buf);
+  *--ptr = 0;
+  for (uint8_t i = 0; i < w; i++) {
+    char c = h & 0XF;
+    *--ptr = c < 10 ? c + '0' : c + 'A' - 10;
+    h >>= 4;
+  }
+  pr->write(ptr);
+}
+//------------------------------------------------------------------------------
 static void printHex(print_t* pr, uint16_t val) {
   bool space = true;
   for (uint8_t i = 0; i < 4; i++) {
@@ -80,7 +91,7 @@ static void printHexLn(print_t* pr, Uint val) {
   pr->println();
 }
 //------------------------------------------------------------------------------
-bool printFatDir(print_t* pr, DirFat_t* dir) {
+static bool printFatDir(print_t* pr, DirFat_t* dir) {
   DirLfn_t* ldir = reinterpret_cast<DirLfn_t*>(dir);
   if (!dir->name[0]) {
     pr->println(F("Unused"));
@@ -132,9 +143,47 @@ bool printFatDir(print_t* pr, DirFat_t* dir) {
   return true;
 }
 //------------------------------------------------------------------------------
+void FatFile::dmpFile(print_t* pr, uint32_t pos, size_t n) {
+  char text[17];
+  text[16] = 0;
+  if (n >= 0XFFF0) {
+    n = 0XFFF0;
+  }
+  if (!seekSet(pos)) {
+    return;
+  }
+  for (size_t i = 0; i <= n; i++) {
+    if ((i & 15) == 0) {
+      if (i) {
+        pr->write(' ');
+        pr->write(text);
+        if (i == n) {
+          break;
+        }
+      }
+      pr->write('\r');
+      pr->write('\n');
+      if (i >= n) {
+        break;
+      }
+      printHex(pr, 4, i);
+      pr->write(' ');
+    }
+    int16_t h = read();
+    if (h < 0) {
+      break;
+    }
+    pr->write(' ');
+    printHex(pr, 2, h);
+    text[i&15] = ' ' <= h && h < 0X7F ? h : '.';
+  }
+  pr->write('\r');
+  pr->write('\n');
+}
+//------------------------------------------------------------------------------
 bool FatPartition::dmpDirSector(print_t* pr, uint32_t sector) {
   DirFat_t dir[16];
-  if (!readSector(sector, reinterpret_cast<uint8_t*>(dir))) {
+  if (!cacheSafeRead(sector, reinterpret_cast<uint8_t*>(dir))) {
     pr->println(F("dmpDir failed"));
     return false;
   }
@@ -160,12 +209,12 @@ bool FatPartition::dmpRootDir(print_t* pr, uint32_t n) {
 }
 //------------------------------------------------------------------------------
 void FatPartition::dmpSector(print_t* pr, uint32_t sector, uint8_t bits) {
-  uint8_t data[512];
-  if (!readSector(sector, data)) {
+  uint8_t data[FatPartition::m_bytesPerSector];
+  if (!cacheSafeRead(sector, data)) {
     pr->println(F("dmpSector failed"));
     return;
   }
-  for (uint16_t i = 0; i < 512;) {
+  for (uint16_t i = 0; i < m_bytesPerSector;) {
     if (i%32 == 0) {
       if (i) {
         pr->println();
@@ -196,7 +245,7 @@ void FatPartition::dmpFat(print_t* pr, uint32_t start, uint32_t count) {
   uint32_t sector = m_fatStartSector + start;
   uint32_t cluster = nf*start;
   for (uint32_t i = 0; i < count; i++) {
-    cache_t* pc = cacheFetchFat(sector + i, FsCache::CACHE_FOR_READ);
+    uint8_t* pc = fatCachePrepare(sector + i, FsCache::CACHE_FOR_READ);
     if (!pc) {
       pr->println(F("cache read failed"));
       return;
@@ -210,7 +259,7 @@ void FatPartition::dmpFat(print_t* pr, uint32_t start, uint32_t count) {
       }
       cluster++;
       pr->write(' ');
-      uint32_t v = fatType() == 32 ? pc->fat32[k] : pc->fat16[k];
+      uint32_t v = fatType() == 32 ? getLe32(pc + 4*k) : getLe16(pc + 2*k);
       printHex(pr, v);
     }
     pr->println();

+ 40 - 43
src/FatLib/FatFile.cpp

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License
@@ -24,8 +24,7 @@
  */
 #define DBG_FILE "FatFile.cpp"
 #include "../common/DebugMacros.h"
-#include "FatFile.h"
-#include "FatVolume.h"
+#include "FatLib.h"
 //------------------------------------------------------------------------------
 // Add a cluster to a file.
 bool FatFile::addCluster() {
@@ -55,7 +54,7 @@ bool FatFile::addCluster() {
 // Return with first sector of cluster in the cache.
 bool FatFile::addDirCluster() {
   uint32_t sector;
-  cache_t* pc;
+  uint8_t* pc;
 
   if (isRootFixed()) {
     DBG_FAIL_MACRO;
@@ -71,18 +70,13 @@ bool FatFile::addDirCluster() {
     goto fail;
   }
   sector = m_vol->clusterStartSector(m_curCluster);
-  pc = m_vol->cacheFetchData(sector, FsCache::CACHE_RESERVE_FOR_WRITE);
-  if (!pc) {
-    DBG_FAIL_MACRO;
-    goto fail;
-  }
-  memset(pc, 0, m_vol->bytesPerSector());
-  // zero rest of clusters
-  for (uint8_t i = 1; i < m_vol->sectorsPerCluster(); i++) {
-    if (!m_vol->writeSector(sector + i, pc->data)) {
+  for (uint8_t i = 0; i < m_vol->sectorsPerCluster(); i++) {
+    pc = m_vol->dataCachePrepare(sector + i, FsCache::CACHE_RESERVE_FOR_WRITE);
+    if (!pc) {
       DBG_FAIL_MACRO;
       goto fail;
     }
+    memset(pc, 0, m_vol->bytesPerSector());
   }
   // Set position to EOF to avoid inconsistent curCluster/curPosition.
   m_curPosition += m_vol->bytesPerCluster();
@@ -95,13 +89,13 @@ bool FatFile::addDirCluster() {
 // cache a file's directory entry
 // return pointer to cached entry or null for failure
 DirFat_t* FatFile::cacheDirEntry(uint8_t action) {
-  cache_t* pc;
-  pc = m_vol->cacheFetchData(m_dirSector, action);
-  if (!pc) {
+  uint8_t* pc = m_vol->dataCachePrepare(m_dirSector, action);
+  DirFat_t* dir = reinterpret_cast<DirFat_t*>(pc);
+  if (!dir) {
     DBG_FAIL_MACRO;
     goto fail;
   }
-  return pc->dir + (m_dirIndex & 0XF);
+  return dir + (m_dirIndex & 0XF);
 
  fail:
   return nullptr;
@@ -206,7 +200,7 @@ uint32_t FatFile::dirSize() {
     return 0;
   }
   if (isRootFixed()) {
-    return 32*m_vol->rootDirEntryCount();
+    return FS_DIR_SIZE*m_vol->rootDirEntryCount();
   }
   uint16_t n = 0;
   uint32_t c = isRoot32() ? m_vol->rootDirStart() : m_firstCluster;
@@ -353,7 +347,7 @@ bool FatFile::mkdir(FatFile* parent, FatName_t* fname) {
   uint32_t sector;
   DirFat_t dot;
   DirFat_t* dir;
-  cache_t* pc;
+  uint8_t* pc;
 
   if (!parent->isDir()) {
     DBG_FAIL_MACRO;
@@ -399,19 +393,20 @@ bool FatFile::mkdir(FatFile* parent, FatName_t* fname) {
 
   // cache sector for '.'  and '..'
   sector = m_vol->clusterStartSector(m_firstCluster);
-  pc = m_vol->cacheFetchData(sector, FsCache::CACHE_FOR_WRITE);
-  if (!pc) {
+  pc = m_vol->dataCachePrepare(sector, FsCache::CACHE_FOR_WRITE);
+  dir = reinterpret_cast<DirFat_t*>(pc);
+  if (!dir) {
     DBG_FAIL_MACRO;
     goto fail;
   }
   // copy '.' to sector
-  memcpy(&pc->dir[0], &dot, sizeof(dot));
+  memcpy(&dir[0], &dot, sizeof(dot));
   // make entry for '..'
   dot.name[1] = '.';
   setLe16(dot.firstClusterLow, parent->m_firstCluster & 0XFFFF);
   setLe16(dot.firstClusterHigh, parent->m_firstCluster >> 16);
   // copy '..' to sector
-  memcpy(&pc->dir[1], &dot, sizeof(dot));
+  memcpy(&dir[1], &dot, sizeof(dot));
   // write first sector
   return m_vol->cacheSync();
 
@@ -619,7 +614,7 @@ bool FatFile::openNext(FatFile* dirFile, oflag_t oflag) {
   }
   while (1) {
     // read entry into cache
-    index = dirFile->curPosition()/32;
+    index = dirFile->curPosition()/FS_DIR_SIZE;
     DirFat_t* dir = dirFile->readDirCache();
     if (!dir) {
       if (dirFile->getError()) {
@@ -735,8 +730,7 @@ int FatFile::read(void* buf, size_t nbyte) {
   uint16_t offset;
   size_t toRead;
   uint32_t sector;  // raw device sector number
-  cache_t* pc;
-
+  uint8_t* pc;
   // error if not open for read
   if (!isReadable()) {
     DBG_FAIL_MACRO;
@@ -749,7 +743,8 @@ int FatFile::read(void* buf, size_t nbyte) {
       nbyte = tmp32;
     }
   } else if (isRootFixed()) {
-    uint16_t tmp16 = 32*m_vol->m_rootDirEntryCount - (uint16_t)m_curPosition;
+    uint16_t tmp16 =
+      FS_DIR_SIZE*m_vol->m_rootDirEntryCount - (uint16_t)m_curPosition;
     if (nbyte > tmp16) {
       nbyte = tmp16;
     }
@@ -798,12 +793,12 @@ int FatFile::read(void* buf, size_t nbyte) {
         n = toRead;
       }
       // read sector to cache and copy data to caller
-      pc = m_vol->cacheFetchData(sector, FsCache::CACHE_FOR_READ);
+      pc = m_vol->dataCachePrepare(sector, FsCache::CACHE_FOR_READ);
       if (!pc) {
         DBG_FAIL_MACRO;
         goto fail;
       }
-      uint8_t* src = pc->data + offset;
+      uint8_t* src = pc + offset;
       memcpy(dst, src, n);
 #if USE_MULTI_SECTOR_IO
     } else if (toRead >= 2*m_vol->bytesPerSector()) {
@@ -880,9 +875,9 @@ DirFat_t* FatFile::readDirCache(bool skipReadOk) {
       }
       goto fail;
     }
-    m_curPosition += 31;
+    m_curPosition += FS_DIR_SIZE - 1;
   } else {
-    m_curPosition += 32;
+    m_curPosition += FS_DIR_SIZE;
   }
   // return pointer to entry
   return reinterpret_cast<DirFat_t*>(m_vol->cacheAddress()) + i;
@@ -912,7 +907,7 @@ bool FatFile::rename(FatFile* dirFile, const char* newPath) {
   uint32_t dirCluster = 0;
   FatFile file;
   FatFile oldFile;
-  cache_t* pc;
+  uint8_t* pc;
   DirFat_t* dir;
 
   // Must be an open file or subdirectory.
@@ -980,12 +975,13 @@ bool FatFile::rename(FatFile* dirFile, const char* newPath) {
   if (dirCluster) {
     // get new dot dot
     uint32_t sector = m_vol->clusterStartSector(dirCluster);
-    pc = m_vol->cacheFetchData(sector, FsCache::CACHE_FOR_READ);
-    if (!pc) {
+    pc = m_vol->dataCachePrepare(sector, FsCache::CACHE_FOR_READ);
+    dir = reinterpret_cast<DirFat_t*>(pc);
+    if (!dir) {
       DBG_FAIL_MACRO;
       goto fail;
     }
-    memcpy(&entry, &pc->dir[1], sizeof(entry));
+    memcpy(&entry, &dir[1], sizeof(entry));
 
     // free unused cluster
     if (!m_vol->freeChain(dirCluster)) {
@@ -994,12 +990,13 @@ bool FatFile::rename(FatFile* dirFile, const char* newPath) {
     }
     // store new dot dot
     sector = m_vol->clusterStartSector(m_firstCluster);
-    pc = m_vol->cacheFetchData(sector, FsCache::CACHE_FOR_WRITE);
-    if (!pc) {
+    uint8_t* pc = m_vol->dataCachePrepare(sector, FsCache::CACHE_FOR_WRITE);
+    dir = reinterpret_cast<DirFat_t*>(pc);
+    if (!dir) {
       DBG_FAIL_MACRO;
       goto fail;
     }
-    memcpy(&pc->dir[1], &entry, sizeof(entry));
+    memcpy(&dir[1], &entry, sizeof(entry));
   }
   // Remove old directory entry;
   oldFile.m_firstCluster = 0;
@@ -1067,7 +1064,7 @@ bool FatFile::rmRfStar() {
   rewind();
   while (1) {
     // remember position
-    index = m_curPosition/32;
+    index = m_curPosition/FS_DIR_SIZE;
 
     DirFat_t* dir = readDirCache();
     if (!dir) {
@@ -1156,7 +1153,7 @@ bool FatFile::seekSet(uint32_t pos) {
       goto fail;
     }
   } else if (isRootFixed()) {
-    if (pos <= 32*m_vol->rootDirEntryCount()) {
+    if (pos <= FS_DIR_SIZE*m_vol->rootDirEntryCount()) {
       goto done;
     }
     DBG_FAIL_MACRO;
@@ -1335,7 +1332,7 @@ bool FatFile::truncate() {
 size_t FatFile::write(const void* buf, size_t nbyte) {
   // convert void* to uint8_t*  -  must be before goto statements
   const uint8_t* src = reinterpret_cast<const uint8_t*>(buf);
-  cache_t* pc;
+  uint8_t* pc;
   uint8_t cacheOption;
   // number of bytes left to write  -  must be before goto statements
   size_t nToWrite = nbyte;
@@ -1423,12 +1420,12 @@ size_t FatFile::write(const void* buf, size_t nbyte) {
         // rewrite part of sector
         cacheOption = FsCache::CACHE_FOR_WRITE;
       }
-      pc = m_vol->cacheFetchData(sector, cacheOption);
+      pc = m_vol->dataCachePrepare(sector, cacheOption);
       if (!pc) {
         DBG_FAIL_MACRO;
         goto fail;
       }
-      uint8_t* dst = pc->data + sectorOffset;
+      uint8_t* dst = pc + sectorOffset;
       memcpy(dst, src, n);
       if (m_vol->bytesPerSector() == (n + sectorOffset)) {
         // Force write if sector is full - improves large writes.

+ 44 - 37
src/FatLib/FatFile.h

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License
@@ -35,7 +35,6 @@
 #include "../common/FsApiConstants.h"
 #include "../common/FsDateTime.h"
 #include "../common/FsName.h"
-#include "../common/FsStructs.h"
 #include "FatPartition.h"
 class FatVolume;
 //------------------------------------------------------------------------------
@@ -76,25 +75,41 @@ struct FatPos_t {
 #define isDirSeparator(c) ((c) == '/')
 //------------------------------------------------------------------------------
 /**
- * \class FatName_t
- * \brief Internal type for File Name - do not use in user apps.
+ * \class FatLfn_t
+ * \brief Internal type for Long File Name - do not use in user apps.
  */
-#if USE_LONG_FILE_NAMES
-class FatName_t : public FsName {
+
+class FatLfn_t : public FsName {
  public:
   /** UTF-16 length of Long File Name */
   size_t len;
   /** Position for sequence number. */
   uint8_t seqPos;
-#else  // USE_LONG_FILE_NAMES
-class FatName_t {
+  /** Flags for base and extension character case and LFN. */
+  uint8_t flags;
+  /** Short File Name */
+  uint8_t sfn[11];
+};
+/**
+ * \class FatSfn_t
+ * \brief Internal type for Short 8.3 File Name - do not use in user apps.
+ */
+class FatSfn_t {
  public:
-#endif  // USE_LONG_FILE_NAMES
   /** Flags for base and extension character case and LFN. */
   uint8_t flags;
   /** Short File Name */
   uint8_t sfn[11];
 };
+
+#if USE_LONG_FILE_NAMES
+/** Internal class for file names */
+typedef FatLfn_t FatName_t;
+#else  // USE_LONG_FILE_NAMES
+/** Internal class for file names */
+typedef FatSfn_t FatName_t;
+#endif  // USE_LONG_FILE_NAMES
+
 /** Derived from a LFN with loss or conversion of characters. */
 const uint8_t FNAME_FLAG_LOST_CHARS = 0X01;
 /** Base-name or extension has mixed case. */
@@ -397,28 +412,6 @@ class FatFile {
   bool isSystem() const {return m_attributes & FILE_ATTR_SYSTEM;}
   /** \return True file is writable. */
   bool isWritable() const {return m_flags & FILE_FLAG_WRITE;}
-  /** Check for a legal 8.3 character.
-   * \param[in] c Character to be checked.
-   * \return true for a legal 8.3 character.
-   */
-  static bool legal83Char(uint8_t c) {
-    if (c == '"' || c == '|') {
-      return false;
-    }
-    // *+,./
-    if (0X2A <= c && c <= 0X2F && c != 0X2D) {
-      return false;
-    }
-    // :;<=>?
-    if (0X3A <= c && c <= 0X3F) {
-      return false;
-    }
-    // [\]
-    if (0X5B <= c && c <= 0X5D) {
-      return false;
-    }
-    return 0X20 < c && c < 0X7F;
-  }
   /** List directory contents.
    *
    * \param[in] pr Print stream for list.
@@ -539,6 +532,16 @@ class FatFile {
    * \return true for success or false for failure.
    */
   bool open(const char* path, oflag_t oflag = O_RDONLY);
+  /** Open existing file wih Short 8.3 names.
+   * \param[in] path with short 8.3 names.
+   *
+   * the purpose of this function is to save flash on Uno
+   * and other small boards.
+   *
+   * Directories will be opened O_RDONLY, files O_RDWR.
+   * \return true for success or false for failure.
+   */
+  bool openExistingSFN(const char* path);
   /** Open the next file or subdirectory in a directory.
    *
    * \param[in] dirFile An open FatFile instance for the directory
@@ -557,6 +560,7 @@ class FatFile {
    * \return true for success or false for failure.
    */
   bool openRoot(FatVolume* vol);
+
   /** Return the next available byte without consuming it.
    *
    * \return The byte if no error and not at eof else -1;
@@ -993,8 +997,8 @@ class FatFile {
     return seekSet(32UL*index) ? readDirCache() : nullptr;
   }
   DirFat_t* cacheDirEntry(uint8_t action);
-  bool cmpName(uint16_t index, FatName_t* fname, uint8_t lfnOrd);
-  bool createLFN(uint16_t index, FatName_t* fname, uint8_t lfnOrd);
+  bool cmpName(uint16_t index, FatLfn_t* fname, uint8_t lfnOrd);
+  bool createLFN(uint16_t index, FatLfn_t* fname, uint8_t lfnOrd);
   uint16_t getLfnChar(DirLfn_t* ldir, uint8_t i);
   uint8_t lfnChecksum(uint8_t* name) {
     uint8_t sum = 0;
@@ -1003,12 +1007,15 @@ class FatFile {
     }
     return sum;
   }
-  static bool makeSFN(FatName_t* fname);
-  bool makeUniqueSfn(FatName_t* fname);
+  static bool makeSFN(FatLfn_t* fname);
+  bool makeUniqueSfn(FatLfn_t* fname);
   bool openCluster(FatFile* file);
-  bool parsePathName(const char* str, FatName_t* fname, const char** ptr);
+  bool parsePathName(const char* str, FatLfn_t* fname, const char** ptr);
+  bool parsePathName(const char* str, FatSfn_t* fname, const char** ptr);
   bool mkdir(FatFile* parent, FatName_t* fname);
-  bool open(FatFile* dirFile, FatName_t* fname, oflag_t oflag);
+  bool open(FatFile* dirFile, FatLfn_t* fname, oflag_t oflag);
+  bool open(FatFile* dirFile, FatSfn_t* fname, oflag_t oflag);
+  bool openSFN(FatSfn_t* fname);
   bool openCachedEntry(FatFile* dirFile, uint16_t cacheIndex, oflag_t oflag,
                        uint8_t lfnOrd);
   DirFat_t* readDirCache(bool skipReadOk = false);

+ 13 - 15
src/FatLib/FatFileLFN.cpp

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License
@@ -26,8 +26,7 @@
 #include "../common/DebugMacros.h"
 #include "../common/upcase.h"
 #include "../common/FsUtf.h"
-#include "FatFile.h"
-#include "FatVolume.h"
+#include "FatLib.h"
 #if USE_LONG_FILE_NAMES
 //------------------------------------------------------------------------------
 static bool isLower(char c) {
@@ -71,7 +70,7 @@ static uint16_t Bernstein(const char* bgn, const char* end, uint16_t hash) {
   return hash;
 }
 //==============================================================================
-bool FatFile::cmpName(uint16_t index, FatName_t* fname, uint8_t lfnOrd) {
+bool FatFile::cmpName(uint16_t index, FatLfn_t* fname, uint8_t lfnOrd) {
   FatFile dir = *this;
   DirLfn_t* ldir;
   fname->reset();
@@ -109,7 +108,7 @@ bool FatFile::cmpName(uint16_t index, FatName_t* fname, uint8_t lfnOrd) {
   return false;
 }
 //------------------------------------------------------------------------------
-bool FatFile::createLFN(uint16_t index, FatName_t* fname, uint8_t lfnOrd) {
+bool FatFile::createLFN(uint16_t index, FatLfn_t* fname, uint8_t lfnOrd) {
   FatFile dir = *this;
   DirLfn_t* ldir;
   uint8_t checksum = lfnChecksum(fname->sfn);
@@ -146,7 +145,7 @@ bool FatFile::createLFN(uint16_t index, FatName_t* fname, uint8_t lfnOrd) {
   return false;
 }
 //------------------------------------------------------------------------------
-bool FatFile::makeSFN(FatName_t* fname) {
+bool FatFile::makeSFN(FatLfn_t* fname) {
   bool is83;
 //  char c;
   uint8_t c;
@@ -177,14 +176,12 @@ bool FatFile::makeSFN(FatName_t* fname) {
 
   for (; ptr < end; ptr++) {
     c = *ptr;
-//  Could skip UTF-8 units where (0XC0 & c) == 0X80
-
     if (c == '.' && ptr == dot) {
       in = 10;  // Max index for full 8.3 name.
       i = 8;    // Place for extension.
       bit = FAT_CASE_LC_EXT;  // bit for extension.
     } else {
-      if (!legal83Char(c)) {
+      if (sfnReservedChar(c)) {
         is83 = false;
         // Skip UTF-8 trailing characters.
         if ((c & 0XC0) == 0X80) {
@@ -231,7 +228,7 @@ bool FatFile::makeSFN(FatName_t* fname) {
   return false;
 }
 //------------------------------------------------------------------------------
-bool FatFile::makeUniqueSfn(FatName_t* fname) {
+bool FatFile::makeUniqueSfn(FatLfn_t* fname) {
   const uint8_t FIRST_HASH_SEQ = 2;  // min value is 2
   uint8_t pos = fname->seqPos;
   DirFat_t* dir;
@@ -287,7 +284,7 @@ bool FatFile::makeUniqueSfn(FatName_t* fname) {
   return true;
 }
 //------------------------------------------------------------------------------
-bool FatFile::open(FatFile* dirFile, FatName_t* fname, oflag_t oflag) {
+bool FatFile::open(FatFile* dirFile, FatLfn_t* fname, oflag_t oflag) {
   bool fnameFound = false;
   uint8_t lfnOrd = 0;
   uint8_t freeNeed;
@@ -302,6 +299,7 @@ bool FatFile::open(FatFile* dirFile, FatName_t* fname, oflag_t oflag) {
   uint16_t time;
   DirFat_t* dir;
   DirLfn_t* ldir;
+  auto vol = dirFile->m_vol;
 
   if (!dirFile->isDir() || isOpen()) {
     DBG_FAIL_MACRO;
@@ -312,7 +310,7 @@ bool FatFile::open(FatFile* dirFile, FatName_t* fname, oflag_t oflag) {
   freeNeed = fname->flags & FNAME_FLAG_NEED_LFN ? 1 + nameOrd : 1;
   dirFile->rewind();
   while (1) {
-    curIndex = dirFile->m_curPosition/32;
+    curIndex = dirFile->m_curPosition/FS_DIR_SIZE;
     dir = dirFile->readDirCache();
     if (!dir) {
       if (dirFile->getError()) {
@@ -415,7 +413,7 @@ bool FatFile::open(FatFile* dirFile, FatName_t* fname, oflag_t oflag) {
       DBG_FAIL_MACRO;
       goto fail;
     }
-    freeFound += dirFile->m_vol->sectorsPerCluster();
+    freeFound += vol->dirEntriesPerCluster();
   }
   if (fnameFound) {
     if (!dirFile->makeUniqueSfn(fname)) {
@@ -456,7 +454,7 @@ bool FatFile::open(FatFile* dirFile, FatName_t* fname, oflag_t oflag) {
     }
   }
   // Force write of entry to device.
-  dirFile->m_vol->cacheDirty();
+  vol->cacheDirty();
 
  open:
   // open entry in cache.
@@ -471,7 +469,7 @@ bool FatFile::open(FatFile* dirFile, FatName_t* fname, oflag_t oflag) {
 }
 //------------------------------------------------------------------------------
 bool FatFile::parsePathName(const char* path,
-                            FatName_t* fname, const char** ptr) {
+                            FatLfn_t* fname, const char** ptr) {
   size_t len = 0;
   // Skip leading spaces.
   while (*path == ' ') {

+ 3 - 52
src/FatLib/FatFilePrint.cpp

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License
@@ -25,57 +25,8 @@
 #include <math.h>
 #define DBG_FILE "FatFilePrint.cpp"
 #include "../common/DebugMacros.h"
-#include "FatFile.h"
-//------------------------------------------------------------------------------
-static void printHex(print_t* pr, uint8_t w, uint16_t h) {
-  char buf[5];
-  char* ptr = buf + sizeof(buf);
-  *--ptr = 0;
-  for (uint8_t i = 0; i < w; i++) {
-    char c = h & 0XF;
-    *--ptr = c < 10 ? c + '0' : c + 'A' - 10;
-    h >>= 4;
-  }
-  pr->write(ptr);
-}
-//------------------------------------------------------------------------------
-void FatFile::dmpFile(print_t* pr, uint32_t pos, size_t n) {
-  char text[17];
-  text[16] = 0;
-  if (n >= 0XFFF0) {
-    n = 0XFFF0;
-  }
-  if (!seekSet(pos)) {
-    return;
-  }
-  for (size_t i = 0; i <= n; i++) {
-    if ((i & 15) == 0) {
-      if (i) {
-        pr->write(' ');
-        pr->write(text);
-        if (i == n) {
-          break;
-        }
-      }
-      pr->write('\r');
-      pr->write('\n');
-      if (i >= n) {
-        break;
-      }
-      printHex(pr, 4, i);
-      pr->write(' ');
-    }
-    int16_t h = read();
-    if (h < 0) {
-      break;
-    }
-    pr->write(' ');
-    printHex(pr, 2, h);
-    text[i&15] = ' ' <= h && h < 0X7F ? h : '.';
-  }
-  pr->write('\r');
-  pr->write('\n');
-}
+#include "FatLib.h"
+
 //------------------------------------------------------------------------------
 bool FatFile::ls(print_t* pr, uint8_t flags, uint8_t indent) {
   FatFile file;

+ 92 - 20
src/FatLib/FatFileSFN.cpp

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License
@@ -24,15 +24,11 @@
  */
 #define DBG_FILE "FatFileSFN.cpp"
 #include "../common/DebugMacros.h"
-#include "../common/FsStructs.h"
-#include "FatFile.h"
-#include "FatVolume.h"
-
-#if !USE_LONG_FILE_NAMES
+#include "FatLib.h"
 //------------------------------------------------------------------------------
 // open with filename in fname
 #define SFN_OPEN_USES_CHKSUM 0
-bool FatFile::open(FatFile* dirFile, FatName_t* fname, oflag_t oflag) {
+bool FatFile::open(FatFile* dirFile, FatSfn_t* fname, oflag_t oflag) {
   uint16_t date;
   uint16_t time;
   uint8_t ms10;
@@ -47,11 +43,8 @@ bool FatFile::open(FatFile* dirFile, FatName_t* fname, oflag_t oflag) {
   DirLfn_t* ldir;
 
   dirFile->rewind();
-  while (1) {
-    if (!emptyFound) {
-      emptyIndex = index;
-    }
-    dir = reinterpret_cast<DirFat_t*>(dirFile->readDirCache(true));
+  while (true) {
+    dir = dirFile->readDirCache(true);
     if (!dir) {
       if (dirFile->getError())  {
         DBG_FAIL_MACRO;
@@ -60,13 +53,15 @@ bool FatFile::open(FatFile* dirFile, FatName_t* fname, oflag_t oflag) {
       // At EOF if no error.
       break;
     }
-    if (dir->name[0] == FAT_NAME_FREE) {
-      emptyFound = true;
-      break;
-    }
-    if (dir->name[0] == FAT_NAME_DELETED) {
+    if (dir->name[0] == FAT_NAME_FREE || dir->name[0] == FAT_NAME_FREE) {
+      if (!emptyFound) {
+        emptyIndex = index;
+        emptyFound = true;
+      }
+      if (dir->name[0] == FAT_NAME_FREE) {
+        break;
+      }
       lfnOrd = 0;
-      emptyFound = true;
     } else if (isFileOrSubdir(dir)) {
       if (!memcmp(fname->sfn, dir->name, 11)) {
         // don't open existing file if O_EXCL
@@ -152,8 +147,84 @@ bool FatFile::open(FatFile* dirFile, FatName_t* fname, oflag_t oflag) {
   return false;
 }
 //------------------------------------------------------------------------------
+bool FatFile::openExistingSFN(const char* path) {
+  FatSfn_t fname;
+  auto vol = FatVolume::cwv();
+  while (*path == '/') {
+    path++;
+  }
+  if (*path == 0) {
+    return openRoot(vol);
+  }
+  *this = *vol->vwd();
+  do {
+    if (!parsePathName(path, &fname, &path)) {
+      DBG_FAIL_MACRO;
+      goto fail;
+    }
+    if (!openSFN(&fname)) {
+      DBG_FAIL_MACRO;
+      goto fail;
+    }
+  } while (*path);
+  return true;
+
+ fail:
+  return false;
+}
+//------------------------------------------------------------------------------
+bool FatFile::openSFN(FatSfn_t* fname) {
+  DirFat_t dir;
+  DirLfn_t* ldir;
+  auto vol = m_vol;
+  uint8_t lfnOrd = 0;
+  if (!isDir()) {
+    DBG_FAIL_MACRO;
+    goto fail;
+  }
+  while (true) {
+    if (read(&dir, 32) != 32) {
+      DBG_FAIL_MACRO;
+      goto fail;
+    }
+    if (dir.name[0] == 0) {
+      DBG_FAIL_MACRO;
+      goto fail;
+    }
+    if (isFileOrSubdir(&dir) && memcmp(fname->sfn, dir.name, 11) == 0) {
+      uint16_t dirIndex = (m_curPosition - 32) >> 5;
+      uint32_t dirCluster = m_firstCluster;
+      memset(this, 0 , sizeof(FatFile));
+      m_attributes = dir.attributes & FILE_ATTR_COPY;
+      if (isFileDir(&dir)) {
+        m_attributes |= FILE_ATTR_FILE;
+      }
+      m_lfnOrd = lfnOrd;
+      m_firstCluster = (uint32_t)getLe16(dir.firstClusterHigh) << 16;
+      m_firstCluster |= getLe16(dir.firstClusterLow);
+      m_fileSize = getLe32(dir.fileSize);
+      m_flags = isFile() ? FILE_FLAG_READ | FILE_FLAG_WRITE : FILE_FLAG_READ;
+      m_vol = vol;
+      m_dirCluster = dirCluster;
+      m_dirSector = m_vol->cacheSectorNumber();
+      m_dirIndex = dirIndex;
+      return true;
+    } else if (isLongName(&dir)) {
+      ldir = reinterpret_cast<DirLfn_t*>(&dir);
+      if (ldir->order & FAT_ORDER_LAST_LONG_ENTRY) {
+        lfnOrd = ldir->order & 0X1F;
+      }
+    } else {
+      lfnOrd = 0;
+    }
+  }
+
+ fail:
+  return false;
+}
+//------------------------------------------------------------------------------
 // format directory name field from a 8.3 name string
-bool FatFile::parsePathName(const char* path, FatName_t* fname,
+bool FatFile::parsePathName(const char* path, FatSfn_t* fname,
                             const char** ptr) {
   uint8_t uc = 0;
   uint8_t lc = 0;
@@ -175,7 +246,7 @@ bool FatFile::parsePathName(const char* path, FatName_t* fname,
       // bit for extension.
       bit = FNAME_FLAG_LC_EXT;
     } else {
-      if (!legal83Char(c) || i > n) {
+      if (sfnReservedChar(c) || i > n) {
         DBG_FAIL_MACRO;
         goto fail;
       }
@@ -204,6 +275,7 @@ bool FatFile::parsePathName(const char* path, FatName_t* fname,
  fail:
   return false;
 }
+#if !USE_LONG_FILE_NAMES
 //------------------------------------------------------------------------------
 bool FatFile::remove() {
   DirFat_t* dir;

+ 2 - 2
src/FatLib/FatFormatter.cpp

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License
@@ -22,7 +22,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
-#include "FatFormatter.h"
+#include "FatLib.h"
 // Set nonzero to use calculated CHS in MBR.  Should not be required.
 #define USE_LBA_TO_CHS 1
 

+ 2 - 4
src/FatLib/FatFormatter.h

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License
@@ -24,10 +24,8 @@
  */
 #ifndef FatFormatter_h
 #define FatFormatter_h
-#include "FatFile.h"
 #include "../common/SysCall.h"
 #include "../common/BlockDevice.h"
-#include "../common/FsStructs.h"
 /**
  * \class FatFormatter
  * \brief Format a FAT volume.
@@ -59,7 +57,7 @@ class FatFormatter {
   uint32_t m_sectorCount;
   uint32_t m_totalSectors;
   BlockDevice* m_dev;
-  print_t*m_pr;
+  print_t* m_pr;
   uint8_t* m_secBuf;
   uint16_t m_reservedSectorCount;
   uint8_t m_partType;

+ 1 - 1
src/FatLib/FatLib.h

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License

+ 2 - 4
src/FatLib/FatName.cpp

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License
@@ -25,9 +25,7 @@
 #define DBG_FILE "FatName.cpp"
 #include "../common/DebugMacros.h"
 #include "../common/FsUtf.h"
-#include "FatFile.h"
-#include "FatVolume.h"
-
+#include "FatLib.h"
 //------------------------------------------------------------------------------
 uint16_t FatFile::getLfnChar(DirLfn_t* ldir, uint8_t i) {
   if (i < 5) {

+ 36 - 34
src/FatLib/FatPartition.cpp

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License
@@ -25,8 +25,7 @@
 #include <string.h>
 #define DBG_FILE "FatPartition.cpp"
 #include "../common/DebugMacros.h"
-#include "../common/FsStructs.h"
-#include "FatPartition.h"
+#include "FatLib.h"
 //------------------------------------------------------------------------------
 bool FatPartition::allocateCluster(uint32_t current, uint32_t* next) {
   uint32_t find;
@@ -158,7 +157,7 @@ bool FatPartition::allocContiguous(uint32_t count, uint32_t* firstCluster) {
 int8_t FatPartition::fatGet(uint32_t cluster, uint32_t* value) {
   uint32_t sector;
   uint32_t next;
-  cache_t* pc;
+  uint8_t* pc;
 
   // error if reserved cluster of beyond FAT
   if (cluster < 2 || cluster > m_lastCluster) {
@@ -168,44 +167,44 @@ int8_t FatPartition::fatGet(uint32_t cluster, uint32_t* value) {
 
   if (fatType() == 32) {
     sector = m_fatStartSector + (cluster >> (m_bytesPerSectorShift - 2));
-    pc = cacheFetchFat(sector, FsCache::CACHE_FOR_READ);
+    pc = fatCachePrepare(sector, FsCache::CACHE_FOR_READ);
     if (!pc) {
       DBG_FAIL_MACRO;
       goto fail;
     }
-    next = getLe32(reinterpret_cast<uint8_t*>
-                  (&pc->fat32[cluster & (m_sectorMask >> 2)]));
+    uint16_t offset = (cluster << 2) & m_sectorMask;
+    next = getLe32(pc + offset);
   } else if (fatType() == 16) {
     cluster &= 0XFFFF;
     sector = m_fatStartSector + (cluster >> (m_bytesPerSectorShift - 1) );
-    pc = cacheFetchFat(sector, FsCache::CACHE_FOR_READ);
+    pc = fatCachePrepare(sector, FsCache::CACHE_FOR_READ);
     if (!pc) {
       DBG_FAIL_MACRO;
       goto fail;
     }
-    next = getLe16(reinterpret_cast<uint8_t*>
-                  (&pc->fat16[cluster & (m_sectorMask >> 1)]));
+    uint16_t offset = (cluster << 1) & m_sectorMask;
+    next = getLe16(pc + offset);
   } else if (FAT12_SUPPORT && fatType() == 12) {
     uint16_t index = cluster;
     index += index >> 1;
     sector = m_fatStartSector + (index >> m_bytesPerSectorShift);
-    pc = cacheFetchFat(sector, FsCache::CACHE_FOR_READ);
+    pc = fatCachePrepare(sector, FsCache::CACHE_FOR_READ);
     if (!pc) {
       DBG_FAIL_MACRO;
       goto fail;
     }
     index &= m_sectorMask;
-    uint16_t tmp = pc->data[index];
+    uint16_t tmp = pc[index];
     index++;
     if (index == m_bytesPerSector) {
-      pc = cacheFetchFat(sector + 1, FsCache::CACHE_FOR_READ);
+      pc = fatCachePrepare(sector + 1, FsCache::CACHE_FOR_READ);
       if (!pc) {
         DBG_FAIL_MACRO;
         goto fail;
       }
       index = 0;
     }
-    tmp |= pc->data[index] << 8;
+    tmp |= pc[index] << 8;
     next = cluster & 1 ? tmp >> 4 : tmp & 0XFFF;
   } else {
     DBG_FAIL_MACRO;
@@ -224,7 +223,7 @@ int8_t FatPartition::fatGet(uint32_t cluster, uint32_t* value) {
 // Store a FAT entry
 bool FatPartition::fatPut(uint32_t cluster, uint32_t value) {
   uint32_t sector;
-  cache_t* pc;
+  uint8_t* pc;
 
   // error if reserved cluster of beyond FAT
   if (cluster < 2 || cluster > m_lastCluster) {
@@ -234,26 +233,26 @@ bool FatPartition::fatPut(uint32_t cluster, uint32_t value) {
 
   if (fatType() == 32) {
     sector = m_fatStartSector + (cluster >> (m_bytesPerSectorShift - 2));
-    pc = cacheFetchFat(sector, FsCache::CACHE_FOR_WRITE);
+    pc = fatCachePrepare(sector, FsCache::CACHE_FOR_WRITE);
     if (!pc) {
       DBG_FAIL_MACRO;
       goto fail;
     }
-    setLe32(reinterpret_cast<uint8_t*>
-           (&pc->fat32[cluster & (m_sectorMask >> 2)]), value);
+    uint16_t offset = (cluster << 2) & m_sectorMask;
+    setLe32(pc + offset, value);
     return true;
   }
 
   if (fatType() == 16) {
     cluster &= 0XFFFF;
     sector = m_fatStartSector + (cluster >> (m_bytesPerSectorShift - 1) );
-    pc = cacheFetchFat(sector, FsCache::CACHE_FOR_WRITE);
+    pc = fatCachePrepare(sector, FsCache::CACHE_FOR_WRITE);
     if (!pc) {
       DBG_FAIL_MACRO;
       goto fail;
     }
-    setLe16(reinterpret_cast<uint8_t*>
-           (&pc->fat16[cluster & (m_sectorMask >> 1)]), value);
+    uint16_t offset = (cluster << 1) & m_sectorMask;
+    setLe16(pc + offset, value);
     return true;
   }
 
@@ -261,7 +260,7 @@ bool FatPartition::fatPut(uint32_t cluster, uint32_t value) {
     uint16_t index = cluster;
     index += index >> 1;
     sector = m_fatStartSector + (index >> m_bytesPerSectorShift);
-    pc = cacheFetchFat(sector, FsCache::CACHE_FOR_WRITE);
+    pc = fatCachePrepare(sector, FsCache::CACHE_FOR_WRITE);
     if (!pc) {
       DBG_FAIL_MACRO;
       goto fail;
@@ -269,15 +268,15 @@ bool FatPartition::fatPut(uint32_t cluster, uint32_t value) {
     index &= m_sectorMask;
     uint8_t tmp = value;
     if (cluster & 1) {
-      tmp = (pc->data[index] & 0XF) | tmp << 4;
+      tmp = (pc[index] & 0XF) | tmp << 4;
     }
-    pc->data[index] = tmp;
+    pc[index] = tmp;
 
     index++;
     if (index == m_bytesPerSector) {
       sector++;
       index = 0;
-      pc = cacheFetchFat(sector, FsCache::CACHE_FOR_WRITE);
+      pc = fatCachePrepare(sector, FsCache::CACHE_FOR_WRITE);
       if (!pc) {
         DBG_FAIL_MACRO;
         goto fail;
@@ -285,9 +284,9 @@ bool FatPartition::fatPut(uint32_t cluster, uint32_t value) {
     }
     tmp = value >> 4;
     if (!(cluster & 1)) {
-      tmp = ((pc->data[index] & 0XF0)) | tmp >> 4;
+      tmp = ((pc[index] & 0XF0)) | tmp >> 4;
     }
-    pc->data[index] = tmp;
+    pc[index] = tmp;
     return true;
   } else {
     DBG_FAIL_MACRO;
@@ -353,7 +352,7 @@ int32_t FatPartition::freeClusterCount() {
   } else if (fatType() == 16 || fatType() == 32) {
     sector = m_fatStartSector;
     while (todo) {
-      cache_t* pc = cacheFetchFat(sector++, FsCache::CACHE_FOR_READ);
+      uint8_t* pc = fatCachePrepare(sector++, FsCache::CACHE_FOR_READ);
       if (!pc) {
         DBG_FAIL_MACRO;
         goto fail;
@@ -363,14 +362,16 @@ int32_t FatPartition::freeClusterCount() {
         n = todo;
       }
       if (fatType() == 16) {
+        uint16_t* p16 = reinterpret_cast<uint16_t*>(pc);
         for (uint16_t i = 0; i < n; i++) {
-          if (pc->fat16[i] == 0) {
+          if (p16[i] == 0) {
             free++;
           }
         }
       } else {
+        uint32_t* p32 = reinterpret_cast<uint32_t*>(pc);
         for (uint16_t i = 0; i < n; i++) {
-          if (pc->fat32[i] == 0) {
+          if (p32[i] == 0) {
             free++;
           }
         }
@@ -412,7 +413,7 @@ bool FatPartition::init(BlockDevice* dev, uint8_t part) {
       goto fail;
     }
     mbr = reinterpret_cast<MbrSector_t*>
-          (cacheFetchData(0, FsCache::CACHE_FOR_READ));
+          (dataCachePrepare(0, FsCache::CACHE_FOR_READ));
     MbrPart_t* mp = mbr->part + part - 1;
 
     if (!mbr || mp->type == 0 || (mp->boot != 0 && mp->boot != 0X80)) {
@@ -422,9 +423,10 @@ bool FatPartition::init(BlockDevice* dev, uint8_t part) {
     volumeStartSector = getLe32(mp->relativeSectors);
   }
   pbs = reinterpret_cast<pbs_t*>
-        (cacheFetchData(volumeStartSector, FsCache::CACHE_FOR_READ));
+        (dataCachePrepare(volumeStartSector, FsCache::CACHE_FOR_READ));
   bpb = reinterpret_cast<BpbFat32_t*>(pbs->bpb);
-  if (!pbs || bpb->fatCount != 2 || getLe16(bpb->bytesPerSector) != 512) {
+  if (!pbs || bpb->fatCount != 2 ||
+    getLe16(bpb->bytesPerSector) != m_bytesPerSector) {
     DBG_FAIL_MACRO;
     goto fail;
   }
@@ -452,7 +454,7 @@ bool FatPartition::init(BlockDevice* dev, uint8_t part) {
   m_rootDirStart = m_fatStartSector + 2 * m_sectorsPerFat;
   // data start for FAT16 and FAT32
   m_dataStartSector = m_rootDirStart +
-    ((32 * m_rootDirEntryCount + m_bytesPerSector - 1)/m_bytesPerSector);
+    ((FS_DIR_SIZE*m_rootDirEntryCount + m_bytesPerSector - 1)/m_bytesPerSector);
 
   // total sectors for FAT16 or FAT32
   totalSectors = getLe16(bpb->totalSectors16);

+ 19 - 34
src/FatLib/FatPartition.h

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License
@@ -43,20 +43,6 @@ const uint8_t FAT_TYPE_FAT16 = 16;
 /** Type for FAT12 partition */
 const uint8_t FAT_TYPE_FAT32 = 32;
 
-//------------------------------------------------------------------------------
-/**
- * \brief Cache type for a sector.
- */
-union cache_t {
-  /** Used to access cached file data sectors. */
-  uint8_t  data[512];
-  /** Used to access cached FAT16 entries. */
-  uint16_t fat16[256];
-  /** Used to access cached FAT32 entries. */
-  uint32_t fat32[128];
-  /** Used to access cached directory entries. */
-  DirFat_t dir[16];
-};
 //==============================================================================
 /**
  * \class FatPartition
@@ -84,6 +70,10 @@ class FatPartition {
   uint8_t bytesPerSectorShift() const {
     return m_bytesPerSectorShift;
   }
+  /** \return Number of directory entries per sector. */
+  uint16_t dirEntriesPerCluster() const {
+    return m_sectorsPerCluster*(m_bytesPerSector/FS_DIR_SIZE);
+  }
   /** \return Mask for sector offset. */
   uint16_t sectorMask() const {
     return m_sectorMask;
@@ -186,8 +176,8 @@ class FatPartition {
   friend class FatFile;
   //----------------------------------------------------------------------------
   static const uint8_t  m_bytesPerSectorShift = 9;
-  static const uint16_t m_bytesPerSector = 512;
-  static const uint16_t m_sectorMask = 0x1FF;
+  static const uint16_t m_bytesPerSector = 1 << m_bytesPerSectorShift;
+  static const uint16_t m_sectorMask = m_bytesPerSector - 1;
   //----------------------------------------------------------------------------
   BlockDevice* m_blockDev;            // sector device
   uint8_t  m_sectorsPerCluster;       // Cluster size in sectors.
@@ -215,15 +205,9 @@ class FatPartition {
   bool cacheSafeWrite(uint32_t sector, const uint8_t* dst, size_t count) {
     return m_cache.cacheSafeWrite(sector, dst, count);
   }
-  bool readSector(uint32_t sector, uint8_t* dst) {
-    return m_blockDev->readSector(sector, dst);
-  }
   bool syncDevice() {
     return m_blockDev->syncDevice();
   }
-  bool writeSector(uint32_t sector, const uint8_t* src) {
-    return m_blockDev->writeSector(sector, src);
-  }
 #if MAINTAIN_FREE_CLUSTER_COUNT
   int32_t  m_freeClusterCount;     // Count of free clusters in volume.
   void setFreeClusterCount(int32_t value) {
@@ -244,26 +228,30 @@ class FatPartition {
 #endif  // MAINTAIN_FREE_CLUSTER_COUNT
 // sector caches
   FsCache m_cache;
+  bool cachePrepare(uint32_t sector, uint8_t option) {
+    return m_cache.prepare(sector, option);
+  }
+  FsCache* dataCache() {return &m_cache;}
 #if USE_SEPARATE_FAT_CACHE
   FsCache m_fatCache;
-  cache_t* cacheFetchFat(uint32_t sector, uint8_t options) {
+  uint8_t* fatCachePrepare(uint32_t sector, uint8_t options) {
     options |= FsCache::CACHE_STATUS_MIRROR_FAT;
-    return reinterpret_cast<cache_t*>(m_fatCache.get(sector, options));
+    return m_fatCache.prepare(sector, options);
   }
   bool cacheSync() {
     return m_cache.sync() && m_fatCache.sync() && syncDevice();
   }
 #else  // USE_SEPARATE_FAT_CACHE
-  cache_t* cacheFetchFat(uint32_t sector, uint8_t options) {
+  uint8_t* fatCachePrepare(uint32_t sector, uint8_t options) {
     options |= FsCache::CACHE_STATUS_MIRROR_FAT;
-    return cacheFetchData(sector, options);
+    return dataCachePrepare(sector, options);
   }
   bool cacheSync() {
     return m_cache.sync() && syncDevice();
   }
 #endif  // USE_SEPARATE_FAT_CACHE
-  cache_t* cacheFetchData(uint32_t sector, uint8_t options) {
-    return reinterpret_cast<cache_t*>(m_cache.get(sector, options));
+  uint8_t* dataCachePrepare(uint32_t sector, uint8_t options) {
+    return m_cache.prepare(sector, options);
   }
   void cacheInvalidate() {
     m_cache.invalidate();
@@ -271,8 +259,8 @@ class FatPartition {
   bool cacheSyncData() {
     return m_cache.sync();
   }
-  cache_t* cacheAddress() {
-    return reinterpret_cast<cache_t*>(m_cache.cacheBuffer());
+  uint8_t* cacheAddress() {
+    return m_cache.cacheBuffer();
   }
   uint32_t cacheSectorNumber() {
     return m_cache.sector();
@@ -299,7 +287,4 @@ class FatPartition {
     return cluster > m_lastCluster;
   }
 };
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-bool printFatDir(print_t* pr, DirFat_t* dir);
-#endif  // DOXYGEN_SHOULD_SKIP_THIS
 #endif  // FatPartition

+ 2 - 2
src/FatLib/FatVolume.cpp

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License
@@ -24,7 +24,7 @@
  */
 #define DBG_FILE "FatVolume.cpp"
 #include "../common/DebugMacros.h"
-#include "FatVolume.h"
+#include "FatLib.h"
 FatVolume* FatVolume::m_cwv = nullptr;
 //------------------------------------------------------------------------------
 bool FatVolume::chdir(const char *path) {

+ 1 - 2
src/FatLib/FatVolume.h

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License
@@ -24,7 +24,6 @@
  */
 #ifndef FatVolume_h
 #define FatVolume_h
-#include "FatPartition.h"
 #include "FatFile.h"
 /**
  * \file

+ 2 - 2
src/FreeStack.cpp

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License
@@ -39,7 +39,7 @@ inline char* stackBegin() {
 }
 //------------------------------------------------------------------------------
 inline char* stackPointer() {
-#if  defined(__AVR__)
+#if defined(__AVR__)
   return reinterpret_cast<char*>(SP);
 #elif defined(__arm__)
   register uint32_t sp asm("sp");

+ 1 - 1
src/FreeStack.h

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License

+ 1 - 1
src/FsLib/FsFile.cpp

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2011-2020 Bill Greiman
+ * Copyright (c) 2011-2021 Bill Greiman
  * This file is part of the SdFat library for SD memory cards.
  *
  * MIT License

部分文件因为文件数量过多而无法显示