PROGMEM vs #define -- for NUMBERS

OK, so I've read all these articles about PROGMEM and why it's good for storing const strings. I get it.

I understand that #define is actually a compiler directive and it substitutes the value into the program code at compile time, thus it ends up in flash memory instead of ram.

I understand that PROGMEM tells the compiler to store the value into flash memory instead of ram. That the Arduino compiler normally puts a variable in ram even if you declare it as const. (Note: The compiler for some of my other microcontrollers knows if it's a const to put it in flash.)

I understand that PROGMEM is preferable to #define for strings, if you use the string more than once in your code, because PROGMEM will only store one copy in flash, whereas the #define compiler directive causes it to be inserted every place you use it.

I try to mostly avoid using literals as a matter of good programming practice.

But no real discussion about PROGMEM vs #define for const numbers.

How about bytes, ints and longs? How about ones that I use only once, and the ones that I use all over the place?

For ints, it seems to to me to be to be pretty much a wash. Because you either store the 16-bit value, or the 16-bit address of the value. When compiled to assembly, the microprocessor fetches the value (directly or indirectly) into its register at the same speed -- correct? (I'm basing this assumption on my knowledge of other processor families.)

So how does this affect memory usage and speed for bytes and longs?

And do I have to use pgm_read_byte(), pgm_read_int(), and pgm_read_long() to get a number stored with PROGMEM out of flash? That seems like a pain-in-the-butt to keep doing all over the place and I'm sure must really slow it down. Thus, a strong argument for #define for numeric constants. (Note: Again, compilers for my other microcontrollers don't require this.)

And why would I need to use pgm_read_whatever() to get it out of flash? With a 16-bit address the processor can address 64K of memory of whatever type. Is the 2K of ram and 32K of flash in separate address spaces?

I could design and run some benchmarks to test this, and I still might, but no doubt a few of you can just tell me and even explain why. I would certainly like to understand the "why" part, It makes me a better geek in the future!

Thanks!

And do I have to use pgm_read_byte(), pgm_read_int(), and pgm_read_long() to get a number stored with PROGMEM out of flash? That seems like a pain-in-the-butt to keep doing all over the place and I'm sure must really slow it down. Thus, a strong argument for #define for numeric constants. (Note: Again, compilers for my other microcontrollers don't require this.)

And why would I need to use pgm_read_whatever() to get it out of flash? With a 16-bit address the processor can address 64K of memory of whatever type. Is the 2K of ram and 32K of flash in separate address spaces?

PROGMEM allows you to store your data in the flash memory which can be accessed throughout the sketch. It also makes it easier to call that data without the need for multiple variables.
char * str1 = " Hello! Welcome to the world";
char * str2 = "You have a lot to learn, so lets get started :)"
Now yes, you can store this with normal arrays, but being that the arduino has limited RAM, using normal arrays is not a good idea. However with PROGMEM, you can still have this data in an array, but in a different memory location.

pgm_read_whatever() to get it out of flash?

Because that is how you access that area of the memory.
#define allows the user to make a variable into a place holder. these are most common when creating multiple arrays. (Read only)

#define Num_of_items 5
byte Item[Num_of_items];
int price[Num_of_items];
float Weight[Num_of_items];

Hope this helps.

DrWizard:
And why would I need to use pgm_read_whatever() to get it out of flash? With a 16-bit address the processor can address 64K of memory of whatever type. Is the 2K of ram and 32K of flash in separate address spaces?

Yes, each type of memory (SRAM, FLASH, and EEPROM) uses a separate address space. Unfortunately the compiler doesn't track which address space each address references so it assumes that all data pointers point to SRAM. Fortunately the LPM (Load Program Memory) instruction for fetching a byte from PROGMEM doesn't take long.
The separate address spaces is why string constants take up SRAM: they have to be copied to SRAM so they can be addressed through a data pointer. In the case of .print() and .println() you can use the macro P() to put your string constant into PROGMEM/FLASH. This casts the address as type _FlashStringHelper and the versions of .print() and .println() that take a _FlashStringHelper know that the address being passed is for the PROGMEM address space so they do the right thing.

macro P()

P()? what is the difference of P() and F(), or was that a typo?

I think its a typo, however there is PSTR()

PSTR() puts strings into flash.

F() uses PSTR(), it just casts its result to a dummy type which removes ambiguity when calling Serial.print().

And do I have to use pgm_read_byte(), pgm_read_int(), and pgm_read_long() to get a number stored with PROGMEM out of flash? That seems like a pain-in-the-butt to keep doing all over the place and I'm sure must really slow it down. Thus, a strong argument for #define for numeric constants. (Note: Again, compilers for my other microcontrollers don't require this.)

With constants, you just use them normally. Leave the compiler to worry about that. However things become subtly more difficult if you use arrays, because the compiler has to assume that given a pointer, the pointer is in RAM. So an array of constants needs a bit more work.

See Gammon Forum : Electronics : Microprocessors : Putting constant data into program memory (PROGMEM) for a discussion about PROGMEM.

I'm sure must really slow it down

That is "I'm guessing it must really slow it down".

For a constant like a baud rate, the compiler will generate an appropriate "load" instruction which will be as fast as it can generate. If you use things like pgm_read_int then the overhead to get data out of PROGMEM is one extra clock cycle (per byte) which is 62.5 nS if you are running at 16 MHz. I'm not sure if that is really slowing it down, in your book.

This is all hand-waving, unless you post example code.

I understand that #define is actually a compiler directive and it substitutes the value into the program code at compile time, thus it ends up in flash memory instead of ram.

I wouldn't even say that. Using #define does a textual substitution, that's all.

So, for example:

#define foo if

foo (a == 42)
  Serial.println ("whoa, a is 42");

There have been many discussions about comparing #define to "const" variables (except that if it is const it isn't a variable, right?).

When you use a constant in an Arduino expression, whether it is a #define'd constant, or a "static const var=" constant, the compiler will normally optimize the expression in the way that makes the most sense. This usually consists of using inline "literal" constants that use flash memory MORE efficiently than PROGMEM.
An expression like: x = y*10 probably compiles to code that looks like:

  ld  r16, y
  ldi r18, #10
  call multiply

rather than defining a specific memory area that contains "10" (ldi r18, #10 is a two-byte instruction. Reading a RAM memory location containing 10 would be at least 4 bytes. Reading a program location containing 10 would be more than that.
It could also have an optimized subroutine just for multiplying numbers by 10, so that it never uses the constant 10 explicitly at all...

Thank you everyone for your helpful information, especially JohnWasser. I didn't realize the Atmel AVR processors used separate address spaces for each kind of memory. That's good to know!

But I don't think anyone really answered my question: For numbers (not strings, and not arrays) is there an advantage to using #define vs. const PROGMEM?

Which is better:
#define MYNUMBER 1177
or
const int MYNUMBER PROGMEM = 1177;

The latter without PROGMEM.

As Coding Badly said:

const int MYNUMBER = 1177;

There is no point trying to out-think the compiler on this one. For constants it will pull the data out of PROGMEM for you, in much the way Westfw said. And in the way he described, that won't generate any "slow" PROGMEM accesses.

I understand that PROGMEM is preferable to #define for strings, if you use the string more than once in your code, because PROGMEM will only store one copy in flash, whereas the #define compiler directive causes it to be inserted every place you use it.

Even this part is debatable, because for literal strings the compiler knows enough to not make dozens of copy of the same unmodifiable string.

That the Arduino compiler normally puts a variable in ram even if you declare it as const.

I don't agree that const variables normally go into RAM. It would depend on the variable.

A good starting point here is to use good programming practices. Then if you find you have speed or memory issues you can raise them on the forum. Don't agonize for hours about "clever" ways to avoid problems you don't even have yet.

Now if you had said (which you haven't) that you want to store a 4 kB "bitmap" (eg. a font) and it won't fit into RAM, and how do you do that in PROGMEM, then that is a reasonable question. And that is one I try to answer here: Gammon Forum : Electronics : Microprocessors : Putting constant data into program memory (PROGMEM).