Hello, I need a smaller SD library for my proyect, the result it's too big for my Arduino Leonardo, somebody can help me?.
Best regards.
Hello, I need a smaller SD library for my proyect, the result it's too big for my Arduino Leonardo, somebody can help me?.
Best regards.
the result it's too big for my Arduino Leonardo
The class uses to much code space? Or the class uses too much SRAM?
somebody can help me?.
Not if it's an SRAM issue. It isn't a library problem. It's a matter of needing a 512 byte buffer to match the physical characteristics of the card.
Here is the smallest SD library. It has lots of quirks and restrictions to get around the 512 byte buffer. You can't create or extend files. Petit FAT File System Module. I don't remember where the port to Arduino is located.
Here is a FAT16 only library that saves flash but still needs the 512 byte buffer GitHub - greiman/Fat16: Smaller FAT16 only library for Arduino.
I wrote a read only library for FAT16/FAT32 that avoided the 512 byte buffer but have not maintained it. It was part of this project Google Code Archive - Long-term storage for Google Code Project Hosting..
how much space is used by the other/your code?
can you post it?
we might see alternatives....
I achieved a modest savings of 3.5K code space and 88 bytes of ram simply by using sdfat instead of sd.
I've been doing a lot of playing around with the SD library the past few days, and found it eats approx 1 KByte of RAM, even for the simplest of SD examples [that also have a Serial.print() in them]. Use of too much code space is a minor issue. Eg, see reply #25 on this thread,
http://forum.arduino.cc/index.php?PHPSESSID=3tmm5qr7fols0shinfc8mq8s05&topic=276274.0
So, if using a mega328 with only 2KB of RAM, you're NOT gonna be able to do many other extensive operations, in general, before overrunning the RAM space. I'm moving my programs using the SD card over to the mega1284 or mega2560 chip.
One thing you can try, if your program uses a lot static char strings, is to use the F() operator which prevents the strings from loading into RAM on bootup. This has freed up an enormous amount of RAM in my programs.
Eg, Serial.print( F("keep this string out of RAM") );
You also want to put the following code check in all of your programs.
http://playground.arduino.cc/Code/AvailableMemory
/*********************************************/
void display_freeram()
{
Serial.print(F("-SRAM left="));
Serial.println(freeRam());
}
/*************************************************/
int freeRam()
{
extern int __heap_start,*__brkval;
int v;
return (int)&v - (__brkval == 0
? (int)&__heap_start : (int) __brkval);
}
oric_dan:
I've been doing a lot of playing around with the SD library the past few days, and found it eats approx 1 KByte of RAM, even for the simplest of SD examples [that also have a Serial.print() in them]. Use of too much code space is a minor issue......So, if using a mega328 with only 2KB of RAM, you're NOT gonna be able to do many other extensive operations, in general, before overrunning the RAM space. I'm moving my programs using the SD card over to the mega1284 or mega2560 chip.
I'm not sure how you measured the ram usage. I took a sketch and commented out the references to SdFat and the ram usage fell by about 650 bytes, not 1K. The actual usage is likely a bit less than the difference I measured.
As for code space not being an issue, speak for yourself. I'm near the limit with both flash and ram and was thrilled to get a 10% savings with so little effort. I'll have to take a look at that Fat16 library.
In addition to optimizing one's own sketch I have found it possible to save large amounts of code and sram by reworking libraries.
In addition to optimizing one's own sketch I have found it possible to save large amounts of code and sram by reworking libraries.
So how did you go about "reworking" the libraries?
In addition to optimizing one's own sketch I have found it possible to save large amounts of code and sram by reworking libraries.
I spend a lot of time minimizing the size of SdFat. You can throw away things you don't need but it is not likely to change the size of your program. member functions you don't need are not loaded.
Here is an example of the minimum flash and RAM required to write a file.
I used a small unbuffered Serial library to to avoid the large Serial RAM requirement.
I am using the an SdFat development version so your number will vary.
With 1.06 on an Uno and no SdFat code:
#include "SdFat.h"
#include "MinimumSerial.h"
#include "SdFatUtil.h"
MinimumSerial MinSerial;
void setup() {
MinSerial.begin(9600);
MinSerial.println(FreeRam());
}
void loop() {}
This program uses 1,484 bytes of flash and has 2,010 bytes of free ram.
Here is the minimal SdFat program:
#include "SdFat.h"
#include "MinimumSerial.h"
#include "SdFatUtil.h"
MinimumSerial MinSerial;
SdFat sd;
SdFile file;
void setup() {
MinSerial.begin(9600);
MinSerial.println(FreeRam());
sd.begin();
file.open("A", FILE_WRITE);
file.println(123);
}
void loop() {}
This program uses 9,966 bytes of flash and has 1,375 bytes of free RAM. So SdFat added 8482 bytes of flash and used 635 bytes of RAM.
Here is a similar test for SD.h
With no SD.h code and using Serial since the unbuffered serial has a conflict, SD.h causes Serial to be loaded.
int FreeRAM() {
extern char *__brkval;
extern char __bss_end;
char top;
return __brkval ? &top - __brkval : &top - &__bss_end;
}
void setup() {
Serial.begin(9600);
Serial.println(FreeRAM());
}
void loop() {}
This program uses 2,476 bytes of flash and has 1,840 bytes of free RAM.
Here is the test program with SD.h code added:
#include <SD.h>
int FreeRAM() {
extern char *__brkval;
extern char __bss_end;
char top;
return __brkval ? &top - __brkval : &top - &__bss_end;
}
File file;
void setup() {
Serial.begin(9600);
Serial.println(FreeRAM());
SD.begin();
file = SD.open("A", FILE_WRITE);
file.println(123);
}
void loop() {}
This program uses 13,566 bytes of flash and has 1,154 bytes of free RAM.
Note that you can not reduce the flash or free RAM much by removing Serial. With Serial.begin() and Serial.print() removed, the program still requires 13,234 byte of flash and will still use about the same amount of RAM because of the unused Serial buffers.
The reason Serial is always included in SD.h is that I had not optimized the ancient version of SdFat that was used as the base for SD.h.
oric_dan:
So how did you go about "reworking" the libraries?
Case by case basis. Sometimes a decent amount of fluff can be removed. Libraries are not tuned to be minimal size for my personal application. They're usually written to be adaptable for many circumstances. Using SdFat instead of SD was an easy one requiring only minor changes to my sketch. I'm still not sure what the SD wrapper actually buys anyone.
In one case I took a library for a display device and its accompanying universal graphics library. I only wanted to output text. I started with someone else's text-only library for this display and edited it line by line. When I was done the ram usage fell from about about 1300 bytes in the original graphics library to 50 bytes with the edited text library. The flash usage also dropped considerably.
I've been reluctant to start editing SdFat because it is far more complicated and I suspect would involve a slower test cycle. My hope is to trim everything else to make my project fit along with SdFat or some other FAT card library. But if it comes to it...
fat16lib:
I spend a lot of time minimizing the size of SdFat. You can throw away things you don't need but it is not likely to change the size of your program. member functions you don't need are not loaded.
Yes, thanks. I figured that out already.
fat16lib:
Here is the minimal SdFat program.... So SdFat added 8482 bytes of flash and used 635 bytes of RAM.
That's almost exactly the same as what I measured. It's really not that bad. But fitting code and memory is going to be close so I'm looking at everything carefully.
I've been reluctant to start editing SdFat because it is far more complicated and I suspect would involve a slower test cycle
SdFat is the fifth SD/FAT library I have written in the last six years. I would love to see you trim it to a far smaller size while maintaining the functionality.
One problem is that I am soon going to replace all the base code with my new generic FAT library that will support FAT12/FAT16/FAtT32 on any block device.
I wrote a limited functionality SD library that easily fit in the 2 KB boot area of a ATmega328 with loader code. It can open a file for read on a FAT16 volume and read the file a byte at a time. The idea was to put a binary file on an SD and the loader would look for an SD with the correct file name and flash the ATmega. I didn't find much interest so I didn't go beyond prototype stage.
This development test uses a total 1,646 bytes of flash. The actual library uses less than 1 KB of flash and the rest is the Arduino support code.
#include <SdBoot.h>
void setup() {
// Initialize the SD and open TEST.BIN
fileOpen((uint8_t*)"TEST BIN"); // FAT internal form of a file name.
// read a byte
fileRead();
}
void loop() {}
BTW, I get the following warnings when using the SDFat library with IDE v1.0.5. I always get a gazillion of the first one in all my programs, but the others may be of interest.
C:\Documents and Settings\Dan\My Documents\Arduino\libraries\SdFat\istream.cpp:
In member function 'void istream::getBool(bool*)':
C:\Documents and Settings\Dan\My Documents\Arduino\libraries\SdFat\istream.cpp:93:
warning: only initialized variables can be placed into program memory area
............
C:\Documents and Settings\Dan\My Documents\Arduino\libraries\SdFat\StdioStream.cpp:
In member function 'char* StdioStream::fgets(char*, int, size_t*)':
C:\Documents and Settings\Dan\My Documents\Arduino\libraries\SdFat\StdioStream.cpp:58:
warning: comparison between signed and unsigned integer expressions
C:\Documents and Settings\Dan\My Documents\Arduino\libraries\SdFat\StdioStream.cpp:
In member function 'size_t StdioStream::print(const __FlashStringHelper*)':
C:\Documents and Settings\Dan\My Documents\Arduino\libraries\SdFat\StdioStream.cpp:258:
warning: '__progmem__' attribute ignored
C:\Documents and Settings\Dan\My Documents\Arduino\libraries\SdFat\StdioStream.cpp:260:
warning: suggest parentheses around assignment used as truth value
C:\Documents and Settings\Dan\My Documents\Arduino\libraries\SdFat\StdioStream.cpp:
In member function 'int StdioStream::printDec(signed char)':
C:\Documents and Settings\Dan\My Documents\Arduino\libraries\SdFat\StdioStream.cpp:339:
warning: control reaches end of non-void function
C:\Documents and Settings\Dan\My Documents\Arduino\libraries\SdFat\utility\FmtNumber.cpp:
In function 'float scanFloat(const char*, char**)':
C:\Documents and Settings\Dan\My Documents\Arduino\libraries\SdFat\utility\FmtNumber.cpp:350:
warning: 'successPtr' may be used uninitialized in this function
fat16lib:
One problem is that I am soon going to replace all the base code with my new generic FAT library that will support FAT12/FAT16/FAtT32 on any block device.
I presume that means it will get bigger. As long as people are using 8-bit uPs with limited memory there will be niche for tiny versions of code.
I wrote a limited functionality SD library that easily fit in the 2 KB boot area of a ATmega328 with loader code. It can open a file for read on a FAT16 volume and read the file a byte at a time. The idea was to put a binary file on an SD and the loader would look for an SD with the correct file name and flash the ATmega. I didn't find much interest so I didn't go beyond prototype stage.
That sounds like a nice idea. I read of someone recently who wanted to boot load from an SD card.
oric_dan, how do you turn on warnings?
Is it just using the compilation verbose output of the IDE?
I presume that means it will get bigger. As long as people are using 8-bit uPs with limited memory there will be niche for tiny versions of code.
No in fact I have found enough optimizations to keep it the same size or smaller. Generalized code does not need to be larger.
warning: only initialized variables can be placed into program memory area
Most of the warnings in SdFat are due to putting strings in flash memory. This is a problem with the old version of gcc in the Arduino IDE.
This program:
void setup() {
Serial.begin(9600);
Serial.println(F("flash"));
}
void loop() {}
Gives this warning.
sketch_nov04a.ino: In function 'void setup()':
sketch_nov04a.ino:3: warning: only initialized variables can be placed into program memory area
I check the warnings and fix the ones that matter. There are some intentionally uninitialized variables where a function fails and returns before a variable is initialized. Some others are in code being developed but not yet made public.
jboyton:
oric_dan, how do you turn on warnings?
Is it just using the compilation verbose output of the IDE?
Yeah. This will also show you the \Temp directory that the compile builds use, assuming you're using Windows [although I'm not sure about the latest versions].
If you check in there [\Local Settings\Temp will be hidden BTW, and you have to change the Property setting], you'll likely find a gazillion old compile build folders that Windoze and the IDE never cleaned up. On my old NotebookPC, I discovered over 20GB of Temp crap that the non-existent WindozeGarbageCollector never erased. Basically, they're all unnecessary trash, I do believe - I erase them constantly.
The other thing is, if you're not using an external editor, you can select it in Preferences, open a sketch, and then drag the sketch files into the editor. Really nice if you have many tabs [separate .ino files] in your sketches, as you can just drag in the ones you want to work on. I use NP++. After editing, you simply save the files, and they are automatically used by the IDE when you click the Compile button.
I find this useful, since in the past, I've had to do a huge amount of 3rd library debugging, as almost nothing would work properly with the mega1284 chip, so I would display and work on both the sketch files and library files in NP++ simultaneously.
fat16lib:
No in fact I have found enough optimizations to keep it the same size or smaller. Generalized code does not need to be larger.
I see. So the problem is that I'd be using soon-to-be-outdated code if I started fiddling with SdFat.
At present I'm interested in a specific subset of the functionality. But it's a different subset than what uFAT or Petit FAT offers. I may take a look and see if there's anything I can do but I get the sense that there won't be easy plums to pick.
oric_dan, thanks for the tips. I have an iMac and 1.0.5 IDE. It appears that the IDE is cleaning up after itself fairly well, or maybe OS X is cleaning up after the IDE. Either way the cryptic temp directories aren't filled with Arduino junk.
I have used the verbose output before in order to generate assembly listings. It's an annoying, manual process though.
I use the verbose settings just to watch the compile process, look for errors [unfortunately they are shown in the same font color as the many 1000s of warning msgs you ALWAYS get, deprecated this and that sillliness], and then watch the uploading to the board.
It sounds like the Mac has a real Garbage Collector. The IDE doesn't clean the temp directories, and neither does Windoze, so over time you end up with 20GB of crap.