关于stm32 HardFault_Handler 异常的处理 死机
2016-07-02 14:37
357 查看
在系统开发的时候,出现了HardFault_Handler硬件异常,也就是死机,尤其是对于调用了os的一系统,程序量大,检测堆栈溢出,以及数组溢出等,找了半天发现什么都没有的情况下,估计想死的心都有了。如果有些程序开始的时候一切没有问题,但是运行几个小时候,会发现死机了,搞个几天下来估计蛋都碎了一地吧。。。
一般来说运行操作系统 是以下几个问题
1.开始的时候给ucos分配的堆栈太小了,随着项目做多了,这类问题一般很容易解决
#define TASK_IO_SIZE 300
#define TASK_IO_PRIO 6
OS_STK TASK_IO_STK[TASK_IO_SIZE];
比如修改300到 1000,做开发的时候 如果ram允许,尽量大些,免的麻烦
2.数组溢出
这类问题一般在通信中,接受数据的时候,特别是长度不定的时候
比如协议为 :开始 功能码 长度 数据1 数据2 。。结束
长度决定了后面的数据多少,在分配接受缓冲的时候 ,突然来了个错误的长度比如255
但是我们分配buffer[100],只定义了100,这样数组就溢出了
所有在放数据之前要对长度进行判断是否合理,以后 如果有长度 或者索引就要想到溢出。。
3.使用了非法的指针 ,比如空指针 ,编译对的 但是运行就错了
u8 *p = null;
*p = 1; 把0地址的数据强制设置为1, 不错才怪
4.使用 OS_ENTER_CRITICAL();
使用了 OS_ENTER_CRITICAL(); 却忘了OS_EXIT_CRITICAL(); 退出临界区
特别是在这个函数OS_ENTER_CRITICAL(); 调用了子函数 也有的这类情况,很容易忘记关闭的这样就造成了“死机现象”
因此如果调用的话 建议在函数中加入OS_CPU_SR cpu_sr = 0u;局部变量 在管理临界区 os的内核程序也是这么用的 ,而且要注意,临界区一般用于全局变量的写操作,时间要非常快的,任务中的变量可以不用添加 。
常见的就上面几种了,说说硬件异常了 怎么来发现,这个才是主要的
举个例子:
a.仿真,运行程序的时候点红色X进入异常
![](http://s13.sinaimg.cn/mw690/001mJUKTgy6LCnd4Shmdc&690)
b.调出堆栈窗口,也就是黑匣子
![](http://s7.sinaimg.cn/mw690/001mJUKTgy6LCo1KS90a6&690)
c.查找问题
![](http://s14.sinaimg.cn/mw690/001mJUKTgy6LCo3VJiB9d&690)
d.找出出错的函数
![](http://s10.sinaimg.cn/mw690/001mJUKTgy6LCofQNQdb9&690)
e.解决问题
![](http://s3.sinaimg.cn/mw690/001mJUKTgy6LCohuh0K92&690)
f 一些思考
很久之前在研究stm32 库源码的时候 发现基本上 每个函数进入之前都做了参数的检测,当初还觉得检查不检查貌似没什么大的作用,自己使用的时候注意就好了,现在是不是改变看法了吗?编程的时候很多问题,在参数检查的时候被过滤掉了,这样在开发大型项目的时候,可以给您免去很多不必要的麻烦,反而会提供开发效率哦
当然网上也有很多,检查寄存器LR SP等地址 来反推出最后运行的汇编函数调用地址的,但是肯定没有上面的直观。
原文:http://blog.sina.com.cn/s/blog_4aa25f130102v0m8.html
一般来说运行操作系统 是以下几个问题
1.开始的时候给ucos分配的堆栈太小了,随着项目做多了,这类问题一般很容易解决
#define TASK_IO_SIZE 300
#define TASK_IO_PRIO 6
OS_STK TASK_IO_STK[TASK_IO_SIZE];
比如修改300到 1000,做开发的时候 如果ram允许,尽量大些,免的麻烦
2.数组溢出
这类问题一般在通信中,接受数据的时候,特别是长度不定的时候
比如协议为 :开始 功能码 长度 数据1 数据2 。。结束
长度决定了后面的数据多少,在分配接受缓冲的时候 ,突然来了个错误的长度比如255
但是我们分配buffer[100],只定义了100,这样数组就溢出了
所有在放数据之前要对长度进行判断是否合理,以后 如果有长度 或者索引就要想到溢出。。
3.使用了非法的指针 ,比如空指针 ,编译对的 但是运行就错了
u8 *p = null;
*p = 1; 把0地址的数据强制设置为1, 不错才怪
4.使用 OS_ENTER_CRITICAL();
使用了 OS_ENTER_CRITICAL(); 却忘了OS_EXIT_CRITICAL(); 退出临界区
特别是在这个函数OS_ENTER_CRITICAL(); 调用了子函数 也有的这类情况,很容易忘记关闭的这样就造成了“死机现象”
因此如果调用的话 建议在函数中加入OS_CPU_SR cpu_sr = 0u;局部变量 在管理临界区 os的内核程序也是这么用的 ,而且要注意,临界区一般用于全局变量的写操作,时间要非常快的,任务中的变量可以不用添加 。
常见的就上面几种了,说说硬件异常了 怎么来发现,这个才是主要的
举个例子:
a.仿真,运行程序的时候点红色X进入异常
b.调出堆栈窗口,也就是黑匣子
c.查找问题
d.找出出错的函数
e.解决问题
f 一些思考
很久之前在研究stm32 库源码的时候 发现基本上 每个函数进入之前都做了参数的检测,当初还觉得检查不检查貌似没什么大的作用,自己使用的时候注意就好了,现在是不是改变看法了吗?编程的时候很多问题,在参数检查的时候被过滤掉了,这样在开发大型项目的时候,可以给您免去很多不必要的麻烦,反而会提供开发效率哦
当然网上也有很多,检查寄存器LR SP等地址 来反推出最后运行的汇编函数调用地址的,但是肯定没有上面的直观。
原文:http://blog.sina.com.cn/s/blog_4aa25f130102v0m8.html
相关文章推荐
- VS 的编译选项 build下的 platform target -- Any CPU和x86有什么影响?
- ssm项目 maven 项目pon.xml 配置
- 聊聊同步、异步、阻塞与非阻塞
- Win7系统登录CF不能选区怎么办?Win7系统登录CF穿越火线没显示选区界面的解决方法
- Linux内核---9.prepare0流程
- Intellij IDEA 编译提示: "Test is already defined as object Test"
- 运维小技巧:使用ss命令代替 netstat,和netstat说再见
- Android开发Calendar的基本使用
- DirectX 3D 之C#开发
- NYOJ86找球号(一)
- Linux内核---8.filechk函数分析
- 探索linux管道的容量
- (1)MySQL语句规范
- 使用DOM4J解析xml
- SHELL判断服务是不是正在运行
- Docker镜像的管理和创建
- Linux内核---7.Makefile学习笔记
- 1016 ProblemP
- shell 脚本的基础
- Tomcat