2

I've been trying to run some code on an ATMEGA2560, and I've finally boiled everything down to this:

Works

#include "Arduino.h"
#include "HardwareSerial.h"

const char bob[7000] = "Hello\0";


void setup(void) {
  Serial.begin(9600);
  Serial.println("jshInit...");
  Serial.println(bob);
}

void loop(void) {
  Serial.println("foo...");
}

Doesn't do anything at all

#include "Arduino.h"
#include "HardwareSerial.h"

const char bob[8000] = "Hello\0";


void setup(void) {
  Serial.begin(9600);
  Serial.println("jshInit...");
  Serial.println(bob);
}

void loop(void) {
  Serial.println("foo...");
}

The only difference here is the size of bob. There are no compiler warnings or anything, even if bob is 20000, the Arduino just refuses to work if the bob array is too big.

Does anyone know what's wrong? I'm compiling with the Arduino IDE here, but for my main project I'm using avr-gcc (GCC) 4.5.3, and I tried 4.8.2 as well - same problem on all of them.

The atmega2560 has 256kb flash and 8kB RAM. It could be I'm using all the RAM (but it should tell me if so?), also there is the const keyword on bob which should mean it goes into flash?

1
  • I just saw this page on PROGMEM and that fixes it - but how do I get a warning if I'm using up RAM, and ideally how do I make const do this automatically Commented Sep 23, 2015 at 10:54

1 Answer 1

3

Yes, you were indeed using up your SRAM.

regarding your comment: You can not somehow use the const keyword to achieve the same thing as by using PROGMEM attribute.

const is used to tell the compiler that the data is to be "read-only". const was intended for uses such as this, not as a means to identify where the data should be stored. If it were used as a means to define data storage, then it loses its correct meaning (changes its semantics) in other situations such as in the function parameter example.

However, if you have lots of constant strings/data, you should indeed use PROGMEM to instruct the compiler to move the data into the flash memory.

If you have data sets that require read/write access and have to be non-volatile you would use the EEPROM.

There are tools like avr-size.exe (part of the GCC toolchain) to check your static SRAM usage at compile time. Keep in mind that you also have to make sure that the dynamic SRAM requirements (STACK) does not exceed the remaining memory during program execution.

Its also possible to determine the SRAM usage at runtime by looking at the stack pointer. If only maximum SRAM usage is of interest, its also possible to write a dummy-pattern to the SRAM (all 0xAA for example), and check up to what address the pattern has been overwritten.

Sign up to request clarification or add additional context in comments.

4 Comments

Since I'm porting from ARM, where they really do put const data into flash, I've got hundreds of const variables. Is there no way of doing it automatically, rather than just spamming all my code with PROGMEM? Looks like it could just be a matter of making my own linker file.
@GordonWilliams: No clue. However, I understand the reasoning from the PROGMEM page regarding const.
Wow, yeah. I'd seem the page but didn't read in depth until now. Seems odd that a generic C pointer is unable to point to something in flash (if I'm reading right). Seems to pretty much kill any hope I had of porting my code.
@GordonWilliams: Well a "generic C pointer" is only a memory address in the end. The compiler needs the information to what memory it points and that is the SRAM by default. So you need a second type of pointer and functions (pgm_*) that recognize it and know how to access that "other memory", which would be the flash in this case. I think it makes sense to implement it the way it is and make the intent clear from a coding perspective.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.