__attribute__((io)), __attribute__((address)) 似乎没有任何效果

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

我正在尝试使用 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 来说,似乎这些单一的提供了 -step 属性,问题是如何使它们发挥作用。两步过程对我来说不是一个选择。
  2. 我知道一般来说人们总是可以这样做:
    *(volatile int*)0x600 = your_data_here;
    但这对我来说也不是一个选择,我需要声明一个实际的变量(因为我想将其映射到按位结构上,以便在不显式使用掩码和逻辑运算的情况下访问各个位。

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

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

手册说这些特殊属性应该允许我强制将变量放置在预定的内存地址。

不,不是。 它明确指出“没有分配内存”。因此,您不能使用它来将变量放置在特定地址。

使用此类属性声明的变量被放置到编译器和链接器确定的 SRAM 中的位置,而不是按要求放置在地址 0x600 处。

也许您遇到了PR112952中报告的问题:属性

io
io_low
address
无法正常工作,具体取决于
-f[no-]data-sections
-f[no-]common
。 请注意,
-fcommon
默认值在 v10 中发生了更改,请参阅 GCC v10 发行说明

我需要声明一个实际的变量

那么你就不能使用这些属性中的任何一个,因为它们不分配内存。 这些属性基本上相当于

(*(volatile Type*) 0x???)
模式,但其地址仅在链接时评估;而对于常量地址的转换,该地址必须在编译时已知。

** 对于位于固定地址的对象,您需要将其放在自己的部分中并使用自定义链接描述文件。**

  • 请注意,与静态存储中的所有其他变量相反,该变量不会在启动时初始化。
  • 这样的链接器脚本可能很棘手,例如当变量应该分配在 RAM 空间的中间时。 RAM 中的其他变量可能会与其发生冲突。 GNU 链接器没有跳过节中某些字节的功能,因此所有 .data 将位于自定义节之前或之后,.bss 和 .rodata 相同。

因为我想将其映射到按位结构上,以便在不显式使用掩码和逻辑运算的情况下访问各个位。

你在这里失去了我。您能举例说明您想要实现的目标吗?


-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
© www.soinside.com 2019 - 2024. All rights reserved.