在一个项目中使用到了Freertos,但是在gui界面显示1秒后切换界面,用到了freertos软件定时器,使用了队列来夸任务传递标志位,导致进入HardFault_Handler,经历了四天时间才找到问题,开始网上各种搜搜,HardFault_Handler定位方法,最后使用CmBacktrace库找到问题
经过层层帅选,和层层测试,下面代码是导致HardFault_Handler中断的最终问题
static void vTimerCallback(xTimerHandle pxTimer)
{
time_struct *ptMsg;
ptMsg = &time;
Lcd_struct *userptMsg;
userptMsg = &Lcd_flag;
switch((uint8_t)Lcd_flag.auto_pwer_off_flag)
{
case true:
if (ptMsg->time_sec_count > 0)
{
ptMsg->time_sec_count--;
}
else
{
if (ptMsg->time_min_count <=0)
{
// POWER_OFF; //关掉电源
// ptMsg->time_sec_count = 0;
// ptMsg->time_min_count = 0;
}
else
{
ptMsg->time_min_count--;
ptMsg->time_sec_count = 59;
}
}
if( xQueueSend(xQueue_timer,(void *) &ptMsg,(TickType_t)2) != pdPASS)
{
}
else
{
/* 发送成功 */
}
break;
case false:
break;
default:;
}
if (userptMsg->power_save_flag == true)
{
if (userptMsg->save_lv_dis_timer < 1) /*保存界面显示时间*/
{
userptMsg->save_lv_dis_timer++;
}
else
{
userptMsg->power_save_flag = false;
if( xQueueSend(xQueue_button,(void *) &userptMsg,(TickType_t)5) != pdPASS)
{
}
else
{
//xQueueReceive(xQueue_button,(void *)&userptMsg,5);/*这里是导致进入HardFault_Handler的最终关键问题*/
/* 发送成功 */
}
}
}
else
{
}
}
查找方法:
一、先把CmBacktrace库加载到工程里面去,参考http://t.csdnimg.cn/zkPPK
二、使用串口打印出来错误信息
固件名称:CmBacktrace,硬件版本号:V1.0.0,软件版本号:V0.1.0
在线程(Tmr Svc)中发生错误异常
=========== 线程堆栈信息 ===========
addr: 2000bfb8 data: a5a5a5a5
addr: 2000bfbc data: a5a5a5a5
addr: 2000bfc0 data: 0000a5a5
addr: 2000bfc4 data: 00001f6b
addr: 2000bfc8 data: 00000000
addr: 2000bfcc data: 0802ad33
addr: 2000bfd0 data: a5a5a5a5
addr: 2000bfd4 data: 00000000
addr: 2000bfd8 data: 2000bfec
addr: 2000bfdc data: a5a5a5a5
addr: 2000bfe0 data: a5a5a5a5
addr: 2000bfe4 data: 0802aed1
addr: 2000bfe8 data: 0802aec1
addr: 2000bfec data: 00000000
addr: 2000bff0 data: a5a5a5a5
addr: 2000bff4 data: a5a5a5a5
====================================
========================= 寄存器信息 =========================
R0 : 00000001 R1 : 00000000 R2 : ffffffff R3 : 000000a5
R12: 2000a69e LR : 08031b31 PC : a5a5a5a4 PSR: 21000000
==============================================================
发生存储器管理错误,原因:企图从不允许访问的区域取指令
查看更多函数调用栈信息,请运行:addr2line -e CmBacktrace.axf -afpiC a5a5a5a4 08031b30 0802ad32 0802aed0 0802aec0
三、使用Windows命令工具进行查找
确定了和队列接收函数和定时器函数有关,然后在锁定在定时器创建函数,一步步屏蔽,仿真调试,经过十多次的反复操作最终确定了xQueueReceive函数的问题。
总结:软件定时器的回调函数是在定时器服务任务中执行的,所以一定不能在回调函数中调用任何会阻塞任务的 API 函数! 比如,定时器回调函数中千万不能调用 vTaskDelay ()、vTaskDelayUnti (),还有一些访问队列或者信号量的非零阻塞时间的 API 函数也不能调用。