解决一次HardFault的bug

51 篇文章 2 订阅
16 篇文章 1 订阅

笔记

正在写固件工程, 程序框架差不多了, 在和设备通讯.
设备上改一个参数, 固件工程中看这个参数是否要保存, 如果是不同的值, 就写入文件.

发现只要一调用这个写参数的函数, 再运行几秒, 固件工程就会进HardFault_Handler.

如果不调用这个函数, 就正常.

开始检查这个函数, 能保证100%的正确.
而且从这个函数出来, 单步几下, 也不会HardFault.

最后想了一个笨招.
这个HardFault在调用写参数文件的函数后, 不是必现么?
好.

在和这个设备通讯的所有函数(大概50+个函数)的入口处都加了一个全局字符串指针赋值. 然后在HardFault_Handler处理中, 查看这个字符串指针, 这样, 是哪个函数出错, 就很清楚了.

char* gpsz_fun_entry = "unknown";

void my_wait_delay(void)
{
	gpsz_fun_entry = "my_wait_delay";
	OSTimeDlyHMSM(0, 0, 0, 100); // 延时一下
}

void cm_backtrace_fault(uint32_t fault_handler_lr, uint32_t fault_handler_sp) {
    uint32_t stack_pointer = fault_handler_sp, saved_regs_addr = stack_pointer;
//    const char *regs_name[] = { "R0 ", "R1 ", "R2 ", "R3 ", "R12", "LR ", "PC ", "PSR" };

#ifdef CMB_USING_DUMP_STACK_INFO
    uint32_t stack_start_addr = main_stack_start_addr;
    size_t stack_size = main_stack_size;
#endif

	if (NULL != gpsz_fun_entry)
	{
		gpsz_fun_entry = gpsz_fun_entry; // debugger set a break point here
	}
	fn_debug_watch(e_debug_watch_event_for_hard_fault);
	my_HardFault_Handler();
    CMB_ASSERT(init_ok);
    /* only call once */
    CMB_ASSERT(!on_fault);

重现了一下, 居然是调用my_wait_delay()时进了HardFault.
my_wait_delay()中调用的都是OS的函数啊.
这时, 有点感觉了. 好像是任务栈开小了.
去看任务栈size的定义

#define EX_UART1_USER_Management_Task_stk_SIZE	    127  //串口1 stack 大小
#define EX_UART2_USER_Management_Task_stk_SIZE		127  //串口2 stack 大小
#define EX_UART3_USER_Management_Task_stk_SIZE		127  //串口3 stack 大小
#define EX_UART4_USER_Management_Task_stk_SIZE		127  //串口4 stack 大小
#define EX_UART5_USER_Management_Task_stk_SIZE		127  //串口5 stack 大小

都改成256试试.

#define EX_UART1_USER_Management_Task_stk_SIZE	    256
#define EX_UART2_USER_Management_Task_stk_SIZE		256
#define EX_UART3_USER_Management_Task_stk_SIZE		256
#define EX_UART4_USER_Management_Task_stk_SIZE		256
#define EX_UART5_USER_Management_Task_stk_SIZE		256

将程序跑起来, 试试.
改了几次参数, 都是好好的.
那说明确实因为调用链比较深, 导致任务栈溢出引起的HardFault.

这个问题找了半天, 很耽误事.
这次靠感觉解决了问题, 先这样.

如果想彻底解决任务栈溢出的问题, 就要在每个函数调用前, 都检查任务栈. 或者在OS的任务栈操作中,设置一个任务栈将要溢出的断言. 这块没做试验呢, 以后有时间搞一下.

查资料, 有大佬说起了主任务栈MSP和任务栈PSP之间的区别和试验方法.
资料如下:
Main Stack Pointer(MSP) vs Process Stack Pointer(PSP)
RedKernel

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值