我正在做一个嵌入式项目。我正在尝试使用 GNU 链接器来布局存储在外部 eeprom 中的一些变量。我通过为 eeprom 变量分配
int __attribute__ ((section (".eeprom"))) eeprom_var1;
我还将为 eeprom 定义初始化变量,即:
int __attribute__ ((section (".eeprom"))) eeprom_var2 = 0x42;
然后,想法是;在初始化 eeprom 时,初始化的变量由正在运行的应用程序从 .text 部分的某个位置复制到 eeprom,就像初始化数据部分一样。显然,eeprom 变量无法读取/写入,但必须通过以下函数访问:
eeprom_read(data, &eeprom_var,sizeof(eeprom_var)).
目前为止,一切都好
现在我想用另一个变量的指针初始化一个 eeprom 变量:
unsigned long long __attribute__ ((section (".eeprom"))) eeprom_var1 = 0x42;
unsigned short __attribute__ ((section (".eeprom"))) eeprom_var2 = (unsigned short )&eeprom_var1;
请注意,EEPROM 使用 16 位地址空间
但这给出了以下错误
foo.c:4:1: error: initializer element is not constant
unsigned short __attribute__ ((section (".eeprom"))) eeprom_var2 = (unsigned short )&eeprom_var1;
^
这是因为强制转换为(无符号短(被读取为作为初始值设定项的操作,这在 C 中是不允许的。但是,在C++中,上述表达式是可以的。
任何人都可以想到解决上述错误的方法吗?
/安德斯
- 在片上 eeprom 中放置变量时,它们始终需要为
const type
型。 - 在片上EEPROM中放置指针时,它们始终需要类型为
type* const
(指向非恒定数据的常量指针(或const type* const
(指向常量数据的常量指针(。
这似乎是您问题的真正根源。当然,一旦它们被宣布为常量,你就不应该抛弃常量。
另外,如果是片上EEPROM,是否有理由不能直接访问存储单元?在大多数系统上,您可以执行此操作,尽管访问时间可能比对 RAM 变量的等效访问慢。
作为旁注,转换为uint16_t
(或无符号短(只会在小端计算机上为您提供 16 个最低有效位。该代码不能移植到大端序。可移植代码将((uint32_t)pointer >> 16)
.
但是,C++上述表达式是可以的。
初始化由C++编译器接受,但在运行时执行(请参阅虚假错误:初始值设定项元素在加载时不可计算(,这可能不是您想要的。
任何人都可以想到解决上述错误的方法吗?
即使在绕过该错误之后,例如
__asm__(".section .eeprom,"aw"n"
".globl eeprom_var2n"
"eeprom_var2: .short eeprom_var1");
extern unsigned short eeprom_var2;
链接器退出并显示错误:
…: relocation truncated to fit: R_386_16 against symbol `eeprom_var1' defined in .eeprom section in /tmp/…