It is a fairly complex machine, but also really powerful. I don't actually have that particular type available to me, just a standard 38-pin esp32 devkit, and i have heard that there are some significant differences, but i don't know exactly which. Is there any reason to use an external SPIFFS over an SD-card, it would be rather easier to get one of them to work first anyway.
What i found here shows that there is 1 SPI port available for general purpose. SPI2. There is no SPI3 on an esp32-S3.
So Try with those pins first to get the SD-card working using the SD examples. If for some reason the unit crashes, it is possible that we need to try other pins. The ESP32 has the possibility of routing peripherals to specific pins. Most Libraries though tend to call SPI.begin() themselves which will revert those assignment to their default. I know that the SD library allows the passing of an SPI object as an argument on initialization.
The code i use for it is this
#define LED_YELLOW 2
#define HSPI_SCK 17
#define HSPI_MISO 16
#define HSPI_MOSI 4
#define SD_CS 15
#define SPI_FRQ 32000000
#define TEST_BLOCKS 4
#include "FS.h"
#include "SD.h"
#include "SPI.h"
SPIClass * hspi = NULL; // the name of the pointer doesn't actually matter
void setup() {
Serial.begin(115200);
pinMode(LED_YELLOW, OUTPUT);
digitalWrite(LED_YELLOW, LOW); // active LOW
hspi = new SPIClass(HSPI); // now on an S3 this should probably be FSPI
hspi->begin(HSPI_SCK, HSPI_MISO, HSPI_MOSI, SD_CS);
hspi->setFrequency(SPI_FRQ);
//hspi->begin();
if (!SD.begin(SD_CS, *hspi, SPI_FRQ)) {
Serial.println("Card Mount Failed");
return;
}
uint8_t cardType = SD.cardType();
if (cardType == CARD_NONE) {
Serial.println("No SD card attached");
return;
}
Serial.print("SD Card Type: ");
if (cardType == CARD_MMC) {
Serial.println("MMC");
} else if (cardType == CARD_SD) {
Serial.println("SDSC");
} else if (cardType == CARD_SDHC) {
Serial.println("SDHC");
} else {
Serial.println("UNKNOWN");
}
uint64_t cardSize = SD.cardSize() / (1024 * 1024);
Serial.printf("SD Card Size: %lluMB\n", cardSize);
listDir(SD, "/", 0);
createDir(SD, "/mydir");
listDir(SD, "/", 0);
removeDir(SD, "/mydir");
listDir(SD, "/", 2);
writeFile(SD, "/hello.txt", "Hello ");
appendFile(SD, "/hello.txt", "World!\n");
readFile(SD, "/hello.txt");
deleteFile(SD, "/foo.txt");
renameFile(SD, "/hello.txt", "/foo.txt");
readFile(SD, "/foo.txt");
testFileIO(SD, "/test.txt");
Serial.printf("Total space: %lluMB\n", SD.totalBytes() / (1024 * 1024));
Serial.printf("Used space: %lluMB\n", SD.usedBytes() / (1024 * 1024));
digitalWrite(LED_YELLOW, HIGH); // active LOW
}
void loop() {
}
void listDir(fs::FS &fs, const char * dirname, uint8_t levels) {
Serial.printf("Listing directory: %s\n", dirname);
File root = fs.open(dirname);
if (!root) {
Serial.println("Failed to open directory");
return;
}
if (!root.isDirectory()) {
Serial.println("Not a directory");
return;
}
File file = root.openNextFile();
while (file) {
if (file.isDirectory()) {
Serial.print(" DIR : ");
Serial.println(file.name());
if (levels) {
listDir(fs, file.name(), levels - 1);
}
} else {
Serial.print(" FILE: ");
Serial.print(file.name());
Serial.print(" SIZE: ");
Serial.println(file.size());
}
file = root.openNextFile();
}
}
void createDir(fs::FS &fs, const char * path) {
Serial.printf("Creating Dir: %s\n", path);
if (fs.mkdir(path)) {
Serial.println("Dir created");
} else {
Serial.println("mkdir failed");
}
}
void removeDir(fs::FS &fs, const char * path) {
Serial.printf("Removing Dir: %s\n", path);
if (fs.rmdir(path)) {
Serial.println("Dir removed");
} else {
Serial.println("rmdir failed");
}
}
void readFile(fs::FS &fs, const char * path) {
Serial.printf("Reading file: %s\n", path);
File file = fs.open(path);
if (!file) {
Serial.println("Failed to open file for reading");
return;
}
Serial.print("Read from file: ");
while (file.available()) {
Serial.write(file.read());
}
file.close();
}
void writeFile(fs::FS &fs, const char * path, const char * message) {
Serial.printf("Writing file: %s\n", path);
File file = fs.open(path, FILE_WRITE);
if (!file) {
Serial.println("Failed to open file for writing");
return;
}
if (file.print(message)) {
Serial.println("File written");
} else {
Serial.println("Write failed");
}
file.close();
}
void appendFile(fs::FS &fs, const char * path, const char * message) {
Serial.printf("Appending to file: %s\n", path);
File file = fs.open(path, FILE_APPEND);
if (!file) {
Serial.println("Failed to open file for appending");
return;
}
if (file.print(message)) {
Serial.println("Message appended");
} else {
Serial.println("Append failed");
}
file.close();
}
void renameFile(fs::FS &fs, const char * path1, const char * path2) {
Serial.printf("Renaming file %s to %s\n", path1, path2);
if (fs.rename(path1, path2)) {
Serial.println("File renamed");
} else {
Serial.println("Rename failed");
}
}
void deleteFile(fs::FS &fs, const char * path) {
Serial.printf("Deleting file: %s\n", path);
if (fs.remove(path)) {
Serial.println("File deleted");
} else {
Serial.println("Delete failed");
}
}
void testFileIO(fs::FS &fs, const char * path) {
File file = fs.open(path);
static uint8_t buf[512];
size_t len = 0;
uint32_t start = millis();
uint32_t end = start;
uint32_t ustart = micros();
uint32_t uend = start;
if (file) {
len = file.size();
size_t flen = len;
start = millis();
ustart = micros();
while (len) {
size_t toRead = len;
if (toRead > 512) {
toRead = 512;
}
file.read(buf, toRead);
len -= toRead;
}
uend = micros() - ustart;
end = millis() - start;
if (end > 100) Serial.printf("%u bytes read for %u ms\n", flen, end);
else Serial.printf("%u bytes read for %u us\n", flen, uend);
file.close();
} else {
Serial.println("Failed to open file for reading");
}
file = fs.open(path, FILE_WRITE);
if (!file) {
Serial.println("Failed to open file for writing");
return;
}
size_t i;
start = millis();
ustart = micros();
for (i = 0; i < TEST_BLOCKS; i++) {
file.write(buf, 512);
}
uend = micros() - ustart;
end = millis() - start;
if (end > 100) Serial.printf("%u bytes written for %u ms\n", TEST_BLOCKS * 512, end);
else Serial.printf("%u bytes written for %u us\n", TEST_BLOCKS * 512, uend);
file.close();
}
You can connect up to 3 devices to the same port so i think it should work in the end, but for the other libraries you may also need to investigate the workings of the function of the class that is being used in the .h & .cpp files (or .hpp etc) to find out what they do and how they do what they do. Most of the libraries do not switch the CS pin for you (actually i haven't found one that does) but hey let's start with one SPI device first.
internal SPIFFS works, but because of it's nature it is also rather slow.