Maximum constant string space

I am working on a sketch that responds to serial messages and have included a help function that will send out a protocol and command list via Serial.print. When I include the (rather long) list of help text in the SendHelp function, my sketch doesn't start properly, or doesn't start at all.

The sketch shows a short serial message when it starts to identify itself. This is about 10 characters. When the sketch doesn't start this message doesn't complete.

I don't call the SendHelp function. I only have to create it to cause the problem.

When the SendHelp function is like this my sketch works

void SendHelp() { return; Serial.println("blah blah blah blah blah blah blah blah blah blah blah blah blah blah "); Serial.println("blah blah blah blah blah blah blah blah blah blah blah blah blah blah "); Serial.println("blah blah blah blah blah blah blah blah blah blah blah blah blah blah "); Serial.println("blah blah blah blah blah blah blah blah blah blah blah blah blah blah "); Serial.println("blah blah blah blah blah blah blah blah blah blah blah blah blah blah "); }

If I remove the "return;" line then my sketch stops in the Setup() function. NB. I don't call SendHelp!

I can't work out if it is the length of some of the lines, or the amount of constant text that causes the problem. I can move the return line down through the function, and everything works until I get to a point where it stops.

I read that the serial interface had buffer limits so I have made some strings 100 chars long and they still work.

Why does the function affect the sketch when it isn't called? Is there a limit to how much constant text I can have? Can I overload the Serial.print function and crash it?

Any help appreciated TIA Steve

Is there a limit to how much constant text I can have?

C doesn’t know that literal strings are constant. In fact, you can modify them. :frowning:
This means that your “blah blah” string ends up stored in RAM, and is limited by the amount of RAM available (somewhat less than 2k.) If the function is included in your sketch at all, the string will be initialized (copied from flash) during the initialization that happens even before setup()

You CAN store your printable strings in flash. Search the forums for “progmem”

Why does the function affect the sketch when it isn't called?

You guessed correctly. Your string constants are using up too much memory. They have to be in RAM to be used so before your program starts all the string constants are copied into RAM. When you put the "return" at the top of your functions the compiler was smart enough to realize that the constants would never be used so it left them out.

Is there a limit to how much constant text I can have?

Yes. RAM is a very limited resource.

Can I overload the Serial.print function and crash it?

Probably not. It has no reason to make a copy of your character string so a long string shouldn't cause any more strain on Serial.print() than a short character string.

Thanks John

3 days for me too. This explains everything - thank you!

So... where can I see the linker map to find out where things are landing in memory?

warren_spencer_1977:

So… where can I see the linker map to find out where things are landing in memory?

Run avr-size on the .elf file in the sketch library. Here’s what I found from the example that I show below:

From avr-size after compiling with avr-gcc 4.3.4 on my Linux system:


[dave@starrx tmp]$  avr-size build5021398062739215153.tmp/*.elf
   text    data     bss     dec     hex filename
   3296      34     168    3498     daa build5021398062739215153.tmp/sketch_jun28b.cpp.elf

The number in the “text” column tells you how much program memory the sketch is using.

The number in the “data” column is the number of bytes in RAM storage that are initialized upon startup. This number will include the number of bytes in const C-style “strings,” or char arrays that are initialized with C-style “strings,” since the “strings” have to be copied from program memory to RAM in the avr-gcc initialization code so that programs can access them normally.

The number in the “bss” column is the number of bytes in RAM static storage.
The sum of the “data” and “bss” numbers do not give the total RAM usage, since they don’t take stack size, heap size or storage for automatic variables into consideration. But you can see how the “data” number grows if you add “normal” C-style strings to the sketch.

The Arduino PROGMEM Reference page gives some information and examples about how to get constant strings (and other constant stuff) into program memory and save some RAM.

Even better (I think)…

Mikal Hart’s Flash library is, in my opinion, an absolutely marvelous set of classes that not only makes it easier (well, it seems easier to me) to get strings (and other stuff) into (and out of) program memory but implements a streaming operator that allows you to access data from program memory without having to copy it into data RAM. It has ways of creating 1-D data arrays and 2-D data tables, not just strings

A simplified demo of some of the string stuff:

// Mikal Hart's Flash library and streaming operator
//
// davekw7x
//
#include <Flash.h>

FLASH_STRING(kirkUniverse, // The name of the "string"
        "What is a man but that lofty spirit, that sense of ...\n"
        "enterprise? That devotion to something that cannot be\n"
        "sensed, cannot be realized, but only ... dreamed!\n"
        "\n--- Capt. James T. Kirk\n");
        
FLASH_STRING(adamsUniverse,
        "There is a theory that if anyone ever figures out exactly\n"
        "what the universe is for and why it is here, it will instantly\n"
        "disappear and be replaced by something even more bizarre and\n"
        "{inexplicable.\n\n"
        "There is another that this has already happened.\n"
        "--- Douglas Adam\n");


void setup()
{
    Serial.begin(115200);
    delay(1000);
    Serial << F("This is an example of streaming a string.  The string is in program memory, not RAM\n");
    
    Serial << F("Now, here's an example of named string in PROGMEM\n");
    Serial << F("The size of the string in PROGMEM is ") << kirkUniverse.length() << " bytes.\n";
    Serial << F("The string takes up ") << sizeof(kirkUniverse) << F(" bytes in RAM.\n");
    
    Serial << F("\nHere's the string:\n\n");
    Serial << kirkUniverse;
   
    
    Serial << F("\n\nWanna see another??? OK:\n\n");
    Serial << adamsUniverse;
 
    Serial << F("\n\nRegards, Dave\n");    
}

void loop(){}

Output from the program


This is an example of streaming a stream.  The string is in program memory, not RAM
Now, here's an example of named string in PROGMEM
The size of the string in PROGMEM is 184 bytes.
The string takes up 4 bytes in RAM.

Here's the string:

What is a man but that lofty spirit, that sense of ...
enterprise? That devotion to something that cannot be
sensed, cannot be realized, but only ... dreamed!

--- Capt. James T. Kirk


Wanna see another??? OK:

There is a theory that if anyone ever figures out exactly
what the universe is for and why it is here, it will instantly
disappear and be replaced by something even more bizarre and
inexplicable.

There is another that this has already happened.
--- Douglas Adam


Regards, Dave

Footnote:
So: You can create strings in program memory and use their names in various ways or you can create instant strings “on the fly” without using space in data RAM.

Keep building more and more strings in program memory (or use more Serial << F(“whatever”:wink: strings in output statements). The RAM requirements do not grow.

Add some “normal” strings, like Serial.println(“whatever”);, and you can see that the “text” (Program Memory) requirements grow as do the “data” (RAM) requirements.

What’s not to like??? Well it’s a new kind of output statement for some Arduino programmers (not harder, I think, just different), but for C++ guys, it’s like a breath of fresh air, right? I mean, the library functions take some space (nothing is free, right)? But the simplicity and convenience of the Flash library notation just gasts my flabber.

Keep paying attention, folks, it’s my understanding that things like the “streaming strings” stuff are coming in an official Arduino release, “real soon, now.”

Thanks! This is awesome information!!