前言 ) ^% D$ p. _& [ 本篇主要是介绍一种处理问题的思路,即当我们在做STM32应用开发过程中,遇到芯片异常复位,或者进入了异常处理时,如何通过集成开发环境,如IAR,KEIL等查看相应的ARM内核寄存器,定位出应用软件产生异常的地方! R' d4 Q# E( B, A$ o3 [- x9 \ 问题描述 某STM32用户反馈,当使用STM32L4芯片的时候,程序运行一段时间后,会忽然复位。复位后程序继续运行,但是还会继续复位,原因不详!2 j6 P% b2 O; w8 z& d4 E! X 3 H1 B& P% i) Z2 [3 y" p+ t 问题分析* V o0 E C. d _ 针对于此类问题,我们可以按照一个统一的思路去处理。分析本案例的大致步骤如下: 1 c. X- P( s4 G- M3 b! H6 \+ l2 g 1、初步确定复位的原因,是硬件复位,如外部NRST被拉低,还是软件复位,包括软件直接调用复位,或者看门狗复位,还是低功耗模式如standby模式被唤醒时产生中断; 2、查看复位状态寄存器了解复位大方向,然后做进一步得拆解分析 3、目前客户项目的复位原因是因为看门狗复位,即客户使用了IWDG,但由于某种原因没有及时喂狗,导致IWDG超时复位。初步怀疑由于客户软件的问题,程序跑飞,进入异常处理。 * f" O# V, L" T& `/ |7 c 因为客户的异常处理函数中并没有做任何动作,导致独立看门狗IWDG复位。基于此,我们先关闭IWDG,然后在所有的异常处理中,先加入死循环并打上断点,对异常原因进行捕捉。 4、正如我们所猜测,的确是由于程序跑飞导致。程序停在了void HardFault_Handler(void) 。 通过查看 SP 以及回溯栈里面的内容,找到了对应的LR,具体方法如下: 当中断产生时,按照上图所示的顺序进行压栈,同时栈指针SP--,即: R0, R1, R2, R3, R12, LR, PC, xPSR。 * T0 [& O8 K$ D& ^4 \* ~ J7 N0 ^如上图所示,当产生异常时,如果call stack窗口显示不出来的话,只能根据core的寄存器手动回溯栈,以 找到出错时的指针。根据ARM core的说明,SP+6,即红框的部分,为中断处理后LR和PC,据此可以追溯 函数异常时的位置! 5、根据出错时的PC和LR,发现是浮点运算的函数,初步判断是因为浮点运算导致,比如没有对齐导致的 Hardfault,但实际检查发现,并不是浮点运算的问题! 6、问题一时陷入了僵局。但有一点是确定的,是因为栈的区域被异常覆盖或者改写导致产生hard fault, . n: V. h' y A g% o# n# R 7、由于问题可以稳定复现,采取逐个排除法最终发现了问题的所在: 当把一个局部数组变量改为全局数组时,问题消失! ; j9 ~5 H$ _8 M; d! J7 ~. V% S4 ?由于局部数组变量是保存在栈当中,所以怀疑是对这个局部数组变量使用不当导致了栈被覆盖或者改写! 追查这个局部变量数组: 4 o* K8 E5 Q9 ]5 i" P............ ' H, S+ u5 p9 s想了解更多,请下载原文阅读 |