c++ - 在 CortexM0 中从 RAM 运行代码时出现 HardFault

标签 c++ assembly memory arm cortex-m

我目前正在为 Arm Cortex-M0+ 微 Controller 开发固件,我遇到了一个相当有趣的问题。我不是在寻找任何答案,而是想与其他开发人员分享这个问题,这样我就可以(希望)阐明我面临的问题。我将在下面描述它:

我有一个程序可以从外部闪存芯片动态加载(正确编译和链接)代码,直接从 MCU RAM 中执行。有趣的是,我在一步步运行时(通过调试器)可以完美执行RAM加载的代码,但在自由运行时它总是会崩溃[正式的HardFault]。我试图禁用所有中断,我仔细检查了指令、内存地址、字节对齐等所有内容,但我仍然无法查明异常的原因。

你们中的一些人对可能发生的事情有任何暗示吗?我很想知道更多关于您的经历!谢谢,

更新 1 (30/05)

自由运行 在这种情况下,意味着不在 RAM 分支之前设置断点。每当我进入分支并执行 RAM 中的指令时,它都会正确运行并返回。只要断点不存在(因此 MCU 会通过分支进行缩放),就会观察到 HardFault。请注意,即使在使用调试器但未设置断点的情况下启动时,它也会崩溃。

更新 2 (30/05)

我使用的是 Cypress S6E1C3 系列 Arm Cortex M0+ FM0+ 微 Controller

更新 3 (30/05)

在深入研究并使用代码后,我可以让它正常工作!然而,它给我带来的问题多于答案。阅读有关 BLX 指令 ( BLX ) 的官方 ARM 文档,我发现分支地址的 LSBit 决定 CPU 指令模式(1 导致它在 Thumb 模式下运行)。通过显式设置此位,我让代码始终有效,即使在自由运行模式。问题是,RAM 中的代码尚未在 Thumb 模式下编译,并且没有明显理由说明为什么使用调试器逐步运行代码会导致指令模式发生变化。 . 有什么想法吗?

K.

最佳答案

Cortex-M 支持 Thumb 模式,不支持 ARM 模式,因此告诉您的编译器为 Cortex-M0+ 编译器保证它将创建 Thumb2 代码。

这就是为什么您需要设置目标地址的低位。

https://en.wikipedia.org/wiki/ARM_Cortex-M#Instruction_sets

Only Thumb-1 and Thumb-2 instruction sets are supported in Cortex-M architectures; the legacy 32-bit ARM instruction set isn't supported.

如果您实际查看内存中的代码字节,您会发现它们是 Thumb2 指令。

唯一的问题是您的调试器如何让它不是错误。也许无论如何它必须专门处理 BLX,并且不模拟错误-如果-在 Thumb-only 微架构行为上切换到 ARM 模式。或者可能只是处理单步中断最终在 Thumb 模式下正确返回。


我认为,“legacy”对于一般的 ARM 模式来说有点夸大其词;我认为高性能 ARM 芯片(具有大型指令缓存)仍然可以从 ARM 模式中获益,以更少的指令完成更多工作并更容易访问更多寄存器。无论如何,这只是维基百科的措辞。

关于c++ - 在 CortexM0 中从 RAM 运行代码时出现 HardFault,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56368081/

相关文章:

c++ - 在 C/C++ 中使用 ProtoBuf 进行深度复制

c++ - 从 C++ 中的偏移量覆盖二进制文件的字节

assembly - 与 0 (x86) 比较后的 JNB

windows - 你能在 Windows 中直接调用任务吗?

linux - PSS/USS Linux-Android。 Pss包含Uss吗?

delphi - delphi TFileStream“内存不足”

c++ - 重载类方法与模板

c++ - c++11 中首选的初始化方式

docker - Bitbucket Pipeline - Docker 内存

assembly - 我的程序集冒泡排序有什么问题?