8

我正在将一些软件从 gcc-toolchain 移植到 armcc-toolchain(处理器保持不变(Cortex-A9))。在 C 代码中使用 memcpy。armcc 将调用 memcpy 替换为调用 __aeabi_memcpy。关于 __aeabi_memcpy 的常见问题解答如下(ARM 编译器如何处理 memcpy()?):

在许多情况下,编译对 memcpy() 的调用时,ARM C 编译器将生成对专门的、优化的库函数的调用。自 RVCT 2.1 起,这些专用功能成为 ARM 体系结构 ABI (AEABI) 的一部分,包括:

__aeabi_memcpy
This function is the same as ANSI C memcpy, except that the return value is void.

但与 gcc 相比,在我的所有情况下,对 memcpy 的调用都可以正常工作,而 armcc 对 memcpy 的调用分别 __aeabi_memcpy 不断产生对齐异常。同时我发现,对 memcpy 的调用可以处理源地址和目标地址不是 4 字节对齐的调用,但前提是它们都不是 4 字节对齐的。例如:

    volatile uint32_t len = 10;
    uint8_t* src = (uint8_t*)0x06000002;         // 2-byte aligned
    uint8_t* dst = (uint8_t*)(0x06000002 + 20);  // 2-byte aligned
    memcpy(dst, src, len);

将工作。但例如:

    volatile uint32_t len = 10;
    uint8_t* src = (uint8_t*)0x06000002;         // 2-byte aligned
    uint8_t* dst = (uint8_t*)(0x06000002 + 22);  // 4-byte aligned
    memcpy(dst, src, len);

将导致对齐异常。因为我使用的是 uint8_t* 类型的指针,所以我明确告诉编译器地址可以有任何对齐。但显然这个 __aeabi_memcpy 不能处理所有的对齐组合。我该如何解决这个问题(最好不使用用户特定版本的 memcpy 更改现有代码中对 memcpy 的所有调用)?感谢帮助。

4

2 回答 2

0

如果您不想更改代码,这里有两个选项:

1) 禁用 Cortex-A9 上的未对齐异常。这完全解决了问题,但您可能会受到性能影响。

2)修补库。您可以在要链接的 lib 文件中重命名符号 __aeabi_memcpy。然后,您可以实现自己的 __aeabi_memcpy 来检测对齐错误,使用专门的例程处理它或跳转到原始的 memcpy 函数。如果您使用的是 linux,您甚至不需要重命名符号。链接器允许您覆盖函数。

这两种解决方案都有些脏,但是如果您不想更改代码,这就是我能想到的。

哦,你应该提交一个错误报告。您看到的行为绝对是一个错误。Memcpy 应该可以在任何对齐情况下正常工作。

于 2014-07-22T09:34:56.910 回答
0

也许这仍然有帮助:ARM 编译器 armcc 应该有一个选项,您可以使用该选项告诉编译器不要执行未对齐的访问,也不要使用会执行此操作的内置库:

--no_unaligned_access

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0472k/chr1359124947629.html

于 2014-11-03T11:04:35.590 回答