程序内存 space 正在被覆盖

Program memory space is being overwritten

我正在使用 AtmelStudio7 为 Atmel Mega645A 控制器编写固件。我有一堆消息显示在 16x2 字符显示器上。为了保留 SRAM space,我试图将这些消息存储在 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 % Full

如果我注释掉大部分 "const char ...." 行,然后重建,我会得到:

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

...看起来差不多。然而,这两个构建都将允许我的程序的其余部分 运行 没问题。

这就是我 运行 遇到麻烦的地方。在 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的第一行之后...我已经注释掉了 “/”剩下的"pointer assignments"。请放心,我在作业末尾有一个“/”。如果我只有 6 个指针赋值,我的代码就可以正常工作。如果我将“/*”向下移动几行以便编译更多的代码行,我的程序的其余部分就会开始崩溃,就好像我的程序内存不足一样。根据 "pointer assignments" 的编译量,我的程序会以不同的方式失败。 (请注意,我在本论坛中输入 "asterisk backslash" 时遇到问题)。当我用八行没有注释掉的代码编译时,编译器报告如下:

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

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

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

很明显我正在填满程序内存,但还没有接近极限。

为了完整起见,在主程序中,我将程序内存中的消息复制到 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 =

行。有人可以告诉我如何执行此操作,这样我就不会覆盖程序的其余部分吗?

更新:在主程序中,如果我在编译前注释掉以下代码行,程序内存使用率下降(至 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 屏幕上显示?

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

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

并且两个或多个翻译单元包含该头文件,这是未定义的行为,因为同一对象有多个定义。由于 compiler/linker 为每个定义或其他任何事情使用内存,这可能表现为高内存使用率。

如果您可以重新排列代码,使定义仅出现在 .c 文件中,则可能会解决问题。其他单位可以通过extern const char M1_1_1[];.

访问数据