在gpio_led_output.c 和 startup_MK65F18.S文件添加下面代码,点击运行产生HardFault中断;
/***gpio_led_output.c***/
static void EnableFault(void)
{
SCB->SHCSR |= \(SCB_SHCSR_USGFAULTENA_Msk|SCB_SHCSR_BUSFAULTENA_Msk|SCB_SHCSR_MEMFAULTENA_Msk);
}
int main(void)
{
/* Define the init structure for the output LED pin*/
gpio_pin_config_t led_config = {
kGPIO_DigitalOutput, 0,
};
/* Board pin, clock, debug console init */
BOARD_InitPins();
BOARD_BootClockRUN();
BOARD_InitDebugConsole();
EnableFault();
*(uint8_t *)0x10000 = 0x12;
/* Print a note to terminal. */
PRINTF("\r\n GPIO Driver example\r\n");
PRINTF("\r\n The LED is blinking.\r\n");
/* Init output LED GPIO. */
GPIO_PinInit(BOARD_LED_GPIO, BOARD_LED_GPIO_PIN, &led_config);
while (1)
{
delay();
GPIO_PortToggle(BOARD_LED_GPIO, 1u << BOARD_LED_GPIO_PIN);
}
}
/****startup_MK65F18.S****/
PUBWEAK HardFault_Handler
SECTION .text:CODE:REORDER:NOROOT(1)
HardFault_Handler
IMPORT hard_fault_handler
一、进入HardFault中断时CPU寄存器的值
二、在进入异常服务程序后, LR的值被自动更新为特殊的 EXC_RETURN,这是一个高28位全为1的值
上图中LR = 0xFFFFFFF9,所以使用的是MSP
三、在内存中找到MSP对应的地址,并查看存储地址的值
四、LR对应的汇编语句,正常执行时,函数返回后的执行地址
五、PC寄存器对应的汇编语句
PC寄存器存储的是中断返回后执行的语句,
1、在异常处理例程完成后需要从中断返回时,LR的值载入到PC中(通常是BX LR指令,也可以是MOV PC,LR指令,或者POP {…, PC}等指令,只要能将LR赋给PC即可),由于LR的值是0xFFFFFFF9,CPU检测到向PC中载入的是这个特殊值时,就知道是中断返回,于是做中断返回的动作(与压入动作相反:从堆栈中弹出核心寄存器的值,恢复到线程模式或Handler模式等)。此时的BX LR 与 一般函数的中所调用的BX LR 有所不同。
2、在进入中断函数之前 PC计数器执行到 0x1964: 0xf7ff 0xf890 BL DbgConsole_Printf ; 0xa88
后发生中断进入到HardFault_Handler函数执行第一条指令BX LR
;但实际上触发中断的是0x1960: 0x7008 STRB R0, [R1]
这条指令;这可能是因为中断触发延时。如果在没有触发中断的情况下PC将执行0X00000F6B
地址处的语句,
break;
0xf6a: 0xe014 B.N 0xf96
LPUART_GetDefaultConfig(&lpuart_config);
当中断返回时,因为是执行这句*(uint8_t *)0x10000 = 0x12;
代码产生了中断,所以在中断返回时PC寄存器将指向0X00001962
地址处执行
0x1962: 0x480b LDR.N R0, [PC, #0x2c] ; 0x1df0 (7664)