PROGMEM

Hi,
does the PROGMEM macro work on the Zero?

The following code compile fine but I can't test it yet because I've no board.

//#include <avr/pgmspace.h>


// save some unsigned ints
const PROGMEM  uint16_t charSet[]  = { 65000, 32796, 16843, 10, 11234};

// save some chars
const char signMessage[] PROGMEM  = {"I AM PREDATOR,  UNSEEN COMBATANT. CREATED BY THE UNITED STATES DEPART"};

unsigned int displayInt;
int k;    // counter variable
char myChar;


void setup() {
  Serial.begin(9600);
  while (!Serial);

  // put your setup code here, to run once:
  // read back a 2-byte int
  for (k = 0; k < 5; k++)
  {
    displayInt = pgm_read_word_near(charSet + k);
    Serial.println(displayInt);
  }
  Serial.println();

  // read back a char
  int len = strlen_P(signMessage);
  for (k = 0; k < len; k++)
  {
    myChar =  pgm_read_byte_near(signMessage + k);
    Serial.print(myChar);
  }

  Serial.println();
}

void loop() {
  // put your main code here, to run repeatedly:

}

Just ran your code on my Zero, on the COM port it ouputs:

65000
32796
16843
10
11234

I AM PREDATOR,  UNSEEN COMBATANT. CREATED BY THE UNITED STATES DEPART

Hi MartinL,

Thanks for your test.

is there a way to verify that the data are in the flash memory and not into the ram?

You can print some of the addresses:

  Serial.println((int)&charSet[0],HEX);
  Serial.println((int)&k,HEX);
  Serial.println((int)loop,HEX);

461A
2000004C
2111

The question is whether PROGMEM prevents the constants from being copied from flash memory to SRAM on the ARM processors, as it does on the AVRs?

It's easy to see the effect of PROGMEM on the UNO, as the IDE nowadays displays the available SRAM and there's also the MemoryFree library, but this is not the case with the Zero and Due.

I've tested the Zero, Due and Uno with the above code. It appears as though the Due and Zero access the constant data irrespective of whether it's declared with PROGMEM or not. The Uno on the other hand requires PROGMEM, otherwise the function pgm_read_byte_near() returns garbage.

This suggests that PROGMEM has no effect on the ARM processors and has been included for backwards code compatibility with AVR processors.

As there's no information about PROGMEM for the Due or Zero on the internet, I looked it up for the ARM based Teensy 3.0/3.1 instead. Here's what Paul Stoffregen (creator of the Teensy boards) said:

On Teensy 3.0, all you have to do is use "const" in the variable declaration. Or at least that's all you're supposed to do. Everything that's "const" gets put into flash without consuming any RAM.

PROGMEM, pgm_read_byte() and the other AVR names are defined only so code designed for AVR can compile. But they do absolutely nothing on Teensy 3.0.

I'd recommend adding const to that huge array. If you're not planning to compile on Teensy 2.0 or other AVR boards, you might as well remove the PROGMEM stuff. Accessing the array normally is much nicer and more readable code that using pgm_read_byte().

Maybe it possible to test this by declaring an array of 16kB as const or with and without PROGMEM and see if the Zero hangs or not...?

If the SAMD (Arduino Zero) is anything like the SAM3X (Arduino Due), you can just use the C++ "const" keyword, and forget all about the AVR's PROGMEM keyword. Even better, flash memory is completely mapped to main memory map, meaning no special calls are required to access it. More efficient, and more readable! For instance, you can just do:

const a[10] ={1,2,3,4,5,6,7,8,9,0};

Serial.println(a[6]+4);