SRAM and storing strings

My current project has a lot of variables and a lot of strings, and I don't want it to crash due to a lack of RAM. I though that I could wrap strings in F() to save space, but then I get

warning: only initialized variables can be placed into program memory area

What's this about?

Also, will the compiler/AVRdude tell me if I have too many variables and am going to use up the RAM?

Thanks,

baum

I though that I could wrap strings in F() to save space

Only under certain circumstances. As I can't see your code, I can't tell what you're doing wrong.

will the compiler/AVRdude tell me if I have too many variables and am going to use up the RAM?

I don't think so.

What's this about?

I think that the message is pretty explicit. Flash/PROGMEM is read-only at run time, so placing an uninitialized variable in Flash/PROGMEM means that it can never be assigned a value, which means that placing it in Flash/PROGMEM is a waste of time and code space.

Specifically, what are you doing that causes the compiler to complain? This is the Programming section, where we expect to see code.

At runtime, PROGMEM behaves like a ROM. It is accessible in read-only mode, but its content cannot be changed. Therefore the only time when you can decide what to put into a PROGMEM-variable is at compile time.

Until you show the code, though, no direct advice can be given.

:slight_smile:

You might want to look into an SD card adapter or serial RAM chip(s) and use of the SPI bus.

My code is 10Kbytes and ~300 lines long... I'll just post setup() for now.

/* Science Research Program Yr. 1 2011 - 2012
 * Reaction test
 * 
 * Connections:
 * Button, LED defines in includes.h; EEPROM to I2C SDA (A4) and SCL (A5)
 */

#include <Wire.h>         //Communication with 24LC256
#include <EEPROM.h>       //storage for seeds and other data
#include <EEPROMAnything.h> //write anything to EEPROM.

#include "includes.h"     //preferences, defines, macros, etc.

unsigned long subjectNumber = 0; //subject number

//For time storage
byte currentRound;  //used like testNames[currentRound], zero indexed;
byte testNames[3]; //control, phone, or texting

/* stores times, in (rounded) milliseconds (raw timing done in micros)
 * format always 0:contol, 1:phone, 2:text
 */
unsigned long testTimes[3];

unsigned int memPointer = 0; //24LC256 memory pointer

byte testRunning = false;

//Start of program

void setup () {
  unsigned int prandSeed;

  Serial.begin(19200); //Change this in Serial Monitor!
  Wire.begin();

  Serial.println(F("SRP Reaction Timer")); //warning right here.

  pinMode(BUTTON_PIN, INPUT);
  digitalWrite(BUTTON_PIN, HIGH); //pullup

  pinMode(LED_PIN, OUTPUT);

  EEPROM_readAnything(PRANDSEED_ADDRESS, prandSeed);
  randomSeed(prandSeed);
}

It also will happen with other Serial.print strings throughout the program. But if this won't work, then why is it listed under the print() reference?

Thanks!
baum

That certainly looks like it should compile.

But if this won't work, then why is it listed under the print() reference?

Where do you see the F() documented?

That certainly looks like it should compile.

It does. But I get a warning.

and F() is @ the Serial.print() reference:

You can pass flash-memory based strings to Serial.print() by wrapping them with F(). For example :
Serial.print(F(“Hello World”))

Nevermind... it's an [avr-gcc bug.](http://only initialized variables can be placed into program memory area)

But on the topic of SRAM... how do I figure out how much of the RAM is being used? What would happen if I used it all up?

Thanks,

baum

how do I figure out how much of the RAM is being used?

The amount of RAM in use changes as your program runs. So, there is no one "This is how much SRAM you are using" point. You can add calls to freeMemory() (once you search and find the function) to your code, at various places, to see how much you have at various points in the program.

What would happen if I used it all up?

Ugly stuff that is hard to track down.

What would happen if I used it all up?

Most likely the program would freeze or cause a reset of the uP.

A very primitive count of my program shows that I have 60 bytes of variables (not counting the scope of variables) + 264 bytes of strings = 324 bytes total, neglecting scope. So I could go neurotic anyway and wrap the strings in F(), but I think I'll be fine: '328P has 2K...

Thanks a lot,

baum

It would be interesting if you started removing F() one by one, leaving the problematic one in place tough, and tell us when the error stops showing up...

Sorry if I wasn't being clear... it comes up as a compiler warning (it still compiles). But it turns out that something in Arduino's Tone.cpp causes this warning, too, so I'll ignore it.

baum

I said "when the error stops showing up", not "when the sketch eventually compiles" :slight_smile:

But I never got an error. I got a warning.

I have exactly the same compilation warnings.
Tone.cpp indeed has the same warning.
It is due to the usage of F() strings (PROGMEM).

Is there a way to workaround this? Ideally I prefer to get Zero warnings.
Why is the the usage of F() strings recommended if the compiler warns against it??

Tone.cpp indeed has the same warning.

The necessary changes to the Tone file have been documented. You could search for the fix, and implement it.

Is there a way to workaround this? Ideally I prefer to get Zero warnings.

See above. There are plenty of other warnings that are not shown to you, so zero warnings is pretty difficult to achieve.

Why is the the usage of F() strings recommended if the compiler warns against it??

The F() macro moves strings into program memory, removing them from SRAM, making SRAM available for other things. The compiler isn't warning against using F() in general, only in what Tone specifically is doing that causes the issue.

The warning is really just a warning in IDE 1.0. It is triggered in tone.cpp, too. If you search the web it is not unique to arduino. I modified arduino.h by adding the following at line ~58.

// Workaround for http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34734
#ifdef PROGMEM
#undef PROGMEM
#define PROGMEM __attribute__((section(".progmem.data")))
#endif

Marek080:
The warning is really just a warning in IDE 1.0. It is triggered in tone.cpp, too. If you search the web it is not unique to arduino. I modified arduino.h by adding the following at line ~58.

// Workaround for http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34734

#ifdef PROGMEM
#undef PROGMEM
#define PROGMEM attribute((section(".progmem.data")))
#endif

Great, exactly what I was looking for! :slight_smile:
I have zero tolerance to compilation warnings, once you get used to them the quality of the code quickly deteriorates.
I don't know why Arduino team is releasing code that has warnings (like tone.cpp). It should not be allowed - period.

As for F() usage, I find it problematic:
A simple usage of:
String test = F("hello");
does not compile: "error: conversion from '__FlashStringHelper*' to non-scalar type 'String' requested"

The String constructors do not support this data type, which is very unfortunate. Sure, I can go to that class and start making it work but it should be working out of the box;