请选择 进入手机版 | 继续访问电脑版

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

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

[复制链接]
STMCU小助手 发布时间:2022-1-1 20:00
11.1 初学者重要提示6 C: S8 J; R9 e' X8 a; M4 {
  MDK本身也是支持硬件异常分析的,就是不够直观
0 `; ?$ u) B# p! `$ m! u6 r4 U! c: D9 J' x2 v
  IAR8带的硬件异常分析比较好用,在本章11.6小节有说明。8 d& L/ n- q7 p/ x: N/ R
11.2 移植方法
* W5 a% R& p$ }1 x0 \直接移植SEGGER的硬件异常代码会有错误警告,这里针对IAR和MDK版本做了些简单修改,方便大家移植到自己的工程里面。
3 u' m1 T) z& u7 L# ?4 z- z/ N. I
9 o/ j; k+ t  l# n: C3 b  MDK版本移植
7 Z/ L# Z6 h2 |+ n1 i% }& ?$ W) J源文件位于本章配套例子的\User\segger\HardFaultHandlerMDK文件夹,添加如下两个文件到工程里面即可。. |! d6 a, p" s$ L0 l0 J

# `* l, z8 O' @, X( y' M4 I
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png
3 R. o5 {. `/ {% I9 N
: ~% r; s+ ]9 s7 G. n
  IAR版本移植
8 ^6 C+ w- ~# t+ d2 u2 j源文件位于本章配套例子的\User\segger\HardFaultHandlerIAR文件夹,添加如下两个文件到工程里面即可。% I8 T8 E( m6 j
4 D/ k* g$ A% Z1 p: j! Q4 f
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png

& Z5 K) @' F0 z+ `8 i* N! l' y. F, z- F4 R& w% N/ U1 W5 f" [' C7 Z
在文件SEGGER_HardFaultHandler.c里面都添加了串口打印功能,方便不用编译器的调试功能时,通过串口打印提示是否进入硬件异常。& e5 X2 q0 Z4 b
6 p& e& s! I/ d; |5 s( P1 _
  1. #define ERR_INFO "\r\nEnter HardFault_Handler, System Halt.\r\n"
    : M/ Y( C! \% f1 A: ]" _$ l- I# z: M
  2. + d( V* u  E" r6 i2 {3 y
  3. #if 1) _: F3 l% B0 b# v7 Y/ {
  4. {
      h& ^& o% g" m4 y6 I( c
  5.         const char *pError = ERR_INFO;
    , E5 y6 i* w, R, Y2 E0 Z$ N
  6.         uint8_t i;. g! [" b8 r. N" R

  7. # f6 B, l5 W' ?: l# ^, p
  8.         for (i = 0; i < strlen(ERR_INFO); i++)
    + Y& ^  p1 H2 J9 H% ~
  9.         {
    / _9 {2 B+ m0 C( N% Z0 _
  10.                 USART1->TDR = pError<i>;+ ?* n8 N8 y5 Y$ p& j
  11.                 /* 等待发送结束 */$ R. o4 t$ `5 A, g
  12.               </i>  while((USART1->ISR & USART_ISR_TC) == 0);
    9 q! j6 H; ?4 g: _8 K
  13.         }        & O' m3 ^. s& e- L8 l+ c. W# m$ a
  14. }6 e" r% I, Z# b' m
  15. #endif
复制代码
# Q8 \9 u, W  `7 B" z# P
11.3 MDK锁定硬件异常位置方法, H  @% }# v$ G6 w0 I
以本章配套的例子为大家做个说明。6 [- K3 ]) X9 b# L

1 B# U  \% H- N; [/ G1、测试方法比较简单,进入调试状态,全速运行,然后按下K1按键,就会进入硬件异常中断,此时停止调试,程序就会自动定位到如下位置:% j2 I6 R4 |) [' z, E2 J
8 b+ N2 x! ^9 J' X" |
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png
0 T. a$ f0 i" A: w8 \6 v

6 ~! F5 Z' Z9 ]8 H2、在Watch1窗口添加变量_Continue1 L. e' Z$ @. m- F& H- A

3 `3 y0 U2 m7 D2 ?" K9 @
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png

- h3 I+ G  F0 d4 \
5 F- A' a/ I+ U( f1 Y( d5 k$ s, f3、修改为任何非0数值,就可以继续单步调试。这个代码后面还有一个第1步中的while循环,也可以继续采用第2步的方法修改。退出硬件异常后就是大家进入硬件异常前下一条要执行的指令(可能还是这个函数本身,因为一个函数由多个指令完成)。定位到出问题的位置:9 u/ D  k1 B9 Q  o3 I, z6 i

: X, x1 v5 d, \5 _9 ^' s2 Y. L, Z
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png

- j3 p/ j$ Z- Z( R( N' T* y# b! l' H8 i$ A. z! H, g# W' Z
11.4 IAR锁定硬件异常位置方法

' |- I" M# H( @# \以本章配套的例子为大家做个说明。: R- b2 v# V( P9 M1 S; e3 P# ~/ {) S
6 c9 q5 q  V) Q' I& G( |* M
1、测试方法比较简单,进入调试状态,全速运行,然后按下K1按键,就会进入硬件异常中断,此时停止调试,程序就会自动定位到如下位置:, ^$ N7 B4 T3 N' o7 {
5 P2 |! {& q  S% N0 G
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png
2 C/ K( n! q5 s, T* ~5 h7 ]& r+ `

& O5 p. R) O* Y9 E+ F8 b3 J2、在Watch1窗口添加变量_Continue
# A1 P0 w8 Y: p9 O9 V( p) P
% D* c7 w+ q9 a) Q7 X
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png

/ D' \4 \6 t2 W+ j7 k
& d( u2 M4 y( \$ t+ }/ ~! k, q3、修改为任何非0数值,就可以继续单步调试。这个代码后面还有一个第1步中的while循环,也可以继续采用第2步的方法修改。退出硬件异常后就是大家进入硬件异常前下一条要执行的指令(可能还是这个函数本身,因为一个函数由多个指令完成)。定位到出问题的位置:
- K/ z9 f. E0 D: W
, Q5 r+ [$ b) ?) E1 \
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png
+ Y5 W, g5 }) h& r6 X/ O( D

3 E# T' M2 F/ ?8 P4 w11.5 硬件异常原因分析" @9 S2 ]1 E+ P
SEGGER提供的这个机制查找出问题的位置比较方便,具体原因需要继续在调试界面里面添加HardFaultRegs结构变量,这个结构体变量添加了所有大家想看的东西。下面是MDK调试状态查看部分结构体数值:2 s6 M3 U) i- G& N! e

- c% M6 S# e% a( P- u$ C
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png

0 }# r3 Z- I& H1 o
6 a, H5 B3 r/ F- d# h具体上面的变量代表什么含义呢,代码里面有注释,查阅起来没有IAR自带的硬件异常提示方便(注意,下面的代码用到了位域)。
9 g7 t- J* q. C0 Z7 U/ d5 y, R2 L% F" e7 s' Z$ Q: h2 ~% }# H- @: R4 ]
  1. #if DEBUG3 T1 g2 a6 t1 ~  z! f
  2. static volatile unsigned int _Continue;  // Set this variable to 1 to run further
    ! b8 o, N* b4 K5 @

  3. " `. v1 `, x+ N
  4. static struct {
    3 W8 F) A/ n4 G: K: g
  5.   struct {
    / F; |# _- U' I/ e1 q
  6.     volatile unsigned int r0;            // Register R0
    4 L( V$ M, o2 D7 N' d
  7.     volatile unsigned int r1;            // Register R1
    - H, T0 O3 u+ y. o& O6 |
  8.     volatile unsigned int r2;            // Register R2
    ' ]5 j& b1 |9 Z8 I  X
  9.     volatile unsigned int r3;            // Register R3" m: A/ D' ^2 K5 D8 r. S( G: ?
  10.     volatile unsigned int r12;           // Register R121 _& I/ z+ N1 ]- l
  11.     volatile unsigned int lr;            // Link register
    ) ^$ z3 |* c7 B4 I8 w9 E/ _1 `5 y' o
  12.     volatile unsigned int pc;            // Program counter: z9 `) B1 e, h  \7 n
  13.     union {0 }3 o7 v0 ^. t2 G5 L
  14.       volatile unsigned int byte;
    8 C: b5 H, {# k/ _: R& e$ ^
  15.       struct {- G& F) `( p0 M9 o
  16.         unsigned int IPSR : 8;           // Interrupt Program Status register (IPSR)/ c. \2 U3 m" S6 T6 O+ E$ F/ g
  17.         unsigned int EPSR : 19;          // Execution Program Status register (EPSR)2 ?7 {5 J& }8 g' [( V$ c  A
  18.         unsigned int APSR : 5;           // Application Program Status register (APSR)
    5 n- g$ j; c3 \9 B
  19.       } bits;% i& X. o8 ?5 `' Q
  20.     } psr;                               // Program status register.$ |2 y, K( ~  @1 x
  21.   } SavedRegs;! P  t; r4 E9 D+ k' b5 l; z

  22.   a" t3 j) h3 L+ m1 P
  23.   union {
    * s% R9 T" w2 Y
  24.     volatile unsigned int byte;
    9 n/ X; [6 H6 g1 ?; \
  25.     struct {
    : J7 k: e9 H3 K. a1 E$ B4 |0 r
  26.       unsigned int MEMFAULTACT    : 1;   // Read as 1 if memory management fault is active
    8 Z5 J# l4 ^+ m  f/ w7 T
  27.       unsigned int BUSFAULTACT    : 1;   // Read as 1 if bus fault exception is active. A  d7 p+ w5 y9 N
  28.       unsigned int UnusedBits1    : 1;
    3 `- l5 G7 X+ ]" H; ~1 S
  29.       unsigned int USGFAULTACT    : 1;   // Read as 1 if usage fault exception is active* k$ J' M  e5 b& g7 Q0 g$ e
  30.       unsigned int UnusedBits2    : 3;( o  g6 b" I! i2 K7 ?% M
  31.       unsigned int SVCALLACT      : 1;   // Read as 1 if SVC exception is active! t; W6 X# P, P7 N. K7 ]4 r
  32.       unsigned int MONITORACT     : 1;   // Read as 1 if debug monitor exception is active
    + K% _+ |" F0 ^/ q5 F
  33.       unsigned int UnusedBits3    : 1;6 L& R1 X4 N  r* V# {+ m
  34.       unsigned int PENDSVACT      : 1;   // Read as 1 if PendSV exception is active7 D2 D* ]* _( e  p/ I
  35.       unsigned int SYSTICKACT     : 1;   // Read as 1 if SYSTICK exception is active$ r4 w" ?4 ^  d7 h$ `
  36.       unsigned int USGFAULTPENDED : 1;   // Usage fault pended; usage fault started but was replaced by a
    ) H: I' ^- y$ U( n; W
  37. higher-priority exception7 q. @* k3 ?0 [$ W
  38.       unsigned int MEMFAULTPENDED : 1;   //  Memory management fault pended; memory management fault started3 Q" ~( K+ ]- H7 L1 J' Q7 @
  39. but was replaced by a higher-priority exception1 r, |  D. k6 t% `6 B
  40.       unsigned int BUSFAULTPENDED : 1;   // Bus fault pended; bus fault handler was started but was replaced( Z- c$ k0 ~4 A
  41. by a higher-priority exception' g; [4 O- |& V. U$ j, ?0 v% k
  42.       unsigned int SVCALLPENDED   : 1;   // SVC pended; SVC was started but was replaced by a higher-priority
    ) R- ~* d7 e7 W2 n3 L1 U
  43. exception9 |- M* j% E1 g; U4 r
  44.       unsigned int MEMFAULTENA    : 1;   // Memory management fault handler enable
    1 L6 U1 X+ b: c; ~; a2 n" [
  45.       unsigned int BUSFAULTENA    : 1;   // Bus fault handler enable
    # R  W! ~# t9 |1 O2 {' r
  46.       unsigned int USGFAULTENA    : 1;   // Usage fault handler enable
      I, b9 W. M; _; Q) \. Z+ z( l
  47.     } bits;
    & h) B3 Z: C- k) P2 ^# ]- B
  48.   } syshndctrl;                          // System Handler Control and State Register (0xE000ED24); \4 z3 \; j0 M$ U& d0 p' B
  49. 3 S8 u- h! ]% \7 U% E9 F
  50.   /* 省略未写 */9 M' l% g8 k8 N# `  B* s
  51. ) A' B5 Y" G2 l% F4 X/ v
  52.   volatile unsigned int afsr;            // Auxiliary Fault Status Register (0xE000ED3C), Vendor controlled (optional)0 H9 A8 l  B3 q8 X1 [* `) y3 a
  53. } HardFaultRegs;
    ' h1 ~, r6 D5 f! s- a: h1 A3 P, F5 O
  54. #endif
复制代码

( O- i2 r% ]' w: G5 G11.6 IAR自带的硬件异常分析: r" h; |8 A, H
还以本章配套的例子为例,进入调试状态,全速运行,然后按下K1按键,就会进入硬件异常中断,此时停止调试,IAR还会弹出一个硬件异常错误分析,刚进来的时候也许是个空白
' l  b- T" d2 a% U* O; q8 ^" G' x( V
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png
8 g/ I' P6 K& U; ^4 z
' P, B- P5 y. e+ s/ g- z# q6 y, k
单步调试刷新下就出来了:5 W4 L, T- G- z* B

5 l/ }5 }. i- Z5 D  |4 s* P5 ^
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png

1 n6 S, i  i" ^2 d) H; b/ z8 J; `4 \4 l3 T
指出了问题的原因是操作的数据地址有问题。$ k& r9 M" e; O$ e# b1 u  S' n6 I; x
# ]  m5 Q5 b$ c. ^- @" Q" N
11.7 实验例程0 E5 d& a1 i3 U0 g3 ]
专门为本章节配套了一个例子:V7-009_移植SEGGER的硬件异常分析机制。大家可以按照本章教程提供的方法进行测试。% S% I" X9 K1 H  `3 e
5 M0 C) O$ i$ Q& U# g* I4 r
11.8 总结" V# H) [- S: s
除了SEGGER的硬件异常分析方案,建议也测试下MDK和IAR的,以后遇到硬件异常问题,解决起来可以得心应手。
, P1 z; h9 ^: d( Y9 o# N; C( y* P, L; Z# Y; r% o: P

) |% [4 x6 l( |  S4 c" x
收藏 评论0 发布时间:2022-1-1 20:00

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版