【LPC54616的自学之路X】MCUXpresso IDE 的HardFault中断代码赏析

一个好的编译器IDE环境会给调试带来很大的帮助。

调试代码难免出现一些尴尬时刻

进HardFault 

虽然代码死了,但是作为开发者肯定很想知道代码为什么死了,死在哪里

通常HardFault中断总是一个While(1)死循环在哪里,死之前在哪不知道,为啥死不知道

 像是KEIL那些比较传统的IDE,出现这种情况,你只能去看死了以后寄存器的值,然后再找了

STM32的CUBEIDE和MCUXpresso IDE出现这种情况

类eclipse环境都有一个叫类似”故障分析器“的东西

从这里调出来【这里我以MCUXpresso IDE为例】

打开以后,界面多一个窗口

这个玩意就是可以在你HardFault的时候,记录下你大概为什么死和死在哪里的功能

STM32那个编译器的比较简陋一些,它只能记下死的时候的寄存器值,至于大概死在哪里,还是得自己用它提供的寄存器值【PC或者LR值】去内存里看一看大概位置

但是,我发现MCUXpresso IDE的这个功能居然支持记录大概死在哪里

它是通过一段在HardFault的汇编代码实现的,感觉这个实现可以学习下

 废话不多说,直接贴代码

#if !defined (__SEMIHOST_HARDFAULT_DISABLE)

__attribute__((naked))
void HardFault_Handler(void){
    __asm(  ".syntax unified\n"
        // Check which stack is in use
            "MOVS   R0, #4  \n"
            "MOV    R1, LR  \n"
            "TST    R0, R1  \n"
            "BEQ    _MSP    \n"
            "MRS    R0, PSP \n"
            "B  _process      \n"
            "_MSP:  \n"
            "MRS    R0, MSP \n"
        // Load the instruction that triggered hard fault
        "_process:     \n"
            "LDR    R1,[R0,#24] \n"
            "LDRH    R2,[r1] \n"
        // Semihosting instruction is "BKPT 0xAB" (0xBEAB)
            "LDR    R3,=0xBEAB \n"
            "CMP     R2,R3 \n"
            "BEQ    _semihost_return \n"
        // Wasn't semihosting instruction so enter infinite loop
            "B . \n"
        // Was semihosting instruction, so adjust location to
        // return to by 1 instruction (2 bytes), then exit function
        "_semihost_return: \n"
            "ADDS    R1,#2 \n"
            "STR    R1,[R0,#24] \n"
    	// Set a return value from semihosting operation.
    	// 32 is slightly arbitrary, but appears to allow most
    	// C Library IO functions sitting on top of semihosting to
    	// continue to operate to some degree
    		    "MOVS   R1,#32 \n"
    		    "STR R1,[ R0,#0 ] \n" // R0 is at location 0 on stack
    	// Return from hard fault handler to application
            "BX LR \n"
        ".syntax divided\n") ;
}

#endif

它这段代码上面有一段关于这个汇编代码的功能的注释

原文如下

// ****************************************************************************
//
//                       ===== DESCRIPTION =====
//
// One of the issues with applications that make use of semihosting operations
// (such as printf calls) is that the code will not execute correctly when the
// debugger is not connected. Generally this will show up with the application
// appearing to just hang. This may include the application running from reset
// or powering up the board (with the application already in FLASH), and also
// as the application failing to continue to execute after a debug session is
// terminated.
//
// The problem here is that the "bottom layer" of the semihosted variants of
// the C library, semihosting is implemented by a "BKPT 0xAB" instruction.
// When the debug tools are not connected, this instruction triggers a hard
// fault - and the default hard fault handler within an application will
// typically just contains an infinite loop - causing the application to
// appear to have hang when no debugger is connected.
//
// The below code provides an example hard fault handler which instead looks
// to see what the instruction that caused the hard fault was - and if it
// was a "BKPT 0xAB", then it instead returns back to the user application.
//
// In most cases this will allow applications containing semihosting
// operations to execute (to some degree) when the debugger is not connected.
//
// == NOTE ==
//
// Correct execution of the application containing semihosted operations
// which are vectored onto this hard fault handler cannot be guaranteed. This
// is because the handler may not return data or return codes that the higher
// level C library code or application code expects. This hard fault handler
// is meant as a development aid, and it is not recommended to leave
// semihosted code in a production build of your application!
//
// ****************************************************************************

// Allow handler to be removed by setting a define (via command line)

我大概翻译下注释和这段代码的功能 

使用半主机作为打印功能的一个问题是当主机没有接调试器的时候,程序会卡住。
卡住的原因是C库半主机变量的底层,半主机执行了BKPT 0xAB指令。

当调试器没有连结的时候,这个指令会卡在HardFault
因为通常情况下HardFault中断里面是一个死循环,而这段汇编代码将不会卡住而是返回到应用程序。正确执行这段代码是不能保证,因为这段处理函数可能不会返回让高层C库或者应用层接收的数据或者代码,只能用于开发不能用于产品。

 代码的功能

首先检查现在用的是MSP还是PSP堆栈

装入触发HardFault的指令

如果是半主机指令,则调整返回的地址,往前移动一条指令,设置一个返回值,让主机还能够运行一下

否则就卡死在这

 关于半主机,有很多帖子讲这个,这里不再赘述

感觉它这个往回移动一条指令这部分做的很好,这样能够大概知道死在哪里,而不需要自己去死的PC和LR附近找半天找不到

 下面来试一试

我们人为写一个”空指针赋值“的问题代码

然后跑起来,让它死机

 IDE马上就捕捉到了故障并显示出详细的故障代码和死的位置,实际调试中这样的信息就很有帮助啦

详细到出问题的行号附近了

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值