ARM Cortex-M4上未对齐的访问导致错误

jv2fixgn  于 2022-12-03  发布在  其他
关注(0)|答案(3)|浏览(539)

我有一个对象的地址不是4字节对齐的。当有STR指令保存2个寄存器时,这会导致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行“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是类中的第一个变量,与this0x08738B82)具有相同的地址,m_end0x08738B86之后。
我如何让对象在4字节上对齐?有人有其他的解决方案吗?

bpsygsoo

bpsygsoo1#

在基于ARM的系统上,您经常无法对未与4字节边界对齐的32位字进行寻址(正如错误所告诉您的那样)。在x86上,您可以访问未对齐的数据,但这会对性能造成巨大影响。如果ARM部件确实支持未对齐的访问(例如,单个字的正常加载),则会对性能造成损失 并且应该有一个可配置的异常陷阱。
ARM(here)、TLDR上的边界错误示例:存储指向unsigned char的指针,然后尝试将其转换为double *(双指针)。
要解决这个问题,你需要请求一个4字节对齐的内存块,然后复制未对齐的字节,并用垃圾字节填充它,以确保它是4字节对齐的(因此需要手动执行数据结构对齐)。然后,你可以根据新地址将该对象解释为4字节对齐。
从TurboJ的注解中,显式错误:
Cortex-M3和M4默认允许非对齐访问。但它们不允许使用STRD指令进行非对齐访问,因此出现故障。
您可能还会发现,研究这一点对于在ARM上强制数据结构对齐很有帮助。

7xzttuei

7xzttuei2#

以下至少适用于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整除,因此上述行不会产生硬故障。

7lrncoxx

7lrncoxx3#

正如您所发现的,Cortex-M4支持4字节非对齐访问,但不支持8字节非对齐访问。后者在UFSR.UNALIGNED位文档中有解释:
UNALIGNED -表示发生了未对齐的访问操作。未对齐的多字访问(如访问未对齐8字节的uint64_t)将始终生成此故障。除Cortex-M0 MCU外,低于4字节的未对齐访问是否生成故障也可配置。
8字节访问可以是STR指令(如示例中所示),也可以只是访问uint64_t

相关问题