Arm Cortex-M4 LDRD 指令导致硬故障

Posted

技术标签:

【中文标题】Arm Cortex-M4 LDRD 指令导致硬故障【英文标题】:Arm Cortex-M4 LDRD instruction causing hardfault 【发布时间】:2021-07-23 20:38:34 【问题描述】:

我注意到在 Cortex-M3 中 LDRD(加载双字)是 listed in the errata,但我没有发现 Cortex-M4 类似,而且无论如何,似乎没有执行期间发生中断。我正在使用 M4 微控制器,并向/从主机传递数据。使用主机(相同架构)处理它的形状的数据很方便 - 例如,如果主机传递一个无符号的 16 位整数,我接受它作为 uint16_t,即使它是两个字节数组data_in:

uint16_t some_data = *(uint16_t *)data_in;

但是,当我尝试使用无符号 64 位整数执行此操作时,生成的 LDRD 指令出现硬错误:

uint64_t some_data = *(uint64_t *)data_in;

生成:

9B01        ldr r3, [sp, #4]
330C        adds r3, #12
E9D32300    ldrd r2, r3, [r3, #0]
4902        ldr r1, =SOME_ADDR <some_data>
E9C12306    strd r2, r3, [r1, #24]

我在E9D32300 ldrd r2, r3, [r3, #0] 上犯了错误。

所以问题是,除了可能的可移植性问题(这里不是问题)之外,我是否通过指向 uint64_t 的位置并尝试将其读取为 uint64_t 来做一些根本错误的事情?无论哪种方式,有没有人在任何地方看到过该指令的错误报告?我没有在官方文档中找到它。

另外,为了完整起见,这段不那么有趣的代码可以正常工作:

uint64_t some_data = ((uint64_t)data_in[7] << 8*7) |
                     ((uint64_t)data_in[6] << 8*6) |
                     ((uint64_t)data_in[5] << 8*5) |
                     ((uint64_t)data_in[4] << 8*4) |
                     ((uint64_t)data_in[3] << 8*3) |
                     ((uint64_t)data_in[2] << 8*2) |
                     ((uint64_t)data_in[1] << 8*1) |
                     ((uint64_t)data_in[0] << 8*0);

【问题讨论】:

请不要假设一个核心有勘误表适用于其他核心。另一个常见错误是勘误表将适用于特定核心和核心的特定转速,而不一定适用于同一产品的其他转速(cortex-m3。但当然没有理由假设勘误表适用于不同的产品 cortex- m4 或同一产品 cortex-m3 的不同版本 如答案所示,但只要您在数据访问中遇到硬故障,首先要寻找的是对齐。在这种情况下,从 ldrh 更改为 ldrd(也可以尝试 ldr)首先想到的是对齐。某些内核可以禁用对齐错误,并且大多数会导致您所期望的结果,例如在较旧的 arm7tdmi 上,尽管它不是您所期望的......但可重复...... 【参考方案1】:

在 ARMv7M 架构参考手册的 A3.2.1 节“对齐行为”中它说:

以下数据访问总是会产生对齐错误:

非半字对齐 LDREXH 和 STREXH。 非字对齐 LDREX 和 STREX。 非字对齐 LDRD 、 LDMIA 、 LDMDB 、 POP 、 LDC 、 VLDR 、 VLDM 和 VPOP 。 非字对齐 STRD、STMIA、STMDB、PUSH、STC、VSTR、VSTM 和 VPUSH。

因此,除非您知道 data_in 至少是 32 位对齐的,否则您不能将其转换为 (uint64_t*) 并期望它能够正常工作。

【讨论】:

啊,谢谢!所以我可能应该在传入的数据结构(包含 data_in)上使用 __ALIGN。 没问题。如果 __ALIGN 是一个扩展为 __attribute__((packed)) 之类的宏,那么这将强制编译器执行您的工作示例中的内容,但为您减少输入。 如果这回答了您的问题,那么请您接受左侧绿色勾号的答案吗?谢谢。

以上是关于Arm Cortex-M4 LDRD 指令导致硬故障的主要内容,如果未能解决你的问题,请参考以下文章

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

ARM探索之旅 | 二ARM Cortex-M 用什么指令集?

Cortex-M3&Cortex-M4-技术综述

嵌入式MCU ARM Cortex-M3工作模式与异常

ARM处理器基础Cortex-M4

组装 THUMB 指令以在 Cortex-M3 上执行