Skip to content

Commit

Permalink
Add SDIO support for RP2040/RP2350
Browse files Browse the repository at this point in the history
  • Loading branch information
greiman committed Jan 1, 2025
1 parent 052d38e commit 67e2647
Show file tree
Hide file tree
Showing 99 changed files with 4,281 additions and 1,529 deletions.
62 changes: 62 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,65 @@
### Warning: This version has major internal changes.

SdFat version 2.3.0 has major changes to implement RP2040/RP2350 SDIO.

In addition there are number of bug fixes.

Begin by running the Rp2040SdioSetup example to try RP2040/RP2350 SDIO.

This example requires a SDIO Card socket with the following six lines.

CLK - A clock signal sent to the card by the MCU.
CMD - A bidirectional line for for commands and responses.
DAT[0:3] - Four bidirectional lines for data transfer.

CLK and CMD can be connected to any GPIO pins. DAT[0:3] can be connected
to any four consecutive GPIO pins in the order DAT0, DAT1, DAT2, DAT3.

Here is an example of SDIO for Pico using an Adafruit socket, PiCowbell
Proto and PiCowbell Proto Doubler.

![Alt text](images/SdioSpi.jpg)

This Socket supports SDIO with:
```
#define RP_CLK_GPIO 10
#define RP_CMD_GPIO 11
#define RP_DAT0_GPIO 12 // DAT1: GPIO13 DAT2: GPIO14, DAT3: GPIO15.
```
It also can be used on SPI1 with:
```
const uint8_t SD_CS_PIN = 15;
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK, &SPI1)
// In setup
SPI1.setSCK(10);
SPI1.setTX(11);
SPI1.setRX(12);
```

This setup gets the following result in the bench example using SDIO.

<pre>
FILE_SIZE_MB = 5
BUF_SIZE = 512 bytes
Starting write test, please wait.

write speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
15014.05,1165,32,32
15289.54,1249,32,32

Starting read test, please wait.

read speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
15624.00,58,32,32
15624.00,51,32,32
</pre>


File copy constructors and file assignment operators have been made private by
default in 2.2.3 to prevent call by value and multiple copies of file instances.

Expand Down
249 changes: 181 additions & 68 deletions doc/Doxyfile

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions doc/SdErrorCodes.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
2022-07-01
2025-01-01

Run the SdErrorCode example to produce an updated list.

Expand All @@ -12,7 +12,7 @@ Code,Symbol - failed operation
0X06,SD_CARD_ERROR_CMD8 - Send and check interface settings
0X07,SD_CARD_ERROR_CMD9 - Read CSD data
0X08,SD_CARD_ERROR_CMD10 - Read CID data
0X09,SD_CARD_ERROR_CMD12 - Stop multiple block read
0X09,SD_CARD_ERROR_CMD12 - Stop multiple block transmission
0X0A,SD_CARD_ERROR_CMD13 - Read card status
0X0B,SD_CARD_ERROR_CMD17 - Read single block
0X0C,SD_CARD_ERROR_CMD18 - Read multiple blocks
Expand Down
Binary file modified doc/html.zip
Binary file not shown.
3 changes: 1 addition & 2 deletions examples/AvrAdcLogger/AvrAdcLogger.ino
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,10 @@
*/
#ifdef __AVR__
#include <SPI.h>

#include "SdFat.h"
#include "AvrAdcLogger.h"
#include "BufferedPrint.h"
#include "FreeStack.h"
#include "SdFat.h"

// Save SRAM if 328.
#ifdef __AVR_ATmega328P__
Expand Down
13 changes: 8 additions & 5 deletions examples/BufferedPrint/BufferedPrint.ino
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Test and benchmark of the fast bufferedPrint class.
//
// Mainly for AVR but may improve print performance with other CPUs.
#include "BufferedPrint.h"
#define DISABLE_FS_H_WARNING // Disable warning for type File not defined.
#include "SdFat.h"

#include "BufferedPrint.h"
// 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.
#define SD_FAT_TYPE 3
Expand All @@ -28,13 +28,16 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
#define SPI_CLOCK SD_SCK_MHZ(50)

// Try to select the best SD card configuration.
#if HAS_SDIO_CLASS
#if defined(HAS_TEENSY_SDIO)
#define SD_CONFIG SdioConfig(FIFO_SDIO)
#elif defined(RP_CLK_GPIO) && defined(RP_CMD_GPIO) && defined(RP_DAT0_GPIO)
// See the Rp2040SdioSetup example for RP2040/RP2350 boards.
#define SD_CONFIG SdioConfig(RP_CLK_GPIO, RP_CMD_GPIO, RP_DAT0_GPIO)
#elif ENABLE_DEDICATED_SPI
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
#else // HAS_SDIO_CLASS
#else // HAS_TEENSY_SDIO
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
#endif // HAS_SDIO_CLASS
#endif // HAS_TEENSY_SDIO

#if SD_FAT_TYPE == 0
SdFat sd;
Expand Down
10 changes: 7 additions & 3 deletions examples/DirectoryFunctions/DirectoryFunctions.ino
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*
* Example use of chdir(), ls(), mkdir(), and rmdir().
*/
#define DISABLE_FS_H_WARNING // Disable warning for type File not defined.
#include "SdFat.h"
#include "sdios.h"

Expand Down Expand Up @@ -28,13 +29,16 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
#define SPI_CLOCK SD_SCK_MHZ(50)

// Try to select the best SD card configuration.
#if HAS_SDIO_CLASS
#if defined(HAS_TEENSY_SDIO)
#define SD_CONFIG SdioConfig(FIFO_SDIO)
#elif defined(RP_CLK_GPIO) && defined(RP_CMD_GPIO) && defined(RP_DAT0_GPIO)
// See the Rp2040SdioSetup example for RP2040/RP2350 boards.
#define SD_CONFIG SdioConfig(RP_CLK_GPIO, RP_CMD_GPIO, RP_DAT0_GPIO)
#elif ENABLE_DEDICATED_SPI
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
#else // HAS_SDIO_CLASS
#else // HAS_TEENSY_SDIO
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
#endif // HAS_SDIO_CLASS
#endif // HAS_TEENSY_SDIO
//------------------------------------------------------------------------------

#if SD_FAT_TYPE == 0
Expand Down
14 changes: 9 additions & 5 deletions examples/ExFatLogger/ExFatLogger.ino
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
//
// The maximum data rate will depend on the quality of your SD,
// the size of the FIFO, and using dedicated SPI.
#define DISABLE_FS_H_WARNING // Disable warning for type File not defined.
#include "SdFat.h"
#include "ExFatLogger.h"
#include "FreeStack.h"
#include "SdFat.h"
//------------------------------------------------------------------------------
// This example was designed for exFAT but will support FAT16/FAT32.
// Note: Uno will not support SD_FAT_TYPE = 3.
Expand Down Expand Up @@ -69,13 +70,16 @@ const uint32_t PREALLOCATE_SIZE_MiB = 1024UL;
#define SPI_CLOCK SD_SCK_MHZ(50)

// Try to select the best SD card configuration.
#if HAS_SDIO_CLASS
#if defined(HAS_TEENSY_SDIO)
#define SD_CONFIG SdioConfig(FIFO_SDIO)
#elif defined(RP_CLK_GPIO) && defined(RP_CMD_GPIO) && defined(RP_DAT0_GPIO)
// See the Rp2040SdioSetup example for RP2040/RP2350 boards.
#define SD_CONFIG SdioConfig(RP_CLK_GPIO, RP_CMD_GPIO, RP_DAT0_GPIO)
#elif ENABLE_DEDICATED_SPI
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
#else // HAS_SDIO_CLASS
#else // HAS_TEENSY_SDIO
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
#endif // HAS_SDIO_CLASS
#endif // HAS_TEENSY_SDIO

// Save SRAM if 328.
#ifdef __AVR_ATmega328P__
Expand All @@ -92,7 +96,7 @@ void logRecord(data_t* data, uint16_t overrun) {
data->adc[0] = 0X8000 | overrun;
} else {
for (size_t i = 0; i < ADC_COUNT; i++) {
data->adc[i] = analogRead(i);
data->adc[i] = analogRead(A0 + i);
}
}
}
Expand Down
10 changes: 7 additions & 3 deletions examples/OpenNext/OpenNext.ino
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*
* Print size, modify date/time, and name for all files in root.
*/
#define DISABLE_FS_H_WARNING // Disable warning for type File not defined.
#include "SdFat.h"

// SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h,
Expand All @@ -27,13 +28,16 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
#define SPI_CLOCK SD_SCK_MHZ(50)

// Try to select the best SD card configuration.
#if HAS_SDIO_CLASS
#if defined(HAS_TEENSY_SDIO)
#define SD_CONFIG SdioConfig(FIFO_SDIO)
#elif defined(RP_CLK_GPIO) && defined(RP_CMD_GPIO) && defined(RP_DAT0_GPIO)
// See the Rp2040SdioSetup example for RP2040/RP2350 boards.
#define SD_CONFIG SdioConfig(RP_CLK_GPIO, RP_CMD_GPIO, RP_DAT0_GPIO)
#elif ENABLE_DEDICATED_SPI
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
#else // HAS_SDIO_CLASS
#else // HAS_TEENSY_SDIO
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
#endif // HAS_SDIO_CLASS
#endif // HAS_TEENSY_SDIO

#if SD_FAT_TYPE == 0
SdFat sd;
Expand Down
16 changes: 12 additions & 4 deletions examples/ReadCsvFile/ReadCsvFile.ino
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#define DISABLE_FS_H_WARNING // Disable warning for type File not defined.
#include "SdFat.h"

// SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h,
Expand All @@ -24,13 +25,16 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
#define SPI_CLOCK SD_SCK_MHZ(50)

// Try to select the best SD card configuration.
#if HAS_SDIO_CLASS
#if defined(HAS_TEENSY_SDIO)
#define SD_CONFIG SdioConfig(FIFO_SDIO)
#elif defined(RP_CLK_GPIO) && defined(RP_CMD_GPIO) && defined(RP_DAT0_GPIO)
// See the Rp2040SdioSetup example for RP2040/RP2350 boards.
#define SD_CONFIG SdioConfig(RP_CLK_GPIO, RP_CMD_GPIO, RP_DAT0_GPIO)
#elif ENABLE_DEDICATED_SPI
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
#else // HAS_SDIO_CLASS
#else // HAS_TEENSY_SDIO
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
#endif // HAS_SDIO_CLASS
#endif // HAS_TEENSY_SDIO

#if SD_FAT_TYPE == 0
SdFat sd;
Expand Down Expand Up @@ -126,7 +130,7 @@ void setup() {
if (!file.open("ReadCsvDemo.csv", FILE_WRITE)) {
error("open failed");
}
// Write test data.
// Write test data. Test missing CRLF on last line.
file.print(
F("abc,123,456,7.89\r\n"
"def,-321,654,-9.87\r\n"
Expand All @@ -143,6 +147,10 @@ void setup() {
if (line[n - 1] != '\n' && n == (sizeof(line) - 1)) {
error("line too long");
}
if (line[n - 1] == '\n') {
// Remove new line.
line[n -1] = 0;
}
if (!parseLine(line)) {
error("parseLine failed");
}
Expand Down
93 changes: 93 additions & 0 deletions examples/Rp2040SdioSetup/Rp2040SdioSetup.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// RP2040 PIO SDIO setup and test.
/*
This example requires a SDIO Card socket with the following six lines.
CLK - A clock signal sent to the card by the MCU.
CMD - A bidirectional line for for commands and responses.
DAT[0:3] - Four bidirectional lines for data transfer.
CLK and CMD can be connected to any GPIO pins. DAT[0:3] can be connected
to any four consecutive GPIO pins in the order DAT0, DAT1, DAT2, DAT3.
For testing, I use several RP2040/RP3350 boards.
The Adafruit Metro RP2040 which has a builtin SDIO socket.
https://learn.adafruit.com/adafruit-metro-rp2040
I use this SD socket breakout board for other boards.
https://learn.adafruit.com/adafruit-microsd-spi-sdio
Wires should be short since signals can be as faster than 50 MHz.
*/
#define DISABLE_FS_H_WARNING // Disable warning for type File not defined.
#include "SdFat.h"
//------------------------------------------------------------------------------
// Example GPIO definitions I use for debug. Edit for your setup.
// Run this example as is to print the symbol for your variant.
//
#if defined(ARDUINO_ADAFRUIT_METRO_RP2040)
#define RP_CLK_GPIO 18
#define RP_CMD_GPIO 19
#define RP_DAT0_GPIO 20 // DAT1: GPIO21, DAT2: GPIO22, DAT3: GPIO23.
#elif defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_RASPBERRY_PI_PICO_2)
#define RP_CLK_GPIO 16
#define RP_CMD_GPIO 17
#define RP_DAT0_GPIO 18 // DAT1: GPIO19, DAT2: GPIO20, DAT3: GPIO21.
#elif defined(ARDUINO_ADAFRUIT_FEATHER_RP2350_HSTX)
#define RP_CLK_GPIO 11
#define RP_CMD_GPIO 10
#define RP_DAT0_GPIO 22 // DAT1: GPIO23, DAT2: GPIO24, DAT3: GPIO25.
#endif // defined(ARDUINO_ADAFRUIT_METRO_RP2040))

#if defined(RP_CLK_GPIO) && defined(RP_CMD_GPIO) && defined(RP_DAT0_GPIO)
#define SD_CONFIG SdioConfig(RP_CLK_GPIO, RP_CMD_GPIO, RP_DAT0_GPIO)
#else // defined(RP_CLK_GPIO) && defined(RP_CMD_GPIO) && defined(RP_DAT0_GPIO)
#warning "Undefined SD_CONFIG. Run this program for the Variant Symbol."
#endif // defined(RP_CLK_GPIO) && defined(RP_CMD_GPIO) && defined(RP_DAT0_GPIO)
//------------------------------------------------------------------------------
// Class File is not defined by SdFat since the RP2040 system defines it.
// 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT.
#define SD_FAT_TYPE 3

#if SD_FAT_TYPE == 1
SdFat32 sd;
File32 file;
#elif SD_FAT_TYPE == 2
SdExFat sd;
ExFile file;
#elif SD_FAT_TYPE == 3
SdFs sd;
FsFile file;
#else // SD_FAT_TYPE
#error Invalid SD_FAT_TYPE
#endif // SD_FAT_TYPE

void setup() {
Serial.begin(9600);
while (!Serial) {
yield();
}
Serial.println("Type any character to start\n");
while (!Serial.available()) {
yield();
}
Serial.print("Variant Symbol: ");
Serial.print("ARDUINO_");
Serial.println(BOARD_NAME);
Serial.println();
#if defined(SD_CONFIG)
if (!sd.begin(SD_CONFIG)) {
sd.initErrorHalt(&Serial);
}
Serial.println("Card successfully initialized.");
Serial.println("\nls:");
sd.ls(LS_A | LS_DATE | LS_SIZE); // Add LS_R for recursive list.
Serial.println("\nDone! Try the bench example next.");
#else // #if defined(SD_CONFIG)
Serial.println("Error: SD_CONFIG undefined for your board.");
Serial.println("Define RP_CLK_GPIO, RP_CMD_GPIO, and RP_DAT0_GPIO above.");
#endif
}

void loop() {}
9 changes: 6 additions & 3 deletions examples/RtcTimestampTest/RtcTimestampTest.ino
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,16 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
#define SPI_CLOCK SD_SCK_MHZ(50)

// Try to select the best SD card configuration.
#if HAS_SDIO_CLASS
#if defined(HAS_TEENSY_SDIO)
#define SD_CONFIG SdioConfig(FIFO_SDIO)
#elif defined(RP_CLK_GPIO) && defined(RP_CMD_GPIO) && defined(RP_DAT0_GPIO)
// See the Rp2040SdioSetup example for RP2040/RP2350 boards.
#define SD_CONFIG SdioConfig(RP_CLK_GPIO, RP_CMD_GPIO, RP_DAT0_GPIO)
#elif ENABLE_DEDICATED_SPI
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
#else // HAS_SDIO_CLASS
#else // HAS_TEENSY_SDIO
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
#endif // HAS_SDIO_CLASS
#endif // HAS_TEENSY_SDIO

#if SD_FAT_TYPE == 0
SdFat sd;
Expand Down
Loading

0 comments on commit 67e2647

Please sign in to comment.