Progmem size limits?..... warning: internal error: out of range error

Hi,

I’ve just started getting an error message I’ve never encountered before (and believe me, I’ve encountered a lot!)…

SD\utility\SdFile.cpp.o:(.rodata._ZTV6SdFile+0x6): warning: internal error: out of range error
core.a(HardwareSerial.cpp.o):(.rodata._ZTV14HardwareSerial+0x6): warning: internal error: out of range error

I use quite a lot of progmem constants for defining errors and log messages, and I first encountered this error when I added a couple more of them. Experimentation indicates that if I remove some of these constants from anywhere in my project then the error disappears, and if I add them back again the error re-appears.

The project is quite large (over 30 libraries, compiles to 136k), each library has been tested and used on it’s own, and it’s only when the entire project gets compiled that I get the error.
Other details…

  • I’m using a Mega 2560,
  • The error message refers to standard arduino library files NOT stuff I’ve written myself.
  • All my libraries have worked together in other projects without problems.
  • I have about 20k of progmem constants.

I define my progmem constants like this…

const prog_char ERR_MESS_01[] PROGMEM = "ERROR – Battery voltage dangerously low.";

and use it like this…

      strcpy_P(_messBuff, ERR_MESS_01);
      logging(_messBuff);

where _messBuff is a predefined array of characters of fixed length, and logging() is my function for echoing to screen and writing to an SD card.

Am I right in thinking there’s a limit to the amount of data I can put into PROGMEM? If so, is there a work-around or alternative technique I can use to achieve the same thing? I find it really useful to be able to log error messages to SD card, and I really don’t want to have to remove a lot of very useful data just because of some memory limits.

Thanks

It gets complicated if your progmem data ends up stored beyond the first 64k of flash. You need to start using the _PF functions (32bit pointers) instead of the _P functions, but I'm not quite sure how you get the 32bit pointers, or how you put the strings in flash once they exceed ~64k. You probably need to import the mysterious GET_FAR_ADDRESS macro (see http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=93874&highlight=remarks )

I'm doing an FAQ on this topic ( Far PGM ). Sadly its unfinished, however you can take an example sketch and have a play.

#define GET_FAR_ADDRESS(var)                          \
({                                                    \
    uint_farptr_t tmp;                                \
                                                      \
    __asm__ __volatile__(                             \
                                                      \
            "ldi    %A0, lo8(%1)"           "\n\t"    \
            "ldi    %B0, hi8(%1)"           "\n\t"    \
            "ldi    %C0, hh8(%1)"           "\n\t"    \
            "clr    %D0"                    "\n\t"    \
        :                                             \
            "=d" (tmp)                                \
        :                                             \
            "p"  (&(var))                             \
    );                                                \
    tmp;                                              \
}) 

#define PROGMEM_FAR  __attribute__((section(".fini7")))

char pgmData[] PROGMEM_FAR = { 'T', 'e', 's', 't', 'i', 'n', 'g', ' ', 'P', 'G', 'M', '\0' };

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

  byte c, i =0;
  while( c = pgm_read_byte_far( GET_FAR_ADDRESS( pgmData  ) + i++ ) ){
     Serial.print( ( char ) c );
  }
}

void loop() {}

Thanks Pyro,

this subject is extending well beyond my abilities, a simple low-level FAQ or tutorial would be most welcome!