IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 解决一次HardFault的bug -> 正文阅读

[嵌入式]解决一次HardFault的bug

笔记

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

发现只要一调用这个写参数的函数, 再运行几秒, 固件工程就会进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

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-01-16 13:13:51  更:2022-01-16 13:14:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 12:34:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码