-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Speeding up SD card writes #1117
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I see the same ~220KB/s write speed, so.. my suggestions are hypothetical. But I've had no issue with SPI speed = 25,000,000 (25MHz) on many SD cards, which should allow a faster write speed if the SD card can deliver it. That leads me to what would be my only other suggestion, I've had one SD card only write at ~22KB/s on the one-bit SPI interface (but is much faster in SDIO mode used by PC USB SD adaptors, and just reading it on SPI was much faster too) and other cheapish SD cards I own write at 220KB/s as I wrote above. I've not spent any large amounts of money on more highly rated SD cards to try - but if I needed fast writes, that would be my next move. 0.25MB/s is faster than I need though. |
Well on my esp8266 I was able to get it going faster by using this library, https://github.com/greiman/SdFat and mainly by making sure it just pre-allocated the file in one contiguous block, and by allowing it to do multi block writes. Sadly, the making of that library won't be making it work for esp32, is there any similar library that works for esp32 or any way to get more control of the functionality? |
Are you sure that library doesn't work with ESP32? I see this issue saying it doesn't work greiman/SdFat#88 however, I just tried it and reduced the SPI frequency from 50MHz to 10MHz and it ran the SdInfo.ino example without any error. I have "hacked" my ESP32 SPI library to make _spi_num "public" (and my very first statement in setup() is SPI._spi_num = HSPI; so when it gets around to initialise the default SPI it doesn't use VSPI which I don't use for my SD card). I don't think that small hack is important here though. I personally use ChaNFS, but that's got glue functions to implement for access to the hardware layer (see smoothieboard firmware for an example). |
When I include the headers for SDFat library there are a whole bunch of collisions and it looks like it will be a pain to even get it to compile. I am not sure what issues will pop up, |
Ah, maybe you have another SDFat library in your "libraries" folder (I removed my old that one I had, to a temporary directory elsewhere) and I installed the new one correctly on my 2nd attempt (you've got to follow the instructions pretty closely). When I did follow the instructions, it didn't complain when compiling or linking (I had link issues on my first attempt, missing bits and pieces because I only had the "src" directory and not the "examples" and "extras" in the right place). I'm not sure I can help further - and I never had any "collisions" - but I would suggest you persist, practice makes perfect (and all that crap). |
Oh, I did comment out two SysCall::Yeild(); function calls. But other than that,the HSPI thing, and the speed change from 50MHz to 10MHz, nothing else. |
Hi jasoroony |
I didn't modify the SDFat library, but I did remove an older version first. I modified the SdInfo.ino: |
Hello jasoroony.
Thanks! |
In Arduino\hardware\espressif\esp32\libraries\SPI\src\SPI.h: Change the class definition from:
to instead say:
|
Thank you very much for your attention. I have tried with the reader that I have, it is a simpe that has 10K pull-up resistors in the MISO, MOSI and SCLK lines, and it does not work. My reader is this; Are you very kind please tell what reader to use? Thanks in advance. |
I have mine wired into a Rep Rap 12864 full graphic LCD + SD card reader. The LCD is on VSPI alone (the LCD doesn't share SPI nicely, it's a real hog) while the SD is on HSPI along with an 8 bit serial latch for more digital outputs. As such, I've got no pull-ups but those 3 lines go through a 74HC4050 to convert any 5v signal to 3.3v, which isn't really needed since I'm running on 3.3v. I do pass 5v to the LCD, so the whole circuit has its own power supply and 3.3v regulator. If your device works with the normal SD library, it should work with this library. If it doesn't work, I'm afraid I can't suggest anything else that I know works. I thought pull up resistors could make the SPI bus less reliable at higher speeds? I don't really know though. You could try running very slow settings (1MHz) and see if it works better? Might give you a clue as to what's the problem. |
hoping ghost is listening :-) is it easy to "hack" again the code to allow the SPI pins on the ESP32 to be not in the normal location?? I have a circuit that uses alternate pins... thanks! |
Collisions occur if you are using some of the included libraries from esp32. With me I am having collisions with the Wifi library, but mostly any connectivity library has the same collisions like (HTTPClient, WiFiClientSecure, WebServer) libraries compiled tested it so far are all giving the same errors which happens specifically between the _default_fcntl.h preproessor values and the FatApiConstants.h from SdFat library. I am doing some investigation about the SdFat library performance along with the official SD library, so that I can either switch to the SD library at all or make some modifications with the SdFat library to make it work with ESP32 arduino core. I am not sure about the solution yet but I think someone faced the same issue and this person solved the problem by renaming the constants in the SdFat library. @schlaegerz That's what i faced so far, maybe there are other libraries with other collisions, if so please let me know. |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
This stale issue has been automatically closed. Thank you for your contributions. |
@schlaegerz And at default speeds, how much time will it take to fetch a 1 or 2 mb file!? |
I'm attempting this again after a year or so and cannot for the life of me figure out how to wire this again to get it working, what is the best way to wire the sd card ti the dev module? I would prefer not to use external resistors, but I have the option if need be. I have both the 6-pin and 9-pin breakout boards for the sd card, but cannot get either one to work. |
@schlaegerz hey i checked on the internet. It says everywhere that SPI is used. https://www.instructables.com/id/Micro-SD-Card-Tutorial/ |
yeah the wiring actually seems okay to me......maybe there are voltage
difference?! SD card works on 5v logic and esp works on 3.3v logic. So is
that a problem?!
…On Fri, Apr 17, 2020 at 5:54 AM schlaegerz ***@***.***> wrote:
So I am using the esp32 dev kit and have the following 9 pin as card
adapter. [image: C1C57DF4-1768-414E-A6F1-0794759AEE86]
<https://user-images.githubusercontent.com/8098360/79506580-12f04600-7feb-11ea-88a6-9176ca7a921c.jpeg>
[image: B332D826-D22C-4F71-A4BA-3F760DE50C91]
<https://user-images.githubusercontent.com/8098360/79506587-184d9080-7feb-11ea-9cea-6def27e097d4.jpeg>
I know the basics of how to get it to work, as I’ve been using an esp8266
with an sd card for years but I cannot get it to work with the esp32 right
now, even with pins that are supposed to work
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#1117 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AOYZRIANDKEBANPC4YWJ32LRM6OSNANCNFSM4EQ6VN2Q>
.
|
Sort of using the SDFat library (which does not seem to be supported on ESP32), does anyone have alternatives to make SD writes faster than .25MB/s? Thanks. |
tl;dr;Use SD_MMC interface: it offers a much better performance (2x at the very least), and the code is very similar to SPI. #include "SD_MMC.h"
void setup() {
// true for 1bit mode
if(!SD_MMC.begin("/sd", true)){
Serial.println("Card Mount Failed");
return;
}
File f = SD_MMC.open("/foo.txt");
}
Long versionSo I spent some time with SD card writes on my esp32 board. Here's what I found so far using a Samsung EVO Plus 32GB card and the sketch at the bottom of this coment. As far as the code for SD_MMC is concerned, it's very similar to the SPI interface, mostly needs a couple of lines of change in code, but offers a significant performance improvement. SPI/SD PerformanceHere are the results of writing a 2MB file using various buffer sizes using the
SD_MMC performanceThere is an immediate 2x performance boost for 512 byte buffer (compared to SPI). Increasing the buffer size gets you significant performance boost.
The pin connectionsThese are documented in code, but I'll reproduce it here for clarity:
The test program// uncomment to use SPI. comment to use SD_MMC
//#define USE_SPI
#include "math.h"
#include "FS.h"
#ifdef USE_SPI
#include "SD.h"
#include "SPI.h"
#define SD_CARD_FS SD
const int ss_cs = 13;
const int mosi = 15;
const int sck = 14;
const int miso = 2;
#else
#include "SD_MMC.h"
#define SD_CARD_FS SD_MMC
#endif
void testFileIO(fs::FS &fs, const char * path, uint32_t buffSize, uint32_t numMB) {
uint8_t * buff = new uint8_t[buffSize];
File file = fs.open(path, FILE_WRITE);
if (file) {
size_t i;
uint32_t start = millis();
auto numToWrite = (numMB * 1024 * 1024) / buffSize;
for (i = 0; i < numToWrite; i++) {
file.write(buff, buffSize);
yield();
}
uint32_t end = millis() - start;
float kbps = numMB * 1024 * 1024 / end;
Serial.printf("%u MB written using %d byte buffer for %u ms @ %f KBps\n", numMB, buffSize, end, kbps);
file.close();
} else {
Serial.println("Failed to open file for writing");
}
file = fs.open(path);
if (file) {
uint32_t len = file.size();
size_t flen = len;
uint32_t start = millis();
while (len) {
size_t toRead = len;
if (toRead > buffSize) {
toRead = buffSize;
}
file.read(buff, toRead);
len -= toRead;
}
uint32_t end = millis() - start;
float kbps = numMB * 1024 * 1024 / end;
Serial.printf("%u MB read using %d byte buffer for %u ms @ %f KBps\n", flen / 1024 / 1024, buffSize, end, kbps);
file.close();
} else {
Serial.println("Failed to open file for reading");
}
delete[] buff;
}
void setup() {
Serial.begin(115200);
#ifdef USE_SPI
SPI.begin(sck, miso, mosi, ss_cs);
if (!SD.begin(ss_cs, SPI)) {
Serial.println("Card Mount Failed");
return;
}
#else
if (!SD_MMC.begin("/sd", true)) {
Serial.println("Card Mount Failed");
return;
}
#endif
for (int i = 0; i <= 7; i++) {
testFileIO(SD_CARD_FS, "/test.txt", 512 * pow(2, i), 2);
}
}
void loop() {
} |
@ketan Thanks a lot for this code! I just ran it and found out, that there now seems to be a limit at 4K buffers. Everything bigger thant that slows down the performance a lot. Do you have any idea what could cause that and where to search for?
Arduino version: 2.0.9 |
Sorry. I don't have an idea. I merely documented what I had observed at the time. |
Hardware:
Board: ESP32 Dev module
Core Installation/update date: 2/13/2018
IDE name: Arduino ID
Flash Frequency: 40Mhz
Upload Speed: ?115200?
Description:
I am trying to figure out how to speed up my SD card writes. I don't really care about the file structure of the SD card, and only want to write a lot of data to an SD card. I was hoping to get at least 1 MB/s of writing but I seem to be getting significantly lower than that no matter what I try I cant get much better than .25 MB/s.
I am not sure if this is a hardware issue, or something that I can fix with software, or if this is just the max speed I can expect.
I am using a micro sd card with an adapter like this:
https://www.amazon.com/SenMod-Adapter-Reader-Module-Arduino/dp/B01JYNEX56/ref=sr_1_2?s=pc&ie=UTF8&qid=1518737045&sr=1-2&keywords=micro+sd+card+adapter+board
I have tried the SD_MMC but haven't been able to get it to work.
Sketch:
I get:
5004: MB per Second: 0.2 :Seconds per MB: 5: numMB 1 buffSize 512
4330: MB per Second: 0.25 :Seconds per MB: 4: numMB 1 buffSize 1024
4812: MB per Second: 0.25 :Seconds per MB: 4: numMB 1 buffSize 2046
46069: MB per Second: 0.217391 :Seconds per MB: 4.6: numMB 10 buffSize 512
45727: MB per Second: 0.222222 :Seconds per MB: 4.5: numMB 10 buffSize 1024
45967: MB per Second: 0.222222 :Seconds per MB: 4.5: numMB 10 buffSize 2046
Debug Messages:
The text was updated successfully, but these errors were encountered: