-
-
Save pawitp/9ed4e7ab00cef0e3d5c1b51ed179c22e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* This program is a simple binary write/read benchmark. | |
* Original from https://github.com/earlephilhower/ESP8266SdFat/blob/1.0.8/examples/bench/bench.ino | |
* Modified by pawitp to test multiple block sizes. | |
*/ | |
#include <SPI.h> | |
#include "SdFat.h" | |
#include "sdios.h" | |
#include "FreeStack.h" | |
using namespace sdfat; | |
// Set USE_SDIO to zero for SPI card access. | |
#define USE_SDIO 0 | |
// SD chip select pin | |
const uint8_t chipSelect = SS; | |
// Size of read/write. | |
const size_t MIN_BUF_SIZE = 512; | |
const size_t MAX_BUF_SIZE = 16 * 1024; | |
// File size in MB where MB = 1,000,000 bytes. | |
const uint32_t FILE_SIZE_MB = 5; | |
// Write pass count. | |
const uint8_t WRITE_COUNT = 2; | |
// Read pass count. | |
const uint8_t READ_COUNT = 2; | |
//============================================================================== | |
// End of configuration constants. | |
//------------------------------------------------------------------------------ | |
// File size in bytes. | |
const uint32_t FILE_SIZE = 1000000UL*FILE_SIZE_MB; | |
uint8_t buf[MAX_BUF_SIZE]; | |
// file system | |
#if USE_SDIO | |
// Traditional DMA version. | |
// SdFatSdio sd; | |
// Faster version. | |
SdFatSdioEX sd; | |
#else // USE_SDIO | |
SdFat sd; | |
#endif // USE_SDIO | |
// Set ENABLE_EXTENDED_TRANSFER_CLASS to use extended SD I/O. | |
// Requires dedicated use of the SPI bus. | |
// SdFatEX sd; | |
// Set ENABLE_SOFTWARE_SPI_CLASS to use software SPI. | |
// Args are misoPin, mosiPin, sckPin. | |
// SdFatSoftSpi<6, 7, 5> sd; | |
// test file | |
SdFile file; | |
// Serial output stream | |
ArduinoOutStream cout(Serial); | |
//------------------------------------------------------------------------------ | |
// Store error strings in flash to save RAM. | |
#define error(s) sd.errorHalt(F(s)) | |
//------------------------------------------------------------------------------ | |
void cidDmp() { | |
cid_t cid; | |
if (!sd.card()->readCID(&cid)) { | |
error("readCID failed"); | |
} | |
cout << F("\nManufacturer ID: "); | |
cout << hex << int(cid.mid) << dec << endl; | |
cout << F("OEM ID: ") << cid.oid[0] << cid.oid[1] << endl; | |
cout << F("Product: "); | |
for (uint8_t i = 0; i < 5; i++) { | |
cout << cid.pnm[i]; | |
} | |
cout << F("\nVersion: "); | |
cout << int(cid.prv_n) << '.' << int(cid.prv_m) << endl; | |
cout << F("Serial number: ") << hex << cid.psn << dec << endl; | |
cout << F("Manufacturing date: "); | |
cout << int(cid.mdt_month) << '/'; | |
cout << (2000 + cid.mdt_year_low + 10 * cid.mdt_year_high) << endl; | |
cout << endl; | |
} | |
//------------------------------------------------------------------------------ | |
void setup() { | |
Serial.begin(9600); | |
// Wait for USB Serial | |
while (!Serial) { | |
SysCall::yield(); | |
} | |
delay(1000); | |
cout << F("\nUse a freshly formatted SD for best performance.\n"); | |
// use uppercase in hex and use 0X base prefix | |
cout << uppercase << showbase << endl; | |
} | |
//------------------------------------------------------------------------------ | |
void loop() { | |
float s; | |
uint32_t t; | |
uint32_t maxLatency; | |
uint32_t minLatency; | |
uint32_t totalLatency; | |
// Discard any input. | |
do { | |
delay(10); | |
} while (Serial.available() && Serial.read() >= 0); | |
// F( stores strings in flash to save RAM | |
cout << F("Type any character to start\n"); | |
while (!Serial.available()) { | |
SysCall::yield(); | |
} | |
cout << F("chipSelect: ") << int(chipSelect) << endl; | |
cout << F("FreeStack: ") << FreeStack() << endl; | |
cout << F("USE_MULTI_BLOCK_IO: ") << USE_MULTI_BLOCK_IO << endl; | |
cout << F("USE_SEPARATE_FAT_CACHE: ") << USE_SEPARATE_FAT_CACHE << endl; | |
#if USE_SDIO | |
if (!sd.begin()) { | |
sd.initErrorHalt(); | |
} | |
#else // USE_SDIO | |
// Initialize at the highest speed supported by the board that is | |
// not over 50 MHz. Try a lower speed if SPI errors occur. | |
if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) { | |
sd.initErrorHalt(); | |
} | |
#endif // USE_SDIO | |
cout << F("Type is FAT") << int(sd.vol()->fatType()) << endl; | |
cout << F("Card size: ") << sd.card()->cardSize()*512E-9; | |
cout << F(" GB (GB = 1E9 bytes)") << endl; | |
cidDmp(); | |
for (int bufSize = MIN_BUF_SIZE; bufSize <= MAX_BUF_SIZE; bufSize *= 2) { | |
// open or create file - truncate existing file. | |
if (!file.open("bench.dat", O_RDWR | O_CREAT | O_TRUNC)) { | |
error("open failed"); | |
} | |
// fill buf with known data | |
for (size_t i = 0; i < (bufSize-2); i++) { | |
buf[i] = 'A' + (i % 26); | |
} | |
buf[bufSize-2] = '\r'; | |
buf[bufSize-1] = '\n'; | |
cout << F("File size ") << FILE_SIZE_MB << F(" MB\n"); | |
cout << F("Buffer size ") << bufSize << F(" bytes\n"); | |
cout << F("Starting write test, please wait.") << endl << endl; | |
// do write test | |
uint32_t n = FILE_SIZE/bufSize; | |
cout <<F("write speed and latency") << endl; | |
cout << F("speed,max,min,avg") << endl; | |
cout << F("KB/Sec,usec,usec,usec") << endl; | |
for (uint8_t nTest = 0; nTest < WRITE_COUNT; nTest++) { | |
file.truncate(0); | |
maxLatency = 0; | |
minLatency = 9999999; | |
totalLatency = 0; | |
t = millis(); | |
for (uint32_t i = 0; i < n; i++) { | |
uint32_t m = micros(); | |
if (file.write(buf, bufSize) != bufSize) { | |
sd.errorPrint("write failed"); | |
file.close(); | |
return; | |
} | |
m = micros() - m; | |
if (maxLatency < m) { | |
maxLatency = m; | |
} | |
if (minLatency > m) { | |
minLatency = m; | |
} | |
totalLatency += m; | |
} | |
file.sync(); | |
t = millis() - t; | |
s = file.fileSize(); | |
cout << s/t <<',' << maxLatency << ',' << minLatency; | |
cout << ',' << totalLatency/n << endl; | |
} | |
cout << endl << F("Starting read test, please wait.") << endl; | |
cout << endl <<F("read speed and latency") << endl; | |
cout << F("speed,max,min,avg") << endl; | |
cout << F("KB/Sec,usec,usec,usec") << endl; | |
// do read test | |
for (uint8_t nTest = 0; nTest < READ_COUNT; nTest++) { | |
file.rewind(); | |
maxLatency = 0; | |
minLatency = 9999999; | |
totalLatency = 0; | |
t = millis(); | |
for (uint32_t i = 0; i < n; i++) { | |
buf[bufSize-1] = 0; | |
uint32_t m = micros(); | |
int32_t nr = file.read(buf, bufSize); | |
if (nr != bufSize) { | |
sd.errorPrint("read failed"); | |
file.close(); | |
return; | |
} | |
m = micros() - m; | |
if (maxLatency < m) { | |
maxLatency = m; | |
} | |
if (minLatency > m) { | |
minLatency = m; | |
} | |
totalLatency += m; | |
if (buf[bufSize-1] != '\n') { | |
error("data check"); | |
} | |
} | |
s = file.fileSize(); | |
t = millis() - t; | |
cout << s/t <<',' << maxLatency << ',' << minLatency; | |
cout << ',' << totalLatency/n << endl; | |
} | |
cout << endl << F("Done") << endl; | |
file.close(); | |
delay(15000); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment