程序存储空间被覆盖

时间:2016-12-22 20:31:49

标签: c memory atmel

我正在使用AtmelStudio7为Atmel Mega645A控制器编写固件。我有一堆消息,我在16x2字符显示器上显示。为了保留SRAM空间,我试图将这些消息存储在ROM程序存储器中。我的问题是,我似乎正在覆盖已经用于其他代码的程序存储器部分。以下是详细信息:

我在主程序开头附近有以下声明:

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

在adht.h中我有以下内容:

#include <avr/pgmspace.h>

我相信我的问题的核心在我创建的头文件languages.h中。在languages.h中,我有数百行代码,如下所示:

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.

当我使用这样的~660行编译时,AtmelStudio会报告以下内容: 程序内存使用:34892字节53.2%已满 数据存储器使用:2919字节71.3%已满 EEPROM存储器使用:170字节8.3%完整

如果我注释掉大部分“const char ....”行并重建,我得到了这个:

程序内存使用:34896字节53.2%已满 数据存储器使用:2919字节71.3%已满 EEPROM存储器使用:170字节8.3%完整

......看起来差不多。但是,这两个版本都将允许我的程序的其余部分运行没有问题。

这是我遇到麻烦的地方。在languages.h中,我有以下代码:

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.

现在你会注意到在M1_1_1的第一行之后...我已经注释掉了 “/ ”其余的“指针赋值”。请放心,我在作业结束时有一个“ /”。如果我只有6个指针分配,我的代码工作正常。如果我将“/ *”向下移动几行以便编译更多行代码,我程序的其余部分就会开始变得惊慌失措,好像我已经没有程序存储器了。我的程序以不同的方式失败,具体取决于编译了多少“指针赋值”。 (注意我在这个论坛中键入“asterisk反斜杠”时遇到问题)。当我使用未注释掉的八行代码进行编译时,编译器将报告以下内容:

程序内存使用:35530字节54.2%已满 数据存储器使用:2919字节71.3%已满 EEPROM存储器使用:170字节8.3%完整

当我取消注释所有这些行时,编译器会报告以下内容:

程序内存使用:44690字节68.2%已满 数据存储器使用:2919字节71.3%已满 EEPROM存储器使用:170字节8.3%完整

很明显,我正在填写程序存储器,但没有接近极限。

为了完成,我在主程序中将消息从程序存储器复制到SRAM中,如下所示:

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); 

稍后我将line1和line2发送到显示器。

所以在我看来问题出在我的

PGM_P const string_table[] PROGMEM =

线(S)。有人可以告诉我我是如何做到这一点的,这样我就不会覆盖我的其他程序吗?

更新:在主程序中,如果我在编译之前注释掉以下代码行,程序内存使用率会下降(达到54%),程序的其余部分工作正常:

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); 

当我取消注释此代码并重新编译时,程序内存使用率会回升至68%,然后当我运行它时,程序的其余部分就会变坏。那么覆盖程序存储器的这些代码行是什么呢?

更新#2:在上面的代码行中,如果我注释掉这两行:

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

我的计划有效。当然,我仍然无法访问存储在程序存储器中的数据。请有人告诉我发生了什么事。如何将数据(字符数组或uint_8数组)放入RAM中,以便显示到16x2屏幕?

1 个答案:

答案 0 :(得分:0)

在标准C中,如果您在头文件中有此内容:

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

并且两个或多个翻译单元包括该头文件,由于具有相同对象的多个定义,因此是未定义的行为。由于编译器/链接器为每个定义或其他任何内容使用内存,这可能表现为高内存使用率。

如果您可以重新排列代码,以便定义只出现在.c文件中,那么可能会解决问题。其他单位可以extern const char M1_1_1[];访问数据。