你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】一个 STM32 芯片异常复位之案例分析

[复制链接]
STMCU小助手 发布时间:2022-2-17 20:35
前言2 w1 f" D8 ?! y9 t4 Y
本篇主要是介绍一种处理问题的思路,即当我们在做STM32应用开发过程中,遇到芯片异常复位,或者进入了异常处理时,如何通过集成开发环境,如IAR,KEIL等查看相应的ARM内核寄存器,定位出应用软件产生异常的地方!1 @+ P7 Q. v! @1 Q* T& f
问题描述
' W7 M# ?$ L5 G" _: y2 Q某STM32用户反馈,当使用STM32L4芯片的时候,程序运行一段时间后,会忽然复位。复位后程序继续运行,但是还会继续复位,原因不详!. t6 w- W) ^8 @; Q: u- Q

. ~% X3 a- i8 [* w0 B2 f# K问题分析
. q' |4 R! I: F8 w6 X7 ]7 L1 {针对于此类问题,我们可以按照一个统一的思路去处理。分析本案例的大致步骤如下:
0 A% g3 J5 C5 l9 b" `. F1、初步确定复位的原因,是硬件复位,如外部NRST被拉低,还是软件复位,包括软件直接调用复位,或者看门狗复位,还是低功耗模式如standby模式被唤醒时产生中断;
; N$ D: J7 G! c- P0 @3 ?1 x: g9 h2、查看复位状态寄存器了解复位大方向,然后做进一步得拆解分析。+ {, \. }2 j+ ^8 B6 l/ a
3、目前客户项目的复位原因是因为看门狗复位,即客户使用了IWDG,但由于某种原因没有及时喂狗,导致IWDG超时复位。初步怀疑由于客户软件的问题,程序跑飞,进入异常处理。; f% i. E# R0 e3 q

4 q  m4 }: C, N9 o; n1 y因为客户的异常处理函数中并没有做任何动作,导致独立看门狗IWDG复位。基于此,我们先关闭IWDG,然后在所有的异常处理中,先加入死循环并打上断点,对异常原因进行捕捉。* f5 \4 C7 L& j9 X4 |; ^1 a" ~

9 z3 I' v) i- m9 I4 A (NR4KB6`M~]LAEO2LRNBCOL.png
6 P0 I0 }% P  d
/ [* I- B: t$ _1 \, B& o, [ @]Z}R989YN3JCOFU$WI(6$B.png 9 L7 N% ], y' {' B$ F

2 ^$ ~; {7 E7 [! \8 k4、正如我们所猜测,的确是由于程序跑飞导致。程序停在了void HardFault_Handler(void) 。通过查看 SP 以及回溯栈里面的内容,找到了对应的LR,具体方法如下:7 O% s' @' ?1 L
0 p) l& g$ P: g! }1 t# L; Z
{$[1QY3C[I[4JTV_9YU9JK8.png
( q0 _- j' U8 x4 l) G; m9 p
( ]2 ]- F- r: N( a当中断产生时,按照上图所示的顺序进行压栈,同时栈指针SP--,即: R0, R1, R2, R3, R12, LR, PC,xPSR。
  V: h! l5 y; d& S
- s( h1 ]- h" c" t8 }; u* ^ ([LLS40YRF@N3Y{M55)I1XW.png
5 T" {6 B6 k0 Q: ~5 w0 m4 k
* [! u9 v; s# u3 y6 F: K) r# ]如上图所示,当产生异常时,如果call stack窗口显示不出来的话,只能根据core的寄存器手动回溯栈,以找到出错时的指针。根据ARM core的说明,SP+6,即红框的部分,为中断处理后LR和PC,据此可以追溯函数异常时的位置!
5 ]4 u) y# P3 o+ A  k" u  z% z* w" J. Z3 K( {6 d& h; E" ]7 m
5、根据出错时的PC和LR,发现是浮点运算的函数,初步判断是因为浮点运算导致,比如没有对齐导致的Hardfault,但实际检查发现,并不是浮点运算的问题!
) \& v" x; @  h9 V2 v6 S, O: E' H3 Q& q
6、问题一时陷入了僵局。但有一点是确定的,是因为栈的区域被异常覆盖或者改写导致产生hard fault,  q& P( M$ x3 g, \! m. z
  l1 S$ t# y2 {, ]
7、由于问题可以稳定复现,采取逐个排除法最终发现了问题的所在:
& t% A, s3 t; Q& Y1 U- s* z6 `& b, @当把一个局部数组变量改为全局数组时,问题消失!" y  s: R6 \( S$ Y( H3 X
由于局部数组变量是保存在栈当中,所以怀疑是对这个局部数组变量使用不当导致了栈被覆盖或者改写!追查这个局部变量数组:
- ~0 S9 S2 r2 V$ ?8 C9 d; V3 \/ q: {2 X  L9 P+ ~
M2QL148W$X5FVH_2[J%`5%L.png / ~* |% F, I& [

8 d  W0 O* ~( z! @- s2 G( z经检查发现,这个原先是8bit的局部变量的数组,在最后被强制转换成了uint32_t *类型的指针,由于是指针, 在对其进行++或--操作时,都是按照4字节宽带操作的,这就相当于扩大了4倍,覆盖了后面的栈的内容, 导致了程序跑飞!
% o6 c0 g- P8 Q1 }8 {! Q9 J& G( d4 U8 }! ~9 ^: K. C
小结5 ^+ f# o* z7 @
当芯片异常复位或者进入异常处理(如Hard fault, Mem Manage, Bus fault等)时,首先考虑的是,如何快速的复现这个问题,当问题被稳定复现的时候,可以通过调试工具在异常处理的地方打上断点停留,这样就可以获取到栈指针SP,通过SP去看栈里面的内容去回溯栈。当然,如果栈的内容被无端改写时,栈里面的内容,如保存的LR就没有太大的参考意义。不过,可以通过观察栈里面的内容,去估测是哪个模块或者函数异常修改了栈的内容,进而定位最终的问题源!* i7 R" N6 {; h% O
! b% A; ]8 G7 A
赞 收藏 评论0 发布时间:2022-2-17 20:35

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版