PROGMEM and 1D array

Hi Everyone,

I'm working on getting a bit of code with PROGMEM and memcpy_PF. At the moment it's not quite there. What needs to change in order to get it working?

I've tried both memcpy_P with a (char *) and memcpy_PF with its uint_farptr_t, but they both produce output which shows neither memcpy is doing what I want.

Here is the program's output
i: 0: 0, i: 1: 0, i: 2: 0, i: 3: 0, i: 4: 0, i: 5: 0,
i: 0: 51, i: 1: F, i: 2: 1F, i: 3: 91, i: 4: F, i: 5: 91,
i: 0: 0, i: 1: 0, i: 2: 0, i: 3: 0, i: 4: 0, i: 5: 0,
i: 0: 51, i: 1: F, i: 2: 1F, i: 3: 91, i: 4: F, i: 5: 91,

And here is the source:

#include <avr/pgmspace.h>   // essential for statically initialized tables not to overwhelm RAM, etc.?

// Global variables:
unsigned char note_set[6] = {0, 0, 0, 0, 0, 0};

void setup() {
Serial.begin (115200);
// this is the data to retrieve from progmem:
const unsigned char PROGMEM mm1 [6] = {0x40, 0x47, 0x52, 0x55, 0x59, 0x64 };

//void *    memcpy_PF (void *dest, uint_farptr_t src, size_t len)
int i;

for (i = 0; i < 6; i++) {  // print values before copy from PROGMEM
  Serial.print("i: "); Serial.print(i, HEX); Serial.print(": ");
  Serial.print(note_set[i], HEX); Serial.print (", ");
}
Serial.println("");

memcpy_P (&note_set[0], (char *) &mm1[0], 6);
for (i = 0; i < 6; i++) {
  Serial.print("i: "); Serial.print(i, HEX); Serial.print(": ");
  Serial.print(note_set[i], HEX); Serial.print (", ");
}
Serial.println("");

for (i = 0; i < 6; i++) note_set[i] = 0; //zero out the contents before next attempt to copy from progmem
for (i = 0; i < 6; i++) {
  Serial.print("i: "); Serial.print(i, HEX); Serial.print(": ");
  Serial.print(note_set[i], HEX); Serial.print (", ");
}
Serial.println("");
memcpy_PF (&note_set[0], (uint_farptr_t) &mm1[0], 6);
for (i = 0; i < 6; i++) {
  Serial.print("i: "); Serial.print(i, HEX); Serial.print(": ");
  Serial.print(note_set[i], HEX); Serial.print (", ");
}
Serial.println("");
}

void loop() {
// main loop... runs forever
while (1);
}

progmem_test_more_simple.ino (1.42 KB)

This version works fine for me on an Arduino UNO. The output is:

i=0:40,  i=1:47,  i=2:52,  i=3:55,  i=4:59,  i=5:64,
// Global variables:
const unsigned char mm1[6] PROGMEM = {0x40, 0x47, 0x52, 0x55, 0x59, 0x64 };
unsigned char note_set[6] = {0, 0, 0, 0, 0, 0};

void setup() {
  Serial.begin (115200);

  memcpy_P(note_set, mm1, 6);
  for (int i = 0; i < 6; i++) {
    Serial.print("i="); 
    Serial.print(i, HEX); 
    Serial.print(":");
    Serial.print(note_set[i], HEX); 
    Serial.print (",  ");
  }
  Serial.println("");
}

void loop() {
  // main loop... runs forever
  while (1);
}

That works fine on my Mega1280 also.

The change you made was to move the PROGMEM array declaration out of the setup() function. Then to double-check using your code, I was able to reproduce the problem by moving the PROGMEM array declaration back into the setup function.

Thank you!

Now I'm wondering: is this a compiler bug or a feature?

Feature.
Variables declared within the scope of a function have a storage class of "automatic" and they live on the stack.
If you want them to have a "static" storage class you have to put "static". Statically allocated variables/objects are candidates for PROGMEM.

void setup() {
   :
   :
static const unsigned char PROGMEM mm1 [6] = {0x40, 0x47, 0x52, 0x55, 0x59, 0x64 };
   :
   :
}

Would have worked.