Program memory space is being overwritten

257 views Asked by At

I am writing firmware for an Atmel Mega645A controller using AtmelStudio7. I have a bunch of messages that I display on a 16x2 character display. In order to preserve SRAM space, I am attempting to store these messages in ROM Program Memory. My problem is that it seems I am overwriting parts of Program Memory that are already being used for other code. Here are the details:

I have the following statements near the beginning of the main program:

#include "adht.h"
#include "languages.h" 

in adht.h I have the following:

#include <avr/pgmspace.h>

I believe the nut of my problem is in my header file languages.h, which I created. In languages.h I have hundreds of lines of code that look like this:

const char M1_1_1[] PROGMEM = {32,32,32,32,69,110,116,101,114,105,110,103};
const char M1_2_1[] PROGMEM = {32,32,83,116,97,110,100,98,121,32,77,111,100,101};
const char M2_1_1[] PROGMEM = {32,32,70,87,32,82,101,118,105,115,105,111,110};
const char M2_2_1[] PROGMEM = {32,32,32,32,40,110,117,109,98,101,114,41};
const char M3_1_1[] PROGMEM = {32,78,79,46,32,79,70,32,84,72,69,82,65,80,89};
const char M3_2_1[] PROGMEM = {32,32,32,32,83,69,83,83,73,79,78,83,58};
    .
    .
    . etc. etc.

When I compile with ~660 lines like this, AtmelStudio reports the following: Program Memory Usage : 34892 bytes 53.2 % Full Data Memory Usage : 2919 bytes 71.3 % Full EEPROM Memory Usage : 170 bytes 8.3 % Full

If I comment out most of the "const char ...." lines, and rebuild, I get this:

Program Memory Usage : 34896 bytes 53.2 % Full Data Memory Usage : 2919 bytes 71.3 % Full EEPROM Memory Usage : 170 bytes 8.3 % Full

... which looks about the same. However both builds will allow the rest of my program to run no problem.

Here is where I am running in to trouble. Further on in languages.h I have the following code:

PGM_P const string_table[] PROGMEM = 
{
    M1_1_1  ,   M1_1_2  ,   M1_1_3  ,   M1_1_4  ,   M1_1_5  ,   M1_1_6}; /* ,
    M1_2_1  ,   M1_2_2  ,   M1_2_3  ,   M1_2_4  ,   M1_2_5  ,   M1_2_6  ,
    M2_1_1  ,   M2_1_2  ,   M2_1_3  ,   M2_1_4  ,   M2_1_5  ,   M2_1_6  ,
    M2_2_1  ,   M2_2_2  ,   M2_2_3  ,   M2_2_4  ,   M2_2_5  ,   M2_2_6  ,
    M3_1_1  ,   M3_1_2  ,   M3_1_3  ,   M3_1_4  ,   M3_1_5  ,   M3_1_6  ,
    .
    .
    . etc. etc.

Now you will note that after the first line of M1_1_1... I have commented out "/" the rest of the "pointer assignments". Rest assured I have a "/" at the end of the assignments. If I only have 6 pointer assignments, my code works OK. If I move the "/*" down a couple lines so that a couple more lines of code get compiled, the rest of my program starts to freak out as if I am out of Program Memory. My program fails in different ways depending on how much of the "pointer assignments" are compiled. (note I am having problems typing "asterisk backslash" in this forum). When I compile with eight lines of the code that are not commented out, the compiler reports the following:

Program Memory Usage : 35530 bytes 54.2 % Full Data Memory Usage : 2919 bytes 71.3 % Full EEPROM Memory Usage : 170 bytes 8.3 % Full

And when I un-comment ALL these lines, the compiler reports the following:

Program Memory Usage : 44690 bytes 68.2 % Full Data Memory Usage : 2919 bytes 71.3 % Full EEPROM Memory Usage : 170 bytes 8.3 % Full

So clearly I am filling up Program Memory, but not getting close to the limit.

To be complete, in the main program I copy the messages from Program Memory into SRAM as follows:

char line1[16]; 
char line2[16];
PGM_P p;
memcpy_P(&p, &string_table[0], sizeof(PGM_P)); 
strcpy_P(line1, p);
memcpy_P(&p, &string_table[1], sizeof(PGM_P));
strcpy_P(line2, p); 

Later on I send line1 and line2 to the display.

So it seems to me that the problem is in my

PGM_P const string_table[] PROGMEM =

line(s). Can someone please tell me how I do this so that I am not overwriting the rest of my program?

UPDATE: in the main program, if I comment out the following lines of code before compiling, the Program Memory usage drops (to 54%), and the rest of the program works fine:

char line1[16]; 
char line2[16];
PGM_P p;
memcpy_P(&p, &string_table[0], sizeof(PGM_P)); 
strcpy_P(line1, p);
memcpy_P(&p, &string_table[1], sizeof(PGM_P));
strcpy_P(line2, p); 

When I un-comment this code and re-compile, Program Memory usage goes back up to 68%, and then the rest of the program freaks out when I run it. So what it is about these lines of code that are overwriting Program Memory?

UPDATE #2: in the lines of code above, if I comment out these two lines:

strcpy_P(line1, p);
strcpy_P(line2, p); 

My program works. Of course I still do not have access to the data that I stored in Program Memory though. Please someone tell me what is going on. How do I get the data (an array of characters, or alternatively an array of uint_8's) into RAM so that I can display to the 16x2 screen?

1

There are 1 answers

3
M.M On BEST ANSWER

In Standard C, if you have this in a header file:

const char M1_1_1[] = {32,32,32,32,69,110,116,101,114,105,110,103};

and two or more translation units include that header file, it is undefined behaviour due to having multiple definitions of the same object. This could manifest itself as high memory usage due to the compiler/linker using memory for each definition, or anything else.

If you can rearrange the code so that the definitions only appear in a .c file, that might solve the problem. Other units can access the data by extern const char M1_1_1[];.