chipKIT® Development Platform

Inspired by Arduino™

SD low performance

Created Fri, 02 Aug 2013 13:03:16 +0000 by Mentor


Mentor

Fri, 02 Aug 2013 13:03:16 +0000

Hi, I have a protoboard with PIC32MX795 and microSD card mounted on it. I got a code from the author to test sd writing so he says the performance of writing 600 bytes is around 70 msec.

this is the code:

#include <SD.h>
#include <UTFT.h>
#include <SPI.h>

extern uint8_t SmallFont[];
const int chipSelect = 53;
File file;
UTFT myGLCD(ITDB43,85,84,83,82);   // Remember to change the model parameter to suit your display module!

void setup() {
  pinMode(53, OUTPUT);
  SD.begin(53);
  myGLCD.InitLCD();
   myGLCD.setFont(SmallFont);
   myGLCD.clrScr();
  myGLCD.print("Initializing SD card...",CENTER,1);
  file = SD.open("WR_TEST2.TXT", O_CREAT | O_WRITE);

  while(millis() < 1000);  // delay so mills() is four digits
 
  for (uint8_t i = 0; i < 100; i++) {
    file.println(millis());
  myGLCD.print(millis(),CENTER,10);  
}
  // not needed in this example since close() will call flush.
  file.flush();  
 
  file.close();
}
void loop() {}

I adapted the code to work with UTFT and my SSD1963 LCD. It works fine but the performance is very poor, 1280 msec to write those 600 bytes. Have to say that my board uses SPI4 so I decided to connect the LCD built-in socket to the standard port many people uses around here and got the same performance.

Any help?

Thanks.


majenko

Fri, 02 Aug 2013 17:51:59 +0000

How about if you don't write to the Graphical LCD while writing to the file? Just record the millis() when you start, record it again at the end, then subtract one from the other.

unsigned long start = millis();
  for (uint8_t i = 0; i < 100; i++) {
    file.println(millis());
  }
  unsigned long end = millis();

  myGLCD.print(end - start, CENTER, 10);

I can't imagine displaying things on a GLCD is particularly fast - especially though SPI.


Mentor

Sat, 03 Aug 2013 09:36:31 +0000

Thank you majenko for your reply. Time has been reduced to 287 msec. which is average but enough. Was trying to test the performance of SD because my tests are about reading from SD and writing to LCD. I guess that reading will be faster (obviously). Would be nice if you can put an example to read into RAM from SD a large amount of data to display on GLCD.

Thanks.


majenko

Sat, 03 Aug 2013 10:21:42 +0000

Reading and writing from/to an SD card is a very subjective thing. SD cards are notoriously slow at writing to using SPI, and different classes of cards (and even different makes of card in the same class) perform very differently. Also the age of the card (amount it has been used, not time age) has an effect. The more a card has been written to the longer it takes for a cell to erase before being written to (when it starts to take too long that cell is deemed to be "dead" and is removed from the card's cell allocation tables).

I have a product in the design pipeline which can record audio to an SD card. It uses much more efficient code than is used in the SD library (it's based on the SD driver for RetroBSD running on a 16-bit chip with 16-bit FIFO driven transfers), and still it cannot record at more than 22KHz in mono as it can't write to the card fast enough. It can, however, play audio at 48KHz in 16-bit stereo, so reading is considerably faster than writing.


Mentor

Tue, 06 Aug 2013 09:18:38 +0000

Ok, I got it running but I don´t know what I´m doing wrong because I have a file named "test1.txt" with 12 char "0927012A0445" into SD. The project is about reading from SD and writing to LCD using UTFT library. I´m having strange results, this is the code:

#include <SD.h>
#include <UTFT.h>
#include <SPI.h>

extern uint8_t BigFont[];
const int chipSelect = 53;
unsigned short buff[10];
char buf[12];
unsigned short buf1;
int i;
File file;

UTFT myGLCD(ITDB43,85,84,83,82);   // Remember to change the model parameter to suit your display module!


void setup() {
  pinMode(53, OUTPUT);
  SD.begin(53);  // Initalize SD.
  myGLCD.InitLCD();  // Initialize LCD.
  myGLCD.setFont(BigFont);  // Big font for printing if needed.
   myGLCD.clrScr();
   file = SD.open("test1.txt"); // Open file test1.txt. It has 12 char into.
     for (int d = 0; d < 2; d++)  // Read 2 sets of 4 characters.
 {
     for (i = 0; i < 4; i++) // Read 4 characters each time.
   {
     buf[i] =file.read() & 0xf;  // Read the hex value of each byte from SD.
   }
     buf1= ((buf[0]*4096)+(buf[1]*256)+(buf[2]*16)+(buf[3])); // Converts 4 characters into one short variable.
     buff[d]=buf1;  // Store converted value.
 }
     myGLCD.print(buff[1],CENTER,1); 
     
        file.close();
}
void loop() {}

The first 4 characters "0927" are correct so when I print I get 2343 after conversion but the 4 next characters "012A" looks like 289 after conversion instead of 298 and so on with the last 4 chars. I checked it individually and the 4 first chars are ok(0927), the 1st of the next 4 chars is wrong( 12A) instead of (012A). Can anyone help?.

Thanks.


pito

Wed, 07 Aug 2013 20:57:25 +0000

It uses much more efficient code than is used in the SD library (it's based on the SD driver for RetroBSD running on a 16-bit chip with 16-bit FIFO driven transfers), and still it cannot record at more than 22KHz in mono as it can't write to the card fast enough.

That is unbelievable.. You have to make 400-600kB/sec writing easily. Your problem might be the latency of the sdcard (up to 250msecs) so you need a FIFO for your samples - size of 2x8x44100/4 bytes at least, imho..


majenko

Wed, 07 Aug 2013 21:41:22 +0000

That is unbelievable.. You have to make 400-600kB/sec writing easily. Your problem might be the latency of the sdcard (up to 250msecs) so you need a FIFO for your samples - size of 2x8x44100/4 bytes at least, imho..

Ain't gonna happen... The chip is a dsPIC33FJ128GP802, so 2x8x44100/4 (176400 bytes) is only about 10.77 times the total memory in the entire chip.

I'm using the microchip MDDFS library but with my own block read/write (based on your code adapted for 16 bit) routines. It's marginally quicker than the standard MDDFS block read/write routines.

Actually, thinking about it, it tops out at 22050 in stereo, not mono, so 44100 in mono. It can't do stereo at 44100, and it can't do 48000 in mono. 22050 in stereo is actually just over the limit - you start to hear the odd bit of skipping where it can't quite keep up.

Part of the issue might be that the writing happens inside the DMA interrupt for the ADC. It only deals with 128 or 256 samples at a time (mono or stereo), so 256 or 512 byte chunks, and that write has to happen in less than the time it takes to read the next block of samples from the ADC.


pito

Thu, 08 Aug 2013 07:40:30 +0000

Sorry: 2x44100/4 in bytes for 250ms (22kbytes, mono). The above number was in bits :)


majenko

Thu, 08 Aug 2013 08:58:59 +0000

Sorry: 2x44100/4 in bytes for 250ms (22kbytes, mono). The above number was in bits :)

With only 16KB to play with that's still over the top - not that I have any memory to spare anyway, what with DMA buffers, SD card buffers, file buffers - it all adds up.