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.
This commit is contained in:
Bill Greiman 2021-10-31 07:11:21 -07:00
parent a5e4bdeb76
commit fb7415151b
168 changed files with 1497 additions and 1659 deletions

View file

@ -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>

File diff suppressed because it is too large Load diff

Binary file not shown.

View file

@ -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.

View file

@ -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();

View file

@ -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.

View file

@ -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();

View file

@ -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() {
}

View file

@ -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.

View file

@ -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();
}
}

View file

@ -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() {}

View file

@ -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;

View file

@ -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)) {

View file

@ -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)) {

View file

@ -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) {

View file

@ -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() {}

View file

@ -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;

View file

@ -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) {}
}

View file

@ -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");

View file

@ -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);

View file

@ -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

View file

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

View file

@ -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;

View file

@ -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)) {

View file

@ -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

View file

@ -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

View file

@ -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();
}

View file

@ -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);

View file

@ -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();
}
}
//------------------------------------------------------------------------------

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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) {

View file

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

View file

@ -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';

View file

@ -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());

View file

@ -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());

View file

@ -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();
}

View file

@ -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());

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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();
}
}

View file

@ -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();

View file

@ -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);

View file

@ -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.

View file

@ -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

View file

@ -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);

View file

@ -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");

View file

@ -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();

View file

@ -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());
}

View file

@ -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;

View file

@ -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();
}

View file

@ -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.

View file

@ -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);

View file

@ -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.

View file

@ -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;

View file

@ -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) {}
}
}

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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).

View file

@ -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.");
}

View file

@ -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

View file

@ -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)

View file

@ -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>

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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.

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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

View file

@ -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) {

View file

@ -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"
//==============================================================================
/**

View file

@ -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();

View file

@ -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.

View file

@ -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 {
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];
};
/**
* \class FatSfn_t
* \brief Internal type for Short 8.3 File Name - do not use in user apps.
*/
class FatSfn_t {
public:
/** 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);

View file

@ -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 == ' ') {

View file

@ -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;

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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) {

View file

@ -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);

View file

@ -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

View file

@ -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) {

View file

@ -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

View file

@ -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");

View file

@ -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

View file

@ -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

Some files were not shown because too many files have changed in this diff Show more