Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@pawitp
Created March 7, 2021 07:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pawitp/9ed4e7ab00cef0e3d5c1b51ed179c22e to your computer and use it in GitHub Desktop.
Save pawitp/9ed4e7ab00cef0e3d5c1b51ed179c22e to your computer and use it in GitHub Desktop.
/*
* 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