avr-gcc:如何将 __attribute__((address)) 与 EEMEM 一起使用?

问题描述 投票:0回答:2

这些属性不兼容吗?地址属性似乎被忽略,没有发出警告(-Wall)。

(仅供参考,EEMEM 在 eeprom.h 中定义为:

#define EEMEM __attribute__((section(".eeprom")))
。)

使用如下声明:

uint8_t storedFlags EEMEM __attribute__((address (100)));

(对于所有其他变量也类似)导致变量按照链接器喜欢的任何顺序放置,忽略我的属性。属性的顺序没有区别。

我知道首选方法(创建部分并将其位置传递给链接器)。我暂时只是想把它们扔到一边,因为我正在积极开发并在 EEPROM 中添加和删除分配;我宁愿事情不要在其他构建中移动,这样我就不必每次都从默认值重新编程 EEPROM。最糟糕的是,我确信我以前确实这样做过,并且成功了。版本差异?巧合的任务? (我有 GCC 3.4 和 8.1,不确定该项目使用了什么;我在这个项目中使用 8.1。)

c gcc attributes avr-gcc
2个回答
0
投票

address属性的文档指出:

具有地址属性的变量用于寻址可能位于 io 地址范围之外的内存映射外设。

查看AVR 内存空间,显示 I/O 地址属于 SRAM 数据内存空间。

这解释了为什么您的构造不能按预期工作,因为 EEMEM 和 address 属性映射到冲突的内存部分。

编辑:使用 avr-gcc 3.6.2 进行测试表明节属性覆盖了地址属性(没有警告)。使用 eeprom_read_byte 从 EEPROM 读取数据,以下示例由 avr-gcc 正确编译(正确是因为地址 0x0123 被传递给 eeprom_read_byte 函数):

#include <avr/eeprom.h>

uint8_t __attribute__((address (0x0123))) storedFlags;
int main(void){
  if (eeprom_read_byte(&storedFlags) == 1){
    return 1;
  }
}

Edit2:在 avr-gcc 11.1 上测试,也生成正确的指令。


0
投票

这些属性的组合没有任何意义。您要么在第

.eeprom
部分中有一个物体,要么在某个固定位置。请注意,属性
address
和朋友不会分配任何内存

属性

address
所做的就是定义一个符号,类似于
-Wl,--defsym,storedFlags=0x100
的效果。

在EEPROM中分配数据时,可以

  1. EEMEM
    标记所有变量。链接器将根据链接器脚本中
    .eeprom
    部分的位置来定位对象。
  2. 当您想按固定顺序手动定位数据时,您可以:
    • 使用包含 EEPROM 中所有对象的大结构。然后根据需要读取/存储组件或全部 EEPROM。
    • 通过分配硬编码地址手动定位对象。在这种情况下,不需要让编译器/链接器定位数据。

一个例子:

#include <avr/eeprom.h>

#define storedFlags_ADDRESS 0x100

uint8_t get_storedFlags (void)
{
    return eeprom_read_byte ((void*) storedFlags_ADDRESS);
}
© www.soinside.com 2019 - 2024. All rights reserved.