Teensy 3.1 / SD card test request

Status
Not open for further replies.

tingo

Well-known member
Could someone with a Teensy 3.1, SD shield and an SD card run the following sketch and reply with the results? I've got mixed reports from 3 different people so far. For 2 it fails, but for 1 it runs fine and I'm out of ideas for why that might be the case.

Sketch:

Code:
/*
 * This sketch illustrates raw write functions in SdFat that
 * can be used for high speed data logging.  These functions
 * are used in the WaveRP library to record audio with the
 * Adafruit Wave Shield using the built-in Arduino ADC.
 *
 * The WaveRP library captures data from the ADC in an ISR
 * that is driven driven by timer one.  Data is collected in
 * two 512 byte buffers and written to the SD card.
 *
 * This sketch simulates logging from a source that produces
 * data at a constant rate of one block every MICROS_PER_BLOCK.
 *
 * If a high quality SanDisk card is used with this sketch
 * no overruns occur and the maximum block write time is
 * under 2000 micros.
 *
 * Note: WaveRP creates a very large file then truncates it
 * to the length that is used for a recording. It only takes
 * a few seconds to erase a 500 MB file since the card only
 * marks the blocks as erased; no data transfer is required.
 */

#include <SdFat.h>
#include <SdFatUtil.h>
#include <SPI.h>

// SD chip select pin
const uint8_t chipSelect = SS;

// number of blocks in the contiguous file
const uint32_t BLOCK_COUNT = 10000UL;

// time to produce a block of data
const uint32_t MICROS_PER_BLOCK = 10000;

// file system
SdFat sd;

// test file
SdFile file;

// file extent
uint32_t bgnBlock, endBlock;

// Serial output stream
ArduinoOutStream cout(Serial);
//------------------------------------------------------------------------------
// store error strings in flash to save RAM
#define error(s) sd.errorHalt_P(PSTR(s))
//------------------------------------------------------------------------------
// log of first overruns
#define OVER_DIM 20
struct {
  uint32_t block;
  uint32_t micros;
} over[OVER_DIM];
//------------------------------------------------------------------------------
void setup(void) {
  Serial.begin(115200);
  while (!Serial) {}  // wait for Leonardo
  SPI.begin();
}
//------------------------------------------------------------------------------
void loop(void) {
  while (Serial.read() >= 0) {}
  // pstr stores strings in flash to save RAM
  cout << pstr("Type any character to start\n");
  while (Serial.read() <= 0) {}
  delay(400);  // catch Due reset problem

  cout << pstr("Free RAM: ") << FreeRam() << endl;

  // initialize the SD card at SPI_FULL_SPEED for best performance.
  // try SPI_HALF_SPEED if bus errors occur.
  if (!sd.begin(chipSelect, SPI_FULL_SPEED)) sd.initErrorHalt();

  // delete possible existing file
  sd.remove("RAW.TXT");

  // create a contiguous file
  if (!file.createContiguous(sd.vwd(), "RAW.TXT", 512UL*BLOCK_COUNT)) {
    error("createContiguous failed");
  }
  // get the location of the file's blocks
  if (!file.contiguousRange(&bgnBlock, &endBlock)) {
    error("contiguousRange failed");
  }
  //*********************NOTE**************************************
  // NO SdFile calls are allowed while cache is used for raw writes
  //***************************************************************

  // clear the cache and use it as a 512 byte buffer
  uint8_t* pCache = (uint8_t*)sd.vol()->cacheClear();

  // fill cache with eight lines of 64 bytes each
  memset(pCache, ' ', 512);
  for (uint16_t i = 0; i < 512; i += 64) {
    // put line number at end of line then CR/LF
    pCache[i + 61] = '0' + (i/64);
    pCache[i + 62] = '\r';
    pCache[i + 63] = '\n';
  }

  cout << pstr("Start raw write of ") << file.fileSize() << pstr(" bytes at\n");
  cout << 512000000UL/MICROS_PER_BLOCK << pstr(" bytes per second\n");
  cout << pstr("Please wait ") << (BLOCK_COUNT*MICROS_PER_BLOCK)/1000000UL;
  cout << pstr(" seconds\n");

  // tell card to setup for multiple block write with pre-erase
  if (!sd.card()->erase(bgnBlock, endBlock)) error("card.erase failed");
  if (!sd.card()->writeStart(bgnBlock, BLOCK_COUNT)) {
    error("writeStart failed");
  }
  // init stats
  uint16_t overruns = 0;
  uint32_t maxWriteTime = 0;
  uint32_t t = micros();
  uint32_t tNext = t;

  // write data
  for (uint32_t b = 0; b < BLOCK_COUNT; b++) {
    // write must be done by this time
    tNext += MICROS_PER_BLOCK;

    // put block number at start of first line in block
    uint32_t n = b;
    for (int8_t d = 5; d >= 0; d--){
      pCache[d] = n || d == 5 ? n % 10 + '0' : ' ';
      n /= 10;
    }
    
    SPI.setBitOrder(MSBFIRST);
    SPI.setClockDivider(SPI_CLOCK_DIV2);
    SPI.setDataMode(SPI_MODE1);
    SPI.transfer(0X15);
    
    // write a 512 byte block
    uint32_t tw = micros();
    if (!sd.card()->writeData(pCache)) error("writeData failed");
    tw = micros() - tw;

    // check for max write time
    if (tw > maxWriteTime) {
      maxWriteTime = tw;
    }
    // check for overrun
    if (micros() > tNext) {
      if (overruns < OVER_DIM) {
        over[overruns].block = b;
        over[overruns].micros = tw;
      }
      overruns++;
      // advance time to reflect overrun
      tNext = micros();
    }
    else {
      // wait for time to write next block
      while(micros() < tNext);
    }
  }
  // total write time
  t = micros() - t;

  // end multiple block write mode
  if (!sd.card()->writeStop()) error("writeStop failed");

  cout << pstr("Done\n");
  cout << pstr("Elapsed time: ") << setprecision(3)<< 1.e-6*t;
  cout << pstr(" seconds\n");
  cout << pstr("Max write time: ") << maxWriteTime << pstr(" micros\n");
  cout << pstr("Overruns: ") << overruns << endl;
  if (overruns) {
    uint8_t n = overruns > OVER_DIM ? OVER_DIM : overruns;
    cout << pstr("fileBlock,micros") << endl;
    for (uint8_t i = 0; i < n; i++) {
      cout << over[i].block << ',' << over[i].micros << endl;
    }
  }
  // close file for next pass of loop
  file.close();
  Serial.println();
}
 
Here are my results;

Type any character to start
Free RAM: 61351
Start raw write of 5120000 bytes at
51200 bytes per second
Please wait 100 seconds
Done
Elapsed time: 100.000 seconds
Max write time: 200 micros
Overruns: 0

Type any character to start
 
I just ran it here. Had to edit "const uint8_t chipSelect = 4", since I tested with the WIZ820+SD adaptor, which has the SD card chip select on pin 4.

Got this:

Code:
Type any character to start
Free RAM: 57271
Start raw write of 5120000 bytes at
51200 bytes per second
Please wait 100 seconds
Done
Elapsed time: 100.000 seconds
Max write time: 1273 micros
Overruns: 0

I tested with the contents of sdfatlib20131225.zip from this page:

http://code.google.com/p/sdfatlib/downloads/detail?name=sdfatlib20131225.zip&can=2&q=
 
Thanks a lot!

Well that's very weird... It works for everyone except for us here. This is what I get when I run this sketch:

Code:
Type any character to start
Free RAM: 57279
Start raw write of 5120000 bytes at
51200 bytes per second
Please wait 100 seconds
error: writeData failed
SD errorCode: 0X15,0XFF

Would you mind telling which cards you are using? Although we've tried another set of cards with no luck.
 
Front side
sd1.jpg

Back side
sd2.jpg
 
Maybe check your wiring?


Checked it multiple times... Even tried soldering to the pins instead of using the breadboard, just in case. The strangest part is that code runs fine if I substitute line SPI.transfer(0X15); for SPI.transfer(0XFF); or SPI.transfer(0XFE);... So depending on the byte I send before writing to the SD card the write either fails or it doesn't.

I've ordered the SanDisk card, hope it works...
 
If you haven't already tried, try formatting the uSD card with one of the sdfat sketches included. One of the sketches allows you to format it.
Early on, I had a problem with the format. I could read it and mount it in linux, but it caused problems when I used it with sdfat.
 
If you haven't already tried, try formatting the uSD card with one of the sdfat sketches included. One of the sketches allows you to format it.
Early on, I had a problem with the format. I could read it and mount it in linux, but it caused problems when I used it with sdfat.

Tried it with both the official SDFormatter and the sketch, still the same.

I just can't get my head around for why it would work fine with SPI.transfer(0XFF); and won't work with SPI.transfer(0X15); seems pretty arbitrary to me...
 
Just wanted to update you all on my ordeal with the weird behaviour of my SD cards.

This I believe is relevant for anyone trying to put an SD card with another device on the same hardware SPI bus and trying to access that other device in between writes to a contiguous file on the SD card.

So I ordered the SanDisk card that Paul has posted and it works just fine no matter what I try to send between the writeStart and writeData commands.

The cards that didn't work for me are:

ATP 1GB: http://uk.rs-online.com/web/p/secure-digital-cards/7761917/
Swissbit 1GB: http://uk.mouser.com/ProductDetail/...=sGAEpiMZZMtyMAXUUxCBEx7plPSciXQAAyUic2qnjWo=

Now, these cards that didn't work are industrial grade and have proper data sheets which specify their current draw during write in addition to leakage currents etc. The SanDisk cards don't seem to have any proper data sheets (or at least I haven't found these). I was wondering if anyone can name any other cards I could try which have proper data sheets?

Here's the picture of the cards described above:

IMG_1050.jpg
 
FYI - It fails on my Teensys... I am using micro SD adapters that are part of some Adafruit TFT displays, so like Paul have to change to CS=4...

With Lexar 4GB Micro SD HC, I receive the error:
Code:
Type any character to start
Free RAM: 57279
Start raw write of 5120000 bytes at
51200 bytes per second
Please wait 100 seconds
error: writeData failed
SD errorCode: 0X15,0X0

Note: I am able to run the SDCard example programs quickstart and I just used their sdformater program to initialize this card.

Now try again with 2nd card and get the same error. This is a Transcend 4gb 10 micro SD HC
microSD.jpg

Again this card was earlier formated using the SDFat format program and still works with their quickstart program:
Code:
Enter the chip select pin number: 4

Card successfully initialized.

Card size: 4036 MB (MB = 1,000,000 bytes)

Volume is FAT32, Cluster size (bytes): 32768

Files found (name date time size):
PARROT.BMP     2014-05-09 13:40:56 61496
PURPLE.BMP     2014-05-03 19:34:44 230456
RAW.TXT        2000-01-01 01:00:00 5120000

Success!  Type any character to restart.
Kurt
 
FYI - It fails on my Teensys... I am using micro SD adapters that are part of some Adafruit TFT displays, so like Paul have to change to CS=4...

Kurt, just to confirm that it's exactly the same behaviour as I observe would you mind running the same code once again but this time substituting the line with
Code:
SPI.transfer(0X15);
with
Code:
SPI.transfer(0XFF);
and posting your results?

Valentin
 
Yep, appears to be like yours:
Code:
Type any character to start
Free RAM: 57279
Start raw write of 5120000 bytes at
51200 bytes per second
Please wait 100 seconds
Done
Elapsed time: 100.223 seconds
Max write time: 177105 micros
Overruns: 2
fileBlock,micros
3393,177105
3394,65524
 
I am not sure if it helps, but I run the same updated test on a different Teensy 3.1, which has the Adafruit 2.8" TFT shield on it (my breakout board). Again CS SD is pin 4, the program works with SDFats quickstart, also I have been able to run the SD test program (after I made the change I mentioned in other threads), that displays a bitmap on the display. But with your test program, I get:
Code:
Type any character to start
Free RAM: 57279
Can't access SD card. Do not reformat.
SD errorCode: 0XF,0X0

I replaced that shield, with the Adafruit 1.8" TFT shield and ran again (same card)
Code:
Type any character to start
Free RAM: 57279
error: createContiguous failed
SD errorCode: 0X13,0X0
I reran the SDCard quick start and it showed all of the files...
(Note: I tried SPI_HALF...) Did not help
 
Status
Not open for further replies.
Back
Top