简体   繁体   English

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

[英]Arm Cortex-M4 LDRD instruction causing hardfault

I notice that in the Cortex-M3 that the LDRD (load double word) is listed in the errata , but I'm not finding similar for Cortex-M4, and at any rate, there does not appear to be an interrupt occurring during execution.我注意到在 Cortex-M3中,勘误表中列出LDRD (加载双字),但我没有发现 Cortex-M4 的类似情况,无论如何,执行期间似乎没有发生中断. I'm working with an M4 microcontroller, and passing data to/from a host.我正在使用 M4 微控制器,并向/从主机传递数据。 It's handy to work with the data in the shape the host (same architecture) deals with it - for example, if the host passes an unsigned 16-bit integer, I accept it as a uint16_t , even though it is in two byte array data_in :使用主机(相同架构)处理的形状的数据很方便 - 例如,如果主机传递一个无符号的 16 位 integer,我接受它作为uint16_t ,即使它在两个字节数组data_in

uint16_t some_data = *(uint16_t *)data_in;

When I try to do this with an unsigned 64-bit integer, however, I get a hardfault on the generated LDRD instruction:但是,当我尝试使用无符号 64 位 integer 执行此操作时,生成的LDRD指令出现硬故障:

uint64_t some_data = *(uint64_t *)data_in;

generates:生成:

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]

and I hardfault on E9D32300 ldrd r2, r3, [r3, #0] .我对E9D32300 ldrd r2, r3, [r3, #0]进行了硬故障。

So the question is, other than possible portability issues (not a problem here) am I doing something fundamentally wrong by pointing to the location of a uint64_t and trying to read it as a uint64_t?所以问题是,除了可能的可移植性问题(这里不是问题)之外,我是否通过指向 uint64_t 的位置并尝试将其读取为 uint64_t 来做一些根本错误的事情? Either way, has anyone seen an erratum for this instruction reported anywhere?无论哪种方式,有没有人看到任何地方报告的该指令的勘误? I'm not finding it in the official docs.我没有在官方文档中找到它。

Also, just for completeness, this much less fun code works fine:此外,为了完整起见,这个不那么有趣的代码可以正常工作:

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);

In the ARMv7M architecture reference manual, section A3.2.1 "Alignment behavior" it says:在 ARMv7M 架构参考手册的 A3.2.1 节“对齐行为”中它说:

The following data accesses always generate an alignment fault:以下数据访问始终会生成 alignment 故障:

  • Non halfword-aligned LDREXH and STREXH.非半字对齐的 LDREXH 和 STREXH。
  • Non word-aligned LDREX and STREX.非字对齐 LDREX 和 STREX。
  • Non word-aligned LDRD, LDMIA, LDMDB, POP, LDC, VLDR, VLDM, and VPOP.非字对齐 LDRD、LDMIA、LDDMB、POP、LDC、VLDR、VLDM 和 VPOP。
  • Non word-aligned STRD, STMIA, STMDB, PUSH, STC, VSTR, VSTM, and VPUSH.非字对齐的 STRD、STMIA、STMDB、PUSH、STC、VSTR、VSTM 和 VPUSH。

So unless you know that data_in is at-least 32-bit aligned, you can't cast it to (uint64_t*) and expect it to work.因此,除非您知道data_in至少是 32 位对齐的,否则您不能将其转换为(uint64_t*)并期望它能够正常工作。

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

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