在debug时经常会出现程序莫名其妙的掉到hardfault的中断中,起初完全不知道是从哪里查找问题,后来有遇到过几次,通过网络资料以及自己的调试,对于解决这样的问题有一些体会,我分析给大家,希望对初学者有用。
1)对于出现这样的问题,一般是内存被破坏了,而对于内存破坏的原因一般是数组越界或者是内存相关的库函数使用不当所致。
我的程序中会用一些内存相关的函数,如memcpy(),sprint(),mallo(),free().
首先说明memcpy()函数,它是把指定长度的一段内存中的数据拷贝到一个内存中。这里最容易出错的是长度,我在程序中不小心把长度定义成无符号型,但是执行了相减运算变成负数,实际上是很大的数据,那拷贝的内存就多了,可能会导致错误。
Sprint()函数是把数值或字符格式化成字符串,并在末尾自动加\0,作为字符串结束符。我有一次不小心就是要改函数把2个字符串粘接到一起,这样中间的\0会没有定义,也导致内存出错了。
Mallo()和free()函数组是动态分配内存和释放,他们必须成对使用,这个规则大家都知道,但是像我在写程序是不小心放错了位置,要么没有释放,要么多次释放,会导致程序出现内存出错。
最后,对于数组越界这个比较好查找原因,写完程序后检查一下再执行,避免这种粗心的错误。
2)我遇到的另一个导致内存错误的原因是使用FreeRTOS时,给某个任务分配的堆栈不足造成。对于给某个任务要分配多大的堆栈的计算,我还不知道确切的计算方法。所以难免会出现这种问题。我使用IAR7.20的IDE,基于该IDE,我来告诉大家怎么定位到时哪个任务造成内存出错了。在IAR配置option->Debugger->Plugins下面选择FreeRTOs and OpenRTOS.然后在程序中需要定义configCHECK_FOR_STACK_OVERFLOW这个宏,然后在调用freertos的vApplicationStackOverflowHook()函数,如
#if( configCHECK_FOR_STACK_OVERFLOW == 1 )
void vApplicationStackOverflowHook( xTaskHandle xTask, signed char* pcTaskName )
{
int i = 0;
i++;
while(1);
}
#endif
当程序跳转到该函数中并停下来后,可以在工具栏中点击freeRTOS,查看queue和task。在底部就能看到这两个项目,这两个项目中就包含了整个工程所创建的任务和队列以及与他们相关的一些信息。这时你可以看到task中某个任务的名字是乱码,优先级是很大的数。那么就是该任务的堆栈分配小了。
FreeRTOS中还有内存分配出错的检测
#if( configUSE_MALLOC_FAILED_HOOK == 1 )
void vApplicationMallocFailedHook( void )
{
int i = 0;
i++;
while(1);
}
#endif
这个可以参考freertos的官方文档。http://www.freertos.org/Stacks-and-stack-overflow-checking.html
3)对于出现hardfault问题时,还可以自行编写函数,来确定更加详细的错误原因。这里需要参考2个文档:keil的application note
Using Cortex_M3 and Cortex_M4 fault exceptions;另一个是著名的M3权威指南的chapter 7 exception。通过读取SCB中某些寄存器的值来确定是什么错误。详细的寄存器描述参考上面的文档。
下面上传一个silabs的一个程序。
文章评论(0条评论)
登录后参与讨论