1,  用Keil的话,可以做如下操作:

先将fault中断函数的内容改为:

HardFault_Handler\

PROC

;EXPORT  HardFault_Handler         [WEAK]

;B                  .

IMPORT hard_fault_handler_c

TST LR, #4

ITE EQ

MRSEQ R0, MSP

MRSNE R0, PSP

B hard_fault_handler_c

ENDP

************************************************insert start*************************************************

摘抄自Triton.zhang——eeworld

1. MSP和PSP 的含义是Main_Stack_Pointer 和Process_Stack_Pointer,在逻辑地址上他们都是R13

2. 权威手册上说的很清楚PSP主要是在Handler的模式下使用,MSP主要在线程模式下使用(当然你在线程模式下也可以调用PSP,需要你做特殊的处理).
3. 这意味着同一个逻辑地址,实际上有两个物理寄存器,一个为MSP,一个为PSP,在不同的工作模式调用不同的物理寄存器。举一个简单的例子,很多MCU的的UART只有一个BUFF,TXBUFF和RXBUFF都是一个地址,当你写BUFF时写入的是TXBUFF, 读操作时调用的是RXBUFF。基本原理就是这样。
4. 至于为什么这么设计,我想是为了在进行模式转换的时候,减少堆栈的保存工作。同时也可以为不同权限的工作模式设置不同的堆栈。

************************************************insert end***************************************************

然后在源程序里添加下面的函数代码:

// hard fault handler in C,

// with stack frame location as input parameter

void hard_fault_handler_c(unsigned int * hardfault_args)

{

unsigned int stacked_r0;

unsigned int stacked_r1;

unsigned int stacked_r2;

unsigned int stacked_r3;

unsigned int stacked_r12;

unsigned int stacked_lr;

unsigned int stacked_pc;

unsigned int stacked_psr;

stacked_r0 = ((unsigned long) hardfault_args[0]);

stacked_r1 = ((unsigned long) hardfault_args[1]);

stacked_r2 = ((unsigned long) hardfault_args[2]);

stacked_r3 = ((unsigned long) hardfault_args[3]);

stacked_r12 = ((unsigned long) hardfault_args[4]);

stacked_lr = ((unsigned long) hardfault_args[5]);

stacked_pc = ((unsigned long) hardfault_args[6]);

stacked_psr = ((unsigned long) hardfault_args[7]);

printf ("[Hard fault handler]\n");

printf ("R0 = %x\n", stacked_r0);

printf ("R1 = %x\n", stacked_r1);

printf ("R2 = %x\n", stacked_r2);

printf ("R3 = %x\n", stacked_r3);

printf ("R12 = %x\n", stacked_r12);

printf ("LR = %x\n", stacked_lr);

printf ("PC = %x\n", stacked_pc);

printf ("PSR = %x\n", stacked_psr);

printf ("BFAR = %x\n", (*((volatile unsigned long *)(0xE000ED38))));

printf ("CFSR = %x\n", (*((volatile unsigned long *)(0xE000ED28))));

printf ("HFSR = %x\n", (*((volatile unsigned long *)(0xE000ED2C))));

printf ("DFSR = %x\n", (*((volatile unsigned long *)(0xE000ED30))));

printf ("AFSR = %x\n", (*((volatile unsigned long *)(0xE000ED3C))));

while(1)

{

;;

}

}

如果使用调试器,则可以在第一个printf处设置断点.没有的话看串口打印结果

通过查看stacked_lr的内容可以知道程序运行到哪个位置出现fault

然后查看编译后汇编代码,可以知道源程序是哪个函数哪一步出现问题,

配合其它寄存器的内容来分析找出原因

2.用IAR的话,把startup_ewarm.c文件中的FaultISR()函数的内容改为:

volatile unsigned int stacked_r0;

volatile unsigned int stacked_r1;

volatile unsigned int stacked_r2;

volatile unsigned int stacked_r3;

volatile unsigned int stacked_r12;

volatile unsigned int stacked_lr;

volatile unsigned int stacked_pc;

volatile unsigned int stacked_psr;

//unsigned long cc;

stacked_r0 = ((unsigned long) hardfault_args[0]);

stacked_r1 = ((unsigned long) hardfault_args[1]);

stacked_r2 = ((unsigned long) hardfault_args[2]);

stacked_r3 = ((unsigned long) hardfault_args[3]);

stacked_r12 = ((unsigned long) hardfault_args[4]);

stacked_lr = ((unsigned long) hardfault_args[5]);

stacked_pc = ((unsigned long) hardfault_args[6]);

stacked_psr = ((unsigned long) hardfault_args[7]);

printf ("[Hard fault handler]\n");

printf ("R0 = %x\n", stacked_r0);

printf ("R1 = %x\n", stacked_r1);

printf ("R2 = %x\n", stacked_r2);

printf ("R3 = %x\n", stacked_r3);

printf ("R12 = %x\n", stacked_r12);

printf ("LR = %x\n", stacked_lr);

printf ("PC = %x\n", stacked_pc);

printf ("PSR = %x\n", stacked_psr);

printf ("BFAR = %x\n", (*((volatile unsigned long *)(0xE000ED38))));

printf ("CFSR = %x\n", (*((volatile unsigned long *)(0xE000ED28))));

printf ("HFSR = %x\n", (*((volatile unsigned long *)(0xE000ED2C))));

printf ("DFSR = %x\n", (*((volatile unsigned long *)(0xE000ED30))));

printf ("AFSR = %x\n", (*((volatile unsigned long *)(0xE000ED3C))));

while(1)

{

;;

}

如果使用调试器,则可以在第一个printf处设置断点.没有的话看串口打印结果

通过查看stacked_lr的内容可以知道程序运行到哪个位置出现fault

然后查看编译后汇编代码,可以知道源程序是哪个函数哪一步出现问题,

配合其它寄存器的内容来分析找出原因

另一种方法:
    默认的HardFaudler 处理方法不是死循环么?将它改成BX LR直接返回的形式。然后再这条语句打个断点,一旦在断点中停下来,说明出错了,然后再返回,就可以返回到出错的位置的下一条语句哪里。
_asm void wait()
{
    BX lr  //BX无条件转移指令
}

void HardFault_Handler(void)
{
    wait();

}

【ARM 汇编基础速成6】ARM汇编之条件执行与分支 - 简书

ARM 指令举例

  1. SWI_Exception:
  2. STMFD SP!, {R2-R3,LR} //把R2,R3,LR值入栈
  3. #0号软中断的处理程序
  4. CMP R0, #0 //将R0和0比较
  5. //以下4行带EQ条件的代码均为当R0为0时应该执行的语句
  6. MRSEQ R2, SPSR //把SPSR读入到R2中
  7. STREQ R2, [R1] /把R2的值存入到[R1]中
  8. ORREQ R2, R2, #0x80 //把R2的Bit7位置1
  9. MSREQ SPSR_c, R2 //把R2的值写入到SPSR_c中,即禁止IRQ
  10. #1号软中断的处理程序
  11. CMP R0, #1 //比较R0值和1
  12. LDREQ R2, [R1] //相等则把[R1]中的数据存入R2中
  13. MSREQ SPSR_c, R2 //相等把R2的值写入到SPSR_c中,恢复IRQ
  14. #11号软中断的处理程序
  15. CMP R0, #11 //比较R0的值和11
  16. MRSEQ R2, SPSR //相等则把SPSR的值转存入到R2中
  17. BICEQ R2, R2, #0x1F //相等则把R2的Bit0~Bit4全部清零
  18. ORREQ R2, R2, #Mode_SYS //相等则把R2与#Mode_SYS相与再存入R2
  19. MSREQ SPSR_c, R2 //相等则把R2的值存入SPSR_c中,即进入系统模式
  20. #12号软中断的处理程序
  21. CMP R0, #12 //比较R0的值和12
  22. MRSEQ R2, SPSR //相等则把SPSR的值存入R2
  23. BICEQ R2, R2, #0x1F //相等则把R2的Bit0~Bit4清零
  24. ORREQ R2, R2, #Mode_USR //相等则把R2与#Mode_USR相与再存入R2中
  25. MSREQ SPSR_c, R2 //相等则把R2存入SPSR_c,即进入用户模式
  26. LDMFD SP!, {R2-R3,PC} //恢复R2、R3、PC值,返回
  27. .END //汇编代码段结束

定位ARM Hard Fault 的方法相关推荐

  1. ARM32平台系统crash(系统崩溃) 问题定位的一种解决方法

    说明 分享一种crash问题定位的一种解决方法,仅供参考. ARM32平台上通过错误使用内存,触发系统异常,系统崩溃.系统异常被挂起后,能在串口中看到异常调用栈打印信息和关键寄存器信息. 如下所示,e ...

  2. Android App定位和规避内存泄露方法研究

    from:http://site.douban.com/android/widget/notes/350758/note/167481484/ 工作中刚好用到,网上搜到的,觉得不错,与大家分享 And ...

  3. cmd窗口快速定位到具体文件夹方法

    在用Python进行机器实战时,打开cmd窗口后,总是到定位到kNN.py所在文件夹才能Python(否则import kNN失败),每次都要输入地址非常麻烦 这里介绍一个cmd窗口快速定位到具体文件 ...

  4. 机器人施教器的信息丢失_一种精准定位学习难度的施教方法及教育机器人与流程...

    本发明涉及智能机器人技术领域,尤其涉及一种精准定位学习难度的施教方法及教育机器人. 背景技术: 近年来国家对教育事业越发重视,随着教育教学形式的多样化,教育机器人也逐步走入人们的生活.教育机器人是以激 ...

  5. 关于百度地图js api的getCurrentPosition定位不准确的解决方法

    关于百度地图js api的getCurrentPosition定位不准确的解决方法 参考文章: (1)关于百度地图js api的getCurrentPosition定位不准确的解决方法 (2)http ...

  6. 相对定位 绝对定位 固定定位 粘性定位 居中的三种方法 calc函数标签的使用方法

    相对定位 绝对定位 固定定位 粘性定位 居中的三种方法 calc函数标签的使用方法 一.相对定位:position:relative; 二.绝对定位:position:absolute; 1.找参照物 ...

  7. ida pro 反汇编 Android so 库后修改 arm 汇编指令的方法总结

    1 前言 最近博主在学习Android逆向的时候,参照吾爱破解论坛的<教我兄弟学Android逆向系列课程>学习的时候,学到第8章<教我兄弟学Android逆向08 IDA爆破签名验 ...

  8. 室内定位技术:分类、方法与应用综述

    [摘要]近年来,面向需求越来越迫切的室内位置服务,室内定位技术发展迅速,是移动互联时代的研究热点,逐步在各行各业发挥作用,给人们的日常生活带来了一定的影响.本文对国内外室内定位技术的研究现状进行了分析 ...

  9. 寻声定位 matlab,一种自动调节范围大的寻声定位拍摄设备的制作方法

    一种自动调节范围大的寻声定位拍摄设备的制作方法 [专利摘要]本实用新型涉及一种自动调节范围大的寻声定位拍摄设备,包括拍摄设备(1).声音识别模块(2).定向拾音模块(3).控制芯片(4).数据电源线( ...

最新文章

  1. 【Mood 19】DailyBuild 2月
  2. IDEA(IntelliJ IDEA)+常用快捷键(short cuts)
  3. Deepmind 预测地图论文背后:神经科学或将助力AI迎来新突破
  4. 9 岁自学编程、24 岁身价涨至数百万美元,与微软一较高低的大佬多厉害?
  5. 【业务知识】档案工作流程
  6. LeetCode 637. 二叉树的层平均值(层次遍历queue)
  7. Fish Redux 使用指南
  8. Python中使用static、class、abstract方法
  9. 终于,J 神还是加入了 Google!
  10. 计算机网络复习-数据链路层
  11. VISSIM二次开发(Python)大作业总结1
  12. 二阶系统响应指标图_一阶系统和二阶系统,了解一下!!!
  13. PHP对接银联电子支付接口开发
  14. 摄像头远程web控制
  15. 川土微电子|数字隔离器替代光耦817
  16. windows 10屏蔽系统自动更新
  17. tplink查看上网记录_Tplink路由器PPPOE拨号不能上网日志查看原因
  18. 计算机word表格加法公式,如何插入公式以求和Word中表格的一列或一行?
  19. Blogspot.com再次解封
  20. M2DGR:多源多场景 地面机器人SLAM数据集(ICRA 2022 )

热门文章

  1. Tableau10.0学习随记-分组问题
  2. css样式之 direction
  3. VC++获取操作系统的版本 GetVersionEx函数
  4. curl 支持ws吗_curl 支持 http2
  5. 用神经网络分类一维矩阵
  6. php jquery点击事件,jQuery操作html元素点击事件详解
  7. java ssh连接 如何不使用密码_如何在java中为ssh连接设置密码
  8. 接触网怎么区分t线f线_这个形态是一种庄家线,它是完全由庄家控盘造成的,散户需重视...
  9. 【控制】多智能体系统总结。5.系统合并。
  10. 【STM32】FreeRTOS 任务切换