c - 工具链与对齐的差异(为什么这甚至有效)

标签 c arm embedded atmel gnu-toolchain

有一个 ATMEL 库不适用于我的工具链(ARM 的 GNU 工具),我知道为什么,但我不知道为什么它适用于旧的 YAGARTO,我想这也适用于 KEIL 和 IAR

我正在使用不支持对整数(4 字节)进行未对齐访问的 ARMV5 处理器 (AT91SAM9)。

有一个全局缓冲区定义为:

static unsigned char pPageBuffer[AT91C_IFLASH_PAGE_SIZE];

缓冲区获取一些数据,然后将数据写入闪存,但数据必须一次取4个字节到闪存,因此有一个名为pAlignedSource的int指针一次取4个字节的数据。

pAlignedSource = (unsigned int*)pPageBuffer;

但是 pPAgeBuffer 不一定是 4 字节对齐的,因为它是一个 char 数组,并且 pAlignedSource 并不指向对齐的地址。这段代码怎么可能总是在其他工具链中工作,但在我的工具链中却不起作用?我已经为编译器定义了正确的 CPU,除了两个编译器获得相同的代码标志之外。

我的问题是当数据从缓冲区复制到闪存时

*pAlignedDestination++ = *pAlignedSource++;

我以数据的扰乱版本结束:/,但是我通过将缓冲区定义为来解决这个问题

static unsigned int pPageBuffer[AT91C_IFLASH_PAGE_SIZE/4];

它确实成功了,但我仍然对此很好奇。为什么它在其他工具链中有效?

最佳答案

写入未对齐的地址是在 ARMv5 上定义的。你可能有 CP15 行为来改变这一点。例如,对于拇指模式,它可能会捕获或执行一些不可预测的事情。在 ARM 模式下,使用 STR 会丢弃较低位而不捕获。使用LDR,低位被屏蔽以形成地址,但数据随后根据低位进行旋转。

编辑:此外,一个编译器/工具集完全有可能对字符缓冲区的开头使用不同的对齐方式。一种工具可以调整一切,而另一种工具则不然。使用gcc,您可以使用attribute((aligned,4))或类似的东西来注释缓冲区。

无论你在做什么,它都是不可移植的(对于“C”来说是未定义),你不应该这样做;这似乎是您得出的结论。

关于c - 工具链与对齐的差异(为什么这甚至有效),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28238258/

相关文章:

c - C中的递归仅在打印不相关的东西时有效

c - 调试 - 字符串问题

c - 为什么我在每个 "Expected expression"时都会收到 "else"错误?

c - 如何创建 volatile 结构函数指针的固定数组

c - 如何在不影响其他位的情况下将 uint8_t 放在 uint16_t 中间

c - 修改单个结构成员

ARM (thumb-2)组装模拟器?

linux - libGLES_CM.so 有什么用?

c - 在 Beaglebone black 上运行 KissFFT 时出错

linux - 在运行时将代码注入(inject)可执行文件