Here are some test results that show advantages of using exFAT.
The huge variation in write times for FAT16/FAT32 make writing simple data loggers that run at over about 5-10 samples per second difficult.
exFAT can improve the situation a great deal by pre-allocating a file. You can then check if an SD is busy to insure one sector will be written in less than a known time.
Here is a loop from a test program that I attached.
Code:
while (file.size() < FILE_SIZE) {
if (waitBusy) {
while (sd.card()->isBusy()) {}
}
uint32_t m = micros();
if (file.write(buf, sizeof(buf)) != sizeof(buf)) {
error("write failed");
}
m = micros() - m;
if (m < minMicros) {
minMicros = m;
}
if (m > maxMicros) {
maxMicros = m;
}
}
I ran this program on a Teensy 3.6 board using the built-in SD with SPI and a quality Samsung microSD formatted exFAT.
I used SPI since errata with SDHC prevent valid busy tests in SDIO mode. See below for SDIO timing with exFAT.
I pre-allocated a 100 MiB file.
Here is the result with waitBusy true.
Code:
Starting write of 100 MiB.
minMicros: 157
maxMicros: 161
32.79 Seconds
3197.85 KB/sec
So the variation in write time is only about four micros if the card is not busy.
If I run it with waitBusy false, I typically get something like this.
Code:
Starting write of 100 MiB.
minMicros: 158
maxMicros: 1524
32.61 Seconds
3215.90 KB/sec
This means you can allocate a small sized FIFO, read data from sensors into the FIFO at the beginning of a loop and if the SD is not busy, write up to 512 bytes to the card.
I wrote an exFAT based logger and ran it on Teensy 3.6. I attached the program and it is an example in the above library. See the logData() function.
I am reading four ADC values every 200 microseconds. That’s a total of 20,000 ADC values/sec.
Here is the output from the logger. Each FIFO entry is eight bytes and holds four ADC values.
Code:
FreeStack: 254992
1024 FIFO entries will be used.
ExFatLogger00.bin
preAllocated: 1024 MiB
FreeStack: 246792
Type any character to stop
Log time: 1213.68 Seconds
File size: 48547800 bytes
totalOverrun: 0
maxFifoCount: 4
maxLogMicros: 30
maxWriteMicros: 162
Log interval: 200 micros
maxDelta: 1 micros
The max time to read the four ADC values was 30 microseconds and the maximum time to write the SD was 162 microseconds so it is is just possible to do every 200 microseconds. Only four FIFO entries were used. The jitter in start time for reading the ADCs is about one microsecond.
You could log data reliability at much higher rates if an interrupt routine was used to put data into the FIFO.
Here are results for pre-allocated files and SDIO using the above test with waitBusy false.
Code:
SDIO with a quality Samsung card.
Starting write of 1024 MiB.
minMicros: 26
maxMicros: 8700
57.10 Seconds
18803.93 KB/sec
Starting write of 1024 MiB.
minMicros: 26
maxMicros: 5696
57.07 Seconds
18815.13 KB/sec
Starting write of 1024 MiB.
minMicros: 26
maxMicros: 8343
57.08 Seconds
18809.86 KB/sec
Starting write of 1024 MiB.
minMicros: 26
maxMicros: 8243
57.06 Seconds
18817.44 KB/sec
You should be able to reliably log data at over 10MB/sec with a large FIFO and SDIO. It would be possible to provide over 20 ms of FIFO on Teensy 3.6 at 10 MB/sec.
I plan to do more tests with SDIO and see if any optimization is possible. Too bad the SDHC controller has so many errata.