c++ - 未对齐访问导致 ARM Cortex-M4 出错

标签 c++ c arm memory-alignment cortex-m

我有一个对象的地址不是 4 字节对齐的。当存在保存 2 个寄存器的 STR 指令时,这会导致 cpu 出现 HardFault 错误。

这是生成的代码:

   00000000 <_ZN8BaseAreaC1EPcmm>:
   0:   b510            push    {r4, lr}
   2:   4604            mov     r4, r0
   4:   6042            str     r2, [r0, #4]
   6:   e9c4 3102       strd    r3, r1, [r4, #8]
   a:   2001            movs    r0, #1
   c:   7420            strb    r0, [r4, #16]
   e:   b921            cbnz    r1, 1a <_ZN8BaseAreaC1EPcmm+0x1a>

这些是在“4: 6042...”行时的寄存器

R0   08738B82  R8          0  
R1   08738BAE  R9          0  
R2          0  R10  082723E0  
R3       2FCC  R11         0  
R4   08738B82  R12         0  
R5   20007630  R13  2000CB38  

正如所见,STR 指令的目标寄存器未按 4 字节对齐。指令 STR r2, [r0, #4] 执行良好。但它会在下一个 STRD r3, r1, [r4, #8] 上发生硬故障。如果我手动将寄存器 R4 更改为 08738B80,它不会出现硬故障。

这是生成上述 asm 的 C++ 代码:

BaseArea::BaseArea(char * const pAddress, unsigned long startOffset, unsigned long endOffset) : 
m_pAddress(pAddress), m_start(startOffset), m_end(endOffset), m_eAreaType(BASE_AREA) {

m_start是类中的第一个变量,与this具有相同的地址(0x08738B82),m_end0x08738B86 之后。

如何让对象按 4 字节对齐? 有人对此有其他解决方案吗?

最佳答案

在基于 ARM 的系统上,您经常无法寻址未与 4 字节边界对齐的 32 位字(正如您的错误告诉您的那样)。在 x86 上,您可以访问非对齐数据,但是这会对性能造成巨大影响。如果 ARM 部件确实支持未对齐访问(例如单字正常加载),则性能会下降并且应该有一个可配置的异常陷阱。

ARM ( here ) 上的边界错误示例,TLDR:存储指向 unsigned char 的指针,然后尝试将其转换为 double *(double指针)。

要解决您的问题,您需要请求一个 4 字节对齐的内存块并复制未对齐的字节 + 用垃圾字节填充它以确保它是 4 字节对齐的(因此执行数据结构对齐手动)。然后,您可以将该对象解释为与其新地址对齐的 4 字节。

来自 TurboJ 的评论,显式错误:

Cortex-M3 and M4 allow unaligned access by default. But they do not allow unalinged access with the STRD instruction, hence the fault.

您可能还会发现查看 this 很有帮助用于强制 ARM 上的数据结构对齐。

关于c++ - 未对齐访问导致 ARM Cortex-M4 出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18269181/

相关文章:

c++ - 命名空间中的无效数据类型转换

C++ 压缩嵌套 for 循环

在 C 中使用多线程计算序列无法按预期工作

arm - 什么是 PDE 缓存?

c++ - 为什么这会导致 Mac 上的无限循环?

c++ - 当getline()读取的行大于系统内存时会发生什么?

c - 尝试使用 OpenCV 在 C 中编译时遇到的问题

c - K&R 练习 2-7,优化?

linux - Linux 内核中的 I2C 写确认轮询

c - 操作系统导致的 irq 延迟是多少?