Go Down

Topic: Just a newby asking the 64k question again - Arduino Mega2560 (Read 7533 times) previous topic - next topic


Feb 06, 2013, 04:29 am Last Edit: Feb 06, 2013, 04:38 am by iceowl Reason: 1
OK, the following works:

Using the multi-progmem-segment method

1) Store 64k of strings in PROGMEM_SEG2  (doesn't have to be exact or padded) denoted with a memory start location of 0x20000
2) Store ~64K of strings in PROGMEM_SEG3  denoted with memory start location of 0x30000
3) Store 20k of pointers to those strings in the lowest progmem space with PROGMEM_FAR which goes...I dunno where.

Plz note that you cannot deposit into memory a chunk of data larger than 64k, at least not with this version of avr-gcc/ld in the arduino 1.0.3.  I believe this will be different once we get to avr-gcc V4.7...someday...maybe.

The strings can be accessed thus:

Code: [Select]

#include <morepgmspace.h>

if(accessing a char* in a string at a location < size of the 64k of stuff in seg 2){

     unsigned int index = pgm_read_word_far(GET_FAR_ADDRESS(dictionary0[0]) +wordNumber*2); //wordNumber is the index into the array of strings called dictionary0
   else {
     unsigned int index = pgm_read_word_far(GET_FAR_ADDRESS(dictionary0[0])+wordNumber*2); //note that the array dictionary0 also has data in SEG3!


char* strcpy_PX(char* des, uint_farptr_t src,unsigned long base)
 unsigned long p = base + src;

 char* s = des;

 do {
   *s = pgm_read_byte_far(p++);
 return des;

Note that you cannot access the data in those SEG2/SEG3 locations through specification of an indexed addressing scheme like

Code: [Select]
unsigned int index = pgm_read_word_far(GET_FAR_ADDRESS(dictionary0[i]);

I have been utterly unsuccessful in storing and reading out of the SEG 1 location which is denoted with a memory start location of 0x10000.  However, I can put 20k of char*s at wherever the attr PROGMEM_FAR puts it.  I have to go back to look at the linker script (avr6.x) to see where that's being mapped to.  I know it's going into .data (or maybe just past it...)

At least I understand what's happening now.   If I try to put anything into PROGMEM_SEG1 I not only get errors trying to read it back, but the bootloader gives me a verification error - which is probably the root cause of the whole problem.  I don't have it in me to look into the bootloader at this point...  On to another problem!

Cheers to all


Apr 03, 2013, 11:27 am Last Edit: Apr 03, 2013, 11:28 am by StanleyAudio Reason: 1

Just joined in and digged out a lot of useful information, thanks

I am working on a project using Mega 2560 for voice announcement, so I need to store a large amount of compressed voices in the program memory. 256kB of flash on Mega2560 can give me about 7 minutes of voice playback.
So I encountered the same problem you guys have - accessing data stored outside the 64kb boundary of program memory.
Thanks pYro_65 for the neat solution of declaring PROGMEN_FAR in the program memory outside first 64kB, that solves the download and crash problem. Using the pgm_read_byte_far() I can read data anywhere in the 256kb program memory.
The GET_FAR_ADDRESS macro for converting program memory address to uint_farptr_t is wonderful, and with all these, I can get my program work; all 7 minutes of voices can be played without problem, thanks.

However, in tidying up my program and orgainzing my voice data in an easy indexing manor, I encountered another minor problem!

I need to store the address of each voice segment into an index table so that I can load the address and read the data accordingly. Of course, the index table contains 32 bit long address. The problem I have is; the GET_FAR_ADDRESS() macro works only in run time when it is called. It can not work in compile time, so when I build up my index table, done in compile time, the compiler doesn't allow me to cast the voice segment name (far address) into uint_farptr_t type.  My question is; anyone of you know how to set up a 32 bit pointer table that points to the far program memory in compile time?
Of course, I can still get my program works by writing a simple initialization rountine (run a sequence of GET_FAR_ADDRESS to iinitialize the table)
and get it run before my main code, but it will be a tidous job to type in all the voice segment names. I want the index table generated automatically in compile time. Any suggestion?


Go Up

Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

via Egeo 16
Torino, 10131