本帖最后由 creep 于 2015-12-5 17:17 编辑 ) t) m# D6 A1 c$ ?: v 下午在社区群里和小伙伴聊天时谈到如果程序Fault时如何找到是哪句代码出现的问题,也就是说怎么找到程序运行到何处时出现Fault的。之前一直使用一种方法感觉不错,分享给有需要的同学。) h% J0 Y7 Q, V0 l( b* h+ _1 g6 ] 大致的思想是当程序出现Falut时会跳转到相应的Fault中断里面,此时压入到堆栈的信息应该就是出现问题代码运行出错Fault的信息,我们要做的就是找到此时压入堆栈的LR的值。为了模拟Fault,我们将0写到地址0里面,此时debug下全速运行,程序就会进入到Fault函数中。 我们在Fault中断函数中添加一个软断点,这样做的好处是debug模式下全速运行,当程序跑飞(Fault时)会自动停在这里,否则我们还要手动停止运行才能发现程序进入了Fault中断函数。1 T$ G. z# M6 g2 C$ e, e2 c. F 为了方便查看程序程序的Fault时的相关信息,我们将错误信息打印到keil的debug Viewer窗口中,关于如何打印信息到keil的debug viewer窗口,可以参考我之前的发的帖子:【STM32F303开发】+ 使用SWO输出调试信息到Debug Viewer窗口5 n( A; Z+ p" R2 o& P3 W& c * v9 i- z P3 r M3/M4内核的MCU的压栈的模式如下,我们根据下面的寄存器的存放顺序来取出压入到堆栈的寄存器的值。 同时将Fault中断时的函数重载如下,用来输出更多的信息,同时判断了是使用MSP还是使用PSP,8 N$ l& o- Z9 Y 8 k1 F# L* Y O4 d& E8 I 具体的void Hard_Fault_Handler(uint32_t stack[])函数根据寄存器SCB->CFSR判断并输出是那种Fault: 最后使用函数stackDump(stack);输出出现Fault时的堆栈的值,取值的顺序是根据上面说的M3/M4内核压栈的顺序得到的: ; E1 G/ y6 x8 B; k 下面我们在debug模式下全速运行如下代码,main函数如下:其中的 *(uint32_t*)paddr = 0; 会导致Fault并进入中断,5 s3 s, O B0 u& N. m3 @2 _ 在debug模式下全速运行,不要设置任何断点,最后程序程序会在debug viewer中输出出错Fault的相应的寄存器的值并停止在__ASM volatile("BKPT #01");,此处得到的LR的值就是我们要找的LR的。+ B) A8 Q7 ] c 此时打开汇编窗口,在汇编窗口里面右键show Disassembly at Address选项输入LR的值然后回车 调转到的汇编的地方就是导致程序出现Fault的地方,注意M3/M4内核使用Thumb指令,要求最低bit为1,9 P$ F1 y9 ~9 U* Z 5 |6 _: [" b: E3 y+ N9 D 上面的过程大致就是找到程序出现Fault跑飞时的方法,基本上能定位到出错的代码,使用OS时要注意判断是哪个SP在起作用。 这个方法很早就看到过,但是今天查资料发现是国外的一个工程师在ARM举行的Technical Conference上做的一个分享,0 l% w9 G, b N! T 具体参考网页:Developing a Generic Hard Fault handler for ARM Cortex-M3/Cortex-M4 如果有问题可在社区QQ群(427779516)讨论% G; N+ b2 d2 y$ O3 W# h& j0 L 上面用到的测试代码: |
基于STM32F334的数字电源
STM32F3DISCOVERY + UCGUI3.90A的移植(源码+视频)
基于STM32F303双电机FOC驱动: 无感原理图/BOM表/代码等开源...
【基于STM32F3的电机控制】_给力外围之 OPAMP
在 STM32 F0、 F2、 F3、 F4 和 L1 系列MCU 中使用硬件实时时钟 (RTC)
基于STM32F334的BUCK同步降压数字电源设计
ST FOC4.3 库关于 STM32F30x 系列 ICS采样代码的修改
STM32F334 上的 ADC 管脚和 DAC 管脚复用问题
如何使用USART或LPUART将STM32F0/F3/L0/L4微控制器从低功耗模式唤醒
在 STM32 F0、 F2、 F3、 F4 和 L1 系列 MCU 中使用硬件实时时钟 (RTC)
《cortex m3 权威指南》是本好书,值得多读几遍!
谢谢指导,不知道你说的ST的出的指导哪里可以找到,能不能给些提示或者连接!# q8 _' i& }+ Z: ~7 ]% B" D
这里导致导致Bus Fault 的那句代码是我故意写的用于触发Fault的。
对地址0写0肯定是不允许的,这是为了模拟怎么找到错误代码的方法。9 e$ O L0 }2 B1 P5 G
因为在一个功能复杂代码很多的程序里去直接定位跑飞(Fault)的代码不是很容易,所以可以使用这个方法去定位问题!
谢谢分享
二姨家,上面有些,21IC ST 论坛
多谢分享!
能不能给个具体点的URL?谢谢!