very long PROGMEM array address is wrong

Here's my problem : I have several arrays of 16383 ints which means that the address of the second array is over an int possibility. When i try to access this array, the address is cast to an int and therefore is wrong.

Here's a snippet of code:

const uint16_t tab0[16383] PROGMEM = {...};
const uint16_t tab1[16383] PROGMEM = {...};

void loop() {
    Serial.println(long(&tab0), HEX); //prints 0xFFFF810a instead of 0x1810a 
}

Is there a way to cast an address as long, or do i have to manually write the correct address by looking at the disassembly code?

Thx for your help.

Here's a snippet of code:

In which the Serial.print() statement has 5 parens... Post some code that ACTUALLY compiles.

Fixed.

chairn:
Fixed.

sketch_jan10a:1: error: expected primary-expression before '...' token
sketch_jan10a:2: error: expected primary-expression before '...' token

NOT fixed.

What board are you using?

Cast to an unsigned long.  Serial.println((unsigned long)(&tab0), HEX);

aarg:
Cast to an unsigned long.

  Serial.println((unsigned long)(&tab0), HEX);

Doesn't work, same result.

robtillaart:
What board are you using?

ATmega 2560

PaulS:
NOT fixed.

... When the anti-spam protection will allow me to edit.

Anyway, i think it's not possible because pointers are treated as int, i.e 16 bits int, which does not allow addressing more than 32KB.

Then you have to post all your code.

Hello and welcome,

Try

Serial.println( pgm_get_far_address( tab0 ), HEX );

PROGMEM above 64k example:

const char above[1024] PROGMEM = "above 64";
const char filler1[31 * 1024] PROGMEM = "filler1";
const char filler2[31 * 1024] PROGMEM = "filler2";
const char below[4 * 1028] PROGMEM = "below 64";

void setup() {
  Serial.begin(115200);
  dumpFF(pgm_get_far_address(below), 0x20);
  dumpFF(pgm_get_far_address(filler1), 0x20);
  dumpFF(pgm_get_far_address(filler2), 0x20);
  dumpFF(pgm_get_far_address(above), 0x20);
}

void dumpFF(unsigned long adr, int len) {
  byte idx;
  if (len) {
    for (; len > 0; len -= 16, adr += 16) {
      phBytesB((byte*)&adr, 4);
      Serial.write(':');
      Serial.write(' ');
      for (idx = 0; idx < 16; idx++) {
        if (idx < len ) {
          phByte(pgm_read_byte_far(adr + idx));
          Serial.write(' ');
        } else {
          Serial.print(F("   "));
        }
      }
      Serial.write('\'');
      for (idx = 0; (idx < 16) && (idx < len); idx++) {
        byte curr = pgm_read_byte_far(adr + idx);
        Serial.write(curr < 0x20 ? '.' : curr);
      }
      Serial.write('\'');
      Serial.println();
    }
  }
}

void psdec(void (*pprint)(byte), byte* ptr, byte len) {
  for (ptr += len - 1; len--;) {
    (*pprint)(*ptr--);
  }
}

void phBytesB(byte* ptr, byte len) {
  psdec(phByte, ptr, len);
}

void phByte(byte val) {
  phNibble(val >> 4);
  phNibble(val);
}

void phNibble(byte val) {
  val &= 0xF;
  Serial.write(val + (val < 10 ? '0' : 'A' - 10));
}

void loop() {}

Here is how i’ve done it + using pgm_read_word_far for reading.

const uint16_t tab0[16383] PROGMEM = {0};
const uint16_t tab1[16383] PROGMEM = {0};
const uint16_t tab2[16383] PROGMEM = {0};
const uint16_t tab3[16383] PROGMEM = {0};
const uint16_t tab4[16383] PROGMEM = {0};
const long tab[] = {(long)&tab0, (long)&tab1, (long)&tab2, (long)&tab3, (long)&tab4};

void setup() {
  // put your setup code here, to run once:
    Serial.begin(115200);
    Serial.println(tab[0], HEX); //104
    Serial.println(tab[1], HEX); //FFFF8106
    Serial.println(tab[2], HEX); //108
    Serial.println(tab[3], HEX); //FFFF810A
    Serial.println(tab[4], HEX); //10C

    Serial.println(pgm_read_word_far(&tab0 + 12); //example
}

And the real addresses are (looking at the assembly code) :
0000010c <__trampolines_end>: //tab4

0000810a <_ZL4tab3>:

00010108 <_ZL4tab2>:

00018106 <_ZL4tab1>:

00020104 <_ZL4tab0>:

edit: with pgm_get_far_address, i have the following results:
20104
18106
10108
810A
10C

So, i guess my problem is solved. I just dont get why this function is not there :
http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html