未对齐的访问导致 ARM Cortex-M4 上的错误 [英] Unaligned access causes error on ARM Cortex-M4
问题描述
我有一个地址不是 4 字节对齐的对象.这会在存在节省 2 个寄存器的 STR 指令时导致 cpu 中出现 HardFault 错误.
I have an object that has an address that is not 4-byte aligned. This causes a HardFault error in the cpu when there is a STR instruction saving 2 registers.
这是生成的代码:
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..."行时的寄存器
These are the registers when at line "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
,它不会出现硬故障.
As seen the target register for STR-instructions are not aligned on 4-byte. The instruction STR r2, [r0, #4]
is executed fine. But it HardFaults on the next STRD r3, r1, [r4, #8]
. If I manually change register R4 to 08738B80
it does not hardfault.
这是生成上述 asm 的 C++ 代码:
This is the C++ code that generates the above asm:
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_end
跟在 0x08738B86
之后.
And m_start
is the first variable in the class and has the same address as this
(0x08738B82
), m_end
follows after on 0x08738B86
.
如何让对象按 4 字节对齐?有人对此有其他解决方案吗?
How do I get the object aligned on 4-byte? Anyone have some other solution to this?
推荐答案
在基于 ARM 的系统上,您经常无法寻址未与 4 字节边界对齐的 32 位字(正如您的错误所告诉您的那样).在 x86 上,您可以访问未对齐的数据,但是对性能有很大的影响.如果 ARM 部件确实支持未对齐的访问(例如单字正常加载),则存在性能损失并且应该有一个可配置的异常陷阱.
On ARM-based systems you frequently cannot address a 32-bit word that is not aligned to a 4-byte boundary (as your error is telling you). On x86 you can access non-aligned data, however there is a huge hit on performance. Where an ARM part does support unaligned accesses (e.g. single word normal load), there is a performance penalty and there should be a configurable exception trap.
ARM 上的边界错误示例(此处),TLDR:存储指针转换为 unsigned char
,然后尝试将其转换为 double *
(双指针).
Example of boundary error on ARM (here), TLDR: storing a pointer to an unsigned char
and then attempting to convert it to a double *
(double pointer).
要解决您的问题,您需要请求一个 4 字节对齐的内存块并复制未对齐的字节 + 用垃圾字节填充它以确保它是 4 字节对齐的(因此执行数据结构对齐手动).然后,您可以将该对象解释为与新地址对齐的 4 字节.
To solve your problem, you would need to request a block of memory that is 4-byte aligned and copy the non-aligned bytes + fill it with garbage bytes to ensure it is 4 byte-aligned (hence perform data structure alignment manually). Then, you can interpret that object as 4-byte aligned from its new address.
来自 TurboJ 的评论,显式错误:
From TurboJ in comments, the explicit error:
Cortex-M3 和 M4 默认允许未对齐访问.但是它们不允许使用 STRD 指令进行完全访问,因此是错误的.
Cortex-M3 and M4 allow unaligned access by default. But they do not allow unalinged access with the STRD instruction, hence the fault.
您可能还会发现查看这个很有帮助强制 ARM 上的数据结构对齐.
You may also find it helpful to look into this for forcing data structure alignment on ARM.
这篇关于未对齐的访问导致 ARM Cortex-M4 上的错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!