Replace ESP8266SdFat w/SdFat 2.3.0, SDIO, ExFAT (#2764)

* Replace ESP8266SdFat w/SdFat 2.3.0, add SDIO and ExFAT support

Remove ESP8266SdFat fork and replaces with upstream SdFat to simplify
maintenance.

This 2.3.0 version adds SDIO support and enables exFAT support.
Also upgraded FAT filename support to 256 chars, identical to  LittleFS.

* Add SDIO support to SD and SDFS, documentation, and examples

* Update SD examples to all support SPI0, SPI1, or SDIO
This commit is contained in:
Earle F. Philhower, III 2025-01-17 15:22:39 -08:00 committed by GitHub
parent 4785c16243
commit 452ef17174
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 246 additions and 85 deletions

6
.gitmodules vendored
View file

@ -10,9 +10,6 @@
[submodule "libraries/LittleFS/lib/littlefs"] [submodule "libraries/LittleFS/lib/littlefs"]
path = libraries/LittleFS/lib/littlefs path = libraries/LittleFS/lib/littlefs
url = https://github.com/littlefs-project/littlefs.git url = https://github.com/littlefs-project/littlefs.git
[submodule "libraries/SdFat"]
path = libraries/ESP8266SdFat
url = https://github.com/earlephilhower/ESP8266SdFat.git
[submodule "libraries/Keyboard"] [submodule "libraries/Keyboard"]
path = libraries/HID_Keyboard path = libraries/HID_Keyboard
url = https://github.com/earlephilhower/Keyboard.git url = https://github.com/earlephilhower/Keyboard.git
@ -49,3 +46,6 @@
[submodule "libraries/ESPHost"] [submodule "libraries/ESPHost"]
path = libraries/ESPHost path = libraries/ESPHost
url = https://github.com/Networking-for-Arduino/ESPHost.git url = https://github.com/Networking-for-Arduino/ESPHost.git
[submodule "libraries/SdFat"]
path = libraries/SdFat
url = https://github.com/greiman/SdFat.git

View file

@ -174,6 +174,23 @@ second SPI port, ``SPI1``. Just use the following call in place of
SD.begin(cspin, SPI1); SD.begin(cspin, SPI1);
Enabling SDIO operation for SD
------------------------------
SDIO support is available thanks to SdFat implementing a PIO-based SDIO controller.
This mode can significantly increase IO performance to SD cards but it requires that
all 4 DAT0..DAT3 lines to be wired to the Pico (most SD breakout boards only provide
1-but SPI mode of operation).
To enable SDIO mode, simply specify the SD_CLK, SD_CMD, and SD_DAT0 GPIO pins. The clock
and command pins can be any GPIO (not limited to legal SPI pins). The DAT0 pin can be any
GPIO with remaining DAT1...3 pins consecutively connected.
..code:: cpp
SD.begin(RP_CLK_GPIO, RP_CMD_GPIO, RP_DAT0_GPIO);
No other changes are required in the application to take advantage of this high
performance mode.
Using VFS (Virtual File System) for POSIX support Using VFS (Virtual File System) for POSIX support
------------------------------------------------- -------------------------------------------------

@ -1 +0,0 @@
Subproject commit 9e1457101ca47b9ace198086dbd8854efc573ccf

View file

@ -37,6 +37,11 @@ const int _MOSI = 7; // AKA SPI TX
const int _CS = 5; const int _CS = 5;
const int _SCK = 6; const int _SCK = 6;
// If you have all 4 DAT pins wired up to the Pico you can use SDIO mode
const int RP_CLK_GPIO = -1; // Set to CLK GPIO
const int RP_CMD_GPIO = -1; // Set to CMD GPIO
const int RP_DAT0_GPIO = -1; // Set to DAT0 GPIO. DAT1..3 must be consecutively connected.
// include the SD library: // include the SD library:
#include <SPI.h> #include <SPI.h>
#include <SD.h> #include <SD.h>
@ -54,21 +59,26 @@ void setup() {
Serial.println("\nInitializing SD card..."); Serial.println("\nInitializing SD card...");
bool sdInitialized = false; bool sdInitialized = false;
// Ensure the SPI pinout the SD card is connected to is configured properly if (RP_CLK_GPIO >= 0) {
// Select the correct SPI based on _MISO pin for the RP2040 // No special requirements on pin locations, this is PIO programmed
if (_MISO == 0 || _MISO == 4 || _MISO == 16) { sdInitialized = SD.begin(RP_CLK_GPIO, RP_CMD_GPIO, RP_DAT0_GPIO);
SPI.setRX(_MISO);
SPI.setTX(_MOSI);
SPI.setSCK(_SCK);
sdInitialized = SD.begin(_CS);
} else if (_MISO == 8 || _MISO == 12) {
SPI1.setRX(_MISO);
SPI1.setTX(_MOSI);
SPI1.setSCK(_SCK);
sdInitialized = SD.begin(_CS, SPI1);
} else { } else {
Serial.println(F("ERROR: Unknown SPI Configuration")); // Ensure the SPI pinout the SD card is connected to is configured properly
return; // Select the correct SPI based on _MISO pin for the RP2040
if (_MISO == 0 || _MISO == 4 || _MISO == 16) {
SPI.setRX(_MISO);
SPI.setTX(_MOSI);
SPI.setSCK(_SCK);
sdInitialized = SD.begin(_CS);
} else if (_MISO == 8 || _MISO == 12) {
SPI1.setRX(_MISO);
SPI1.setTX(_MOSI);
SPI1.setSCK(_SCK);
sdInitialized = SD.begin(_CS, SPI1);
} else {
Serial.println(F("ERROR: Unknown SPI Configuration"));
return;
}
} }
if (!sdInitialized) { if (!sdInitialized) {
@ -114,7 +124,7 @@ void setup() {
Serial.println(); Serial.println();
// print the type and size of the first FAT-type volume // print the type and size of the first FAT-type volume
uint32_t volumesize; uint64_t volumesize;
Serial.print("Volume type is: FAT"); Serial.print("Volume type is: FAT");
Serial.println(SD.fatType(), DEC); Serial.println(SD.fatType(), DEC);
@ -130,7 +140,7 @@ void setup() {
Serial.println((float)volumesize / 1024.0); Serial.println((float)volumesize / 1024.0);
Serial.print("Card size: "); Serial.print("Card size: ");
Serial.println((float)SD.size() / 1000); Serial.println((float)SD.size64() / 1000);
FSInfo fs_info; FSInfo fs_info;
SDFS.info(fs_info); SDFS.info(fs_info);

View file

@ -30,6 +30,11 @@ const int _MOSI = 7;
const int _CS = 5; const int _CS = 5;
const int _SCK = 6; const int _SCK = 6;
// If you have all 4 DAT pins wired up to the Pico you can use SDIO mode
const int RP_CLK_GPIO = -1; // Set to CLK GPIO
const int RP_CMD_GPIO = -1; // Set to CMD GPIO
const int RP_DAT0_GPIO = -1; // Set to DAT0 GPIO. DAT1..3 must be consecutively connected.
#include <SPI.h> #include <SPI.h>
#include <SD.h> #include <SD.h>
@ -39,13 +44,31 @@ void setup() {
Serial.print("Initializing SD card..."); Serial.print("Initializing SD card...");
// Ensure the SPI pinout the SD card is connected to is configured properly bool sdInitialized = false;
SPI.setRX(_MISO); if (RP_CLK_GPIO >= 0) {
SPI.setTX(_MOSI); // No special requirements on pin locations, this is PIO programmed
SPI.setSCK(_SCK); sdInitialized = SD.begin(RP_CLK_GPIO, RP_CMD_GPIO, RP_DAT0_GPIO);
} else {
// Ensure the SPI pinout the SD card is connected to is configured properly
// Select the correct SPI based on _MISO pin for the RP2040
if (_MISO == 0 || _MISO == 4 || _MISO == 16) {
SPI.setRX(_MISO);
SPI.setTX(_MOSI);
SPI.setSCK(_SCK);
sdInitialized = SD.begin(_CS);
} else if (_MISO == 8 || _MISO == 12) {
SPI1.setRX(_MISO);
SPI1.setTX(_MOSI);
SPI1.setSCK(_SCK);
sdInitialized = SD.begin(_CS, SPI1);
} else {
Serial.println(F("ERROR: Unknown SPI Configuration"));
return;
}
}
// see if the card is present and can be initialized: // see if the card is present and can be initialized:
if (!SD.begin(_CS)) { if (!sdInitialized) {
Serial.println("Card failed, or not present"); Serial.println("Card failed, or not present");
// don't do anything more: // don't do anything more:
return; return;

View file

@ -30,6 +30,11 @@ const int _MOSI = 7;
const int _CS = 5; const int _CS = 5;
const int _SCK = 6; const int _SCK = 6;
// If you have all 4 DAT pins wired up to the Pico you can use SDIO mode
const int RP_CLK_GPIO = -1; // Set to CLK GPIO
const int RP_CMD_GPIO = -1; // Set to CMD GPIO
const int RP_DAT0_GPIO = -1; // Set to DAT0 GPIO. DAT1..3 must be consecutively connected.
#include <SPI.h> #include <SPI.h>
#include <SD.h> #include <SD.h>
@ -39,13 +44,31 @@ void setup() {
Serial.print("Initializing SD card..."); Serial.print("Initializing SD card...");
// Ensure the SPI pinout the SD card is connected to is configured properly bool sdInitialized = false;
SPI.setRX(_MISO); if (RP_CLK_GPIO >= 0) {
SPI.setTX(_MOSI); // No special requirements on pin locations, this is PIO programmed
SPI.setSCK(_SCK); sdInitialized = SD.begin(RP_CLK_GPIO, RP_CMD_GPIO, RP_DAT0_GPIO);
} else {
// Ensure the SPI pinout the SD card is connected to is configured properly
// Select the correct SPI based on _MISO pin for the RP2040
if (_MISO == 0 || _MISO == 4 || _MISO == 16) {
SPI.setRX(_MISO);
SPI.setTX(_MOSI);
SPI.setSCK(_SCK);
sdInitialized = SD.begin(_CS);
} else if (_MISO == 8 || _MISO == 12) {
SPI1.setRX(_MISO);
SPI1.setTX(_MOSI);
SPI1.setSCK(_SCK);
sdInitialized = SD.begin(_CS, SPI1);
} else {
Serial.println(F("ERROR: Unknown SPI Configuration"));
return;
}
}
// see if the card is present and can be initialized: // see if the card is present and can be initialized:
if (!SD.begin(_CS)) { if (!sdInitialized) {
Serial.println("Card failed, or not present"); Serial.println("Card failed, or not present");
// don't do anything more: // don't do anything more:
return; return;

View file

@ -28,6 +28,11 @@ const int _MOSI = 7;
const int _CS = 5; const int _CS = 5;
const int _SCK = 6; const int _SCK = 6;
// If you have all 4 DAT pins wired up to the Pico you can use SDIO mode
const int RP_CLK_GPIO = -1; // Set to CLK GPIO
const int RP_CMD_GPIO = -1; // Set to CMD GPIO
const int RP_DAT0_GPIO = -1; // Set to DAT0 GPIO. DAT1..3 must be consecutively connected.
#include <SPI.h> #include <SPI.h>
#include <SD.h> #include <SD.h>
@ -39,12 +44,30 @@ void setup() {
Serial.print("Initializing SD card..."); Serial.print("Initializing SD card...");
// Ensure the SPI pinout the SD card is connected to is configured properly bool sdInitialized = false;
SPI.setRX(_MISO); if (RP_CLK_GPIO >= 0) {
SPI.setTX(_MOSI); // No special requirements on pin locations, this is PIO programmed
SPI.setSCK(_SCK); sdInitialized = SD.begin(RP_CLK_GPIO, RP_CMD_GPIO, RP_DAT0_GPIO);
} else {
// Ensure the SPI pinout the SD card is connected to is configured properly
// Select the correct SPI based on _MISO pin for the RP2040
if (_MISO == 0 || _MISO == 4 || _MISO == 16) {
SPI.setRX(_MISO);
SPI.setTX(_MOSI);
SPI.setSCK(_SCK);
sdInitialized = SD.begin(_CS);
} else if (_MISO == 8 || _MISO == 12) {
SPI1.setRX(_MISO);
SPI1.setTX(_MOSI);
SPI1.setSCK(_SCK);
sdInitialized = SD.begin(_CS, SPI1);
} else {
Serial.println(F("ERROR: Unknown SPI Configuration"));
return;
}
}
if (!SD.begin(_CS)) { if (!sdInitialized) {
Serial.println("initialization failed!"); Serial.println("initialization failed!");
return; return;
} }

View file

@ -28,6 +28,11 @@ const int _MOSI = 7;
const int _CS = 5; const int _CS = 5;
const int _SCK = 6; const int _SCK = 6;
// If you have all 4 DAT pins wired up to the Pico you can use SDIO mode
const int RP_CLK_GPIO = -1; // Set to CLK GPIO
const int RP_CMD_GPIO = -1; // Set to CMD GPIO
const int RP_DAT0_GPIO = -1; // Set to DAT0 GPIO. DAT1..3 must be consecutively connected.
#include <SPI.h> #include <SPI.h>
#include <SD.h> #include <SD.h>
@ -39,12 +44,30 @@ void setup() {
Serial.print("Initializing SD card..."); Serial.print("Initializing SD card...");
// Ensure the SPI pinout the SD card is connected to is configured properly bool sdInitialized = false;
SPI.setRX(_MISO); if (RP_CLK_GPIO >= 0) {
SPI.setTX(_MOSI); // No special requirements on pin locations, this is PIO programmed
SPI.setSCK(_SCK); sdInitialized = SD.begin(RP_CLK_GPIO, RP_CMD_GPIO, RP_DAT0_GPIO);
} else {
// Ensure the SPI pinout the SD card is connected to is configured properly
// Select the correct SPI based on _MISO pin for the RP2040
if (_MISO == 0 || _MISO == 4 || _MISO == 16) {
SPI.setRX(_MISO);
SPI.setTX(_MOSI);
SPI.setSCK(_SCK);
sdInitialized = SD.begin(_CS);
} else if (_MISO == 8 || _MISO == 12) {
SPI1.setRX(_MISO);
SPI1.setTX(_MOSI);
SPI1.setSCK(_SCK);
sdInitialized = SD.begin(_CS, SPI1);
} else {
Serial.println(F("ERROR: Unknown SPI Configuration"));
return;
}
}
if (!SD.begin(_CS)) { if (!sdInitialized) {
Serial.println("initialization failed!"); Serial.println("initialization failed!");
return; return;
} }

View file

@ -42,6 +42,11 @@ const int _MOSI = 7; // AKA SPI TX
const int _CS = 5; const int _CS = 5;
const int _SCK = 6; const int _SCK = 6;
// If you have all 4 DAT pins wired up to the Pico you can use SDIO mode
const int RP_CLK_GPIO = -1; // Set to CLK GPIO
const int RP_CMD_GPIO = -1; // Set to CMD GPIO
const int RP_DAT0_GPIO = -1; // Set to DAT0 GPIO. DAT1..3 must be consecutively connected.
#include <SPI.h> #include <SPI.h>
#include <SD.h> #include <SD.h>
@ -58,21 +63,26 @@ void setup() {
Serial.println("\nInitializing SD card..."); Serial.println("\nInitializing SD card...");
bool sdInitialized = false; bool sdInitialized = false;
// Ensure the SPI pinout the SD card is connected to is configured properly if (RP_CLK_GPIO >= 0) {
// Select the correct SPI based on _MISO pin for the RP2040 // No special requirements on pin locations, this is PIO programmed
if (_MISO == 0 || _MISO == 4 || _MISO == 16) { sdInitialized = SD.begin(RP_CLK_GPIO, RP_CMD_GPIO, RP_DAT0_GPIO);
SPI.setRX(_MISO);
SPI.setTX(_MOSI);
SPI.setSCK(_SCK);
sdInitialized = SD.begin(_CS);
} else if (_MISO == 8 || _MISO == 12) {
SPI1.setRX(_MISO);
SPI1.setTX(_MOSI);
SPI1.setSCK(_SCK);
sdInitialized = SD.begin(_CS, SPI1);
} else { } else {
Serial.println(F("ERROR: Unknown SPI Configuration")); // Ensure the SPI pinout the SD card is connected to is configured properly
return; // Select the correct SPI based on _MISO pin for the RP2040
if (_MISO == 0 || _MISO == 4 || _MISO == 16) {
SPI.setRX(_MISO);
SPI.setTX(_MOSI);
SPI.setSCK(_SCK);
sdInitialized = SD.begin(_CS);
} else if (_MISO == 8 || _MISO == 12) {
SPI1.setRX(_MISO);
SPI1.setTX(_MOSI);
SPI1.setSCK(_SCK);
sdInitialized = SD.begin(_CS, SPI1);
} else {
Serial.println(F("ERROR: Unknown SPI Configuration"));
return;
}
} }
if (!sdInitialized) { if (!sdInitialized) {

View file

@ -36,11 +36,17 @@ public:
SDFS.setConfig(SDFSConfig(csPin, SPI_HALF_SPEED, spi)); SDFS.setConfig(SDFSConfig(csPin, SPI_HALF_SPEED, spi));
return SDFS.begin(); return SDFS.begin();
} }
bool begin(uint8_t csPin, uint32_t cfg = SPI_HALF_SPEED, HardwareSPI &spi = SPI) { bool begin(uint8_t csPin, uint32_t cfg = SPI_HALF_SPEED, HardwareSPI &spi = SPI) {
SDFS.setConfig(SDFSConfig(csPin, cfg, spi)); SDFS.setConfig(SDFSConfig(csPin, cfg, spi));
return SDFS.begin(); return SDFS.begin();
} }
bool begin(uint8_t clkPin, uint8_t cmdPin, uint8_t dat0Pin, uint32_t cfg = SD_SCK_MHZ(50)) {
SDFS.setConfig(SDFSConfig(clkPin, cmdPin, dat0Pin, cfg));
return SDFS.begin();
}
void end(bool endSPI = true) { void end(bool endSPI = true) {
SDFS.end(); SDFS.end();
if (endSPI && _spi) { if (endSPI && _spi) {

View file

@ -63,13 +63,13 @@ FileImplPtr SDFSImpl::open(const char* path, OpenMode openMode, AccessMode acces
} }
free(pathStr); free(pathStr);
} }
File32 fd = _fs.open(path, flags); FsFile fd = _fs.open(path, flags);
if (!fd) { if (!fd) {
DEBUGV("SDFSImpl::openFile: fd=%p path=`%s` openMode=%d accessMode=%d", DEBUGV("SDFSImpl::openFile: fd=%p path=`%s` openMode=%d accessMode=%d",
&fd, path, openMode, accessMode); &fd, path, openMode, accessMode);
return FileImplPtr(); return FileImplPtr();
} }
auto sharedFd = std::make_shared<File32>(fd); auto sharedFd = std::make_shared<FsFile>(fd);
return std::make_shared<SDFSFileImpl>(this, sharedFd, path); return std::make_shared<SDFSFileImpl>(this, sharedFd, path);
} }
@ -88,7 +88,7 @@ DirImplPtr SDFSImpl::openDir(const char* path) {
} }
// At this point we have a name of "/blah/blah/blah" or "blah" or "" // At this point we have a name of "/blah/blah/blah" or "blah" or ""
// If that references a directory, just open it and we're done. // If that references a directory, just open it and we're done.
File32 dirFile; FsFile dirFile;
const char *filter = ""; const char *filter = "";
if (!pathStr[0]) { if (!pathStr[0]) {
// openDir("") === openDir("/") // openDir("") === openDir("/")
@ -133,7 +133,7 @@ DirImplPtr SDFSImpl::openDir(const char* path) {
DEBUGV("SDFSImpl::openDir: path=`%s`\n", path); DEBUGV("SDFSImpl::openDir: path=`%s`\n", path);
return DirImplPtr(); return DirImplPtr();
} }
auto sharedDir = std::make_shared<File32>(dirFile); auto sharedDir = std::make_shared<FsFile>(dirFile);
auto ret = std::make_shared<SDFSDirImpl>(filter, this, sharedDir, pathStr); auto ret = std::make_shared<SDFSDirImpl>(filter, this, sharedDir, pathStr);
free(pathStr); free(pathStr);
return ret; return ret;

View file

@ -45,7 +45,8 @@ class SDFSConfig : public FSConfig {
public: public:
static constexpr uint32_t FSId = 0x53444653; static constexpr uint32_t FSId = 0x53444653;
SDFSConfig(uint8_t csPin = 4, uint32_t spi = SD_SCK_MHZ(10), HardwareSPI &port = SPI) : FSConfig(FSId, false), _csPin(csPin), _part(0), _spiSettings(spi), _spi(&port) { } SDFSConfig(uint8_t csPin = 4, uint32_t spi = SD_SCK_MHZ(10), HardwareSPI &port = SPI) : FSConfig(FSId, false), _sdio(false), _clkPin(255), _csPin(csPin), _cmdPin(255), _dat0Pin(255), _part(0), _spiSettings(spi), _spi(&port) { }
SDFSConfig(uint8_t clkPin, uint8_t cmdPin, uint8_t dataPin, uint32_t spi = SD_SCK_MHZ(10)) : FSConfig(FSId, false), _sdio(true), _clkPin(clkPin), _cmdPin(cmdPin), _dat0Pin(dataPin), _part(0), _spiSettings(spi), _spi(nullptr) { }
SDFSConfig setAutoFormat(bool val = true) { SDFSConfig setAutoFormat(bool val = true) {
_autoFormat = val; _autoFormat = val;
@ -69,7 +70,11 @@ public:
} }
// Inherit _type and _autoFormat // Inherit _type and _autoFormat
bool _sdio;
uint8_t _clkPin; // SDIO only;
uint8_t _csPin; uint8_t _csPin;
uint8_t _cmdPin; // SDIO only
uint8_t _dat0Pin; // SDIO only
uint8_t _part; uint8_t _part;
uint32_t _spiSettings; uint32_t _spiSettings;
HardwareSPI *_spi; HardwareSPI *_spi;
@ -131,11 +136,20 @@ public:
if (_mounted) { if (_mounted) {
return true; return true;
} }
SdSpiConfig ssc(_cfg._csPin, SHARED_SPI, _cfg._spiSettings, _cfg._spi); if (!_cfg._sdio) {
_mounted = _fs.begin(ssc); SdSpiConfig ssc(_cfg._csPin, SHARED_SPI, _cfg._spiSettings, _cfg._spi);
if (!_mounted && _cfg._autoFormat) {
format();
_mounted = _fs.begin(ssc); _mounted = _fs.begin(ssc);
if (!_mounted && _cfg._autoFormat) {
format();
_mounted = _fs.begin(ssc);
}
} else {
SdioConfig ssc(_cfg._clkPin, _cfg._cmdPin, _cfg._dat0Pin);
_mounted = _fs.begin(ssc);
if (!_mounted && _cfg._autoFormat) {
format();
_mounted = _fs.begin(ssc);
}
} }
FsDateTime::setCallback(dateTimeCB); FsDateTime::setCallback(dateTimeCB);
return _mounted; return _mounted;
@ -153,8 +167,7 @@ public:
return false; return false;
} }
bzero(st, sizeof(*st)); bzero(st, sizeof(*st));
File32 f; FsFile f = _fs.open(path, O_RDONLY);
f = _fs.open(path, O_RDONLY);
if (!f) { if (!f) {
return false; return false;
} }
@ -169,8 +182,8 @@ public:
if (f.getCreateDateTime(&date, &time)) { if (f.getCreateDateTime(&date, &time)) {
st->ctime = FatToTimeT(date, time); st->ctime = FatToTimeT(date, time);
} }
if (f.getAccessDate(&date)) { if (f.getAccessDateTime(&date, &time)) {
st->atime = FatToTimeT(date, 0); st->atime = FatToTimeT(date, time);
} }
f.close(); f.close();
return true; return true;
@ -272,7 +285,7 @@ protected:
class SDFSFileImpl : public FileImpl { class SDFSFileImpl : public FileImpl {
public: public:
SDFSFileImpl(SDFSImpl *fs, std::shared_ptr<File32> fd, const char *name) SDFSFileImpl(SDFSImpl *fs, std::shared_ptr<FsFile> fd, const char *name)
: _fs(fs), _fd(fd), _opened(true) { : _fs(fs), _fd(fd), _opened(true) {
_name = std::shared_ptr<char>(new char[strlen(name) + 1], std::default_delete<char[]>()); _name = std::shared_ptr<char>(new char[strlen(name) + 1], std::default_delete<char[]>());
strcpy(_name.get(), name); strcpy(_name.get(), name);
@ -284,7 +297,7 @@ public:
} }
int availableForWrite() override { int availableForWrite() override {
return _opened ? _fd->availableSpaceForWrite() : 0; return _opened ? _fd->availableForWrite() : 0;
} }
size_t write(const uint8_t *buf, size_t size) override { size_t write(const uint8_t *buf, size_t size) override {
@ -373,9 +386,9 @@ public:
time_t getLastWrite() override { time_t getLastWrite() override {
time_t ftime = 0; time_t ftime = 0;
if (_opened && _fd) { if (_opened && _fd) {
DirFat_t tmp; uint16_t date, time;
if (_fd.get()->dirEntry(&tmp)) { if (_fd.get()->getModifyDateTime(&date, &time)) {
ftime = SDFSImpl::FatToTimeT(*(uint16_t*)tmp.modifyDate, *(uint16_t*)tmp.modifyTime); ftime = SDFSImpl::FatToTimeT(date, time);
} }
} }
return ftime; return ftime;
@ -384,9 +397,9 @@ public:
time_t getCreationTime() override { time_t getCreationTime() override {
time_t ftime = 0; time_t ftime = 0;
if (_opened && _fd) { if (_opened && _fd) {
DirFat_t tmp; uint16_t date, time;
if (_fd.get()->dirEntry(&tmp)) { if (_fd.get()->getCreateDateTime(&date, &time)) {
ftime = SDFSImpl::FatToTimeT(*(uint16_t*)tmp.createDate, *(uint16_t*)tmp.createTime); ftime = SDFSImpl::FatToTimeT(date, time);
} }
} }
return ftime; return ftime;
@ -394,14 +407,14 @@ public:
protected: protected:
SDFSImpl* _fs; SDFSImpl* _fs;
std::shared_ptr<File32> _fd; std::shared_ptr<FsFile> _fd;
std::shared_ptr<char> _name; std::shared_ptr<char> _name;
bool _opened; bool _opened;
}; };
class SDFSDirImpl : public DirImpl { class SDFSDirImpl : public DirImpl {
public: public:
SDFSDirImpl(const String& pattern, SDFSImpl* fs, std::shared_ptr<File32> dir, const char *dirPath = nullptr) SDFSDirImpl(const String& pattern, SDFSImpl* fs, std::shared_ptr<FsFile> dir, const char *dirPath = nullptr)
: _pattern(pattern), _fs(fs), _dir(dir), _valid(false), _dirPath(nullptr) { : _pattern(pattern), _fs(fs), _dir(dir), _valid(false), _dirPath(nullptr) {
if (dirPath) { if (dirPath) {
_dirPath = std::shared_ptr<char>(new char[strlen(dirPath) + 1], std::default_delete<char[]>()); _dirPath = std::shared_ptr<char>(new char[strlen(dirPath) + 1], std::default_delete<char[]>());
@ -466,19 +479,22 @@ public:
bool next() override { bool next() override {
const int n = _pattern.length(); const int n = _pattern.length();
do { do {
File32 file; FsFile file;
file.openNext(_dir.get(), O_READ); file.openNext(_dir.get(), O_READ);
if (file) { if (file) {
_valid = 1; _valid = 1;
_size = file.fileSize(); _size = file.fileSize();
_isFile = file.isFile(); _isFile = file.isFile();
_isDirectory = file.isDir(); _isDirectory = file.isDir();
DirFat_t tmp; uint16_t date, time;
if (file.dirEntry(&tmp)) { if (file.getModifyDateTime(&date, &time)) {
_time = SDFSImpl::FatToTimeT(*(uint16_t*)tmp.modifyDate, *(uint16_t*)tmp.modifyTime); _time = SDFSImpl::FatToTimeT(date, time);
_creation = SDFSImpl::FatToTimeT(*(uint16_t*)tmp.createDate, *(uint16_t*)tmp.createTime);
} else { } else {
_time = 0; _time = 0;
}
if (file.getCreateDateTime(&date, &time)) {
_creation = SDFSImpl::FatToTimeT(date, time);
} else {
_creation = 0; _creation = 0;
} }
file.getName(_lfn, sizeof(_lfn)); file.getName(_lfn, sizeof(_lfn));
@ -499,9 +515,9 @@ public:
protected: protected:
String _pattern; String _pattern;
SDFSImpl* _fs; SDFSImpl* _fs;
std::shared_ptr<File32> _dir; std::shared_ptr<FsFile> _dir;
bool _valid; bool _valid;
char _lfn[64]; char _lfn[256];
time_t _time; time_t _time;
time_t _creation; time_t _creation;
std::shared_ptr<char> _dirPath; std::shared_ptr<char> _dirPath;

1
libraries/SdFat Submodule

@ -0,0 +1 @@
Subproject commit 67e26476f15a3bae5f390d91b6cc01830920c55d

View file

@ -51,7 +51,7 @@ compiler.warning_flags.all=-Wall -Wextra -Werror=return-type -Wno-ignored-qualif
compiler.netdefines={build.libpicowdefs} -DLWIP_IGMP=1 -DLWIP_CHECKSUM_CTRL_PER_NETIF=1 compiler.netdefines={build.libpicowdefs} -DLWIP_IGMP=1 -DLWIP_CHECKSUM_CTRL_PER_NETIF=1
compiler.psramdefines={build.psram_cs} {build.psram_freq} compiler.psramdefines={build.psram_cs} {build.psram_freq}
compiler.defines={build.led} {build.usbstack_flags} {build.usbpid} {build.usbvid} {build.usbpwr} {compiler.psramdefines} '-DUSB_MANUFACTURER={build.usb_manufacturer}' '-DUSB_PRODUCT={build.usb_product}' {compiler.netdefines} {build.variantdefines} -DARDUINO_VARIANT="{build.variant}" -DPICO_FLASH_SIZE_BYTES={build.flash_total} "@{runtime.platform.path}/lib/{build.chip}/platform_def.txt" compiler.defines={build.led} {build.usbstack_flags} {build.usbpid} {build.usbvid} {build.usbpwr} {compiler.psramdefines} '-DUSB_MANUFACTURER={build.usb_manufacturer}' '-DUSB_PRODUCT={build.usb_product}' {compiler.netdefines} {build.sdfatdefines} {build.variantdefines} -DARDUINO_VARIANT="{build.variant}" -DPICO_FLASH_SIZE_BYTES={build.flash_total} "@{runtime.platform.path}/lib/{build.chip}/platform_def.txt"
compiler.includes="-iprefix{runtime.platform.path}/" "@{runtime.platform.path}/lib/{build.chip}/platform_inc.txt" "@{runtime.platform.path}/lib/core_inc.txt" "-I{runtime.platform.path}/include" compiler.includes="-iprefix{runtime.platform.path}/" "@{runtime.platform.path}/lib/{build.chip}/platform_inc.txt" "@{runtime.platform.path}/lib/core_inc.txt" "-I{runtime.platform.path}/include"
compiler.flags={build.toolchainopts} -ffunction-sections -fdata-sections {build.flags.exceptions} {build.flags.stackprotect} {build.picodebugflags} compiler.flags={build.toolchainopts} -ffunction-sections -fdata-sections {build.flags.exceptions} {build.flags.stackprotect} {build.picodebugflags}
compiler.wrap="@{runtime.platform.path}/lib/{build.chip}/platform_wrap.txt" "@{runtime.platform.path}/lib/core_wrap.txt" compiler.wrap="@{runtime.platform.path}/lib/{build.chip}/platform_wrap.txt" "@{runtime.platform.path}/lib/core_wrap.txt"
@ -114,6 +114,7 @@ build.espwifitype=
build.debugscript=picoprobe_cmsis_dap.tcl build.debugscript=picoprobe_cmsis_dap.tcl
build.picodebugflags= build.picodebugflags=
build.variantdefines= build.variantdefines=
build.sdfatdefines=-DFILE_COPY_CONSTRUCTOR_SELECT=FILE_COPY_CONSTRUCTOR_PUBLIC -DUSE_UTF8_LONG_NAMES=1 -DSDFAT_FILE_TYPE=3 -DDISABLE_FS_H_WARNING=1
# Allow Pico boards to be auto-discovered by the IDE # Allow Pico boards to be auto-discovered by the IDE
#discovery.rp2040.pattern={runtime.tools.pqt-python3.path}/python3 -I "{runtime.platform.path}/tools/pluggable_discovery.py" #discovery.rp2040.pattern={runtime.tools.pqt-python3.path}/python3 -I "{runtime.platform.path}/tools/pluggable_discovery.py"

View file

@ -27,6 +27,7 @@ EOL
fi fi
# Add items to the following list with "\n" netween them to skip running. No spaces, tabs, etc. allowed # Add items to the following list with "\n" netween them to skip running. No spaces, tabs, etc. allowed
read -d '' skiplist << EOL || true read -d '' skiplist << EOL || true
/SdFat/
/#attic/ /#attic/
/AvrAdcLogger/ /AvrAdcLogger/
/examplesV1/ /examplesV1/

View file

@ -225,6 +225,14 @@ env.Append(
"-std=gnu++17", "-std=gnu++17",
], ],
CPPDEFINES=[
# SdFat definitions required for SDFS
("FILE_COPY_CONSTRUCTOR_SELECT", "FILE_COPY_CONSTRUCTOR_PUBLIC"),
("USE_UTF8_LONG_NAMES", "1"),
("SDFAT_FILE_TYPE", "3"),
("DISABLE_FS_H_WARNING", "1")
],
CPPPATH=[ CPPPATH=[
os.path.join(FRAMEWORK_DIR, "cores", "rp2040"), os.path.join(FRAMEWORK_DIR, "cores", "rp2040"),
os.path.join(FRAMEWORK_DIR, "cores", "rp2040", "api", "deprecated"), os.path.join(FRAMEWORK_DIR, "cores", "rp2040", "api", "deprecated"),