瀏覽代碼

[add] addr2line

rtthread_MCoreDump
huangyulong 2 月之前
父節點
當前提交
5fbd0ef37a

+ 6
- 0
EWARM/stm32_broad_mini.ewp 查看文件

@@ -1236,6 +1236,12 @@
1236 1236
         </group>
1237 1237
         <group>
1238 1238
             <name>MCoreDump</name>
1239
+            <group>
1240
+                <name>addr2line</name>
1241
+                <file>
1242
+                    <name>$PROJ_DIR$\..\Middlewares\MCoreDump\addr2line\addr2line.c</name>
1243
+                </file>
1244
+            </group>
1239 1245
             <group>
1240 1246
                 <name>arch</name>
1241 1247
                 <file>

+ 579
- 0
Middlewares/MCoreDump/addr2line.c 查看文件

@@ -0,0 +1,579 @@
1
+#include "addr2line.h"
2
+
3
+// 错误类型打印
4
+#define DUMP_CPU_ARM_CORTEX_M0          0
5
+#define DUMP_CPU_ARM_CORTEX_M3          1
6
+#define DUMP_CPU_ARM_CORTEX_M4          2
7
+#define DUMP_CPU_ARM_CORTEX_M7          3
8
+
9
+#define DUMP_CPU_PLATFORM_TYPE      DUMP_CPU_ARM_CORTEX_M4
10
+
11
+/* system handler control and state register */
12
+#ifndef DUMP_SYSHND_CTRL
13
+    #define DUMP_SYSHND_CTRL                (*(volatile unsigned int*)  (0xE000ED24u))
14
+#endif
15
+
16
+/* memory management fault status register */
17
+#ifndef DUMP_NVIC_MFSR
18
+    #define DUMP_NVIC_MFSR                  (*(volatile unsigned char*) (0xE000ED28u))
19
+#endif
20
+
21
+/* bus fault status register */
22
+#ifndef DUMP_NVIC_BFSR
23
+    #define DUMP_NVIC_BFSR                  (*(volatile unsigned char*) (0xE000ED29u))
24
+#endif
25
+
26
+/* usage fault status register */
27
+#ifndef DUMP_NVIC_UFSR
28
+    #define DUMP_NVIC_UFSR                  (*(volatile unsigned short*)(0xE000ED2Au))
29
+#endif
30
+
31
+/* hard fault status register */
32
+#ifndef DUMP_NVIC_HFSR
33
+    #define DUMP_NVIC_HFSR                  (*(volatile unsigned int*)  (0xE000ED2Cu))
34
+#endif
35
+
36
+/* debug fault status register */
37
+#ifndef DUMP_NVIC_DFSR
38
+    #define DUMP_NVIC_DFSR                  (*(volatile unsigned short*)(0xE000ED30u))
39
+#endif
40
+
41
+/* memory management fault address register */
42
+#ifndef DUMP_NVIC_MMAR
43
+    #define DUMP_NVIC_MMAR                  (*(volatile unsigned int*)  (0xE000ED34u))
44
+#endif
45
+
46
+/* bus fault manage address register */
47
+#ifndef DUMP_NVIC_BFAR
48
+    #define DUMP_NVIC_BFAR                  (*(volatile unsigned int*)  (0xE000ED38u))
49
+#endif
50
+
51
+/* auxiliary fault status register */
52
+#ifndef DUMP_NVIC_AFSR
53
+    #define DUMP_NVIC_AFSR                  (*(volatile unsigned short*)(0xE000ED3Cu))
54
+#endif
55
+
56
+/**
57
+ * Cortex-M fault registers
58
+ */
59
+struct dump_hard_fault_regs
60
+{
61
+    struct
62
+    {
63
+        unsigned int r0;                 // Register R0
64
+        unsigned int r1;                 // Register R1
65
+        unsigned int r2;                 // Register R2
66
+        unsigned int r3;                 // Register R3
67
+        unsigned int r12;                // Register R12
68
+        unsigned int lr;                 // Link register
69
+        unsigned int pc;                 // Program counter
70
+        union
71
+        {
72
+            unsigned int value;
73
+            struct
74
+            {
75
+                unsigned int IPSR : 8;   // Interrupt Program Status register (IPSR)
76
+                unsigned int EPSR : 19;  // Execution Program Status register (EPSR)
77
+                unsigned int APSR : 5;   // Application Program Status register (APSR)
78
+            } bits;
79
+        } psr;                           // Program status register.
80
+    } saved;
81
+
82
+    union
83
+    {
84
+        unsigned int value;
85
+        struct
86
+        {
87
+            unsigned int MEMFAULTACT    : 1; // Read as 1 if memory management fault is active
88
+            unsigned int BUSFAULTACT    : 1; // Read as 1 if bus fault exception is active
89
+            unsigned int UnusedBits1    : 1;
90
+            unsigned int USGFAULTACT    : 1; // Read as 1 if usage fault exception is active
91
+            unsigned int UnusedBits2    : 3;
92
+            unsigned int SVCALLACT      : 1; // Read as 1 if SVC exception is active
93
+            unsigned int MONITORACT     : 1; // Read as 1 if debug monitor exception is active
94
+            unsigned int UnusedBits3    : 1;
95
+            unsigned int PENDSVACT      : 1; // Read as 1 if PendSV exception is active
96
+            unsigned int SYSTICKACT     : 1; // Read as 1 if SYSTICK exception is active
97
+            unsigned int USGFAULTPENDED : 1; // Usage fault pended; usage fault started but was replaced by a higher-priority exception
98
+            unsigned int MEMFAULTPENDED : 1; // Memory management fault pended; memory management fault started but was replaced by a higher-priority exception
99
+            unsigned int BUSFAULTPENDED : 1; // Bus fault pended; bus fault handler was started but was replaced by a higher-priority exception
100
+            unsigned int SVCALLPENDED   : 1; // SVC pended; SVC was started but was replaced by a higher-priority exception
101
+            unsigned int MEMFAULTENA    : 1; // Memory management fault handler enable
102
+            unsigned int BUSFAULTENA    : 1; // Bus fault handler enable
103
+            unsigned int USGFAULTENA    : 1; // Usage fault handler enable
104
+        } bits;
105
+    } syshndctrl;                        // System Handler Control and State Register (0xE000ED24)
106
+
107
+    union
108
+    {
109
+        unsigned char value;
110
+        struct
111
+        {
112
+            unsigned char IACCVIOL    : 1; // Instruction access violation
113
+            unsigned char DACCVIOL    : 1; // Data access violation
114
+            unsigned char UnusedBits  : 1;
115
+            unsigned char MUNSTKERR   : 1; // Unstacking error
116
+            unsigned char MSTKERR     : 1; // Stacking error
117
+            unsigned char MLSPERR     : 1; // Floating-point lazy state preservation (M4/M7)
118
+            unsigned char UnusedBits2 : 1;
119
+            unsigned char MMARVALID   : 1; // Indicates the MMAR is valid
120
+        } bits;
121
+    } mfsr;                              // Memory Management Fault Status Register (0xE000ED28)
122
+    unsigned int mmar;                   // Memory Management Fault Address Register (0xE000ED34)
123
+
124
+    union
125
+    {
126
+        unsigned char value;
127
+        struct
128
+        {
129
+            unsigned char IBUSERR    : 1; // Instruction access violation
130
+            unsigned char PRECISERR  : 1; // Precise data access violation
131
+            unsigned char IMPREISERR : 1; // Imprecise data access violation
132
+            unsigned char UNSTKERR   : 1; // Unstacking error
133
+            unsigned char STKERR     : 1; // Stacking error
134
+            unsigned char LSPERR     : 1; // Floating-point lazy state preservation (M4/M7)
135
+            unsigned char UnusedBits : 1;
136
+            unsigned char BFARVALID  : 1; // Indicates BFAR is valid
137
+        } bits;
138
+    } bfsr;                              // Bus Fault Status Register (0xE000ED29)
139
+    unsigned int bfar;                   // Bus Fault Manage Address Register (0xE000ED38)
140
+
141
+    union
142
+    {
143
+        unsigned short value;
144
+        struct
145
+        {
146
+            unsigned short UNDEFINSTR : 1; // Attempts to execute an undefined instruction
147
+            unsigned short INVSTATE   : 1; // Attempts to switch to an invalid state (e.g., ARM)
148
+            unsigned short INVPC      : 1; // Attempts to do an exception with a bad value in the EXC_RETURN number
149
+            unsigned short NOCP       : 1; // Attempts to execute a coprocessor instruction
150
+            unsigned short UnusedBits : 4;
151
+            unsigned short UNALIGNED  : 1; // Indicates that an unaligned access fault has taken place
152
+            unsigned short DIVBYZERO0 : 1; // Indicates a divide by zero has taken place (can be set only if DIV_0_TRP is set)
153
+        } bits;
154
+    } ufsr;                              // Usage Fault Status Register (0xE000ED2A)
155
+
156
+    union
157
+    {
158
+        unsigned int value;
159
+        struct
160
+        {
161
+            unsigned int UnusedBits  : 1;
162
+            unsigned int VECTBL      : 1; // Indicates hard fault is caused by failed vector fetch
163
+            unsigned int UnusedBits2 : 28;
164
+            unsigned int FORCED      : 1; // Indicates hard fault is taken because of bus fault/memory management fault/usage fault
165
+            unsigned int DEBUGEVT    : 1; // Indicates hard fault is triggered by debug event
166
+        } bits;
167
+    } hfsr;                              // Hard Fault Status Register (0xE000ED2C)
168
+
169
+    union
170
+    {
171
+        unsigned int value;
172
+        struct
173
+        {
174
+            unsigned int HALTED   : 1;   // Halt requested in NVIC
175
+            unsigned int BKPT     : 1;   // BKPT instruction executed
176
+            unsigned int DWTTRAP  : 1;   // DWT match occurred
177
+            unsigned int VCATCH   : 1;   // Vector fetch occurred
178
+            unsigned int EXTERNAL : 1;   // EDBGRQ signal asserted
179
+        } bits;
180
+    } dfsr;                              // Debug Fault Status Register (0xE000ED30)
181
+
182
+    unsigned int afsr;                   // Auxiliary Fault Status Register (0xE000ED3C), Vendor controlled (optional)
183
+};
184
+
185
+enum
186
+{
187
+    PRINT_MAIN_STACK_CFG_ERROR,
188
+    PRINT_FIRMWARE_INFO,
189
+    PRINT_ASSERT_ON_THREAD,
190
+    PRINT_ASSERT_ON_HANDLER,
191
+    PRINT_THREAD_STACK_INFO,
192
+    PRINT_MAIN_STACK_INFO,
193
+    PRINT_THREAD_STACK_OVERFLOW,
194
+    PRINT_MAIN_STACK_OVERFLOW,
195
+    PRINT_CALL_STACK_INFO,
196
+    PRINT_CALL_STACK_ERR,
197
+    PRINT_FAULT_ON_THREAD,
198
+    PRINT_FAULT_ON_HANDLER,
199
+    PRINT_REGS_TITLE,
200
+    PRINT_HFSR_VECTBL,
201
+    PRINT_MFSR_IACCVIOL,
202
+    PRINT_MFSR_DACCVIOL,
203
+    PRINT_MFSR_MUNSTKERR,
204
+    PRINT_MFSR_MSTKERR,
205
+    PRINT_MFSR_MLSPERR,
206
+    PRINT_BFSR_IBUSERR,
207
+    PRINT_BFSR_PRECISERR,
208
+    PRINT_BFSR_IMPREISERR,
209
+    PRINT_BFSR_UNSTKERR,
210
+    PRINT_BFSR_STKERR,
211
+    PRINT_BFSR_LSPERR,
212
+    PRINT_UFSR_UNDEFINSTR,
213
+    PRINT_UFSR_INVSTATE,
214
+    PRINT_UFSR_INVPC,
215
+    PRINT_UFSR_NOCP,
216
+    PRINT_UFSR_UNALIGNED,
217
+    PRINT_UFSR_DIVBYZERO0,
218
+    PRINT_DFSR_HALTED,
219
+    PRINT_DFSR_BKPT,
220
+    PRINT_DFSR_DWTTRAP,
221
+    PRINT_DFSR_VCATCH,
222
+    PRINT_DFSR_EXTERNAL,
223
+    PRINT_MMAR,
224
+    PRINT_BFAR,
225
+};
226
+
227
+static const char *const print_info[] = {
228
+    [PRINT_MAIN_STACK_CFG_ERROR]  = "ERROR: Unable to get the main stack information, please check the configuration of the main stack\n",
229
+    [PRINT_FIRMWARE_INFO]         = "Firmware name: %s, hardware version: %s, software version: %s\n",
230
+    [PRINT_ASSERT_ON_THREAD]      = "Assert on thread %s\n",
231
+    [PRINT_ASSERT_ON_HANDLER]     = "Assert on interrupt or bare metal(no OS) environment\n",
232
+    [PRINT_THREAD_STACK_INFO]     = "===== Thread stack information =====\n",
233
+    [PRINT_MAIN_STACK_INFO]       = "====== Main stack information ======\n",
234
+    [PRINT_THREAD_STACK_OVERFLOW] = "Error: Thread stack(%08x) was overflow\n",
235
+    [PRINT_MAIN_STACK_OVERFLOW]   = "Error: Main stack(%08x) was overflow\n",
236
+    [PRINT_CALL_STACK_INFO]       = "Show more call stack info by run: addr2line -e %s%s -a -f %.*s\n",
237
+    [PRINT_CALL_STACK_ERR]        = "Dump call stack has an error\n",
238
+    [PRINT_FAULT_ON_THREAD]       = "Fault on thread %s\n",
239
+    [PRINT_FAULT_ON_HANDLER]      = "Fault on interrupt or bare metal(no OS) environment\n",
240
+    [PRINT_REGS_TITLE]            = "=================== Registers information ====================\n",
241
+    [PRINT_HFSR_VECTBL]           = "Hard fault is caused by failed vector fetch\n",
242
+    [PRINT_MFSR_IACCVIOL]         = "Memory management fault is caused by instruction access violation\n",
243
+    [PRINT_MFSR_DACCVIOL]         = "Memory management fault is caused by data access violation\n",
244
+    [PRINT_MFSR_MUNSTKERR]        = "Memory management fault is caused by unstacking error\n",
245
+    [PRINT_MFSR_MSTKERR]          = "Memory management fault is caused by stacking error\n",
246
+    [PRINT_MFSR_MLSPERR]          = "Memory management fault is caused by floating-point lazy state preservation\n",
247
+    [PRINT_BFSR_IBUSERR]          = "Bus fault is caused by instruction access violation\n",
248
+    [PRINT_BFSR_PRECISERR]        = "Bus fault is caused by precise data access violation\n",
249
+    [PRINT_BFSR_IMPREISERR]       = "Bus fault is caused by imprecise data access violation\n",
250
+    [PRINT_BFSR_UNSTKERR]         = "Bus fault is caused by unstacking error\n",
251
+    [PRINT_BFSR_STKERR]           = "Bus fault is caused by stacking error\n",
252
+    [PRINT_BFSR_LSPERR]           = "Bus fault is caused by floating-point lazy state preservation\n",
253
+    [PRINT_UFSR_UNDEFINSTR]       = "Usage fault is caused by attempts to execute an undefined instruction\n",
254
+    [PRINT_UFSR_INVSTATE]         = "Usage fault is caused by attempts to switch to an invalid state (e.g., ARM)\n",
255
+    [PRINT_UFSR_INVPC]            = "Usage fault is caused by attempts to do an exception with a bad value in the EXC_RETURN number\n",
256
+    [PRINT_UFSR_NOCP]             = "Usage fault is caused by attempts to execute a coprocessor instruction\n",
257
+    [PRINT_UFSR_UNALIGNED]        = "Usage fault is caused by indicates that an unaligned access fault has taken place\n",
258
+    [PRINT_UFSR_DIVBYZERO0]       = "Usage fault is caused by Indicates a divide by zero has taken place (can be set only if DIV_0_TRP is set)\n",
259
+    [PRINT_DFSR_HALTED]           = "Debug fault is caused by halt requested in NVIC\n",
260
+    [PRINT_DFSR_BKPT]             = "Debug fault is caused by BKPT instruction executed\n",
261
+    [PRINT_DFSR_DWTTRAP]          = "Debug fault is caused by DWT match occurred\n",
262
+    [PRINT_DFSR_VCATCH]           = "Debug fault is caused by Vector fetch occurred\n",
263
+    [PRINT_DFSR_EXTERNAL]         = "Debug fault is caused by EDBGRQ signal asserted\n",
264
+    [PRINT_MMAR]                  = "The memory management fault occurred address is %08x\n",
265
+    [PRINT_BFAR]                  = "The bus fault occurred address is %08x\n",
266
+};
267
+
268
+static struct dump_hard_fault_regs regs;
269
+
270
+#if (DUMP_CPU_PLATFORM_TYPE != DUMP_CPU_ARM_CORTEX_M0)
271
+/**
272
+ * fault diagnosis then print cause of fault
273
+ */
274
+static void fault_diagnosis(void)
275
+{
276
+    if (regs.hfsr.bits.VECTBL)
277
+    {
278
+        addr2line_print(print_info[PRINT_HFSR_VECTBL]);
279
+    }
280
+    if (regs.hfsr.bits.FORCED)
281
+    {
282
+        /* Memory Management Fault */
283
+        if (regs.mfsr.value)
284
+        {
285
+            if (regs.mfsr.bits.IACCVIOL)
286
+            {
287
+                addr2line_print(print_info[PRINT_MFSR_IACCVIOL]);
288
+            }
289
+            if (regs.mfsr.bits.DACCVIOL)
290
+            {
291
+                addr2line_print(print_info[PRINT_MFSR_DACCVIOL]);
292
+            }
293
+            if (regs.mfsr.bits.MUNSTKERR)
294
+            {
295
+                addr2line_print(print_info[PRINT_MFSR_MUNSTKERR]);
296
+            }
297
+            if (regs.mfsr.bits.MSTKERR)
298
+            {
299
+                addr2line_print(print_info[PRINT_MFSR_MSTKERR]);
300
+            }
301
+
302
+#if (DUMP_CPU_PLATFORM_TYPE == DUMP_CPU_ARM_CORTEX_M4) || (DUMP_CPU_PLATFORM_TYPE == DUMP_CPU_ARM_CORTEX_M7)
303
+            if (regs.mfsr.bits.MLSPERR)
304
+            {
305
+                addr2line_print(print_info[PRINT_MFSR_MLSPERR]);
306
+            }
307
+#endif
308
+
309
+            if (regs.mfsr.bits.MMARVALID)
310
+            {
311
+                if (regs.mfsr.bits.IACCVIOL || regs.mfsr.bits.DACCVIOL)
312
+                {
313
+                    addr2line_print(print_info[PRINT_MMAR], regs.mmar);
314
+                }
315
+            }
316
+        }
317
+        /* Bus Fault */
318
+        if (regs.bfsr.value)
319
+        {
320
+            if (regs.bfsr.bits.IBUSERR)
321
+            {
322
+                addr2line_print(print_info[PRINT_BFSR_IBUSERR]);
323
+            }
324
+            if (regs.bfsr.bits.PRECISERR)
325
+            {
326
+                addr2line_print(print_info[PRINT_BFSR_PRECISERR]);
327
+            }
328
+            if (regs.bfsr.bits.IMPREISERR)
329
+            {
330
+                addr2line_print(print_info[PRINT_BFSR_IMPREISERR]);
331
+            }
332
+            if (regs.bfsr.bits.UNSTKERR)
333
+            {
334
+                addr2line_print(print_info[PRINT_BFSR_UNSTKERR]);
335
+            }
336
+            if (regs.bfsr.bits.STKERR)
337
+            {
338
+                addr2line_print(print_info[PRINT_BFSR_STKERR]);
339
+            }
340
+
341
+#if (DUMP_CPU_PLATFORM_TYPE == DUMP_CPU_ARM_CORTEX_M4) || (DUMP_CPU_PLATFORM_TYPE == DUMP_CPU_ARM_CORTEX_M7)
342
+            if (regs.bfsr.bits.LSPERR)
343
+            {
344
+                addr2line_print(print_info[PRINT_BFSR_LSPERR]);
345
+            }
346
+#endif
347
+
348
+            if (regs.bfsr.bits.BFARVALID)
349
+            {
350
+                if (regs.bfsr.bits.PRECISERR)
351
+                {
352
+                    addr2line_print(print_info[PRINT_BFAR], regs.bfar);
353
+                }
354
+            }
355
+
356
+        }
357
+        /* Usage Fault */
358
+        if (regs.ufsr.value)
359
+        {
360
+            if (regs.ufsr.bits.UNDEFINSTR)
361
+            {
362
+                addr2line_print(print_info[PRINT_UFSR_UNDEFINSTR]);
363
+            }
364
+            if (regs.ufsr.bits.INVSTATE)
365
+            {
366
+                addr2line_print(print_info[PRINT_UFSR_INVSTATE]);
367
+            }
368
+            if (regs.ufsr.bits.INVPC)
369
+            {
370
+                addr2line_print(print_info[PRINT_UFSR_INVPC]);
371
+            }
372
+            if (regs.ufsr.bits.NOCP)
373
+            {
374
+                addr2line_print(print_info[PRINT_UFSR_NOCP]);
375
+            }
376
+            if (regs.ufsr.bits.UNALIGNED)
377
+            {
378
+                addr2line_print(print_info[PRINT_UFSR_UNALIGNED]);
379
+            }
380
+            if (regs.ufsr.bits.DIVBYZERO0)
381
+            {
382
+                addr2line_print(print_info[PRINT_UFSR_DIVBYZERO0]);
383
+            }
384
+        }
385
+    }
386
+    /* Debug Fault */
387
+    if (regs.hfsr.bits.DEBUGEVT)
388
+    {
389
+        if (regs.dfsr.value)
390
+        {
391
+            if (regs.dfsr.bits.HALTED)
392
+            {
393
+                addr2line_print(print_info[PRINT_DFSR_HALTED]);
394
+            }
395
+            if (regs.dfsr.bits.BKPT)
396
+            {
397
+                addr2line_print(print_info[PRINT_DFSR_BKPT]);
398
+            }
399
+            if (regs.dfsr.bits.DWTTRAP)
400
+            {
401
+                addr2line_print(print_info[PRINT_DFSR_DWTTRAP]);
402
+            }
403
+            if (regs.dfsr.bits.VCATCH)
404
+            {
405
+                addr2line_print(print_info[PRINT_DFSR_VCATCH]);
406
+            }
407
+            if (regs.dfsr.bits.EXTERNAL)
408
+            {
409
+                addr2line_print(print_info[PRINT_DFSR_EXTERNAL]);
410
+            }
411
+        }
412
+    }
413
+}
414
+#endif
415
+
416
+int coredump_fault_diagnosis(void)
417
+{
418
+    /* the Cortex-M0 is not support fault diagnosis */
419
+#if (DUMP_CPU_PLATFORM_TYPE != DUMP_CPU_ARM_CORTEX_M0)
420
+    regs.syshndctrl.value = DUMP_SYSHND_CTRL;  // System Handler Control and State Register
421
+    regs.mfsr.value       = DUMP_NVIC_MFSR;    // Memory Fault Status Register
422
+    regs.mmar             = DUMP_NVIC_MMAR;    // Memory Management Fault Address Register
423
+    regs.bfsr.value       = DUMP_NVIC_BFSR;    // Bus Fault Status Register
424
+    regs.bfar             = DUMP_NVIC_BFAR;    // Bus Fault Manage Address Register
425
+    regs.ufsr.value       = DUMP_NVIC_UFSR;    // Usage Fault Status Register
426
+    regs.hfsr.value       = DUMP_NVIC_HFSR;    // Hard Fault Status Register
427
+    regs.dfsr.value       = DUMP_NVIC_DFSR;    // Debug Fault Status Register
428
+    regs.afsr             = DUMP_NVIC_AFSR;    // Auxiliary Fault Status Register
429
+
430
+    fault_diagnosis();
431
+    return 0;
432
+#endif
433
+
434
+    return -1;
435
+}
436
+
437
+int addr2line_print_stack_before(uint32_t lr)
438
+{
439
+    int on_thread_before_fault = lr & (1UL << 2);
440
+    /* check which stack was used before (MSP or PSP) */
441
+    if (on_thread_before_fault)
442
+        addr2line_print(print_info[PRINT_FAULT_ON_THREAD], rt_thread_self()->name != NULL ? rt_thread_self()->name : "NO_NAME");
443
+    else
444
+        addr2line_print(print_info[PRINT_FAULT_ON_HANDLER]);
445
+
446
+    coredump_fault_diagnosis();
447
+    return 0;
448
+}
449
+
450
+void addr2line_trigger_exception(void)
451
+{
452
+    volatile int *SCB_CCR = (volatile int *)0xE000ED14; // SCB->CCR
453
+    int x, y, z;
454
+
455
+    *SCB_CCR |= (1 << 4);     /* bit4: DIV_0_TRP. */
456
+    x = 10;
457
+    y = strlen("");
458
+    z = x / y;
459
+    addr2line_print("z:%d\n", z);
460
+}
461
+
462
+
463
+// addr to line
464
+#include <stdbool.h>
465
+
466
+#pragma section = ".text"
467
+
468
+static bool is_in_text(uint32_t addr)
469
+{
470
+#if 0
471
+    uint32_t code_start_addr = (uint32_t)&CODE_SECTION_START(CMB_CODE_SECTION_NAME);
472
+    uint32_t code_size = (uint32_t)&CODE_SECTION_END(CMB_CODE_SECTION_NAME) - code_start_addr;
473
+#else
474
+    uint32_t code_start_addr = (uint32_t)__section_begin(".text");
475
+    uint32_t code_size = (uint32_t)__section_end(".text") - code_start_addr;
476
+#endif
477
+
478
+    if (code_start_addr < addr && addr <= code_start_addr + code_size)
479
+    {
480
+        return true;
481
+    }
482
+
483
+    return false;
484
+}
485
+
486
+static bool disassembly_ins_is_bl_blx(uint32_t addr)
487
+{
488
+#define BL_INS_MASK         0xF800
489
+#define BL_INS_HIGH         0xF800
490
+#define BL_INS_LOW          0xF000
491
+#define BLX_INX_MASK        0xFF00
492
+#define BLX_INX             0x4700
493
+
494
+    uint16_t ins1 = *((uint16_t *)addr);
495
+    uint16_t ins2 = *((uint16_t *)(addr + 2));
496
+
497
+    if ((ins2 & BL_INS_MASK) == BL_INS_HIGH && (ins1 & BL_INS_MASK) == BL_INS_LOW)
498
+    {
499
+        return true;
500
+    }
501
+    else if ((ins2 & BLX_INX_MASK) == BLX_INX)
502
+    {
503
+        return true;
504
+    }
505
+    else
506
+    {
507
+        return false;
508
+    }
509
+}
510
+
511
+void addr2line_print(uint32_t *addr, int size)
512
+{
513
+    addr2line_print("\naddr2line -e " PROJECT_NAME " -a -f ");
514
+    size /= sizeof(uint32_t);
515
+
516
+    for (int i = 1; i < size; i++)
517
+    {
518
+        const uint32_t lr = addr[i];
519
+
520
+        if (false == is_in_text(lr))
521
+            continue;
522
+
523
+        uint32_t pc = lr - sizeof(size_t); // 假设当前是lr寄存器的值,向下增长4就是pc寄存器的值
524
+
525
+        if (pc % 2 == 0) // thumb 指令pc寄存器值一定是偶数
526
+            continue;
527
+
528
+        pc = lr - 1; // lr寄存器值保存的是pc+1
529
+
530
+        if (true == disassembly_ins_is_bl_blx(pc - sizeof(size_t))) // pc 的上一条指令是跳转指令
531
+            addr2line_print("%08x ", pc);
532
+    }
533
+
534
+    addr2line_print("\n");
535
+}
536
+
537
+#if 0
538
+static void test_addr2line(void)
539
+{
540
+    uint32_t sg_test_stack[] =
541
+    {
542
+        0x00000001, 0x000514d5, 0x000000f0, 0x00000001,
543
+        0x000c3fcc, 0x00000000, 0x000538b4, 0x00549822,
544
+        0xdeadbeef, 0x00000000, 0x00000000, 0x00000000,
545
+        0x00000000, 0x00000000, 0x00000000, 0x00000000,
546
+        0x00000000, 0x00000000, 0x00000000, 0x00000000,
547
+        0x00000000, 0x00000000, 0x00000000, 0x00000000,
548
+        0x00000000, 0x0000000a, 0x00000210, 0x00000000,
549
+        0x00000000, 0x00000006, 0x000514eb, 0x000516f8,
550
+        0x49000000, 0x00000004, 0x0000007d, 0x00000000,
551
+        0x00000000, 0x00000000, 0x00000000, 0x00000000,
552
+        0x00000000, 0x00000000, 0x00000000, 0x00000000,
553
+        0x00000000, 0x00000000, 0x00000000, 0x00000000,
554
+        0x00000000, 0x00000010, 0x00000000, 0x00000200,
555
+        0x00000000, 0x000008f4, 0x000537bb, 0x000000f0,
556
+        0x00000000, 0x00000001, 0x00000002, 0x20033378,
557
+        0x000468e3, 0x00000000, 0x20036c3c, 0x20036c78,
558
+        0x000b8789, 0x00000000, 0x20016dd8, 0x20008198,
559
+        0x000b819f, 0x00000000, 0x2003727c, 0x20016dd8,
560
+        0x0006047f, 0x00000050, 0x00000000, 0x20016dd8,
561
+        0x00000001, 0x00000001, 0x000604dd, 0x00000000,
562
+        0x2003092c, 0x20030b1c, 0x200334f4, 0x200334b4,
563
+        0x00060215, 0x2003764c, 0x20036e98, 0x00000008,
564
+        0x200081f4, 0x200334b4, 0x00000000, 0x0068007a,
565
+        0x00000000, 0x20030b1c, 0x00063dd3, 0x007a0068,
566
+        0x00000000, 0x00000000, 0x00000000, 0x00000000,
567
+        0xffffffff, 0x20033520, 0x2003060c, 0x2002cc84,
568
+        0x2002cbf4, 0x20033378, 0x0005ce35, 0x20030e20,
569
+        0x000d17c8, 0x20030214, 0x00000014, 0xdeadbeef,
570
+        0xdeadbeef, 0xdeadbeef, 0x00057c99, 0x00000000,
571
+        0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
572
+        0x000302e7
573
+    };
574
+
575
+    uint32_t *addr = sg_test_stack;
576
+    int size = sizeof(sg_test_stack);
577
+    _addr2line_print(addr, size);
578
+}
579
+#endif

+ 11
- 0
Middlewares/MCoreDump/addr2line.h 查看文件

@@ -0,0 +1,11 @@
1
+#ifndef ADDR2LINE_H
2
+#define ADDR2LINE_H
3
+
4
+// 触发一个异常
5
+void addr2line_trigger_exception(void);
6
+// 打印地址供CMD命令行运行
7
+void addr2line_print(uint32_t *addr, int size);
8
+// 打印异常错误类型
9
+int addr2line_print_stack_before(uint32_t exc_return);
10
+
11
+#endif

+ 596
- 0
Middlewares/MCoreDump/addr2line/addr2line.c 查看文件

@@ -0,0 +1,596 @@
1
+#include <stddef.h>
2
+#include <rtthread.h>
3
+#include "addr2line.h"
4
+
5
+#define PROJECT_NAME "project"
6
+#define addr2line_print rt_kprintf
7
+
8
+// 错误类型打印
9
+#define DUMP_CPU_ARM_CORTEX_M0          0
10
+#define DUMP_CPU_ARM_CORTEX_M3          1
11
+#define DUMP_CPU_ARM_CORTEX_M4          2
12
+#define DUMP_CPU_ARM_CORTEX_M7          3
13
+
14
+#define DUMP_CPU_PLATFORM_TYPE      DUMP_CPU_ARM_CORTEX_M4
15
+
16
+/* system handler control and state register */
17
+#ifndef DUMP_SYSHND_CTRL
18
+    #define DUMP_SYSHND_CTRL                (*(volatile unsigned int*)  (0xE000ED24u))
19
+#endif
20
+
21
+/* memory management fault status register */
22
+#ifndef DUMP_NVIC_MFSR
23
+    #define DUMP_NVIC_MFSR                  (*(volatile unsigned char*) (0xE000ED28u))
24
+#endif
25
+
26
+/* bus fault status register */
27
+#ifndef DUMP_NVIC_BFSR
28
+    #define DUMP_NVIC_BFSR                  (*(volatile unsigned char*) (0xE000ED29u))
29
+#endif
30
+
31
+/* usage fault status register */
32
+#ifndef DUMP_NVIC_UFSR
33
+    #define DUMP_NVIC_UFSR                  (*(volatile unsigned short*)(0xE000ED2Au))
34
+#endif
35
+
36
+/* hard fault status register */
37
+#ifndef DUMP_NVIC_HFSR
38
+    #define DUMP_NVIC_HFSR                  (*(volatile unsigned int*)  (0xE000ED2Cu))
39
+#endif
40
+
41
+/* debug fault status register */
42
+#ifndef DUMP_NVIC_DFSR
43
+    #define DUMP_NVIC_DFSR                  (*(volatile unsigned short*)(0xE000ED30u))
44
+#endif
45
+
46
+/* memory management fault address register */
47
+#ifndef DUMP_NVIC_MMAR
48
+    #define DUMP_NVIC_MMAR                  (*(volatile unsigned int*)  (0xE000ED34u))
49
+#endif
50
+
51
+/* bus fault manage address register */
52
+#ifndef DUMP_NVIC_BFAR
53
+    #define DUMP_NVIC_BFAR                  (*(volatile unsigned int*)  (0xE000ED38u))
54
+#endif
55
+
56
+/* auxiliary fault status register */
57
+#ifndef DUMP_NVIC_AFSR
58
+    #define DUMP_NVIC_AFSR                  (*(volatile unsigned short*)(0xE000ED3Cu))
59
+#endif
60
+
61
+/**
62
+ * Cortex-M fault registers
63
+ */
64
+struct dump_hard_fault_regs
65
+{
66
+    struct
67
+    {
68
+        unsigned int r0;                 // Register R0
69
+        unsigned int r1;                 // Register R1
70
+        unsigned int r2;                 // Register R2
71
+        unsigned int r3;                 // Register R3
72
+        unsigned int r12;                // Register R12
73
+        unsigned int lr;                 // Link register
74
+        unsigned int pc;                 // Program counter
75
+        union
76
+        {
77
+            unsigned int value;
78
+            struct
79
+            {
80
+                unsigned int IPSR : 8;   // Interrupt Program Status register (IPSR)
81
+                unsigned int EPSR : 19;  // Execution Program Status register (EPSR)
82
+                unsigned int APSR : 5;   // Application Program Status register (APSR)
83
+            } bits;
84
+        } psr;                           // Program status register.
85
+    } saved;
86
+
87
+    union
88
+    {
89
+        unsigned int value;
90
+        struct
91
+        {
92
+            unsigned int MEMFAULTACT    : 1; // Read as 1 if memory management fault is active
93
+            unsigned int BUSFAULTACT    : 1; // Read as 1 if bus fault exception is active
94
+            unsigned int UnusedBits1    : 1;
95
+            unsigned int USGFAULTACT    : 1; // Read as 1 if usage fault exception is active
96
+            unsigned int UnusedBits2    : 3;
97
+            unsigned int SVCALLACT      : 1; // Read as 1 if SVC exception is active
98
+            unsigned int MONITORACT     : 1; // Read as 1 if debug monitor exception is active
99
+            unsigned int UnusedBits3    : 1;
100
+            unsigned int PENDSVACT      : 1; // Read as 1 if PendSV exception is active
101
+            unsigned int SYSTICKACT     : 1; // Read as 1 if SYSTICK exception is active
102
+            unsigned int USGFAULTPENDED : 1; // Usage fault pended; usage fault started but was replaced by a higher-priority exception
103
+            unsigned int MEMFAULTPENDED : 1; // Memory management fault pended; memory management fault started but was replaced by a higher-priority exception
104
+            unsigned int BUSFAULTPENDED : 1; // Bus fault pended; bus fault handler was started but was replaced by a higher-priority exception
105
+            unsigned int SVCALLPENDED   : 1; // SVC pended; SVC was started but was replaced by a higher-priority exception
106
+            unsigned int MEMFAULTENA    : 1; // Memory management fault handler enable
107
+            unsigned int BUSFAULTENA    : 1; // Bus fault handler enable
108
+            unsigned int USGFAULTENA    : 1; // Usage fault handler enable
109
+        } bits;
110
+    } syshndctrl;                        // System Handler Control and State Register (0xE000ED24)
111
+
112
+    union
113
+    {
114
+        unsigned char value;
115
+        struct
116
+        {
117
+            unsigned char IACCVIOL    : 1; // Instruction access violation
118
+            unsigned char DACCVIOL    : 1; // Data access violation
119
+            unsigned char UnusedBits  : 1;
120
+            unsigned char MUNSTKERR   : 1; // Unstacking error
121
+            unsigned char MSTKERR     : 1; // Stacking error
122
+            unsigned char MLSPERR     : 1; // Floating-point lazy state preservation (M4/M7)
123
+            unsigned char UnusedBits2 : 1;
124
+            unsigned char MMARVALID   : 1; // Indicates the MMAR is valid
125
+        } bits;
126
+    } mfsr;                              // Memory Management Fault Status Register (0xE000ED28)
127
+    unsigned int mmar;                   // Memory Management Fault Address Register (0xE000ED34)
128
+
129
+    union
130
+    {
131
+        unsigned char value;
132
+        struct
133
+        {
134
+            unsigned char IBUSERR    : 1; // Instruction access violation
135
+            unsigned char PRECISERR  : 1; // Precise data access violation
136
+            unsigned char IMPREISERR : 1; // Imprecise data access violation
137
+            unsigned char UNSTKERR   : 1; // Unstacking error
138
+            unsigned char STKERR     : 1; // Stacking error
139
+            unsigned char LSPERR     : 1; // Floating-point lazy state preservation (M4/M7)
140
+            unsigned char UnusedBits : 1;
141
+            unsigned char BFARVALID  : 1; // Indicates BFAR is valid
142
+        } bits;
143
+    } bfsr;                              // Bus Fault Status Register (0xE000ED29)
144
+    unsigned int bfar;                   // Bus Fault Manage Address Register (0xE000ED38)
145
+
146
+    union
147
+    {
148
+        unsigned short value;
149
+        struct
150
+        {
151
+            unsigned short UNDEFINSTR : 1; // Attempts to execute an undefined instruction
152
+            unsigned short INVSTATE   : 1; // Attempts to switch to an invalid state (e.g., ARM)
153
+            unsigned short INVPC      : 1; // Attempts to do an exception with a bad value in the EXC_RETURN number
154
+            unsigned short NOCP       : 1; // Attempts to execute a coprocessor instruction
155
+            unsigned short UnusedBits : 4;
156
+            unsigned short UNALIGNED  : 1; // Indicates that an unaligned access fault has taken place
157
+            unsigned short DIVBYZERO0 : 1; // Indicates a divide by zero has taken place (can be set only if DIV_0_TRP is set)
158
+        } bits;
159
+    } ufsr;                              // Usage Fault Status Register (0xE000ED2A)
160
+
161
+    union
162
+    {
163
+        unsigned int value;
164
+        struct
165
+        {
166
+            unsigned int UnusedBits  : 1;
167
+            unsigned int VECTBL      : 1; // Indicates hard fault is caused by failed vector fetch
168
+            unsigned int UnusedBits2 : 28;
169
+            unsigned int FORCED      : 1; // Indicates hard fault is taken because of bus fault/memory management fault/usage fault
170
+            unsigned int DEBUGEVT    : 1; // Indicates hard fault is triggered by debug event
171
+        } bits;
172
+    } hfsr;                              // Hard Fault Status Register (0xE000ED2C)
173
+
174
+    union
175
+    {
176
+        unsigned int value;
177
+        struct
178
+        {
179
+            unsigned int HALTED   : 1;   // Halt requested in NVIC
180
+            unsigned int BKPT     : 1;   // BKPT instruction executed
181
+            unsigned int DWTTRAP  : 1;   // DWT match occurred
182
+            unsigned int VCATCH   : 1;   // Vector fetch occurred
183
+            unsigned int EXTERNAL : 1;   // EDBGRQ signal asserted
184
+        } bits;
185
+    } dfsr;                              // Debug Fault Status Register (0xE000ED30)
186
+
187
+    unsigned int afsr;                   // Auxiliary Fault Status Register (0xE000ED3C), Vendor controlled (optional)
188
+};
189
+
190
+enum
191
+{
192
+    PRINT_MAIN_STACK_CFG_ERROR,
193
+    PRINT_FIRMWARE_INFO,
194
+    PRINT_ASSERT_ON_THREAD,
195
+    PRINT_ASSERT_ON_HANDLER,
196
+    PRINT_THREAD_STACK_INFO,
197
+    PRINT_MAIN_STACK_INFO,
198
+    PRINT_THREAD_STACK_OVERFLOW,
199
+    PRINT_MAIN_STACK_OVERFLOW,
200
+    PRINT_CALL_STACK_INFO,
201
+    PRINT_CALL_STACK_ERR,
202
+    PRINT_FAULT_ON_THREAD,
203
+    PRINT_FAULT_ON_HANDLER,
204
+    PRINT_REGS_TITLE,
205
+    PRINT_HFSR_VECTBL,
206
+    PRINT_MFSR_IACCVIOL,
207
+    PRINT_MFSR_DACCVIOL,
208
+    PRINT_MFSR_MUNSTKERR,
209
+    PRINT_MFSR_MSTKERR,
210
+    PRINT_MFSR_MLSPERR,
211
+    PRINT_BFSR_IBUSERR,
212
+    PRINT_BFSR_PRECISERR,
213
+    PRINT_BFSR_IMPREISERR,
214
+    PRINT_BFSR_UNSTKERR,
215
+    PRINT_BFSR_STKERR,
216
+    PRINT_BFSR_LSPERR,
217
+    PRINT_UFSR_UNDEFINSTR,
218
+    PRINT_UFSR_INVSTATE,
219
+    PRINT_UFSR_INVPC,
220
+    PRINT_UFSR_NOCP,
221
+    PRINT_UFSR_UNALIGNED,
222
+    PRINT_UFSR_DIVBYZERO0,
223
+    PRINT_DFSR_HALTED,
224
+    PRINT_DFSR_BKPT,
225
+    PRINT_DFSR_DWTTRAP,
226
+    PRINT_DFSR_VCATCH,
227
+    PRINT_DFSR_EXTERNAL,
228
+    PRINT_MMAR,
229
+    PRINT_BFAR,
230
+};
231
+
232
+static const char *const print_info[] = {
233
+    [PRINT_MAIN_STACK_CFG_ERROR]  = "ERROR: Unable to get the main stack information, please check the configuration of the main stack\n",
234
+    [PRINT_FIRMWARE_INFO]         = "Firmware name: %s, hardware version: %s, software version: %s\n",
235
+    [PRINT_ASSERT_ON_THREAD]      = "Assert on thread %s\n",
236
+    [PRINT_ASSERT_ON_HANDLER]     = "Assert on interrupt or bare metal(no OS) environment\n",
237
+    [PRINT_THREAD_STACK_INFO]     = "===== Thread stack information =====\n",
238
+    [PRINT_MAIN_STACK_INFO]       = "====== Main stack information ======\n",
239
+    [PRINT_THREAD_STACK_OVERFLOW] = "Error: Thread stack(%08x) was overflow\n",
240
+    [PRINT_MAIN_STACK_OVERFLOW]   = "Error: Main stack(%08x) was overflow\n",
241
+    [PRINT_CALL_STACK_INFO]       = "Show more call stack info by run: addr2line -e %s%s -a -f %.*s\n",
242
+    [PRINT_CALL_STACK_ERR]        = "Dump call stack has an error\n",
243
+    [PRINT_FAULT_ON_THREAD]       = "Fault on thread %s\n",
244
+    [PRINT_FAULT_ON_HANDLER]      = "Fault on interrupt or bare metal(no OS) environment\n",
245
+    [PRINT_REGS_TITLE]            = "=================== Registers information ====================\n",
246
+    [PRINT_HFSR_VECTBL]           = "Hard fault is caused by failed vector fetch\n",
247
+    [PRINT_MFSR_IACCVIOL]         = "Memory management fault is caused by instruction access violation\n",
248
+    [PRINT_MFSR_DACCVIOL]         = "Memory management fault is caused by data access violation\n",
249
+    [PRINT_MFSR_MUNSTKERR]        = "Memory management fault is caused by unstacking error\n",
250
+    [PRINT_MFSR_MSTKERR]          = "Memory management fault is caused by stacking error\n",
251
+    [PRINT_MFSR_MLSPERR]          = "Memory management fault is caused by floating-point lazy state preservation\n",
252
+    [PRINT_BFSR_IBUSERR]          = "Bus fault is caused by instruction access violation\n",
253
+    [PRINT_BFSR_PRECISERR]        = "Bus fault is caused by precise data access violation\n",
254
+    [PRINT_BFSR_IMPREISERR]       = "Bus fault is caused by imprecise data access violation\n",
255
+    [PRINT_BFSR_UNSTKERR]         = "Bus fault is caused by unstacking error\n",
256
+    [PRINT_BFSR_STKERR]           = "Bus fault is caused by stacking error\n",
257
+    [PRINT_BFSR_LSPERR]           = "Bus fault is caused by floating-point lazy state preservation\n",
258
+    [PRINT_UFSR_UNDEFINSTR]       = "Usage fault is caused by attempts to execute an undefined instruction\n",
259
+    [PRINT_UFSR_INVSTATE]         = "Usage fault is caused by attempts to switch to an invalid state (e.g., ARM)\n",
260
+    [PRINT_UFSR_INVPC]            = "Usage fault is caused by attempts to do an exception with a bad value in the EXC_RETURN number\n",
261
+    [PRINT_UFSR_NOCP]             = "Usage fault is caused by attempts to execute a coprocessor instruction\n",
262
+    [PRINT_UFSR_UNALIGNED]        = "Usage fault is caused by indicates that an unaligned access fault has taken place\n",
263
+    [PRINT_UFSR_DIVBYZERO0]       = "Usage fault is caused by Indicates a divide by zero has taken place (can be set only if DIV_0_TRP is set)\n",
264
+    [PRINT_DFSR_HALTED]           = "Debug fault is caused by halt requested in NVIC\n",
265
+    [PRINT_DFSR_BKPT]             = "Debug fault is caused by BKPT instruction executed\n",
266
+    [PRINT_DFSR_DWTTRAP]          = "Debug fault is caused by DWT match occurred\n",
267
+    [PRINT_DFSR_VCATCH]           = "Debug fault is caused by Vector fetch occurred\n",
268
+    [PRINT_DFSR_EXTERNAL]         = "Debug fault is caused by EDBGRQ signal asserted\n",
269
+    [PRINT_MMAR]                  = "The memory management fault occurred address is %08x\n",
270
+    [PRINT_BFAR]                  = "The bus fault occurred address is %08x\n",
271
+};
272
+
273
+static struct dump_hard_fault_regs regs;
274
+
275
+#if (DUMP_CPU_PLATFORM_TYPE != DUMP_CPU_ARM_CORTEX_M0)
276
+/**
277
+ * fault diagnosis then print cause of fault
278
+ */
279
+static void fault_diagnosis(void)
280
+{
281
+    if (regs.hfsr.bits.VECTBL)
282
+    {
283
+        addr2line_print(print_info[PRINT_HFSR_VECTBL]);
284
+    }
285
+    if (regs.hfsr.bits.FORCED)
286
+    {
287
+        /* Memory Management Fault */
288
+        if (regs.mfsr.value)
289
+        {
290
+            if (regs.mfsr.bits.IACCVIOL)
291
+            {
292
+                addr2line_print(print_info[PRINT_MFSR_IACCVIOL]);
293
+            }
294
+            if (regs.mfsr.bits.DACCVIOL)
295
+            {
296
+                addr2line_print(print_info[PRINT_MFSR_DACCVIOL]);
297
+            }
298
+            if (regs.mfsr.bits.MUNSTKERR)
299
+            {
300
+                addr2line_print(print_info[PRINT_MFSR_MUNSTKERR]);
301
+            }
302
+            if (regs.mfsr.bits.MSTKERR)
303
+            {
304
+                addr2line_print(print_info[PRINT_MFSR_MSTKERR]);
305
+            }
306
+
307
+#if (DUMP_CPU_PLATFORM_TYPE == DUMP_CPU_ARM_CORTEX_M4) || (DUMP_CPU_PLATFORM_TYPE == DUMP_CPU_ARM_CORTEX_M7)
308
+            if (regs.mfsr.bits.MLSPERR)
309
+            {
310
+                addr2line_print(print_info[PRINT_MFSR_MLSPERR]);
311
+            }
312
+#endif
313
+
314
+            if (regs.mfsr.bits.MMARVALID)
315
+            {
316
+                if (regs.mfsr.bits.IACCVIOL || regs.mfsr.bits.DACCVIOL)
317
+                {
318
+                    addr2line_print(print_info[PRINT_MMAR], regs.mmar);
319
+                }
320
+            }
321
+        }
322
+        /* Bus Fault */
323
+        if (regs.bfsr.value)
324
+        {
325
+            if (regs.bfsr.bits.IBUSERR)
326
+            {
327
+                addr2line_print(print_info[PRINT_BFSR_IBUSERR]);
328
+            }
329
+            if (regs.bfsr.bits.PRECISERR)
330
+            {
331
+                addr2line_print(print_info[PRINT_BFSR_PRECISERR]);
332
+            }
333
+            if (regs.bfsr.bits.IMPREISERR)
334
+            {
335
+                addr2line_print(print_info[PRINT_BFSR_IMPREISERR]);
336
+            }
337
+            if (regs.bfsr.bits.UNSTKERR)
338
+            {
339
+                addr2line_print(print_info[PRINT_BFSR_UNSTKERR]);
340
+            }
341
+            if (regs.bfsr.bits.STKERR)
342
+            {
343
+                addr2line_print(print_info[PRINT_BFSR_STKERR]);
344
+            }
345
+
346
+#if (DUMP_CPU_PLATFORM_TYPE == DUMP_CPU_ARM_CORTEX_M4) || (DUMP_CPU_PLATFORM_TYPE == DUMP_CPU_ARM_CORTEX_M7)
347
+            if (regs.bfsr.bits.LSPERR)
348
+            {
349
+                addr2line_print(print_info[PRINT_BFSR_LSPERR]);
350
+            }
351
+#endif
352
+
353
+            if (regs.bfsr.bits.BFARVALID)
354
+            {
355
+                if (regs.bfsr.bits.PRECISERR)
356
+                {
357
+                    addr2line_print(print_info[PRINT_BFAR], regs.bfar);
358
+                }
359
+            }
360
+
361
+        }
362
+        /* Usage Fault */
363
+        if (regs.ufsr.value)
364
+        {
365
+            if (regs.ufsr.bits.UNDEFINSTR)
366
+            {
367
+                addr2line_print(print_info[PRINT_UFSR_UNDEFINSTR]);
368
+            }
369
+            if (regs.ufsr.bits.INVSTATE)
370
+            {
371
+                addr2line_print(print_info[PRINT_UFSR_INVSTATE]);
372
+            }
373
+            if (regs.ufsr.bits.INVPC)
374
+            {
375
+                addr2line_print(print_info[PRINT_UFSR_INVPC]);
376
+            }
377
+            if (regs.ufsr.bits.NOCP)
378
+            {
379
+                addr2line_print(print_info[PRINT_UFSR_NOCP]);
380
+            }
381
+            if (regs.ufsr.bits.UNALIGNED)
382
+            {
383
+                addr2line_print(print_info[PRINT_UFSR_UNALIGNED]);
384
+            }
385
+            if (regs.ufsr.bits.DIVBYZERO0)
386
+            {
387
+                addr2line_print(print_info[PRINT_UFSR_DIVBYZERO0]);
388
+            }
389
+        }
390
+    }
391
+    /* Debug Fault */
392
+    if (regs.hfsr.bits.DEBUGEVT)
393
+    {
394
+        if (regs.dfsr.value)
395
+        {
396
+            if (regs.dfsr.bits.HALTED)
397
+            {
398
+                addr2line_print(print_info[PRINT_DFSR_HALTED]);
399
+            }
400
+            if (regs.dfsr.bits.BKPT)
401
+            {
402
+                addr2line_print(print_info[PRINT_DFSR_BKPT]);
403
+            }
404
+            if (regs.dfsr.bits.DWTTRAP)
405
+            {
406
+                addr2line_print(print_info[PRINT_DFSR_DWTTRAP]);
407
+            }
408
+            if (regs.dfsr.bits.VCATCH)
409
+            {
410
+                addr2line_print(print_info[PRINT_DFSR_VCATCH]);
411
+            }
412
+            if (regs.dfsr.bits.EXTERNAL)
413
+            {
414
+                addr2line_print(print_info[PRINT_DFSR_EXTERNAL]);
415
+            }
416
+        }
417
+    }
418
+}
419
+#endif
420
+
421
+int coredump_fault_diagnosis(void)
422
+{
423
+    /* the Cortex-M0 is not support fault diagnosis */
424
+#if (DUMP_CPU_PLATFORM_TYPE != DUMP_CPU_ARM_CORTEX_M0)
425
+    regs.syshndctrl.value = DUMP_SYSHND_CTRL;  // System Handler Control and State Register
426
+    regs.mfsr.value       = DUMP_NVIC_MFSR;    // Memory Fault Status Register
427
+    regs.mmar             = DUMP_NVIC_MMAR;    // Memory Management Fault Address Register
428
+    regs.bfsr.value       = DUMP_NVIC_BFSR;    // Bus Fault Status Register
429
+    regs.bfar             = DUMP_NVIC_BFAR;    // Bus Fault Manage Address Register
430
+    regs.ufsr.value       = DUMP_NVIC_UFSR;    // Usage Fault Status Register
431
+    regs.hfsr.value       = DUMP_NVIC_HFSR;    // Hard Fault Status Register
432
+    regs.dfsr.value       = DUMP_NVIC_DFSR;    // Debug Fault Status Register
433
+    regs.afsr             = DUMP_NVIC_AFSR;    // Auxiliary Fault Status Register
434
+
435
+    fault_diagnosis();
436
+    return 0;
437
+#endif
438
+
439
+    return -1;
440
+}
441
+
442
+int addr2line_print_stack_before(uint32_t exc_return)
443
+{
444
+    int on_thread_before_fault = exc_return & (1UL << 2);
445
+    /* check which stack was used before (MSP or PSP) */
446
+    if (on_thread_before_fault)
447
+        addr2line_print(print_info[PRINT_FAULT_ON_THREAD], rt_thread_self()->name != NULL ? rt_thread_self()->name : "NO_NAME");
448
+    else
449
+        addr2line_print(print_info[PRINT_FAULT_ON_HANDLER]);
450
+
451
+    coredump_fault_diagnosis();
452
+    return 0;
453
+}
454
+
455
+void addr2line_trigger_exception(void)
456
+{
457
+    volatile int *SCB_CCR = (volatile int *)0xE000ED14; // SCB->CCR
458
+    int x, y, z;
459
+
460
+    *SCB_CCR |= (1 << 4);     /* bit4: DIV_0_TRP. */
461
+    x = 10;
462
+    y = strlen("");
463
+    z = x / y;
464
+    addr2line_print("z:%d\n", z);
465
+}
466
+
467
+
468
+// addr to line
469
+#include <stdbool.h>
470
+
471
+#pragma section = ".text"
472
+
473
+static bool is_in_text(uint32_t addr)
474
+{
475
+#if 0
476
+    uint32_t code_start_addr = (uint32_t)&CODE_SECTION_START(CMB_CODE_SECTION_NAME);
477
+    uint32_t code_size = (uint32_t)&CODE_SECTION_END(CMB_CODE_SECTION_NAME) - code_start_addr;
478
+#else
479
+    uint32_t code_start_addr = (uint32_t)__section_begin(".text");
480
+    uint32_t code_size = (uint32_t)__section_end(".text") - code_start_addr;
481
+#endif
482
+
483
+    if (code_start_addr < addr && addr <= code_start_addr + code_size)
484
+    {
485
+        return true;
486
+    }
487
+
488
+    return false;
489
+}
490
+
491
+static bool disassembly_ins_is_bl_blx(uint32_t addr)
492
+{
493
+#define BL_INS_MASK         0xF800
494
+#define BL_INS_HIGH         0xF800
495
+#define BL_INS_LOW          0xF000
496
+#define BLX_INX_MASK        0xFF00
497
+#define BLX_INX             0x4700
498
+
499
+    uint16_t ins1 = *((uint16_t *)addr);
500
+    uint16_t ins2 = *((uint16_t *)(addr + 2));
501
+
502
+    if ((ins2 & BL_INS_MASK) == BL_INS_HIGH && (ins1 & BL_INS_MASK) == BL_INS_LOW)
503
+    {
504
+        return true;
505
+    }
506
+    else if ((ins2 & BLX_INX_MASK) == BLX_INX)
507
+    {
508
+        return true;
509
+    }
510
+    else
511
+    {
512
+        return false;
513
+    }
514
+}
515
+
516
+void addr2line_cmd_with_pc_print(uint32_t *thread_pc, uint32_t *addr, int size)
517
+{
518
+    addr2line_print("addr2line -e " PROJECT_NAME " -a -f ");
519
+    size /= sizeof(uint32_t);
520
+
521
+    if (thread_pc)
522
+        addr2line_print("%08x ", thread_pc);
523
+
524
+    for (int i = 1; i < size; i++)
525
+    {
526
+        const uint32_t lr = addr[i];
527
+
528
+        if (false == is_in_text(lr))
529
+            continue;
530
+
531
+        uint32_t pc = lr - sizeof(size_t); // 假设当前是lr寄存器的值,向下增长4就是pc寄存器的值
532
+
533
+        if (pc % 2 == 0) // thumb 指令pc寄存器值一定是偶数
534
+            continue;
535
+        
536
+
537
+        pc = lr - 1; // lr寄存器值保存的是pc+1
538
+
539
+        if ((uint32_t)thread_pc == pc) // 忽略:已经指定打印过了
540
+            continue;
541
+
542
+        if (true == disassembly_ins_is_bl_blx(pc - sizeof(size_t))) // pc 的上一条指令是跳转指令
543
+            addr2line_print("%08x ", pc);
544
+    }
545
+
546
+    addr2line_print("\n\n");
547
+}
548
+
549
+void addr2line_cmd_print(uint32_t *addr, int size)
550
+{
551
+    addr2line_cmd_with_pc_print(NULL, addr, size);
552
+}
553
+
554
+#if 0
555
+static void test_addr2line(void)
556
+{
557
+    uint32_t sg_test_stack[] =
558
+    {
559
+        0x00000001, 0x000514d5, 0x000000f0, 0x00000001,
560
+        0x000c3fcc, 0x00000000, 0x000538b4, 0x00549822,
561
+        0xdeadbeef, 0x00000000, 0x00000000, 0x00000000,
562
+        0x00000000, 0x00000000, 0x00000000, 0x00000000,
563
+        0x00000000, 0x00000000, 0x00000000, 0x00000000,
564
+        0x00000000, 0x00000000, 0x00000000, 0x00000000,
565
+        0x00000000, 0x0000000a, 0x00000210, 0x00000000,
566
+        0x00000000, 0x00000006, 0x000514eb, 0x000516f8,
567
+        0x49000000, 0x00000004, 0x0000007d, 0x00000000,
568
+        0x00000000, 0x00000000, 0x00000000, 0x00000000,
569
+        0x00000000, 0x00000000, 0x00000000, 0x00000000,
570
+        0x00000000, 0x00000000, 0x00000000, 0x00000000,
571
+        0x00000000, 0x00000010, 0x00000000, 0x00000200,
572
+        0x00000000, 0x000008f4, 0x000537bb, 0x000000f0,
573
+        0x00000000, 0x00000001, 0x00000002, 0x20033378,
574
+        0x000468e3, 0x00000000, 0x20036c3c, 0x20036c78,
575
+        0x000b8789, 0x00000000, 0x20016dd8, 0x20008198,
576
+        0x000b819f, 0x00000000, 0x2003727c, 0x20016dd8,
577
+        0x0006047f, 0x00000050, 0x00000000, 0x20016dd8,
578
+        0x00000001, 0x00000001, 0x000604dd, 0x00000000,
579
+        0x2003092c, 0x20030b1c, 0x200334f4, 0x200334b4,
580
+        0x00060215, 0x2003764c, 0x20036e98, 0x00000008,
581
+        0x200081f4, 0x200334b4, 0x00000000, 0x0068007a,
582
+        0x00000000, 0x20030b1c, 0x00063dd3, 0x007a0068,
583
+        0x00000000, 0x00000000, 0x00000000, 0x00000000,
584
+        0xffffffff, 0x20033520, 0x2003060c, 0x2002cc84,
585
+        0x2002cbf4, 0x20033378, 0x0005ce35, 0x20030e20,
586
+        0x000d17c8, 0x20030214, 0x00000014, 0xdeadbeef,
587
+        0xdeadbeef, 0xdeadbeef, 0x00057c99, 0x00000000,
588
+        0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
589
+        0x000302e7
590
+    };
591
+
592
+    uint32_t *addr = sg_test_stack;
593
+    int size = sizeof(sg_test_stack);
594
+    _addr2line_print(addr, size);
595
+}
596
+#endif

+ 15
- 0
Middlewares/MCoreDump/addr2line/addr2line.h 查看文件

@@ -0,0 +1,15 @@
1
+#ifndef ADDR2LINE_H
2
+#define ADDR2LINE_H
3
+
4
+#include <stdint.h>
5
+
6
+// 触发一个异常
7
+void addr2line_trigger_exception(void);
8
+// 打印地址供CMD命令行运行
9
+void addr2line_cmd_print(uint32_t *addr, int size);
10
+// 指定pc,pc还没有在addr范围内的情况使用
11
+void addr2line_cmd_with_pc_print(uint32_t *thread_pc, uint32_t *addr, int size);
12
+// 打印异常错误类型
13
+int addr2line_print_stack_before(uint32_t lr);
14
+
15
+#endif

+ 6
- 0
Middlewares/MCoreDump/rtthread_port.c 查看文件

@@ -11,6 +11,7 @@
11 11
 #include <rtthread.h>
12 12
 #include "coredump.h"
13 13
 #include "arch/mcd_arch_interface.h"
14
+#include "addr2line/addr2line.h"
14 15
 
15 16
 #define PRINT_COREDUMP_INFO_STRING 1 // 打印字符串格式的coredump信息
16 17
 
@@ -216,6 +217,9 @@ static int mcd_print_coredump_info_string(struct thread_info_ops *ops)
216 217
                 }
217 218
 
218 219
                 print_registers((void *)get_cur_core_regset_address(), get_cur_fp_regset_address(), thread->name);
220
+#define STACK_FRAME_SIZE (17 * 4) // 17个寄存器
221
+                rt_uint32_t addr2 = (rt_uint32_t)thread->sp - STACK_FRAME_SIZE;
222
+                addr2line_cmd_with_pc_print((rt_uint32_t *)get_cur_core_regset_address()->pc, (uint32_t *)addr2, memlen + STACK_FRAME_SIZE);
219 223
             }
220 224
             else
221 225
             {
@@ -225,6 +229,7 @@ static int mcd_print_coredump_info_string(struct thread_info_ops *ops)
225 229
                 fp_regset_type fp_regset;
226 230
                 collect_registers((uint32_t *)thread->sp, &core_regset, &fp_regset); // rtos栈寄存器格式转换成core_regset类型的
227 231
                 print_registers(&core_regset, &fp_regset, thread->name);
232
+                addr2line_cmd_with_pc_print((rt_uint32_t *)core_regset.pc, (uint32_t *)addr, memlen);
228 233
             }
229 234
 
230 235
             print_mem(addr, memlen);
@@ -256,6 +261,7 @@ void mcd_rtos_thread_ops(struct thread_info_ops *ops)
256 261
 MCD_WEAK rt_err_t rtt_hard_fault_exception_hook(void *context)
257 262
 {
258 263
     arch_hard_fault_exception_hook(context);
264
+    addr2line_print_stack_before((uint32_t)context);
259 265
     return -RT_ERROR;
260 266
 }
261 267
 

Loading…
取消
儲存