- SCB->CCR |= 0x18; // enable div-by-0 and unaligned fault
**Hard Fault:**在调试程序过程中,这种异常最常见。上面三种异常发生任何一种异常都会引起Hard Fault,在上面的三种异常未使能的情况下,默认发生异常时进入Hard Fault中断服务程序。使能前三种异常也要在初始化时配置:
[cpp] view plain copy
-
SCB->SHCSR |= 0x00007000; // enable Usage Fault, Bus Fault, and MMU Fault
在默认复位初始化时,Hard Fault使能,其它三者不使能,因此当程序中出现不合法内存访问(一般是指针错误引起)或非法的程序行为(一般就是数学里面常见的除0)时都将产生Hard Fault中断。
2 Hard Fault调试方法
假设IDE环境为Keil,芯片为STM32F103。
在stm32f10x_it.c中,添加软件断点,一旦调试时出现Hard Fault则会在停在__breakpoint(0)处。
[cpp] view plain copy
-
/**
-
* @brief This function handles Hard Fault exception.
-
* @param None
-
* @retval None
-
*/
-
void HardFault_Handler(void)
-
{
-
/* Go to infinite loop when Hard Fault exception occurs */
-
if (CoreDebug->DHCSR & 1) { //check C_DEBUGEN == 1 -> Debugger Connected
-
__breakpoint(0); // halt program execution here
-
}
-
while (1)
-
{
-
}
-
}
当进入Hard Fault断点后,菜单栏Peripherals >Core Peripherals >Fault Reports打开异常发生的报告,查看发生异常的原因。
上面的报告发生了BUS FAULT,并将Fault的中断服务转向Hard Fault。
相对于检测发生了什么异常,定位异常发生位置显得更重要。
(1)打开Call Stack窗口(如下图左侧,断点停在Hard Fault服务程序中)
(2)在Call Stack的HardFault_Handler上右键Show Caller Code(有的Keil版本也可以直接双击)
这时将跳转到发生异常的源代码位置(如上图),异常发生在p->hour=0这一行。这里错误很明显:指针p尚未为成员变量分配内存空间,直接访问未分配的内粗空间肯定出错。
再说明2点:
[1] 在复杂的情况下,即使定位了异常发生位置也很难容易的改正错误,要学会使用Watch窗口对发生错误的指针变量进行跟踪;
[2] 在问题不明晰的情况下,尝试分析反汇编代码,就自己遇到的,部分情况下的异常发生在BL等跳转指令处,BL跳转到了不合法的内存地址产生异常
在没有JTAG的情况下,通过串口打印出堆栈信息:
1 /\* Private typedef -----------------------------------------------------------\*/
2 enum { r0, r1, r2, r3, r12, lr, pc, psr};
3
4 /\* Private define ------------------------------------------------------------\*/
5 /\* Private macro -------------------------------------------------------------\*/
6 /\* Private variables ---------------------------------------------------------\*/
7 extern __IO uint16_t ADC_InjectedConvertedValueTab[32];
8 uint32_t Index = 0;
9
10 /\* Private function prototypes -----------------------------------------------\*/
11 void Hard\_Fault\_Handler(uint32\_t stack[]);
12
13 /\* Private functions ---------------------------------------------------------\*/
14
15 static void printUsageErrorMsg(uint32\_t CFSRValue)
16 {
17 printf("Usage fault: \r\n");
18 CFSRValue >>= 16; // right shift to lsb
19
20 if((CFSRValue & (1<<9)) != 0) {
21 printf("Divide by zero \r\n");
22 }
23 if((CFSRValue & (1<<8)) != 0) {
24 printf("Unaligned access \r\n");
25 }
26 }
27
28 static void printBusFaultErrorMsg(uint32\_t CFSRValue)
29 {
30 printf("Bus fault: \r\n");
31 CFSRValue = ((CFSRValue & 0x0000FF00) >> 8); // mask and right shift to lsb
32 }
33
34 static void printMemoryManagementErrorMsg(uint32\_t CFSRValue)
35 {
36 printf("Memory Management fault: \r\n");
37 CFSRValue &= 0x000000FF; // mask just mem faults
38 }
39
40 static void stackDump(uint32\_t stack[])
41 {
42 static char msg[80];
43 sprintf(msg, "R0 = 0x%08x\r\n", stack[r0]); printf(msg);
44 sprintf(msg, "R1 = 0x%08x\r\n", stack[r1]); printf(msg);
45 sprintf(msg, "R2 = 0x%08x\r\n", stack[r2]); printf(msg);
46 sprintf(msg, "R3 = 0x%08x\r\n", stack[r3]); printf(msg);
47 sprintf(msg, "R12 = 0x%08x\r\n", stack[r12]); printf(msg);
48 sprintf(msg, "LR = 0x%08x\r\n", stack[lr]); printf(msg);
49 sprintf(msg, "PC = 0x%08x\r\n", stack[pc]); printf(msg);
50 sprintf(msg, "PSR = 0x%08x\r\n", stack[psr]); printf(msg);
51 }
52
53 void Hard\_Fault\_Handler(uint32\_t stack[])
54 {
55 static char msg[80];
56 //if((CoreDebug->DHCSR & 0x01) != 0) {
57 printf("\r\nIn Hard Fault Handler\r\n");
58 sprintf(msg, "SCB->HFSR = 0x%08x\r\n", SCB->HFSR);


**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新**
**[如果你需要这些资料,可以戳这里获取](https://gitee.com/vip204888)**