Pages: [1]   Go Down
Author Topic: Using PROGMEM > 64K  (Read 1333 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 1
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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] ={ ....
or
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?
« Last Edit: November 28, 2012, 06:22:49 am by gurgle » Logged

Global Moderator
Dallas
Online Online
Shannon Member
*****
Karma: 197
Posts: 12741
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset


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.
« Last Edit: November 28, 2012, 02:29:22 pm by Coding Badly » Logged

SF Bay Area (USA)
Offline Offline
Tesla Member
***
Karma: 124
Posts: 6637
Strongly opinionated, but not official!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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...
Logged

Pages: [1]   Go Up
Jump to: