程序内存 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[];
.
访问数据
我正在使用 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[];
.