精华内容
下载资源
问答
  • Hardfault

    2018-06-15 11:26:53
    这一次的hardfault大概花了一天的时间才解决,有三个同事前辈帮忙。主要是因为使用了calloc分配内存后,就是没有使用memset来清零。而后面程序默认为它是0,导致跑飞。跑飞。...

    这一次的hardfault大概花了一天的时间才解决,有三个同事前辈帮忙。

    主要是因为使用了calloc分配内存后,就是没有使用memset来清零。而后面程序默认为它是0,导致跑飞。

    跑飞。

    展开全文
  • hard fault handler

    2019-05-16 17:19:57
    k65 hard fault 设置,
  • 处理hardfault问题

    2020-08-04 05:12:06
    在debug时经常会出现程序莫名其妙的掉到hardfault的中断中,起初完全不知道是从哪里查找问题,后来有遇到过几次,通过网络资料以及自己的调试,对于解决这样的问题有一些体会,我分析给大家,希望对初学者有用。
  • 电机控制的Demo,在调试CAN通信时,出现软件进入HardFault_Handler中断故障。 问题描述: 在调试CAN通信时,为了只调试CAN模块,所以将外设初始化位置的TIM1,TIM2的初始化屏蔽掉,然后出现了程序进入HardFault_...

    项目场景:

            电机控制的Demo,在调试CAN通信时,出现软件进入HardFault_Handler中断故障。


    问题描述:

       在调试CAN通信时,为了只调试CAN模块,所以将外设初始化位置的TIM1,TIM2的初始化屏蔽掉,然后出现了程序进入HardFault_Handler中断故障。


    原因分析:

             根据bug出现的过程,初步确定是由于将TIM1,TIM2禁掉导致的,但是,即使禁掉TIMx,也不应该影响到CAN,继续分析发现,虽然禁掉TIMx,但是在任务Task中,还有对TIM1的寄存器(比较寄存器,使能寄存器)有写的操作,所以,单片机任务是有问题的,报出故障。


    解决方案:

            将对不使用的外设的寄存器的写操作禁掉,问题的到了解决。

    展开全文
  • STM32常见Hard Fault的诊断信息,STM32常见Hard Fault的诊断信息
  • Cortex-M3_内核HardFault错误调试定位方法 Cortex-M3_内核HardFault错误调试定位方法 Cortex-M3_内核HardFault错误调试定位方法 Cortex-M3_内核HardFault错误调试定位方法
  • STM32 HardFault的诊断

    2016-06-06 17:33:09
    STM32 HardFault的诊断,阐述多种引发STM32 HardFault的原因与方法。
  • HardFault定位步骤

    千次阅读 2016-05-18 13:35:21
    HardFault

    以下内容是参考《CM3权威指南》和stm32f10x的解决方法总结的,有些内容会有所出入。实操中找不到和图片相同的内容时记得要灵活变通。

    1.在stm32f4xx_it.c中的HardFault_Handler()中添加断点。当硬错误发生时就可以马上暂停程序执行。

    2.此时查看R14(LR)寄存器的值,确定哪个指针的值是有效的。根据图片里的数值,我取MSP的值0x20000938。

    1

    2

    3.打开Memory窗口,跳至MSP=0x20000938的内存位置。从这里向高地址数六个(也就是第七个?我也不是很清楚~)unsigned long,那个0x0800xxxx的数字就是出错的程序位置了。

    3

    4.打开反汇编窗口,右键->”Show Disassembly at Address”,输入我看到的第七个地址0x080021F2,就可跳转到发生HardFault的那一行代码了。

    4

    参考链接:http://bbs.ednchina.com/BLOG_ARTICLE_3024685.HTM

    (另外在FreeRTOS中有个更详细的指南,我没看~:
    http://www.freertos.org/Debugging-Hard-Faults-On-Cortex-M-Microcontrollers.html

    展开全文
  • 鬼魅一样的 Hard Fault

    2018-03-16 16:11:04
    程序会莫名其妙的跳到 Hard Fault 中断,在程序中,产生该中断的位置不固定,忽而在这里,忽而在那里。
  • STM32 HardFault的诊断.zip

    2020-08-28 16:33:36
    HardFault的诊断方法,官方培训资料
  • HardFault排查

    2020-06-10 00:57:47
    HardFault排查背景知识简介发生中断时处理器的行为HardFault错误信息的挖掘编译器通过栈来实现函数调用对信息的继续挖掘通用寄存器特殊功能寄存器SCB寄存器附录一:Hardfault Handler示例代码附录二:MAP文件和List...

    背景知识简介

    发生中断时处理器的行为

    不考虑其他细节,M3内核在发生中断时首先自动将如下8个寄存器压栈。因此在中断处理函数中,发生中断时正常执行时的寄存器数值已经被压入了堆栈中。在中断处理函数开始执行时,除了PC,LR,SP等控制寄存器,从r0-r12等这些通用寄存器的数据是没有变化的。下图描述了M3内核将寄存器压栈的顺序:
    在这里插入图片描述

    HardFault错误信息的挖掘

    编译器通过栈来实现函数调用

    C编译器通过栈来实现函数的调用,即在栈中记录程序执行的轨迹并辅助寄存器进行参数传递。具体如何实现C函数的调用,历史上有很多的规范,这些规范叫做调用惯例。对于ARM处理器来说,有一个官方的规范AAPCS(Procedure Call Standard for the ARM® Architecture)详细描述了进行函数调用时如何进行参数的传递和调用路径的记录等。如下仅对使用栈记录调用路径的行为进行简单描述:

    查看编译器生成的汇编代码可以得知,大多数的函数调用通过BL语句实现,BL语句将当前程序下一条指令的地址存入LR寄存器,并跳转到指定的地方(子函数开始的地方)开始执行。子函数中如果还需要调用孙子函数,就会在函数的入口处将LR的值压栈,以便函数执行结束后能够返回父函数。因此依次找到栈中LR的数值,就能找到调用路径中各个函数的地址。最后根据map文件翻译出各函数的名称,就可以得到函数的调用路径了。

    如下是一个简单函数汇编代码的例子,函数OnPowerOff调用了函数FS_Deinit,函数FS_Deinit调用了SPIFFS_unmount。可以看出OnPowerOff函数的入口如将LR压入栈中(此时LR中保存的是函数OnPowerOff的返回地址,也就是调用OnPowerOff的父函数中的某条指令的地址),然后调用了FS_Deinit。同样FS_Deinit也在入口处将LR压入栈中(此时LR中保存的是OnPowerOff函数中POP指令的地址),然后再调用SPIFFS_unmount。返回的过程,依次将栈中保存的返回地址直接出栈到PC寄存器,完成函数的返回。这样,如果某个函数将栈中的返回地址写坏,则函数在返回时就会跳转到某个随机的地方,这就是常说的“程序跑飞了”。

    OnPowerOff PROC
    
    ;;;202 void OnPowerOff(void)
    
    0001b2 b510 PUSH {r4,lr}
    
    ;;;203 {
    
    ;;;204 FS_Deinit();
    
    0001b4 f7fffffe BL FS_Deinit
    
    ;;;205 }
    
    0001b8 bd10 POP {r4,pc}
    
    ;;;206
    
    ENDP
    
    FS_Deinit PROC
    
    ;;;166 void FS_Deinit(void)
    
    000158 b510 PUSH {r4,lr}
    
    ;;;167 {
    
    ;;;168 SPIFFS_unmount(&g_fs);
    
    00015a 4810 LDR r0,|L1.412|
    
    00015c f7fffffe BL SPIFFS_unmount
    
    ;;;169 return;
    
    ;;;170 }
    
    000160 bd10 POP {r4,pc}
    
    ;;;171
    
    ENDP
    

    对信息的继续挖掘

    通用寄存器

    通用寄存器中可供挖掘的信息并不多,通常情况下r0-r3寄存器保存着函数的前四个参数(其余的参数在栈中保存),需要注意的是:这四个寄存器的数值仅在函数开始执行的时候是可靠的,在函数执行的过程中可能被改变。在函数返回时,寄存器r0和r1用于保存返回值(根据返回数据的大小,决定仅使用r0还是同时使用r0和r1)。同样这两个寄存器仅在子函数刚返回时数值才是可靠的。

    特殊功能寄存器

    特殊功能寄存器就是PCLRSP了。

    SP指向当前的栈顶,在知晓栈的结构时,可以根据SP访问栈中的数据。

    在中断处理函数中LR有特殊用法,其中保存了返回被中断地点的方法,而不是通常情况下的返回地址。因此在Hardfault处理函数中寄存器LR和PC的值没有太多参考意义,被处理器自动压栈的LR和PC最有用,PC记录了被中断打断前正在执行的指令地址也是正在执行的函数地址),LR记录了被中断打断前,正在执行的函数的父函数的地址。根据这两个地址,可以找到引发Hardfault异常的函数和语句,以及其父函数(如果辅以汇编代码继续对栈的内容进行分析,则可以回溯整个调用路径)。

    而具体引发Hardfault异常的原因,可以根据下面章节介绍的SCB寄存器来查看。

    SCB寄存器

    在M3/M4处理器标准外设中,有一个叫做SCB(System Control Block)的部分,其中有6个寄存器记录了发生Hardfault异常的原因。

    CMSIS规范中对SCB寄存器的定义:

    typedef struct
    {
    	__I uint32_t CPUID;
    	
    	__IO uint32_t ICSR;
    	
    	__IO uint32_t VTOR;
    	
    	__IO uint32_t AIRCR;
    	
    	__IO uint32_t SCR;
    	
    	__IO uint32_t CCR;
    	
    	__IO uint8_t SHP[12];
    	
    	__IO uint32_t SHCSR;
    	
    	__IO uint32_t CFSR;
    	
    	__IO uint32_t HFSR;
    	
    	__IO uint32_t DFSR;
    	
    	__IO uint32_t MMFAR;
    	
    	__IO uint32_t BFAR;
    	
    	__IO uint32_t AFSR;
    	
    	__I uint32_t PFR[2];
    	
    	__I uint32_t DFR;
    	
    	__I uint32_t ADR;
    	
    	__I uint32_t MMFR[4];
    	
    	__I uint32_t ISAR[5];
    	
    	uint32_t RESERVED0[5];
    	
    	__IO uint32_t CPACR;
    
    } SCB_Type;
    

    寄存器CFSRHFSRMMFARBFAR是我们需要关注的,AFSR是平台相关的暂时忽略。上述寄存器中CFSR又可以分为三个寄存器分别是:UFSR,BFSR,MFSR。上述寄存器的内存分布如下图所示:
    在这里插入图片描述
    各寄存器数据的描述如下:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    解读SCB寄存器时应首先根据HFSR寄存器判断产生Hardfault的原因,如果确认是fault上访的情况,则依次检查BFSR、UFSR和HFSR确定具体的错误原因和地址。

    附录一:Hardfault Handler示例代码

    附加一段Hardfault Handler中断响应函数的示例,该函数中打印所有通用寄存器,特殊功能寄存器和SCB寄存器,并对SCB寄存器的内容进行了基本的解读,配合上述文字,可以更精确的定位发生Hardfault的原因和位置。

    #define SCB_CFSR_MMFSR_IACCVIOL (0x01 << 0)
    
    #define SCB_CFSR_MMFSR_DACCVIOL (0x01 << 1)
    
    #define SCB_CFSR_MMFSR_MUNSTKERR (0x01 << 3)
    
    #define SCB_CFSR_MMFSR_MSTKERR (0x01 << 4)
    
    #define SCB_CFSR_MMFSR_MMARVALID (0x01 << 7)
    
    #define SCB_CFSR_BFSR_IBUSERR (0x01 << (0 + 8))
    
    #define SCB_CFSR_BFSR_PRECISERR (0x01 << (1 + 8))
    
    #define SCB_CFSR_BFSR_IMPRECISERR (0x01 << (2 + 8))
    
    #define SCB_CFSR_BFSR_UNSTKERR (0x01 << (3 + 8))
    
    #define SCB_CFSR_BFSR_STKERR (0x01 << (4 + 8))
    
    #define SCB_CFSR_BFSR_BFARVALID (0x01 << (7 + 8))
    
    #define SCB_CFSR_UFSR_UNDEFINSTR (0x01 << (0 + 16))
    
    #define SCB_CFSR_UFSR_INVSTATE (0x01 << (1 + 16))
    
    #define SCB_CFSR_UFSR_INVPC (0x01 << (2 + 16))
    
    #define SCB_CFSR_UFSR_NOCP (0x01 << (3 + 16))
    
    #define SCB_CFSR_UFSR_UNALIGNED (0x01 << (8 + 16))
    
    #define SCB_CFSR_UFSR_DIVBYZERO (0x01 << (9 + 16))
    
    void FAULT_PrintFaultRegs(void)
    {
    	DBG_SendPolling("MMFSR : 0xx[%s%s%s%s%s]\r\n",
    	SCB->CFSR & SCB_CFSR_MEMFAULTSR_Msk,
    	(0 == (SCB_CFSR_MMFSR_IACCVIOL & SCB->CFSR)) ? "":"IACCVIOL|",
    	(0 == (SCB_CFSR_MMFSR_DACCVIOL & SCB->CFSR)) ? "":"DACCVIOL|",
    	(0 == (SCB_CFSR_MMFSR_MUNSTKERR & SCB->CFSR)) ? "":"MUNSTKERR|",
    	(0 == (SCB_CFSR_MMFSR_MSTKERR & SCB->CFSR)) ? "":"MSTKERR|",
    	(0 == (SCB_CFSR_MMFSR_MMARVALID & SCB->CFSR)) ? "":"MMARVALID|");
    	
    	DBG_SendPolling("BFSR : 0xx[%s%s%s%s%s%s]\r\n",
    	SCB->CFSR & SCB_CFSR_BUSFAULTSR_Msk,
    	(0 == (SCB_CFSR_BFSR_IBUSERR & SCB->CFSR)) ? "":"IBUSERR|",
    	(0 == (SCB_CFSR_BFSR_PRECISERR & SCB->CFSR)) ? "":"PRECISERR|",
    	(0 == (SCB_CFSR_BFSR_IMPRECISERR & SCB->CFSR))? "":"IMPRECISERR|",
    	(0 == (SCB_CFSR_BFSR_UNSTKERR & SCB->CFSR)) ? "":"UNSTKERR|",
    	(0 == (SCB_CFSR_BFSR_STKERR & SCB->CFSR)) ? "":"STKERR|",
    	(0 == (SCB_CFSR_BFSR_BFARVALID & SCB->CFSR)) ? "":"BFARVALID|");
    	
    	DBG_SendPolling("UFSR : 0xx[%s%s%s%s%s%s]\r\n",
    	SCB->CFSR & SCB_CFSR_USGFAULTSR_Msk,
    	(0 == (SCB_CFSR_UFSR_UNDEFINSTR & SCB->CFSR)) ? "":"UNDEFINSTR|",
    	(0 == (SCB_CFSR_UFSR_INVSTATE & SCB->CFSR)) ? "":"INVSTATE|",
    	(0 == (SCB_CFSR_UFSR_INVPC & SCB->CFSR)) ? "":"INVPC|",
    	(0 == (SCB_CFSR_UFSR_NOCP & SCB->CFSR)) ? "":"NOCP|",
    	(0 == (SCB_CFSR_UFSR_UNALIGNED & SCB->CFSR)) ? "":"UNALIGNED|",
    	(0 == (SCB_CFSR_UFSR_DIVBYZERO & SCB->CFSR)) ? "":"DIVBYZERO|");
    	
    	DBG_SendPolling("HFSR : 0xx[%s%s%s]\r\n",
    	SCB->HFSR,
    	(0 == (SCB_HFSR_DEBUGEVT_Msk & SCB->HFSR)) ? "":"DEBUGEVT|",
    	(0 == (SCB_HFSR_FORCED_Msk & SCB->HFSR)) ? "":"FORCED|",
    	(0 == (SCB_HFSR_VECTTBL_Msk & SCB->HFSR)) ? "":"VECTTBL|");
    	
    	DBG_SendPolling("DFSR : 0xx\r\n", SCB->DFSR);
    	
    	DBG_SendPolling("MMFAR : 0xx\r\n", SCB->MMFAR);
    	
    	DBG_SendPolling("BFAR : 0xx\r\n", SCB->BFAR);
    	
    	DBG_SendPolling("\r\n");
    	return;
    }
    
    void FAULT_PrintGeneralRegs(uint32_t *stackaddr)
    {
    	DBG_SendPolling("\r\nExceptions:\r\n");
    	
    	DBG_SendPolling("r0 : 0xx\r\n", stackaddr[14]);
    	
    	DBG_SendPolling("r1 : 0xx\r\n", stackaddr[15]);
    	
    	DBG_SendPolling("r2 : 0xx\r\n", stackaddr[16]);
    	
    	DBG_SendPolling("r3 : 0xx\r\n", stackaddr[17]);
    	
    	DBG_SendPolling("r4 : 0xx\r\n", stackaddr[6]);
    	
    	DBG_SendPolling("r5 : 0xx\r\n", stackaddr[7]);
    	
    	DBG_SendPolling("r6 : 0xx\r\n", stackaddr[8]);
    	
    	DBG_SendPolling("r7 : 0xx\r\n", stackaddr[9]);
    	
    	DBG_SendPolling("r8 : 0xx\r\n", stackaddr[10]);
    	
    	DBG_SendPolling("r9 : 0xx\r\n", stackaddr[11]);
    	
    	DBG_SendPolling("r10 : 0xx\r\n", stackaddr[12]);
    	
    	DBG_SendPolling("r11 : 0xx\r\n", stackaddr[13]);
    	
    	DBG_SendPolling("r12 : 0xx\r\n", stackaddr[18]);
    	
    	DBG_SendPolling("lr : 0xx\r\n", stackaddr[19]);
    	
    	DBG_SendPolling("pc : 0xx\r\n", stackaddr[20]);
    	
    	DBG_SendPolling("xpsr: 0xx\r\n", stackaddr[21]);
    	
    	DBG_SendPolling("current xpsr: 0xx\r\n", stackaddr[5]);
    	
    	DBG_SendPolling("current lr : 0xx\r\n", stackaddr[4]);
    	
    	DBG_SendPolling("primask : 0xx\r\n", stackaddr[3]);
    	
    	DBG_SendPolling("basepri : 0xx\r\n", stackaddr[2]);
    	
    	DBG_SendPolling("faultmask: 0xx\r\n", stackaddr[1]);
    	
    	DBG_SendPolling("control : 0xx\r\n", stackaddr[0]);
    	
    	DBG_SendPolling("\r\n");
    	
    	return;
    
    }
    
    __ASM void HardFault_Handler(void)
    {
    	IMPORT FAULT_PrintGeneralRegs
    	
    	IMPORT FAULT_PrintFaultRegs
    	
    	PRESERVE8
    	
    	push {r4,r5,r6,r7,r8,r9,r10,r11}
    	
    	mrs r0, xpsr
    	
    	push {r0}
    	
    	mov r0, lr
    	
    	push {r0}
    	
    	mrs r0, primask
    	
    	push {r0}
    	
    	mrs r0, basepri
    	
    	push {r0}
    	
    	mrs r0, faultmask
    	
    	push {r0}
    	
    	mrs r0, control
    	
    	push {r0}
    	
    	mov r0, sp
    	
    	ldr r1, =FAULT_PrintGeneralRegs
    	
    	blx r1
    	
    	ldr r1, =FAULT_PrintFaultRegs
    	
    	blx r1
    
    	b .
    	nop
    }
    

    上述代码的输出见附录二所示。

    附录二:MAP文件和List文件的解读

    Keil在生成程序的时候,可以生成两个辅助文件非常有帮助,他们分别是map文件和list文件。打开他们的方法如下图所示:

    HardFault错误信息的挖掘

    这两个文件我仅能大概读懂,下面介绍一下如何根据PC和LR寄存器中的地址数据,通过map文件找到该指令所在的函数,并根据list文件找到出错的代码行号。抛砖引玉,欢迎大牛拍砖:

    map文件是连接器生成的二进制文件的信息,其中描述了各符号的交叉引用、函数和数据排布的顺序和大小等各种有用信息。要根据指令地址查找函数主要关注map文件中的Image Symbol Table这一部分内容。

    Symbol Name Value Ov Type Size Object(Section)
    
    main 0x00006245 Thumb Code 106 main.o(.text)
    
    OnPowerOff 0x000062af Thumb Code 8 main.o(.text)
    
    FAULT_PrintFaultRegs 0x000062dd Thumb Code 464 fault.o(.text)
    
    FAULT_PrintGeneralRegs 0x000064ad Thumb Code 194 fault.o(.text)
    

    随意取出其中的一部分,对于每行共有5列数据,每行代表一个符号(函数和全局变量)的数据。分别是:“符号名,符号地址,类型,长度,所在的.o文件”。我们主要关注“符号名,符号地址和长度”这部分内容

    根据地址查找函数名,就是检索MAP文件的“Image Symbol Table”部分,查找到函数地址和所查询地址最接近,且函数地址比所查询地址小的函数。并根据函数的长度确认是否在函数的范围内。

    举一个真实的例子:

    比如说在发生Hardfault错误时,使用上述Hardfault Handler示例代码打印出的错误信息如下:

    Exceptions:

    寄存器数值
    r00x4006a000
    r10x0000000a
    r20x00000002
    r30x00000003
    r40x0001f420
    r50x0001f420
    r60x00000000
    r70x00000000
    r80x00000000
    r90x00000000
    r100x00000000
    r110x00000000
    r120x40048000
    lr0x00010681
    pc0x00010642
    xpsr0x01000000
    current xpsr0x00000003
    current lr0xffffffe9
    primask0x00000000
    basepri0x00000000
    faultmask0x00000000
    control0x00000000
    MMFSR0x00000000
    BFSR0x00000400[IMPRECISERR]
    UFSR0x00000000[]
    HFSR0x40000000[FORCED]
    DFSR0x00000008
    MMFAR0xe000ed34
    BFAR0xe000ed38

    错误类型为“非精确的数据访问违例”。处理器自动压入堆栈的PC寄存器的数据为0x00010642,在map文件中查找字符串“0x000106”(故意抹去末尾数据),找到的两个匹配数据是如下黄色表示的内容,但是这里两个地址都比出现错误的地址0x00010642大,错误并非发生在这两个函数中。

    FS_Lock 0x000104ef Thumb Code 24 fs.o(.text)
    
    FS_Unlock 0x00010507 Thumb Code 10 fs.o(.text)
    
    UART7816_Init 0x00010673 Thumb Code 16 uart7816.o(.text)
    
    UART7816_SetBaudRate 0x00010683 Thumb Code 228 uart7816.o(.text)
    
    UART7816_StartClock 0x00010767 Thumb Code 18 uart7816.o(.text)
    
    UART7816_StopClock 0x00010779 Thumb Code 28 uart7816.o(.text)
    

    接着扩大范围继续循环,搜索“0x000105”,结果如下(仅关注Image Symbol Table部分):

    .text 0x00010530 Section 0 uart7816.o(.text)
    
    _timerInit 0x00010531 Thumb Code 58 uart7816.o(.text)
    
    _gpioInit 0x0001056b Thumb Code 118 uart7816.o(.text)
    
    _uartInit 0x000105e1 Thumb Code 146 uart7816.o(.text)
    
    …
    
    FS_Unlock 0x00010507 Thumb Code 10 fs.o(.text)
    

    其中和0x00010642最为接近且小于0x00010642的为函数_uartInit,且函数地址0x000105e1+146大于0x00010642,,所以确认发生错误的指令在函数_uartInit中。

    下面轮到List文件出场了,List文件实际上是编译器生成的C代码和汇编的对照表,其中_uartInit的部分内容如下:

    _uartInit PROC
    
    ;;;110 static void _uartInit(void)
    
    0000b0 48d2 LDR r0,|L1.1020|
    
    ;;;111 {
    
    ;;;112
    
    ;;;113 SIM_SCGC4 |= SIM_SCGC4_UART0_MASK;
    
    0000b2 6b40 LDR r0,[r0,#0x34]
    
    0000b4 f4406080 ORR r0,r0,#0x400
    
    0000b8 49d0 LDR r1,|L1.1020|
    
    0000ba 6348 STR r0,[r1,#0x34]
    
    ;;;114
    
    ;;;115 UART0_C2 &= (uint8_t)~(uint8_t)((UART_C2_TE_MASK | UART_C2_RE_MASK));
    
    0000bc 48d1 LDR r0,|L1.1028|
    
    0000be 78c0 LDRB r0,[r0,#3]
    
    0000c0 f00000f3 AND r0,r0,#0xf3
    
    0000c4 49cf LDR r1,|L1.1028|
    
    0000c6 70c8 STRB r0,[r1,#3]
    
    ;;;116
    
    ;;;117 UART0_BDH = UART_BDH_SBR(0x02);
    
    0000c8 2002 MOVS r0,#2
    
    0000ca 7008 STRB r0,[r1,#0]
    
    ;;;118
    
    ;;;119 UART0_BDL = UART_BDL_SBR(0xE8);
    
    0000cc 20e8 MOVS r0,#0xe8
    
    0000ce 7048 STRB r0,[r1,#1]
    
    ;;;120
    
    ;;;121 UART0_MA1 = UART_MA1_MA(0x00);
    
    0000d0 2000 MOVS r0,#0
    
    0000d2 7208 STRB r0,[r1,#8]
    
    ;;;122
    
    ;;;123 UART0_MA2 = UART_MA2_MA(0x00);
    
    0000d4 7248 STRB r0,[r1,#9]
    
    ;;;124
    
    ;;;125 UART0_C4 = UART_C4_BRFA(0x00);
    
    0000d6 7288 STRB r0,[r1,#0xa]
    
    ;;;126
    
    ;;;127 UART0_C1 = (UART_C1_M_MASK | UART_C1_PE_MASK);
    
    0000d8 2012 MOVS r0,#0x12
    
    0000da 7088 STRB r0,[r1,#2]
    
    ;;;128
    
    ;;;129 UART0_S2 = (UART_S2_LBKDIF_MASK | UART_S2_RXEDGIF_MASK);
    
    0000dc 20c0 MOVS r0,#0xc0
    
    0000de 7148 STRB r0,[r1,#5]
    
    ;;;130
    
    ;;;131 UART0_MODEM = 0x00U;
    
    0000e0 2000 MOVS r0,#0
    
    0000e2 7348 STRB r0,[r1,#0xd]
    
    ;;;132
    
    ;;;133 UART0_IR = UART_IR_TNP(0x00);
    
    0000e4 7388 STRB r0,[r1,#0xe]
    
    ;;;134
    
    ;;;135 UART0_TWFIFO = UART_TWFIFO_TXWATER(0x00);
    
    0000e6 74c8 STRB r0,[r1,#0x13]
    
    ;;;136
    
    ;;;137 UART0_RWFIFO = UART_RWFIFO_RXWATER(0x01);
    
    0000e8 2001 MOVS r0,#1
    
    0000ea 7548 STRB r0,[r1,#0x15]
    
    ;;;138
    
    ;;;139 UART0_SFIFO = UART_SFIFO_TXEMPT_MASK |
    
    0000ec 20c7 MOVS r0,#0xc7
    
    0000ee 7488 STRB r0,[r1,#0x12]
    
    ;;;140 UART_SFIFO_RXEMPT_MASK |
    
    ;;;141 UART_SFIFO_RXOF_MASK |
    
    ;;;142 UART_SFIFO_TXOF_MASK |
    
    ;;;143 UART_SFIFO_RXUF_MASK;
    
    ;;;144
    
    ;;;145 UART0_CFIFO = (UART_CFIFO_TXFLUSH_MASK | UART_CFIFO_RXFLUSH_MASK);
    
    0000f0 20c0 MOVS r0,#0xc0
    
    0000f2 7448 STRB r0,[r1,#0x11]
    
    ;;;146
    
    ;;;147 UART0_PFIFO &= (uint8_t)~(uint8_t)(
    
    0000f4 4608 MOV r0,r1
    
    0000f6 7c00 LDRB r0,[r0,#0x10]
    
    0000f8 f0000077 AND r0,r0,#0x77
    
    0000fc 7408 STRB r0,[r1,#0x10]
    
    ;;;148 UART_PFIFO_TXFE_MASK |
    
    ;;;149 UART_PFIFO_RXFE_MASK
    
    ;;;150 );
    
    ;;;151
    
    ;;;152 UART0_WN7816 = UART_WN7816_GTN(0x00);
    
    0000fe 2000 MOVS r0,#0
    
    000100 7708 STRB r0,[r1,#0x1c]
    
    ;;;153
    
    ;;;154 UART0_WF7816 = UART_WF7816_GTFD(0x01);
    
    000102 2001 MOVS r0,#1
    
    000104 7748 STRB r0,[r1,#0x1d]
    
    ;;;155
    
    ;;;156 UART0_WP7816A_T0 = UART_WP7816A_T0_WI_H(0x00);
    
    000106 2000 MOVS r0,#0
    
    000108 49be LDR r1,|L1.1028|
    
    00010a 313c ADDS r1,r1,#0x3c
    
    00010c 7008 STRB r0,[r1,#0]
    
    ;;;157 UART0_WP7816B_T0 = UART_WP7816B_T0_WI_L(0x0A);
    
    00010e 210a MOVS r1,#0xa
    
    000110 48bc LDR r0,|L1.1028|
    
    000112 f880103d STRB r1,[r0,#0x3d]
    
    ;;;158 //UART0_WP7816 = UART_WP7816_WTX(0x0A);
    
    ;;;159
    
    ;;;160 UART0_ET7816 = (UART_ET7816_TXTHRESHOLD(0x00) | UART_ET7816_RXTHRESHOLD(0x00));
    
    000116 2000 MOVS r0,#0
    
    000118 49ba LDR r1,|L1.1028|
    
    00011a 7788 STRB r0,[r1,#0x1e]
    
    ;;;161
    
    ;;;162 UART0_IS7816 = UART_IS7816_WT_MASK |
    
    00011c 20f7 MOVS r0,#0xf7
    
    00011e 7688 STRB r0,[r1,#0x1a]
    
    ;;;163 UART_IS7816_CWT_MASK |
    
    ;;;164 UART_IS7816_BWT_MASK |
    
    ;;;165 UART_IS7816_INITD_MASK |
    
    ;;;166 UART_IS7816_GTV_MASK |
    
    ;;;167 UART_IS7816_TXT_MASK |
    
    ;;;168 UART_IS7816_RXT_MASK;
    
    ;;;169
    
    ;;;170 UART0_IE7816 = 0x00U;
    
    000120 2000 MOVS r0,#0
    
    000122 7648 STRB r0,[r1,#0x19]
    
    ;;;171
    
    ;;;172 UART0_C7816 = (UART_C7816_INIT_MASK | UART_C7816_ISO_7816E_MASK);
    
    000124 2005 MOVS r0,#5
    
    000126 7608 STRB r0,[r1,#0x18]
    
    ;;;173 (void) UART0_S1;
    
    000128 4608 MOV r0,r1
    
    00012a 7900 LDRB r0,[r0,#4]
    
    ;;;174 (void) UART0_D;
    
    00012c 4608 MOV r0,r1
    
    00012e 79c0 LDRB r0,[r0,#7]
    
    ;;;175
    
    ;;;176 UART0_C5 &= (uint8_t)~(uint8_t)(
    
    000130 4608 MOV r0,r1
    
    000132 7ac0 LDRB r0,[r0,#0xb]
    
    000134 f0000010 AND r0,r0,#0x10
    
    000138 72c8 STRB r0,[r1,#0xb]
    
    ;;;177 UART_C5_TDMAS_MASK |
    
    ;;;178 UART_C5_RDMAS_MASK |
    
    ;;;179 0x4FU
    
    ;;;180 );
    
    ;;;181
    
    ;;;182 UART0_C3 = 0x00U;
    
    00013a 2000 MOVS r0,#0
    
    00013c 7188 STRB r0,[r1,#6]
    
    ;;;183
    
    ;;;184 UART0_C2 = 0x00U;
    
    00013e 70c8 STRB r0,[r1,#3]
    
    ;;;185
    
    ;;;186 return;
    
    ;;;187 }
    
    000140 4770 BX lr
    
    ;;;188
    
    ENDP
    

    出错的地址是0x00010642,相对于函数起始地址0x000105e1的偏移为0x61,根据List文件中的内容,_UartInit中第一条指令在文件中的偏移是0xb0
    0000b0 48d2 LDR r0,|L1.1020|这里是错误问题所在函数的起始地址

    因此出错代码的偏移应该是0x61+0xb0 = 0x111。
    ;;;157 UART0_WP7816B_T0 = UART_WP7816B_T0_WI_L(0x0A);

    因此可以定位出发生错误的语句在uart7816.c中的157行。

    找到产生错误的语句后,在有针对性的查找CPU手册中串口寄存器WP7816B的部分,发现用错了头文件,的确是访问了非法的内存区域。

    至此,问题解决。

    本文摘录的地址

    展开全文
  • STM32出现HardFault_Handler故障的原因主要有两个方面: 1、内存溢出或者访问越界。这个需要自己写程序的时候规范代码,遇到了需要慢慢排查。 2、堆栈溢出。增加堆栈的大小。
  • KEIL STM32 HardFault_Handler 硬件中断 解决办法 分享
  • ameba-hardfault

    2018-04-17 15:36:46
    ameba-hardfault&lt;-ameba-overview*如有任何工程问题,请填写工程单,并发正式邮件,问题解决速度可提高10%。--》排除hardfault方法方法一、(强烈推荐)这个两个地址可以到application.asm和application.map...
  • Hard Fault 异常报错

    2021-03-16 10:20:52
    Hard Fault 异常报错 1.别人有做的介绍我就不说了 参考https://blog.csdn.net/wangshuchangfrank/article/details/51381161 2.我要说的是不一样的现象 2.1在stm32f10x_it.c中,添加软件断点,一旦调试时出现Hard ...
  • STM32出现HardFault故障的解决方法.pdf
  • STM32硬件错误HardFault_Handler的处理方法

    万次阅读 多人点赞 2017-10-08 10:39:02
    STM32硬件错误HardFault_Handler的处理方法
  • 原创的,hardfault错误信息挖掘方法,内附错误处理函数的代码。
  • Cortex-M0 HardFault定位

    2015-11-17 09:56:34
    该文件用于指导定位程序是从哪里进入的HardFault的,定位程序出错的地点
  • 在STM32(即其他任何Cortex-M单片机)进入HardFault时,,通过Python ctypes操作JLinkARM.dll控制JLink,,读取并分析单片机的栈调用层次、及其他状态寄存器,分析HardFault发生的原因和位置
  • 在进行STM32调试时,当单片机进入HardFault_Handler中断后,可通过此办法快速定位出现问题的代码段,进而快速定位出现问题代码段。
  • keil 定位hardfault

    2021-05-18 15:18:51
    首先,在程序中我设置了一个hardfault: 然后运行程序程序复位,通过log打印可以看到通用寄存器的值: 我们主要看lr的值,然后debug调试程序,打开keil的Disassembly窗口,在View菜单中, 拖动鼠标找到0x800d...
  • hard fault 学习记录

    2019-06-25 17:04:00
    hard fault 学习记录 使用 segger 的 hard fault 的源文件后,当调试时,发生硬件错误的时候,可以查看 HardFaultRegs 中的内容,并对比 segger_HardFaultHandler.c 中的定义,就能得出具体是哪种错误...
  • 使用指针调用函数产生 Hard Fault 官方文档产生随机数方法
  • Hard fault (硬错误,也有译为硬件错误的)是在STM32上编写程序中常常产生的错误,造成Hard Fault错误的原因也是最为纷繁复杂的。本文详细介绍了产生该错误后的查找方法。
  • 在单片机进入hardfault是非常常见的一个问题,对于新手来说这是最令人头疼的,对于ARM内核的不熟悉,但是查找问题变得很困难,希望这篇文章能解决你的问题
  • HardFault产生原因

    千次阅读 2018-08-26 01:25:05
    HardFault产生原因 1.内存的溢出,包括堆栈的溢出。 其 中 单 片 机 内 存 和 堆 栈 的 关 系 , 可 以 参 考 http://blog.csdn.net/c12345423/article/details/53004747 2.越界访问。 这常指数组的使用,具体...
  • uCos移植中进入HardFault_Handler问题.pdf
  • 电子-HardFault的诊断.pdf,单片机/嵌入式STM32-F0/F1/F2

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 9,965
精华内容 3,986
关键字:

hardfault