Compile time far data address in Mega2560 with G++

Go To Last Post
4 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The linker attempts to place data in the first 64kB of a big AVR and the code at higher addresses.

In practice,  you have 200kB of data with 30kB code.   So most data is outside the 64kB address range.

 

// linker places this first e.g. < 64kB
const unsigned char lady_128x127x4_bmp[] PROGMEM = {
    ...
};
// linker places this section after the regular PROGMEM e.g. > 64kB
const unsigned char lady_128x127x8_bmp[] __attribute__((section(".fini2")))= {
    ...
};
// you can only access the first 64kB of Flash with xxxx_P() functions
// you can access ANY data with the xxxx_PF() functions

// you can only use pgm_get_far_address(x) at runtime

I would like to have an array of far pointers at compile time.

// all pointers are 16-bit i.e. < 64kB
const uint8_t *bmps[] = {
    lady_128x127x4_bmp,
    lady_128x127x8_bmp,
};

// I would like to specify 32-bit (or 24-bit) addresses
// this simply sign extends the 16-bit address into 32-bits
const uint_farptr bmps[] = {
    lady_128x127x4_bmp,
    lady_128x127x8_bmp,
};

// in an ideal world you could have a far modifier
const far uint8_t *bmps[] = {
    lady_128x127x4_bmp,
    lady_128x127x8_bmp,
};

There must be some sort of mechanism.   After all,  the linker is happy to put code above 64kB.   And you don't need to handle function pointers differently.

 

Yes,   I can write functions that accept farptr and calculate the farptr at runtime with pgm_get_faraddress().

But it would be a lot tidier if struct or array can be initialised at compile time.

 

Google finds this subject but I could not find the answer.

 

David.

 

Edit.   Added G++ to Title

Last Edited: Wed. Nov 15, 2017 - 08:12 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Data (in Flash, below and above 64kB):

const __memx uint8_t lady_128x127x4_bmp[] = {
    ...
};

const __memx uint8_t lady_128x127x8_bmp[] = {
    ...
};

Table of 24 bit pointers to the data (also in Flash):

const __memx uint8_t * const __memx bmps[] = {
    lady_128x127x4_bmp,
    lady_128x127x8_bmp,
};

Accessing the data:

    PORTD = bmps[bmp][ind];

 

david.prentice wrote:
There must be some sort of mechanism. After all, the linker is happy to put code above 64kB. And you don't need to handle function pointers differently.
That is a completely different mechanism (no 24 bit pointers involved).

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry. I forgot to mention that this is G++. I am at a Tablet at the moment. I will try __memx later on the PC.

If it works, it will be the ideal solution.
.
David.

 

Edit.   __memx is not recognised by the G++ compiler.   I have edited the Thread Title

Last Edited: Wed. Nov 15, 2017 - 08:15 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
I forgot to mention that this is G++.

In a C file:

const __memx uint8_t lady_128x127x4_bmp[] = {
    ...
};

const __memx uint8_t lady_128x127x8_bmp[] = {
    ...
};

struct bmpptr_padded {
    const __memx uint8_t * bmpptr;
    uint8_t padding;
};

const struct bmpptr_padded bmps[] = {
    { lady_128x127x4_bmp, 0 },
    { lady_128x127x8_bmp, 0 },
};

In C++:

extern uint32_t bmps[];

    PORTD = pgm_read_byte_far( bmps[bmp] + ind );

(this time the table is in RAM to simplify the access)

Stefan Ernst

Last Edited: Wed. Nov 15, 2017 - 09:18 AM