Better support for Mega 2560 Flash Access

One of the main issues with using the Arduino IDE with the mega 2560 is that flash storage above 64KB is rather painful to access. Because the address goes from 16 bits to 18 bits to access all of flash (256KB in total) you end up having to call pgm_get_far_address and pgm_read_byte_far, pgm_read_dword_far, pgm_read_float_far to name a few.

QUESTION 1:
What my question is is whether there is a compiler that supports 24bits for a flash address natively. Having such a compiler would mean that using things like:

const char sSomething1[] PROGMEM = "First string";
const char sSomething2[] PROGMEM = "Second string";
...
const char * const Sstrings[] PROGMEM = {(const char *)&sSomething1, (const char *)&sSomething2...}; 

would work because 24 bits addresses would be put into Sstrings. Both sSomething1 etc and Sstrings would be in flash. At present this is not possible as doing so will have 16 bit values in Sstrings which will break if the strings go above 64KB.

It is also not possible, in Arduino IDE, to try to get the address (above 64KB) using something like:

... pgm_get_far_address (Sstring[1])....

I know that the existing libraries, which primarily work on 16 bit flash addresses will either need rewriting or perhaps a (uint16_t) flashaddress could be used for the passed flash address to revert to 16 bit address when you know it is in the bottom 64KB for backward compatibility.

QUESTION 2:
Can anyone explain how the existing compiler and linker work when dealing with flash addresses over 64KB on 2560?

It would appear that what is roughly happening is that 16 bit addresses are being created by the compiler for flash addresses and the linker is then remapping this to addresses above 64KB in some cases.

The issue that occurs here is when the total flash data storage is over 64KB (which, in my view, would be the main reason to use a mega 2560) the compiler must be well aware of this.

In essence I want to know what the voodoo magic is that deals with these issues and resolves the 16 bit compiler to a larger address at linking time.

Many thanks in advance for any answers...

Geoffrey.

For code, the compiled implements "trampolines." These are essentially vectors in the low 64k that allow 16bit target addresses to be used to reach all possible code addresses. (I'm not quite sure exactly when these are used. Pointers to functions are one case.)

But in general, the "gcc model" of a CPU does not handle bank-switched memory very well (or at all, really), and what you'd like to have probably doesn't exist :frowning:

See also: Issues · arduino/ArduinoCore-avr · GitHub

I think avr-gcc introduced 24bit "generic" pointers in recent revisions, but I also think that they're not supported in C++, and perhaps they aren't implemented in a way that makes anyone in a hurry to use them: Named Address Spaces (Using the GNU Compiler Collection (GCC)) and http://saaadhu.github.io/appnote.html

So maybe using a different Microcontroller like a teensy 4.1 might be a solution.
Though I never tried to compile a bigger than 64 kB sourcecode-file into such a microcontroller (like Teensy or SAMD21 boards.

best regards Stefan

I think the problem happens when you store a 32-bit FLASH address into a 16-bit "pointer" type. For 'far' pointers the compiler uses uint32_t variables. If you use 'uint32_t' type instead of char* you cn t least preserve the upper bytes:

const char sSomething1[] PROGMEM = "First string";
const char sSomething2[] PROGMEM = "Second string";
...
const uint32_t Sstrings[] PROGMEM = {&sSomething1, &sSomething2...}; 

The ARM based boards will NOT have the problem. They have a uniform 32bit address space, which is just what gcc understands and wants. My "personal model" of "when do you skip an 8bit microcontroller and use a 32bit" has more to do with the memory addressing getting weird, and less to do with just speed.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.