Skip to content

Commit

Permalink
Add SDIO support to SD snf SDFS, document, example
Browse files Browse the repository at this point in the history
  • Loading branch information
earlephilhower committed Jan 17, 2025
1 parent db8e44e commit f48f5e8
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 19 deletions.
17 changes: 17 additions & 0 deletions docs/fs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,23 @@ second SPI port, ``SPI1``. Just use the following call in place of
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
-------------------------------------------------
Expand Down
39 changes: 25 additions & 14 deletions libraries/SD/examples/CardInfo/CardInfo.ino
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ const int _MOSI = 7; // AKA SPI TX
const int _CS = 5;
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 <SPI.h>
#include <SD.h>
Expand All @@ -54,21 +60,26 @@ void setup() {
Serial.println("\nInitializing SD card...");

bool sdInitialized = false;
// 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);
if (RP_CLK_GPIO >= 0) {
// No special requirements on pin locations, this is PIO programmed
sdInitialized = SD.begin(RP_CLK_GPIO, RP_CMD_GPIO, RP_DAT0_GPIO);
} else {
Serial.println(F("ERROR: Unknown SPI Configuration"));
return;
// 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 (!sdInitialized) {
Expand Down
6 changes: 6 additions & 0 deletions libraries/SD/src/SD.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,17 @@ class SDClass {
SDFS.setConfig(SDFSConfig(csPin, SPI_HALF_SPEED, spi));
return SDFS.begin();
}

bool begin(uint8_t csPin, uint32_t cfg = SPI_HALF_SPEED, HardwareSPI &spi = SPI) {
SDFS.setConfig(SDFSConfig(csPin, cfg, spi));
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) {
SDFS.end();
if (endSPI && _spi) {
Expand Down
24 changes: 19 additions & 5 deletions libraries/SDFS/src/SDFS.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ class SDFSConfig : public FSConfig {
public:
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) {
_autoFormat = val;
Expand All @@ -69,7 +70,11 @@ class SDFSConfig : public FSConfig {
}

// Inherit _type and _autoFormat
bool _sdio;
uint8_t _clkPin; // SDIO only;
uint8_t _csPin;
uint8_t _cmdPin; // SDIO only
uint8_t _dat0Pin; // SDIO only
uint8_t _part;
uint32_t _spiSettings;
HardwareSPI *_spi;
Expand Down Expand Up @@ -131,11 +136,20 @@ class SDFSImpl : public FSImpl {
if (_mounted) {
return true;
}
SdSpiConfig ssc(_cfg._csPin, SHARED_SPI, _cfg._spiSettings, _cfg._spi);
_mounted = _fs.begin(ssc);
if (!_mounted && _cfg._autoFormat) {
format();
if (!_cfg._sdio) {
SdSpiConfig ssc(_cfg._csPin, SHARED_SPI, _cfg._spiSettings, _cfg._spi);
_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);
return _mounted;
Expand Down

0 comments on commit f48f5e8

Please sign in to comment.