Curious about your T3.5/3.6 microSD write speed and write latency?
Here's a simple benchmark, derived from https://github.com/greiman/SdFat/blo...sySdioDemo.ino
Shows sequential write speed, average write latency (for given transfer size) and worst case write latency:
Code:
// SdFatSdioEx simple performance test for Teensy 3.5/3.6 onboard uSD
#include "SdFat.h"
#define SERIAL_SPEED 115200
#define BLOCK_DIM 512
// Check SD free space!
#define PREALLOCATED_BLOCKS 512000UL // 256 MB; compromise between statistics and total benchmark time
#define BUF_DIM 256*BLOCK_DIM // 128KiB: will comfortably fit T3.5/3.6
#define FILE_SIZE PREALLOCATED_BLOCKS*BLOCK_DIM
SdFatSdioEX sdEx;
File file;
uint8_t buf[BUF_DIM];
// buffer as uint32_t
uint32_t* buf32 = (uint32_t*)buf;
void errorHalt(const char* msg)
{
sdEx.errorHalt(msg);
}
//------------------------------------------------------------------------------
uint32_t kHzSdClk()
{
return sdEx.card()->kHzSdClk();
}
//------------------------------------------------------------------------------
////////////
// RUNTEST
////////////
void runTest()
{
// Fill buffer with 0
memset(buf32, 0, sizeof(buf32));
// Zero Stats
uint32_t singleWriteMicros = 0;
uint32_t maxSingleWriteMicros = 0;
if (!file.open("TeensyDemo.bin", O_RDWR | O_CREAT))
{
errorHalt("open failed");
}
Serial.println("\nPreallocating file (takes awhile)...\n");
// Preallocate (off cycle)
for (uint32_t i = 0; i < PREALLOCATED_BLOCKS; i++)
{
uint32_t nblocks = file.write(buf, BLOCK_DIM);
if (nblocks != BLOCK_DIM)
{
errorHalt("Preallocation failed");
}
}
file.rewind();
Serial.println("Starting write benchmark");
delay(2000);
Serial.println("\nTransfer size\tWrite speed\tAvg write time\tMax write time");
Serial.println("bytes\t\tKB/s\t\tus\t\tus\n");
for (size_t nb = BLOCK_DIM; nb <= BUF_DIM; nb *= 2)
{
maxSingleWriteMicros = 0;
uint32_t nRdWr = FILE_SIZE/nb;
Serial.print(nb);
Serial.print("\t\t");
uint32_t t = micros();
for (uint32_t n = 0; n < nRdWr; n++)
{
singleWriteMicros = micros();
if (nb != file.write(buf, nb))
{
errorHalt("write failed");
}
singleWriteMicros = micros() - singleWriteMicros;
if (singleWriteMicros > maxSingleWriteMicros)
maxSingleWriteMicros = singleWriteMicros;
}
t = micros() - t;
// Write speed
Serial.print(1000.0f*FILE_SIZE/t, 1);
Serial.print("\t\t");
// Avg write time (us)
Serial.print(t / nRdWr);
Serial.print("\t\t");
// Max write time (us)
Serial.println(maxSingleWriteMicros);
file.rewind(); // Ready for next write size
t = micros();
}
file.close();
Serial.print("\n SD clock speed (kHzSdClk): ");
Serial.print(kHzSdClk());
Serial.println(" KHz\n");
Serial.println("Done");
}
//-----------------------------------------------------------------------------
//////////
//
// SETUP
//
//////////
void setup()
{
Serial.begin(SERIAL_SPEED);
while (!Serial);
Serial.println("SdFatSdioEX write benchmark\nSdFatSdioEx uses extended multi-block transfers without DMA");
if (!sdEx.begin())
{
sdEx.initErrorHalt("SdFatSdioEX begin() failed");
}
// make sdEx the current volume.
sdEx.chvol();
runTest();
}
//-----------------------------------------------------------------------------
/////////
//
// LOOP
//
/////////
void loop()
{
}
Results for my Teensy 3.6 overclocked to 240 MHz: card is an old Lexar 4GB class10 (not UHS):
Code:
SdFatSdioEX write benchmark
SdFatSdioEx uses extended multi-block transfers without DMA
Preallocating file (takes awhile)...
Starting write benchmark
Transfer size Write speed Avg write time Max write time
bytes KB/s us us
512 13227.7 38 94524
1024 13316.5 76 94673
2048 13483.4 151 9957
4096 12967.5 315 97443
8192 13206.4 620 95952
16384 13214.3 1239 98412
32768 13189.5 2484 98668
65536 13071.9 5013 193157
131072 13187.0 9939 106151
SD clock speed (kHzSdClk): 48000 KHz
Done
Many thanks to Bill Greiman for his excellent SdFat library!