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

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

[复制链接]
STMCU小助手 发布时间:2022-1-1 20:00
11.1 初学者重要提示
% ~& [" {* c, A, g# U% a  MDK本身也是支持硬件异常分析的,就是不够直观
! U9 u7 Z) a- |( q4 v" I* T1 o- J! a& `4 O+ ]
  IAR8带的硬件异常分析比较好用,在本章11.6小节有说明。
! e8 L9 t5 X! f11.2 移植方法
1 s! W, N4 b# m. |直接移植SEGGER的硬件异常代码会有错误警告,这里针对IAR和MDK版本做了些简单修改,方便大家移植到自己的工程里面。) h' y# c1 y1 w* q7 b2 s( H

( r* R7 V- L- x. o/ t  MDK版本移植6 Q, ~. E! [9 T2 h* y; \" n, o
源文件位于本章配套例子的\User\segger\HardFaultHandlerMDK文件夹,添加如下两个文件到工程里面即可。
  M9 d5 l3 v/ C3 Y
$ J: d& M6 j# J- d
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png

# m& C& s- z, ^4 j$ m; Y
/ |8 k5 {+ E4 @) T* |& H  IAR版本移植
: b+ U, m! i5 E: y源文件位于本章配套例子的\User\segger\HardFaultHandlerIAR文件夹,添加如下两个文件到工程里面即可。
7 D1 ~% y2 n) [& j! U6 N& ~5 ?5 R! F
5 }+ @) k* [* Y# r
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png

+ K) u3 [; P: e* o
6 s' L& T; N% j- f* h# J6 j在文件SEGGER_HardFaultHandler.c里面都添加了串口打印功能,方便不用编译器的调试功能时,通过串口打印提示是否进入硬件异常。9 B8 `: L2 y7 V' }0 r

, d. {: p; u& b2 h
  1. #define ERR_INFO "\r\nEnter HardFault_Handler, System Halt.\r\n"6 N( C8 |5 [% B4 @: W- V+ i0 b

  2. 8 E0 ^" K4 u5 Q% ]- _
  3. #if 1
    . A# o/ K5 P$ o0 _8 l; G
  4. {
    & b! W9 {0 ~1 l% ~
  5.         const char *pError = ERR_INFO;
    8 I! L% n+ ]: M+ ^2 j
  6.         uint8_t i;- D, K+ [! U  r
  7. % Q, y! u5 l4 L* c
  8.         for (i = 0; i < strlen(ERR_INFO); i++)9 W7 l: w$ a' p' i
  9.         {6 D5 N% I& e* x) ]( @3 G
  10.                 USART1->TDR = pError<i>;
    ( H. U9 Q2 S6 N# W% [8 o1 e
  11.                 /* 等待发送结束 */$ T2 u8 e1 \% T% d
  12.               </i>  while((USART1->ISR & USART_ISR_TC) == 0);
    + c$ g& [' F1 b6 `4 U
  13.         }        # ]; x. c* w6 N  B- i
  14. }
    0 B$ G9 }  _& i& f) h
  15. #endif
复制代码
9 E, r) [6 F  V( [
11.3 MDK锁定硬件异常位置方法; N8 N% x+ I8 w" L* c: b$ @! |" _
以本章配套的例子为大家做个说明。( M7 b3 H  w& x$ |7 k% j% @( D& K) d

% B7 `2 Y! R/ w9 V" R6 Y- a/ f1、测试方法比较简单,进入调试状态,全速运行,然后按下K1按键,就会进入硬件异常中断,此时停止调试,程序就会自动定位到如下位置:& u+ }9 S& C/ K# m8 |

6 y. [$ @: n) b: \9 K
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png

& F1 X/ L/ h- @7 e9 w  E  O4 `6 V* \1 }6 R  a6 ]9 j! r
2、在Watch1窗口添加变量_Continue
' `, T- S' ^, h. X) H+ T& d2 y- D' t0 U/ R: ^
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png

3 t2 ~* \0 n2 J1 L! t8 ^
+ }( I2 Y5 G+ f0 x- e- ~9 C0 B6 @3、修改为任何非0数值,就可以继续单步调试。这个代码后面还有一个第1步中的while循环,也可以继续采用第2步的方法修改。退出硬件异常后就是大家进入硬件异常前下一条要执行的指令(可能还是这个函数本身,因为一个函数由多个指令完成)。定位到出问题的位置:/ q. w- \  B- G- E- C/ `, G
4 \1 |( F5 U" K/ ~6 e# m
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png

  [, n/ U) A, v; c
# s1 H/ P: L8 r$ j11.4 IAR锁定硬件异常位置方法

6 q+ ^# \/ u5 J7 @. U以本章配套的例子为大家做个说明。
* T' w. h- V0 C1 U* a3 c1 i8 e% g
1 s- p' a9 E! F5 T: Q2 B$ n. J1、测试方法比较简单,进入调试状态,全速运行,然后按下K1按键,就会进入硬件异常中断,此时停止调试,程序就会自动定位到如下位置:
6 ?/ ]" Q( k1 p  c' l$ v) W* h: z' }. t: ^: q/ I1 m
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png

) W* C" \" k1 P4 {
  j& e8 o+ b+ `- V4 j( ~/ B2、在Watch1窗口添加变量_Continue7 z: ]# L) q0 E* m8 _2 ^
0 I$ b6 B! u, J( r6 s& h6 p; v2 k& K
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png

* A% |/ s3 t+ E5 X# H. v# E( {9 B, T- _
3、修改为任何非0数值,就可以继续单步调试。这个代码后面还有一个第1步中的while循环,也可以继续采用第2步的方法修改。退出硬件异常后就是大家进入硬件异常前下一条要执行的指令(可能还是这个函数本身,因为一个函数由多个指令完成)。定位到出问题的位置:% d: R2 S3 {: U/ _2 A2 u

0 V$ C0 M4 D* n! Y
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png
! U9 S) @: ]& [4 x
/ `  U. U9 u2 r# E# ~, S
11.5 硬件异常原因分析
+ a. M! \  |7 [7 A; w( ]/ q1 KSEGGER提供的这个机制查找出问题的位置比较方便,具体原因需要继续在调试界面里面添加HardFaultRegs结构变量,这个结构体变量添加了所有大家想看的东西。下面是MDK调试状态查看部分结构体数值:
7 s. @9 A' p: m0 _# f! ?  C
# h$ m# B4 a- C# t- a" G1 l; ^
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png
! D9 `8 v7 b4 B/ O5 }) v
" Y% h/ k5 c: L& J3 C) W' V
具体上面的变量代表什么含义呢,代码里面有注释,查阅起来没有IAR自带的硬件异常提示方便(注意,下面的代码用到了位域)。
) n+ f+ B- i& d! a8 F0 Y% b" m5 l) n3 A3 }% Z: j
  1. #if DEBUG- A* W3 j. E6 I: r) k; h, B* }- J
  2. static volatile unsigned int _Continue;  // Set this variable to 1 to run further
    , E! G6 X* g& i" E0 p

  3. 8 f" F4 v; \% O7 W
  4. static struct {
    * O' A. u9 Q5 y8 X4 Q
  5.   struct {
      ?$ O: W6 o# N4 }
  6.     volatile unsigned int r0;            // Register R0
    $ _" M: w% T3 H5 f" q  F; o+ L) |
  7.     volatile unsigned int r1;            // Register R1
    & a  o. p/ G8 D
  8.     volatile unsigned int r2;            // Register R2+ \" z; G, w$ t, H4 t- M8 e- K
  9.     volatile unsigned int r3;            // Register R3  _& V% t- _' s9 D: I+ I9 o/ u
  10.     volatile unsigned int r12;           // Register R12# `, o  L0 Q4 T  i8 e. h; K
  11.     volatile unsigned int lr;            // Link register# W. B; H6 H+ a- l' H: E$ u& K
  12.     volatile unsigned int pc;            // Program counter
    & ]) l  }  j% \1 k  j6 h
  13.     union {
    $ n! @: S$ T2 K5 \; O4 b
  14.       volatile unsigned int byte;
    2 H! @, U, N4 G& D5 q
  15.       struct {
    $ C' e0 Y6 [: V4 Y: n
  16.         unsigned int IPSR : 8;           // Interrupt Program Status register (IPSR)
    6 ?  S9 G" |5 a, P
  17.         unsigned int EPSR : 19;          // Execution Program Status register (EPSR)( p  T1 |+ S8 `  u; Z
  18.         unsigned int APSR : 5;           // Application Program Status register (APSR)1 l- ^. }2 S& V7 a$ B
  19.       } bits;
    & F  R, i8 A& K- q8 g2 v; ?
  20.     } psr;                               // Program status register./ D: ]  ?8 f$ q
  21.   } SavedRegs;
    , z, ]" X  o0 B/ ?: l4 S3 X
  22. : o4 J6 {% w2 M* O) ?3 I
  23.   union {
    ! p4 d" [; Q4 `4 i! I
  24.     volatile unsigned int byte;  V$ r" [/ m  F3 [5 r! F
  25.     struct {
    - z. Z% h. h" P% M! S4 R% u
  26.       unsigned int MEMFAULTACT    : 1;   // Read as 1 if memory management fault is active  U6 z: ~- n0 w* ?' a8 Z
  27.       unsigned int BUSFAULTACT    : 1;   // Read as 1 if bus fault exception is active
    : i( ^& n# r3 T. K+ \4 t
  28.       unsigned int UnusedBits1    : 1;+ w1 e% Q+ N! e8 G. j$ S  _- r
  29.       unsigned int USGFAULTACT    : 1;   // Read as 1 if usage fault exception is active3 j! I4 c2 A8 Y
  30.       unsigned int UnusedBits2    : 3;4 @8 G; q! w$ r/ h. Y5 a7 B* Y
  31.       unsigned int SVCALLACT      : 1;   // Read as 1 if SVC exception is active
    ! I, `/ C% O1 b
  32.       unsigned int MONITORACT     : 1;   // Read as 1 if debug monitor exception is active
    1 u0 y# v4 M7 B8 V
  33.       unsigned int UnusedBits3    : 1;
    8 @. ~. X+ M+ p& ?& [: |
  34.       unsigned int PENDSVACT      : 1;   // Read as 1 if PendSV exception is active9 d% o% E9 ~% K% T. Y1 |
  35.       unsigned int SYSTICKACT     : 1;   // Read as 1 if SYSTICK exception is active
    / R4 _: z2 S* [) h
  36.       unsigned int USGFAULTPENDED : 1;   // Usage fault pended; usage fault started but was replaced by a! Z" u3 k+ [7 C' W9 U
  37. higher-priority exception
    3 y5 R$ k, `/ E: V& V9 T3 k
  38.       unsigned int MEMFAULTPENDED : 1;   //  Memory management fault pended; memory management fault started( n$ Y9 M, |$ }' l  o* q. _
  39. but was replaced by a higher-priority exception! f1 L) E5 k; \7 |$ v
  40.       unsigned int BUSFAULTPENDED : 1;   // Bus fault pended; bus fault handler was started but was replaced4 p+ R  X) T  N9 g1 L3 T
  41. by a higher-priority exception
    8 G: S. W* K! _' M* z" Y
  42.       unsigned int SVCALLPENDED   : 1;   // SVC pended; SVC was started but was replaced by a higher-priority4 {4 K  b5 r+ j+ L+ b2 J
  43. exception
    % J& z7 P  w% V  B6 e; I7 I
  44.       unsigned int MEMFAULTENA    : 1;   // Memory management fault handler enable$ u/ X, @9 R1 ~4 h) D% Y7 d9 d
  45.       unsigned int BUSFAULTENA    : 1;   // Bus fault handler enable( x4 ^2 b7 U3 x9 C5 @6 G
  46.       unsigned int USGFAULTENA    : 1;   // Usage fault handler enable, R  f& e5 r, j- G. d2 [- I, C6 a, T
  47.     } bits;
    # J! s+ H* J  }4 p  r: Z9 g
  48.   } syshndctrl;                          // System Handler Control and State Register (0xE000ED24)5 @1 A3 s9 ]7 w# V3 H' F) _

  49. 4 k1 f) Q9 \: r$ T
  50.   /* 省略未写 */
    ; @& ~$ @( L# w

  51. / Z6 s9 M" q6 @: H* d( J$ V
  52.   volatile unsigned int afsr;            // Auxiliary Fault Status Register (0xE000ED3C), Vendor controlled (optional)
    + W) h( e, t8 a) j$ I
  53. } HardFaultRegs;
    9 J5 x4 I7 L7 a1 t4 t
  54. #endif
复制代码
5 [7 o/ J1 p0 ~5 t; z" P
11.6 IAR自带的硬件异常分析
& n, w# S9 k9 E  A8 J还以本章配套的例子为例,进入调试状态,全速运行,然后按下K1按键,就会进入硬件异常中断,此时停止调试,IAR还会弹出一个硬件异常错误分析,刚进来的时候也许是个空白- Z! n7 F! }, F* m- i" N
  q( o5 ^. s, h, a7 n$ |. [
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png
& H% k# \/ I( c( H) h4 g
: L# n6 x% V, h& o) D% r, L+ z
单步调试刷新下就出来了:
0 @: J4 C( p( p: p1 o% j* ?6 T/ V
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2Jsb2cvMTM3OTEwNy8yMDE5MDQvMTM3OTEwNy0yMDE5.png
( N5 V/ j9 I3 q) v

5 }$ \" R2 {. s& |" q! O指出了问题的原因是操作的数据地址有问题。' F8 M1 _! I1 [5 d; v
0 f  Q' |% m6 U  Y
11.7 实验例程; L+ w( D0 l! d
专门为本章节配套了一个例子:V7-009_移植SEGGER的硬件异常分析机制。大家可以按照本章教程提供的方法进行测试。# M- S7 q) N1 A. b7 J) \
: a+ {, r* }5 [
11.8 总结, w2 e3 N1 q* U% J( c
除了SEGGER的硬件异常分析方案,建议也测试下MDK和IAR的,以后遇到硬件异常问题,解决起来可以得心应手。* P2 X! g/ f! L; I$ ~
" w2 w1 F# ]" c9 f
: b( C2 ^% J& G4 w% y, M
赞 收藏 评论0 发布时间:2022-1-1 20:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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