|
最近在搞stm32的IAP功能,在app运行的时候进入HardFault_Handler函数。 $ r! E# M) V4 l& h % S+ o- T6 ]! j0 k. g 程序介绍:/ s3 f& x/ x% @) B/ F: B- B ] 1.bootloader程序为串口接收app应用程序的bin文件,用写flash函数(参考正点原子的IAP程序)将接收到的bin文件写到app区域,然后跳转到app应用程序执行。 2.应用程序为简单的测试程序,在主程序中500ms闪灯。 % e: ^+ G$ b, H9 g* G- g 3 ^8 v7 i2 v4 {- P9 |4 L o3 k5 D 问题: bootloader程序可以正常接收bin文件,正常跳转到app程序区域,在app执行过程中,初始化程序会进入HardFault_Handler函数。$ I& y, \9 O: g: \/ H 解决方法: 首先将bootloader程序和app应用程序通过jlink写到单片机中,app应用程序区域设置正确,程序写的地方就正确。然后用jlink仿真app应用程序,仿真app程序需要注意bootloader程序能够正常跳转到app程序中,我在此为了仿真初始化完成后就直接跳到APP程序中了。& j; f# x4 W+ f; O5 c$ F) Y9 A8 k* ` 如下图所示(bootloader主程序):9 c( D2 p( j1 i E
app应用程序主程序0 |2 C0 @ C# n1 s4 ~" a8 d+ t
409行为app中断向量表地址 接下来直接在app应用程序中debug调试程序,因为bootloader程序可以直接跳转,所以可以跑到应用程序中,在HardFault_Handler函数处加断点,打开view下面的call stack windows框(查看出错时栈的情况),如下图所示:
( f$ A! [- }. B; } 4 K3 _: Y1 j8 g0 F 现在进入错误处理的函数中,看看栈窗口的情况:8 g) l: o" a4 k7 R% p
可以看到此时有串口中断,还有定时器8的初始化,再回过头来看一下我的app应用的初始化过程,初始化定时器8前面,没有初始化过串口,而且应用程序中,串口初始化是被屏蔽的,所以这里不应该出现串口中断压入栈中,那串口中断是从哪里来的,往前找会发现,在bootloader程序中,我打开串口中断接收的数据,在跳转之前没有关闭串口中断,在这段程序中串口中断还存在,还在起作用,而且中断向量已经发生偏移,不是在应用程序的程序指针范围之内,所以程序指针跑飞了。 ; [! F5 c4 Y& B1 d: b# y8 {5 Z 基于以上分析,我在bootloader的程序中,在跳转函数之前加一句关闭串口中断的语句,如下图所示:: T- N5 ~$ ?9 L' D* x% R
: n7 e) B) j: N) F + ]$ S' |! e, X U* ?% d. R 添加函数HAL_NVIC_DisableIRQ(USART1_IRQn);关闭串口中断,再来测试一下,发现应用程序能够正常工作了。 所以在bootloader中跳转之前将打开过的中断全部关闭,在应用程序中用到时再次初始化。- ]7 |5 [3 ]9 K0 P. { 6 w0 V+ k6 p2 L; q3 H3 K 以上是在这种情况下的解决方法,可以用其他情况下查找HardFault_Handler的问题出错位置,一定要注重栈窗口中的每一个函数及函数内部的参数,有时不一定是函数出现错误,也有可以是定义的变量超出范围,这时需要点开函数的+号,查看每一个变量是否合理,如下图所示:
查看函数里面的变量,以上就是查找问题的方法,需要灵活应用。$ F' w4 w# ]5 T5 A+ U5 Z7 x; g 转自:李蛟23的博客+ X. |. Q4 Q4 a, u# K8 Y" `: v' s ! U* G" U9 F" ]% S8 J& [; O+ O $ \' O: l1 F7 s7 W o; J; D $ h1 v9 }, N- W+ ~ |
| 感谢分享!!!! |
微信公众号
手机版