繁体   English   中英

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

[英]Unaligned access causes error on ARM Cortex-M4

我有一个 object,它的地址不是 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是 class 中的第一个变量,与this具有相同的地址( 0x08738B82 ), m_end0x08738B86之后。

如何使 object 在 4 字节上对齐? 有人对此有其他解决方案吗?

在基于ARM的系统上,您经常无法处理未与4字节边界对齐的32位字(正如您的错误告诉您的那样)。 在x86上,您可以访问非对齐数据,但性能会受到很大影响。 如果ARM部件支持未对齐访问(例如,单字正常负载),则存在性能损失, 并且应该存在可配置的异常陷阱。

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

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

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

默认情况下,Cortex-M3和M4允许未对齐访问。 但是他们不允许使用STRD指令进行无法访问,因此就是错误。

你也可以发现它有助于看看对ARM迫使数据结构对齐。

以下情况至少适用于ARM体系结构(在cortex M0上验证):

使用加载和存储指令时,我们访问的内存必须能够被我们尝试从内存访问/到内存的字节数整除,否则我们将获得硬故障异常。

例如:

LDR r0, = 0x1001
LDR r1, [r0]

上面代码中的第二行将给出硬错误,因为它试图读取4个字节,但内存地址不能被4整除

如果我们将上面代码中的第二行更改为以下内容

LDRB r1, [r0]; //从地址加载1个字节

上面的行不会产生硬故障,因为我们试图访问1个字节(可以从任何内存位置访问1个字节)

另请注意以下示例;

LDR r0,= 0x1002
LDRH r1,[r0];   //Load half word from 0x1002

上述行不会产生硬故障,因为内存访问是2个字节,地址可以被2整除。

正如您所发现的,Cortex-M4 支持 4 字节未对齐访问,但不支持 8 字节未对齐访问。 后者在 UFSR.UNALIGNED 位的文档中有解释:

UNALIGNED - 表示发生了未对齐的访问操作。 未对齐的多字访问,例如访问非 8 字节对齐的uint64_t ,将始终生成此错误。 除了 Cortex-M0 MCU 之外,4 字节以下的未对齐访问是否产生故障也是可配置的。

8 字节访问可以是 STR 指令(如您的示例所示)或只是访问uint64_t

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM