Go Down

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

iceowl

#30
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
     strcpy_PX(newWord,index,PROGMEM_SEG2_BASE);
 
   }
   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!
     strcpy_PX(newWord,index,PROGMEM_SEG3_BASE);

   }

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++);
 }
 while(*s++);
 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
Joe

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

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?

Thanks
Stan

Go Up