我正在32位ARM mcu(Atmel SAM4SD32C,Cortex-M4 / ARMv7E-M部件)上实现二进制日志系统,并且正在设计我的数据结构 . 我的目标是将日志格式描述为打包结构,并简单地将结构与char数组结合,以便写入日志设备(SD卡,通过FatFS,在本例中) .
基本上,我有一个非常简单的结构:
typedef struct adc_samples_t
{
int32_t adc_samples[6];
uint64_t acq_time;
int8_t overrun;
uint8_t padding_1;
uint8_t padding_2;
uint8_t padding_3;
} __attribute__((packed, aligned(4))) adc_sample_set;
现在,我的架构是32位,所以据我所知,访问任何成员/其他/然后 overrun
成员应该是32位对齐,因此没有额外的开销 . 此外, aligned(4)
属性应强制结构的任何实例化都在32位对齐的边界上 .
但是,编译上面的结构定义会产生一堆警告:
In file included from ../src/main.c:13:0:
<snip>\src\fs\fs-logger.h(10,10): warning: packed attribute causes inefficient alignment for 'adc_samples' [-Wattributes]
int32_t adc_samples[6];
^
<snip>\src\fs\fs-logger.h(12,11): warning: packed attribute causes inefficient alignment for 'acq_time' [-Wattributes]
uint64_t acq_time;
据我所知(我现在意识到这是一个很大的假设),我认为32位对齐是32位臂上最佳元件定位所需要的 . 奇怪的是,唯一发出/不发出警告的成员是overrun和padding_X成员,我不明白其原因 . (好的,ARM docs说 Byte accesses are always aligned.
)
究竟是什么发生在这里?我假设(可能不正确)结构实例化将在4字节边界上 . 编译器是否需要更宽的对齐(在8字节边界上)?
编辑:好的,深入研究ARM文档(这里的神奇字词是“Cortex-M4对齐”:
3.3.5 . 地址对齐对齐访问是一种操作,其中字对齐地址用于字,双字或多字访问,或者半字对齐地址用于半字访问 . 字节访问始终对齐 . Cortex-M4处理器仅支持以下指令的非对齐访问:LDR,LDRT LDRH,LDRHT LDRSH,LDRSHT STR,STRT STRH,STRHT所有其他加载和存储指令如果执行未对齐访问,则会生成UsageFault异常,因此它们的访问权限必须是地址对齐 . 有关UsageFaults的更多信息,请参阅故障处理 . 未对齐访问通常比对齐访问慢 . 此外,某些内存区域可能不支持未对齐的访问 . 因此,ARM建议程序员确保访问是一致的 . 要捕获意外生成的未对齐访问,请使用配置和控制寄存器中的UNALIGN_TRP位,请参见配置和控制寄存器 .
我的32位对齐值如何不是字对齐的?用户指南将“对齐”定义如下:
对齐存储在一个地址的数据项,该地址可以被定义数据大小的字节数整除,据说是对齐的 . 对齐的单词和半字分别具有可被4和2整除的地址 . 因此,字对齐和半字对齐的术语规定了可被4和2整除的地址 .
2 回答
它是 .
但是你在这里没有32位对齐[在最初问的问题] because:
given that:
换句话说,如果你仍然想要一个压缩结构在你强制所有成员对齐之后仍然有一些最小对齐,因此类型本身没有任何东西,你需要指定 - 事实上这可能实际上不是make
-Wpacked
闭嘴是另一回事 - GCC可能只是在它实际考虑任何进一步的对齐修饰符之前反复吐出 .请注意,就序列化而言,无论如何都不一定需要打包它 . 这些成员完全符合9个单词,所以唯一的编译器填充在任何地方都是一个额外的单词,最后将总大小舍入到40个字节,因为
acq_time
强制结构自然对齐为8.除非你想操作一个在这些事情的同时,你可以完全忽略它,并仍然将成员视为一个36字节的块 .好的,在这一点上,我有点确信警告是错误发出的 .
我有一个静态定义的结构实例,并且在某一点上我将其归零:
该功能的反汇编如下:
注意,上面的
r3
是0x2001ef70
,实际上是4字节对齐的 .r2
是文字值0
.str
操作码需要4字节对齐 .strd
操作码也只需要4字节对齐,因为它看起来确实是两个连续的4字节操作,但我不知道它在内部是如何工作的 .如果我故意错误对齐我的结构,强制慢速路径复制操作:
我得到以下程序集:
所以,非常清楚,我正在使用我原来的结构定义获得正确的对齐复制行为, despite 编译器显然错误地警告它会导致访问效率低下 .