未对齐的访问导致 ARM Cortex-M4 上的错误 [英] Unaligned access causes error on ARM Cortex-M4

查看:31
本文介绍了未对齐的访问导致 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆