当Cortex-M3出现硬故障时,如何保持堆栈竞争
How to retain a stacktrace when Cortex-M3 gone in hardfault?
使用以下设置:
- 基于Cortex-M3的µC
- gcc臂交叉工具链
- 使用C和C++
- FreeRtos 7.5.3
- 月食Luna
- Segger Jlink与JLinkGDBServer
- 代码信心FreeRtos调试插件
使用JLinkGDBServer和eclipse作为调试前端,我在执行代码时总是有一个很好的堆栈。当使用Code Confidence freertos工具(eclipse插件(时,我还会看到当前未运行的所有线程的堆栈争用(如果没有该插件,我只看到活动线程的堆栈竞用(。到目前为止还不错。
但现在,当我的应用程序出现硬故障时,堆栈竞争就失去了。好吧,我知道如何找出导致硬故障的代码地址的技术(如图所示(。但与完全堆叠相比,这是非常糟糕的信息。
好吧,有些时候,当陷入硬故障时,无法保留堆栈争用,例如,当堆栈被故障代码损坏时。但如果堆栈是健康的,我认为进行堆栈竞赛可能是可能的(不是吗?(。
我认为在硬故障时失去堆栈跟踪的原因是,Cortex-M3架构会自动将堆栈指针从PSP切换到MSP。现在的一个想法是,(也许(将MSP设置为以前的PSP值(也许还需要做一些额外的堆栈准备?(。
关于如何做到这一点或其他方法,在出现硬故障时保持堆栈竞争,有什么建议吗?
编辑2015-07-07,增加更多细节。
我用这个代码来引发一个硬故障:
__attribute__((optimize("O0"))) static void checkHardfault() {
volatile uint32_t* varAtOddAddress = (uint32_t*)-1;
(*varAtOddAddress)++;
}
当进入checkHardfault()
时,我的stacktrace看起来像这样:
gdb-> backtrace
#0 checkHardfault () at Main.cxx:179
#1 0x100360f6 in GetOneEvent () at Main.cxx:185
#2 0x1003604e in executeMainLoop () at Main.cxx:121
#3 0x1001783a in vMainTask (pvParameters=0x0) at Main.cxx:408
#4 0x00000000 in ?? ()
当遇到硬故障(在(*varAtOddAddress)++;
(并发现自己在HardFault_Handler()
中时,堆栈竞争是:
gdb-> backtrace
#0 HardFault_Handler () at Hardfault.c:312
#1 <signal handler called>
#2 0x10015f36 in prvPortStartFirstTask () at freertos/portable/GCC/ARM_CM3/port.c:224
#3 0x10015fd6 in xPortStartScheduler () at freertos/portable/GCC/ARM_CM3/port.c:301
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
让调试器向您提供硬故障前状态详细信息的最快方法是将处理器返回到硬故障前的状态。
在调试器中,编写一个脚本,从各种硬件寄存器获取信息,并将PC、LR、R0-R14恢复到导致硬故障之前的状态,然后进行堆栈转储。
当然,当你因为从炸开的堆栈中弹出东西或踩踏记忆中的东西而出现严重错误时,这并不总是有帮助的。您通常倾向于破坏一堆重要的寄存器,返回内存中的某个疯狂位置,然后执行其中的任何内容。在你真正的问题发生后,你可能会经历数千(数百万?(个周期的硬断层。
考虑使用以下gdb宏来恢复寄存器内容:
define hfstack
set $frame_ptr = (unsigned *)$sp
if $lr & 0x10
set $sp = $frame_ptr + (8 * 4)
else
set $sp = $frame_ptr + (26 * 4)
end
set $lr = $frame_ptr[5]
set $pc = $frame_ptr[6]
bt
end
document hfstack
set the correct stack context after a hard fault on Cortex M
end
- 函数何时会在c++中包含stack_Unwind_Resume调用
- 我可以信任表示整数的浮点或双精度来保持精度吗
- Python中的for循环与C++有何不同
- 算法问题:查找从堆栈中弹出的所有序列
- Constexpr替代了新的放置方式,可以让内存中的对象保持未初始化状态
- 使用模板进行堆栈实现; "name followed by :: must be a class or namespace"
- Visual Studio(或任何其他工具)能否将地址解释为调用堆栈(boost上下文)的开头
- 缓存std::数组的选定元素,并在c++中自动保持其一致性
- 为什么调用堆栈数组会导致内存泄漏
- gdb错误:Backtrace已停止:上一帧与此帧相同(堆栈已损坏?)
- 在 leetcode 上提交解决方案时出现堆栈缓冲区溢出错误
- 我的 int main() 中出现堆栈溢出错误
- 在 C++ 中在堆栈上创建实例时如何保持多态性?
- 如何制作硬编码堆栈,而不是硬编码并保持程序正常运行
- 无堆栈协程与堆叠协程有何不同
- 什么是堆栈?arrayStack ?arrayQueue ?堆栈队列 ?它们在C++上有何不同
- 如何保持在堆栈上分配的对象的动态类型
- 递归地搜索堆栈,但保持堆栈完整
- 当Cortex-M3出现硬故障时,如何保持堆栈竞争
- C++标准对堆栈溢出有何规定