有一个 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/