【问题标题】:__attribute__((io)), __attribute__((address)) in gcc for AVR don't seem to have any effect__attribute__((io)), __attribute__((address)) 在 AVR 的 gcc 中似乎没有任何效果
【发布时间】:2019-07-15 19:44:33
【问题描述】:

我正在尝试使用 AVR 风格的 gcc (https://gcc.gnu.org/onlinedocs/gcc/AVR-Variable-Attributes.html#AVR-Variable-Attributes) 专门提供的变量属性。

手册说这些特殊属性应该允许我强制将变量放置在预定的内存地址。他们甚至举了一个例子:

volatile int porta __attribute__((address (0x600)));

但是,当我从上述文档中编译和调试此代码示例时,使用该属性声明的变量被放置到编译器和链接器确定的 SRAM 中的一个位置,而不是按照请求的地址 0x600。实际上,如果我从声明中完全删除属性,最终结果不会改变 - 变量被放置在相同的“任何”地址。当我使用“io”和“io_low”属性而不是“address”时,也会发生同样的事情。

我正在使用针对 8 位 MCU (ATMega64) 的最新版本 Atmel Studio 7.0.19.31 中打包的 gcc 工具链。

因此问题是:有没有人尝试使用这些特殊的 AVR 特定属性并取得成功?

重要提示:

  1. 我知道,一般来说,要在 gcc 中将变量放置在固定地址,您需要遵循两步过程(使用节属性,然后修改链接器脚本),但特别是对于 AVR,它似乎提供了这些单步属性,问题是如何使它们起作用。两步流程对我来说不是一个选项。
  2. 我知道,一般来说,总是可以做到这一点: *(volatile int*)0x600 = your_data_here; 但这对我来说也不是一个选项,我需要声明一个实际变量(因为我想将它映射到按位结构上,以便在不显式使用掩码和逻辑运算的情况下访问各个位。

所以我真的在寻找一种使提供的属性起作用的方法,而不是一种解决方法。我错过了什么?

【问题讨论】:

  • 这些东西不是解决方法,它们是有效的东西。试图让位域工作或编译指示和其他指令,这些都是变通方法,并导致代码的维护生命周期。如果工作保障是目标,则继续使用行之有效的解决方案。
  • 如果你的属性有任何东西,工具链在做什么?
  • 这似乎是一个错误...但是...您是使用工具链附带的链接器脚本还是使用您自己的?
  • 使用开箱即用的链接器脚本而不做任何更改。
  • 我也是标准方法的粉丝,但在 IAR EWB 中,我将 PORTA_Bit4 作为一个单独的变量(由于将按位结构映射到固定地址),这使得代码更可读:PORTA_Bit4 = 0;。读取是通过相同的赋值运算符完成的: foo = PORTA_Bit4;我正在尝试迁移到 avr-gcc 并保持相同的可读性。遗憾的是,通过指针进行类型转换并使用位掩码和逻辑运算符的标准解决方案只允许创建一个用于读取的宏,通过赋值运算符进行写入是不可能的,您必须求助于带有参数的宏。

标签: gcc avr avr-gcc


【解决方案1】:
typedef struct {
  uint8_t rx:4;
  uint8_t tx:4;
} Pio_TXRXMUX_t;
#define Pio_TXRXMUX (*(volatile Pio_TXRXMUX_t *)(0x22)) //PORTA on ATMEGA1280

【讨论】:

  • 感谢您提供此代码 sn-p,它可能会提供一些有限的即时帮助。 proper explanation 将通过展示为什么这是解决问题的好方法,并使其对有其他类似问题的未来读者更有用,从而大大提高其长期价值。请edit您的回答添加一些解释,包括您所做的假设。
猜你喜欢
  • 2022-01-15
  • 2012-08-01
  • 2013-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多