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

【经验分享】STM32H7移植SEGGER的硬件异常分析

[复制链接]
STMCU小助手 发布时间:2021-10-29 23:16
11.1 初学者重要提示! I: `; z% M# [2 X6 N5 e$ k
  MDK本身也是支持硬件异常分析的,就是不够直观。
) A/ H; E2 O* V9 H  F  IAR8带的硬件异常分析比较好用,在本章11.6小节有说明。6 ?/ s9 C7 B! ?0 Q' @0 A* m% Z4 f
11.2 移植方法
+ F# I, ^4 t/ j9 h2 o6 F直接移植SEGGER的硬件异常代码会有错误警告,这里针对IAR和MDK版本做了些简单修改,方便大家移植到自己的工程里面。
2 V% }; m6 W, l( X+ C' K) K- h7 P) C8 A) d/ n
  MDK版本移植! U+ i' S' a6 u- u/ s& y' L* }3 ?
源文件位于本章配套例子的\User\segger\HardFaultHandlerMDK文件夹,添加如下两个文件到工程里面即可。) R' @1 h4 e& z5 e9 Y& Q- k! s

- e  w+ Z# W, a9 [2 j6 `
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png

" y( r4 R: f: J6 L) s
# D7 B. X9 y! p: X! H9 q! K5 q  IAR版本移植
0 q) V7 }+ |  k5 M4 [9 v4 d3 i源文件位于本章配套例子的\User\segger\HardFaultHandlerIAR文件夹,添加如下两个文件到工程里面即可。9 ~5 `9 a( G9 U4 E2 r: \# k# M

) L; j3 s0 S' w+ n9 f
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png
/ H0 d& J% G) }) ?( X+ r

. N" K+ ?: u+ W: ~1 L在文件SEGGER_HardFaultHandler.c里面都添加了串口打印功能,方便不用编译器的调试功能时,通过串口打印提示是否进入硬件异常。3 P* e2 \$ v2 m1 q' ]9 i) i- r
: {4 T& \: X' o9 m
  1. #define ERR_INFO "\r\nEnter HardFault_Handler, System Halt.\r\n"
    $ O, j1 b* n9 h; t; V  Z1 t0 V, {& q
  2. / @: Y6 E8 F' P4 y% t
  3. #if 1
    # }; z) ~% p, y
  4. {- t2 S# @4 j. N% h  N) g/ `% M
  5.         const char *pError = ERR_INFO;2 c6 H% y, i* r2 ^
  6.         uint8_t i;* h: M) U% @+ b. Q/ Z

  7. + `5 H5 G. m5 B) g
  8.         for (i = 0; i < strlen(ERR_INFO); i++)
    2 V! m& u  }5 s: r: l, E
  9.         {$ b( P( N# @: x/ {" p; p4 P
  10.                 USART1->TDR = pError;. {, c1 V/ n9 f7 E) |3 A& \7 Q
  11.                 /* 等待发送结束 */) o8 u# s: I2 b: U! F: C
  12.                 while((USART1->ISR & USART_ISR_TC) == 0);
    ) H4 w: C( s" b  a- M3 s& N
  13.         }        
    6 T5 U: j% r5 v- u
  14. }
    / f" z3 r5 m6 Y4 T/ O
  15. #endif
复制代码
2 C) Z; H1 p- l  }- }2 `2 |
11.3 MDK锁定硬件异常位置方法
9 P1 }3 y8 B+ t5 z4 M以本章配套的例子为大家做个说明。
6 e$ T% W' {8 _" }' V: R
9 S! H, l* T" v& F% \1 _9 `1、测试方法比较简单,进入调试状态,全速运行,然后按下K1按键,就会进入硬件异常中断,此时停止调试,程序就会自动定位到如下位置:9 p+ S& @. Z( K! L6 o
( o3 r( b) r$ F% M
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png
% B4 p/ n( D  Z! i

1 }) ^% c; [. z$ l0 a+ w2、在Watch1窗口添加变量_Continue6 _/ B6 S0 S. ~& j  u0 Y$ M4 l

1 j6 W; U6 `5 D, F% s
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png

1 g0 K# S' j+ @: L; m0 m/ p! k$ C& M  ?, x% a
3、修改为任何非0数值,就可以继续单步调试。这个代码后面还有一个第1步中的while循环,也可以继续采用第2步的方法修改。退出硬件异常后就是大家进入硬件异常前下一条要执行的指令(可能还是这个函数本身,因为一个函数由多个指令完成)。定位到出问题的位置:
: b8 Z9 M. c( y, d( E, Z0 Q% N- S2 c# [0 b8 Q% X; V0 L9 F8 I
* D1 C0 R1 N# f" f5 C& m" B: J; R

( P0 |& ^8 c8 v11.4 IAR锁定硬件异常位置方法
0 l4 T, f0 G  L+ C$ _以本章配套的例子为大家做个说明。" u3 {+ [9 K0 a( Q/ k

2 f9 C+ i/ P0 e# K1、测试方法比较简单,进入调试状态,全速运行,然后按下K1按键,就会进入硬件异常中断,此时停止调试,程序就会自动定位到如下位置:
$ J1 ?5 V) h4 N( p: W: f9 s& M" t/ C2 @0 [" y, i$ E2 R
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png
2 K4 c$ m+ H4 a$ F0 |# p$ h
; ]& E; _$ j0 p$ d9 ?
2、在Watch1窗口添加变量_Continue; i7 z1 Q4 _2 M1 \; n
0 M# V: Z& Q" Q5 B
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png
' {- t: c. y* I+ D" u6 n4 F
; A4 n% O; Q' k& W6 |# O  n9 r
3、修改为任何非0数值,就可以继续单步调试。这个代码后面还有一个第1步中的while循环,也可以继续采用第2步的方法修改。退出硬件异常后就是大家进入硬件异常前下一条要执行的指令(可能还是这个函数本身,因为一个函数由多个指令完成)。定位到出问题的位置:
5 n$ K2 ~6 }% R- s7 m) `8 X3 p) v4 g& X8 e, S
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png

* n! W# c6 Q  }. d, e7 c& v; `7 i1 K6 }4 b. _/ q9 w, }" x! v5 @
11.5 硬件异常原因分析" s$ C3 g, ~0 o0 v* b6 Y
SEGGER提供的这个机制查找出问题的位置比较方便,具体原因需要继续在调试界面里面添加HardFaultRegs结构变量,这个结构体变量添加了所有大家想看的东西。下面是MDK调试状态查看部分结构体数值:
' n5 M( z1 W* l) h" P, F' J8 ^2 w7 D7 |$ C  Y3 A" f: c7 v
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png

2 P+ {' h" A3 h
- i" U: W  r) P( _- P具体上面的变量代表什么含义呢,代码里面有注释,查阅起来没有IAR自带的硬件异常提示方便(注意,下面的代码用到了位域)。
3 w1 |/ p5 B6 K9 D( P6 A, @
8 I0 H6 B9 ]7 U5 w1 S2 {  q+ Z9 T
  1. #if DEBUG
    + p, C, Q. F8 u$ R' m! H* u
  2. static volatile unsigned int _Continue;  // Set this variable to 1 to run further5 s4 n! z$ q& V  X! f% s
  3. ' z* S  u: \8 `7 r
  4. static struct {! |" `" B! b, N  n4 c" j# f& B
  5.   struct {
    ) @5 ]: i: ]9 e( q  [' N! I& `
  6.     volatile unsigned int r0;            // Register R0* M) Z5 V; X; p* Q1 F: B; b
  7.     volatile unsigned int r1;            // Register R11 M  \: {5 \- A$ s0 S
  8.     volatile unsigned int r2;            // Register R2
    5 a: T8 Z, ?4 t9 G2 n. S) @
  9.     volatile unsigned int r3;            // Register R38 E" O( p0 g) r* W- z
  10.     volatile unsigned int r12;           // Register R12* Z( H) w$ m' F! h1 d: ?
  11.     volatile unsigned int lr;            // Link register  G& P2 X- j% X  P7 y
  12.     volatile unsigned int pc;            // Program counter
    ! ^# ]" N$ e* ]
  13.     union {' N6 [  g/ T! E4 h6 e" C% \
  14.       volatile unsigned int byte;
    $ m9 ?! Y. F' |9 [8 X; P
  15.       struct {, \7 e$ A7 p6 _- C
  16.         unsigned int IPSR : 8;           // Interrupt Program Status register (IPSR)# T  ?; v, K3 K. f$ m5 R. s
  17.         unsigned int EPSR : 19;          // Execution Program Status register (EPSR)1 ^, _7 |& N9 n) g8 h% N
  18.         unsigned int APSR : 5;           // Application Program Status register (APSR)9 @# m; }. w5 a' t$ f: L
  19.       } bits;3 W) ?) I6 X: V" I& A1 ]  a- E" t
  20.     } psr;                               // Program status register.
    2 G" C0 p0 G- C0 |* m( a
  21.   } SavedRegs;
    8 ]) q& c4 }7 F; Q- V

  22. ) A3 Q; I0 T+ _4 Y
  23.   union {
    0 b7 B8 N, [/ \" g
  24.     volatile unsigned int byte;
      V- E2 ^4 e+ ]* Q$ |; i# L6 o! `" R
  25.     struct {
    6 v$ u6 t* N+ R7 H7 ~
  26.       unsigned int MEMFAULTACT    : 1;   // Read as 1 if memory management fault is active
    * N# G; b& t% t, Q* K/ M* {
  27.       unsigned int BUSFAULTACT    : 1;   // Read as 1 if bus fault exception is active; s. R: a% O: `4 t' T3 p: y
  28.       unsigned int UnusedBits1    : 1;9 v  X; I/ D8 m! K& ^
  29.       unsigned int USGFAULTACT    : 1;   // Read as 1 if usage fault exception is active( x+ x2 E# ^1 |# z! ?% x2 L
  30.       unsigned int UnusedBits2    : 3;, {9 e& L* v1 L, w$ Q* g) r
  31.       unsigned int SVCALLACT      : 1;   // Read as 1 if SVC exception is active
    , r' F2 Q) `& [* H' L5 n) H5 p
  32.       unsigned int MONITORACT     : 1;   // Read as 1 if debug monitor exception is active" u" Q4 d0 n+ {6 Q0 }/ c; y& U
  33.       unsigned int UnusedBits3    : 1;
    4 {% j8 }# @+ T5 ]. Q. N) @
  34.       unsigned int PENDSVACT      : 1;   // Read as 1 if PendSV exception is active5 f$ O9 b$ H. o7 U
  35.       unsigned int SYSTICKACT     : 1;   // Read as 1 if SYSTICK exception is active
    8 d+ t) X7 r) Y6 L1 A. D' t
  36.       unsigned int USGFAULTPENDED : 1;   // Usage fault pended; usage fault started but was replaced by a
    6 \* e8 ^4 b! s4 G3 z) G- `5 g& w
  37. higher-priority exception
    - M# m7 y9 A( C
  38.       unsigned int MEMFAULTPENDED : 1;   //  Memory management fault pended; memory management fault started
    4 f% U1 Y( H5 D0 r  L
  39. but was replaced by a higher-priority exception
      b: F  a8 o2 ?
  40.       unsigned int BUSFAULTPENDED : 1;   // Bus fault pended; bus fault handler was started but was replaced
    ( X" d5 E4 ?2 O6 ~
  41. by a higher-priority exception
    - f+ c9 D5 p7 p' @
  42.       unsigned int SVCALLPENDED   : 1;   // SVC pended; SVC was started but was replaced by a higher-priority( a- X3 l  T- a% ], d
  43. exception, Y  Q6 ~/ p6 W4 `
  44.       unsigned int MEMFAULTENA    : 1;   // Memory management fault handler enable( J5 w. r4 U2 |$ ~1 {
  45.       unsigned int BUSFAULTENA    : 1;   // Bus fault handler enable
    ; Y+ L2 h* v+ J- o& A
  46.       unsigned int USGFAULTENA    : 1;   // Usage fault handler enable
    0 O% @$ T/ U) q  j
  47.     } bits;
    % N2 i, `! j2 O( r, ~4 d$ y
  48.   } syshndctrl;                          // System Handler Control and State Register (0xE000ED24)
    8 A- ~0 M5 P" q
  49. 2 [7 p3 o7 r) w6 Q. V2 [+ }
  50.   /* 省略未写 */
    4 w: C: O9 ?, w0 P4 L

  51. 1 }+ f# u6 `, Z: m) `0 E8 t
  52.   volatile unsigned int afsr;            // Auxiliary Fault Status Register (0xE000ED3C), Vendor controlled (optional)4 E2 i0 g4 _: n- z
  53. } HardFaultRegs;
    7 I. V% O+ l& u, _8 W4 N. w2 V; E
  54. #endif
复制代码

  M: p. t+ H1 S) \0 E11.6 IAR自带的硬件异常分析4 Z" Y; ~2 e) q
还以本章配套的例子为例,进入调试状态,全速运行,然后按下K1按键,就会进入硬件异常中断,此时停止调试,IAR还会弹出一个硬件异常错误分析,刚进来的时候也许是个空白
/ u. ?/ o+ L  q, a$ s
/ V9 h' a" Y9 Y# I
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png
* ~8 {5 D: H  O! ]0 P* T" V- c3 @

9 P0 D: p7 H: \8 R4 L4 D6 `单步调试刷新下就出来了:
3 y6 y" k  x) E8 R7 W- X6 N( O; j4 C/ j% `) Z3 Z, @& v. t, Y
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png
+ N- F1 Z( a! G$ V7 ]6 L" v4 U

2 ~% o2 r5 d( r4 h( C9 f指出了问题的原因是操作的数据地址有问题。
/ x% |9 `" q, Z2 W
$ }; R& P/ Q* G7 ]8 i/ p11.7 实验例程) V! H$ Q! |, ^0 G) ^& j' G
专门为本章节配套了一个例子:V7-009_移植SEGGER的硬件异常分析机制。大家可以按照本章教程提供的方法进行测试。8 z4 W3 i& u5 x9 Z$ X9 B, m8 ?1 W

, a1 J7 d9 S3 Z11.8 总结' k5 A+ q) V- S/ j
除了SEGGER的硬件异常分析方案,建议也测试下MDK和IAR的,以后遇到硬件异常问题,解决起来可以得心应手。$ V5 L+ ^0 a: ]; q
- i) X3 P% S! P+ l# x

! g5 Q0 a1 F' l) X9 v) }  y
: K2 j  `' W( b6 U
9 F+ r( J5 ?5 k% b% g
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png
赞 收藏 评论0 发布时间:2021-10-29 23:16

举报

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