Go Down

Topic: Using PROGMEM > 64K (Read 3021 times) previous topic - next topic


Nov 28, 2012, 12:11 pm Last Edit: Nov 28, 2012, 12:22 pm by gurgle Reason: 1
I have been deveoping an Arduino projecct with some image data in PROGMEM that pushes the total PROGMEM usage above 64K. The problem is that once this boundary is exceeded several core functions that use PROGMEM structures start playing up. In particular the portInputRegister macros don't work and all the I/O fails!

Arduino.h extract:
#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) )

The pgm_read_byte_far() macro (refered to in other posts and forums) is not really practical in this situation as all PROGMEM access would have to change. A better solution is to leave the core data in the low 64K and have another segment in a higher area of memory.

After much experimentation I found that the following will push the data into the highest area of the .text segment above the code:

const uint16_t First_Quarter[0xD24] __attribute__((section(".fini7"))) ={  .....

rather than the following that leaves it in the lower 64K:
const prog_uint16_t First_Quarter[0xD24] ={ ....
const uint16_t First_Quarter[0xD24] PROGMEM ={ ....

Then you can selectively access data with the pgm_get_far_address macros for the data in the upper memory area:
uint_farptr_t MoonPic = pgm_get_far_address(First_Quarter);

Q. Is __attribute__((section(".fini7"))) a valid method for this workaround or is there a better solution?

Coding Badly

Nov 28, 2012, 08:27 pm Last Edit: Nov 28, 2012, 08:29 pm by Coding Badly Reason: 1

Thank you for taking the time to write your post.

Your solution is certainly clever!

The ideal solution would be a section specifically to serve this purpose and a macro like PROGMEM to force data into that section.

Normally, the .finiN sections are used for shutdown code.  When main returns, the run-time library executes code in all the .finiN sections with the final section essentially being a halt.

In the Arduino world, main never returns which leaves the .finiN sections free for you to use as you wish.

I have no idea if the .finiN sections are guaranteed to be placed after all other sections (at the highest addresses).  You may want to spend some time with the GCC linker documentation to determine if the guarantee is or is not made.


I have no idea if the .finiN sections are guaranteed to be placed after all other sections (at the highest addresses).

yes. they are.  For reasons that aren't entirely clear, progmem data is normally put in the flash address space FIRST.
This is controlled by the linker scripts, ie /hardware/tools/avr/avr/bin/../lib/ldscripts/avr6.x
According to that, .fini7 is for "C++ destructors", and I don't see anything that looks significantly more appropriate for "high" progmem...

Go Up