【问题标题】:avr-gcc: How to use __attribute__((address)) with EEMEM?avr-gcc:如何将 __attribute__((address)) 与 EEMEM 一起使用?
【发布时间】:2022-01-15 14:57:12
【问题描述】:

这些属性不兼容吗?地址属性似乎被忽略,不发出警告(-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


    【解决方案1】:

    address 属性的documentation 声明:

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

    查看AVR memory space 显示 I/O 地址位于 SRAM 数据存储空间之下。

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

    编辑:使用 avr-gcc 3.6.2 进行的测试表明 section 属性覆盖了 address 属性(没有警告)。使用 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 上测试,也生成正确的指令。

    【讨论】:

    • 我不确定他们的意思; IO 空间位于 SRAM 中,仅通过使用某些快速指令(IN、OUT 等)访问它的能力来区分。基本上所有外围设备都已经超出了该范围。官方标题只是访问那些带有原始(文字)指针的标题。另外,如果它取决于部分,它不应该说它需要哪个部分(例如.data)吗?那么这只是一个多余的属性吗?还是记录不全?
    • 用 avr-gcc 3.6.2 进行的一些测试表明,section 属性似乎覆盖了地址。因此,指定节属性将擦除地址属性,链接器会将变量从地址 0 开始放置在 EEPROM 空间中。似乎只使用地址属性会导致正确的明显位置。由于需要使用 eeprom_* 函数来访问 EEPROM 地址,因此无需指定 .eeprom 部分 AFAICS。我将添加一个示例。
    • 有趣:无论如何都在 .data 中使用它,这很愚蠢,因为那里链接了其他东西,但无论如何,这都是外围空间(0 到 0xfff 或大约在大多数情况下)芯片,而 EEPROM 更小),所以实际上不会有任何冲突。缺点:无法初始化 .eeprom,仍然需要以某种方式链接。所以这个用例的原始问题仍然存在,嗯。
    猜你喜欢
    • 2019-07-15
    • 2021-11-22
    • 1970-01-01
    • 1970-01-01
    • 2019-07-17
    • 2012-06-15
    • 2015-12-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多