【发布时间】:2017-12-12 12:43:08
【问题描述】:
到目前为止,我在向量表中定义了一个 C 语言硬故障处理程序:
.sect ".intvecs"
.word _top_of_main_stack
.word _c_int00
.word NMI
.word Hard_Fault
.word Reserved
.word Reserved
.word Reserved
.word Reserved
.word Reserved
.word Reserved
.word Reserved
.word Reserved
.word Reserved
.word Reserved
.word Reserved
.word Reserved
....
....
....
我们的一项测试通过写入不存在的地址来触发硬故障(故意)。测试完成后,处理程序返回调用函数,皮质从故障中恢复。值得一提的是,处理程序没有任何参数。
现在我正处于编写真正处理程序的阶段。 我为堆栈帧创建了一个结构,这样我们就可以在出现故障时打印 PC、LR 和 xPSR:
typedef struct
{
int R0 ;
int R1 ;
int R2 ;
int R3 ;
int R12 ;
int LR ;
int ReturnAddress ;
int xPSR ;
} InterruptStackFrame_t ;
定义了我在 C 中的硬故障处理程序:
void Hard_Fault(InterruptStackFrame_t* p_stack_frame)
{
// Write to external memory that I can read from outside
/* prints a message containing information about stack frame:
* p_stack_frame->LR, p_stack_frame->PC, p_stack_frame->xPSR,
* (uint32_t)p_stack_frame (SP)
*/
}
我创建了一个汇编函数:
.thumbfunc _hard_fault_wrapper
_hard_fault_wrapper: .asmfunc
MRS R0, MSP ; store pointer to stack frame
BL Hard_Fault ; go to C function handler
POP {R0-R7} ; pop out all stack frame
MOV PC, R5 ; jump to LR that was in the stack frame (the calling function before the fault)
.endasmfunc
现在是说我没有操作系统的正确时机,所以我不必检查 LR 的 bit[2],因为我肯定知道我使用的是 MSP 而不是 PSP。
程序编译并正常运行,我使用 JTAG 确保所有寄存器恢复到所需值。
当执行最后一条命令 (MOV PC, R5) 时,PC 返回到正确的地址,但在某些时候,调试器指示 M0 被锁定在硬故障中并且无法恢复。
我不明白使用 C 函数作为处理程序或调用 C 函数的汇编函数之间的区别。
有谁知道问题出在哪里?
最终,我将使用一个断言函数来卡住处理器,但我希望它是可选的并且由我决定。
【问题讨论】:
-
您能否验证C函数
void Hard_Fault(InterruptStackFrame_t* p_stack_frame)的地址是偶数地址?查看地图文件。当处理器进入锁定状态并冻结时,还要检查S_LOCKUP位的值。 -
为什么不从异常中正常返回并让逻辑恢复寄存器(看起来您正在丢弃寄存器,但不确定您使用的是什么 C 编译器或约定)。
-
@Gaurav 我验证了 Hard_Fault 的地址是偶数(以 d0 结尾)。 S_LOCKUP 的值为 0:00000000000000110000000000000011 只有 S_HALT、S_REGRDY_ST、C_HALT 和 C_DEBUGEN 处于开启状态(读取调试故障状态寄存器 - 0xE000EDF0)
标签: c assembly exception-handling cortex-m faulthandler