Pārlūkot izejas kodu

[add] MCoreDump可以使用

rtthread_MCoreDump
huangyulong 2 mēnešus atpakaļ
vecāks
revīzija
f74bc35ef1

+ 6
- 3
EWARM/stm32_broad_mini.ewp Parādīt failu

@@ -1092,6 +1092,12 @@
1092 1092
             <file>
1093 1093
                 <name>$PROJ_DIR$\..\Middlewares\rtthread\libcpu\arm\cortex-m3\cpuport.c</name>
1094 1094
             </file>
1095
+            <file>
1096
+                <name>$PROJ_DIR$\..\Middlewares\MCoreDump\example\mcd_example.c</name>
1097
+                <excluded>
1098
+                    <configuration>stm32_broad_mini</configuration>
1099
+                </excluded>
1100
+            </file>
1095 1101
             <file>
1096 1102
                 <name>$PROJ_DIR$\startup_stm32f103xb.s</name>
1097 1103
             </file>
@@ -1257,9 +1263,6 @@
1257 1263
                     <name>$PROJ_DIR$\..\Middlewares\MCoreDump\src\arm\mcd_arm.c</name>
1258 1264
                 </file>
1259 1265
             </group>
1260
-            <file>
1261
-                <name>$PROJ_DIR$\..\Middlewares\MCoreDump\example\mcd_example.c</name>
1262
-            </file>
1263 1266
         </group>
1264 1267
         <group>
1265 1268
             <name>RTT</name>

+ 24
- 13
Middlewares/MCoreDump/arch/armv7m/armv7m.c Parādīt failu

@@ -127,7 +127,7 @@ get_reg_done1
127 127
     nop
128 128
 }
129 129
 
130
-#elif 1//defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) || defined(__GNUC__)
130
+#elif 1 //defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) || defined(__GNUC__)
131 131
 
132 132
 #define mcd_get_regset(regset)                                              \
133 133
     __asm volatile("  mov r0, %0                \n"                         \
@@ -151,6 +151,15 @@ get_reg_done1
151 151
                    " str  r1, [r0, #0]          \n" ::"r"(regset)           \
152 152
                    : "memory", "cc");
153 153
 
154
+// 不更新当前寄存器到全局变量(在异常中断中已填充)
155
+void mcd_hard_fault_exception_dump(void)
156
+{
157
+    struct thread_info_ops ops;
158
+    mcd_rtos_thread_ops(&ops);
159
+    mcd_gen_coredump(&ops);
160
+}
161
+
162
+// 只保存当前线程或非线程(主栈):更新当前寄存器到全局变量
154 163
 void mcd_mini_dump(void)
155 164
 {
156 165
     struct thread_info_ops ops;
@@ -166,6 +175,7 @@ void mcd_mini_dump(void)
166 175
     mcd_gen_coredump(&ops);
167 176
 }
168 177
 
178
+// 保存RTOS所有线程:更新当前寄存器到全局变量
169 179
 void mcd_multi_dump(void)
170 180
 {
171 181
     struct thread_info_ops ops;
@@ -222,9 +232,7 @@ void mcd_multi_dump(void)
222 232
  * @param core_regset Pointer to structure for storing ARM core registers
223 233
  * @param fp_regset Pointer to structure for storing FPU registers
224 234
  */
225
-void collect_registers_armv7m(uint32_t *stack_top,
226
-                                    core_regset_type *core_regset,
227
-                                    fp_regset_type *fp_regset)
235
+void collect_registers_armv7m(uint32_t *stack_top, core_regset_type *core_regset, fp_regset_type *fp_regset)
228 236
 {
229 237
     /*
230 238
      * This function uses the same stack frame parsing approach as collect_registers_armv7ms
@@ -337,17 +345,12 @@ int armv7m_hard_fault_exception_hook(void *context)
337 345
      * Since HardFault_Handler now uses the same stacking order as PendSV_Handler,
338 346
      * we can directly use collect_registers_armv7m function.
339 347
      */
340
-
348
+#if 0
341 349
     struct exception_stack_frame *exception_stack = (struct exception_stack_frame *)context;
342 350
 
343 351
     /* Calculate stack pointer to the beginning of the saved context */
344 352
     uint32_t *stack_ptr = (uint32_t *)exception_stack;
345 353
 
346
-#ifdef RT_USING_FINSH
347
-    extern long list_thread(void);
348
-    list_thread();
349
-#endif
350
-
351 354
     /*
352 355
      * Move backward through the stack to reach the beginning of saved context.
353 356
      * Stack layout (working backwards from exception_stack):
@@ -362,6 +365,14 @@ int armv7m_hard_fault_exception_hook(void *context)
362 365
     /* If no FPU support, skip EXC_RETURN and point to r4 directly */
363 366
     stack_ptr -= 1; /* exc_return */
364 367
 #endif
368
+#else
369
+    uint32_t *stack_ptr = context;
370
+    stack_ptr += 1; /* 跳过:exc_return */
371
+//  stack_ptr += 1; // 如开启fpuflag
372
+#endif
373
+
374
+    //extern void DumpCore(void *sp);
375
+    //DumpCore(stack_ptr);
365 376
 
366 377
     /*
367 378
      * Now stack_ptr points to where collect_registers_armv7m expects:
@@ -369,11 +380,11 @@ int armv7m_hard_fault_exception_hook(void *context)
369 380
      * - Without FPU: points to r4 (first register to be read)
370 381
      */
371 382
     collect_registers_armv7m(stack_ptr,
372
-                           get_cur_core_regset_address(),
373
-                           get_cur_fp_regset_address());
383
+                             get_cur_core_regset_address(),
384
+                             get_cur_fp_regset_address());
374 385
 
375 386
     /* Generate coredump using memory mode */
376
-    mcd_faultdump(MCD_OUTPUT_MEMORY);
387
+    mcd_faultdump(MCD_OUTPUT_FAULT_SERIAL);
377 388
 
378 389
     return 0;
379 390
 }

+ 17
- 12
Middlewares/MCoreDump/inc/coredump.h Parādīt failu

@@ -16,13 +16,13 @@
16 16
 
17 17
 /**
18 18
  * @brief Function pointer type for coredump data output
19
- * 
19
+ *
20 20
  * This function pointer type defines the interface for writing coredump data
21 21
  * to different output destinations (memory, serial, filesystem, etc.).
22
- * 
22
+ *
23 23
  * @param data Pointer to the data buffer to be written
24 24
  * @param len Length of the data buffer in bytes
25
- * 
25
+ *
26 26
  * @note The implementation should handle the data appropriately based on the
27 27
  *       chosen output mode and ensure data integrity.
28 28
  */
@@ -30,11 +30,11 @@ typedef void (*mcd_writeout_func_t)(uint8_t *, int);
30 30
 
31 31
 /**
32 32
  * @brief Thread information operations structure
33
- * 
33
+ *
34 34
  * This structure contains function pointers for retrieving thread information
35 35
  * in a RTOS environment. It's designed to avoid dynamic memory allocation
36 36
  * during fault handling, as malloc operations may fail during hard faults.
37
- * 
37
+ *
38 38
  * The structure provides a generic interface for different RTOS systems
39 39
  * to supply thread information for multi-threaded coredump generation.
40 40
  */
@@ -46,14 +46,14 @@ struct thread_info_ops
46 46
      * @return Total thread count
47 47
      */
48 48
     int32_t (*get_threads_count)(struct thread_info_ops *);
49
-    
49
+
50 50
     /**
51 51
      * @brief Get current executing thread index
52
-     * @param ops Pointer to this operations structure  
52
+     * @param ops Pointer to this operations structure
53 53
      * @return Current thread index
54 54
      */
55 55
     int32_t (*get_current_thread_idx)(struct thread_info_ops *);
56
-    
56
+
57 57
     /**
58 58
      * @brief Get register set for a specific thread
59 59
      * @param ops Pointer to this operations structure
@@ -64,14 +64,14 @@ struct thread_info_ops
64 64
     void (*get_thread_regset)(struct thread_info_ops *, int32_t,
65 65
                               core_regset_type *core_regset,
66 66
                               fp_regset_type *fp_regset);
67
-    
67
+
68 68
     /**
69 69
      * @brief Get number of memory areas to dump
70 70
      * @param ops Pointer to this operations structure
71 71
      * @return Number of memory areas
72 72
      */
73 73
     int32_t (*get_memarea_count)(struct thread_info_ops *);
74
-    
74
+
75 75
     /**
76 76
      * @brief Get memory area information
77 77
      * @param ops Pointer to this operations structure
@@ -82,7 +82,7 @@ struct thread_info_ops
82 82
      */
83 83
     int32_t (*get_memarea)(struct thread_info_ops *, int32_t,
84 84
                            uint32_t *, uint32_t *);
85
-    
85
+
86 86
     /** Private data for RTOS-specific implementations */
87 87
     void *priv;
88 88
 };
@@ -129,7 +129,12 @@ void mcd_init(mcd_writeout_func_t func);
129 129
  *
130 130
  * @see mcd_multi_dump() for full system coredump
131 131
  */
132
+// 不更新当前寄存器到全局变量(在异常中断中已填充)
133
+void mcd_hard_fault_exception_dump(void);
134
+// 只保存当前线程或非线程(主栈):更新当前寄存器到全局变量
132 135
 void mcd_mini_dump(void);
136
+// 保存RTOS所有线程:更新当前寄存器到全局变量
137
+void mcd_multi_dump(void);
133 138
 
134 139
 /**
135 140
  * @brief Generate coredump with all threads information
@@ -151,7 +156,7 @@ void mcd_mini_dump(void);
151 156
  *
152 157
  * @see mcd_mini_dump() for single thread coredump
153 158
  */
154
-void mcd_multi_dump(void);
159
+//void mcd_multi_dump(void);
155 160
 
156 161
 /**
157 162
  * @brief Generate coredump using provided thread operations

+ 6
- 5
Middlewares/MCoreDump/inc/mcd_cfg.h Parādīt failu

@@ -161,10 +161,10 @@ typedef uint32_t mcd_irq_state_t;
161 161
  */
162 162
 
163 163
 /* Automatic FPU detection - based on compiler definitions */
164
-#if	/* ARMCC */ (  (defined ( __CC_ARM ) && defined ( __TARGET_FPU_VFP ))    \
165
-	/* Clang */ || (defined ( __clang__ ) && defined ( __VFP_FP__ ) && !defined(__SOFTFP__)) \
166
-	/* IAR */   || (defined ( __ICCARM__ ) && defined ( __ARMVFP__ ))        \
167
-	/* GNU */   || (defined ( __GNUC__ ) && defined ( __VFP_FP__ ) && !defined(__SOFTFP__)) )
164
+#if /* ARMCC */ (  (defined ( __CC_ARM ) && defined ( __TARGET_FPU_VFP ))    \
165
+    /* Clang */ || (defined ( __clang__ ) && defined ( __VFP_FP__ ) && !defined(__SOFTFP__)) \
166
+    /* IAR */   || (defined ( __ICCARM__ ) && defined ( __ARMVFP__ ))        \
167
+    /* GNU */   || (defined ( __GNUC__ ) && defined ( __VFP_FP__ ) && !defined(__SOFTFP__)) )
168 168
 #define MCD_FPU_SUPPORT          1    /* FPU supported and enabled */
169 169
 #else
170 170
 #define MCD_FPU_SUPPORT          0    /* No FPU support */
@@ -217,7 +217,8 @@ typedef enum {
217 217
     MCD_OUTPUT_SERIAL = 0,                /* Output via serial port */
218 218
     MCD_OUTPUT_MEMORY,                    /* Store in memory buffer */
219 219
     MCD_OUTPUT_FILESYSTEM,                /* Save to filesystem */
220
-    MCD_OUTPUT_FLASH                      /* Store in flash (reserved) */
220
+    MCD_OUTPUT_FLASH,                      /* Store in flash (reserved) */
221
+    MCD_OUTPUT_FAULT_SERIAL, // 异常时打印到串口
221 222
 } mcd_output_mode_t;
222 223
 
223 224
 /* Return codes */

+ 35
- 33
Middlewares/MCoreDump/osal/rtthread.c Parādīt failu

@@ -23,11 +23,11 @@ typedef struct
23 23
 
24 24
 /* Architecture-specific exception hook function */
25 25
 #ifdef PKG_USING_MCOREDUMP_ARCH_ARMV7M
26
-#define arch_hard_fault_exception_hook armv7m_hard_fault_exception_hook
26
+    #define arch_hard_fault_exception_hook armv7m_hard_fault_exception_hook
27 27
 #elif defined(PKG_USING_MCOREDUMP_ARCH_ARMV8M)
28
-#define arch_hard_fault_exception_hook armv8m_hard_fault_exception_hook
28
+    #define arch_hard_fault_exception_hook armv8m_hard_fault_exception_hook
29 29
 #else
30
-#error "MCoredump does not support this architecture"
30
+    #error "MCoredump does not support this architecture"
31 31
 #endif
32 32
 
33 33
 static rt_int32_t is_thread_object(rt_thread_t thread)
@@ -36,7 +36,7 @@ static rt_int32_t is_thread_object(rt_thread_t thread)
36 36
     return ((thread->type & ~RT_Object_Class_Static) == RT_Object_Class_Thread);
37 37
 }
38 38
 
39
-static int32_t rtthread_thr_cnts(struct thread_info_ops *ops)
39
+static int32_t rtthread_thread_cnts(struct thread_info_ops *ops)
40 40
 {
41 41
     rtthread_ti_priv_t *priv = (rtthread_ti_priv_t *)ops->priv;
42 42
     rt_int32_t idx = 0;
@@ -49,13 +49,13 @@ static int32_t rtthread_thr_cnts(struct thread_info_ops *ops)
49 49
     {
50 50
         information = rt_object_get_information(RT_Object_Class_Thread);
51 51
         mcd_assert(information != RT_NULL);
52
-        
52
+
53 53
         current_thread = rt_thread_self();
54 54
         priv->cur_idx = -1;  /* Initialize current thread index */
55 55
 
56 56
         for (node = information->object_list.next;
57
-                node != &(information->object_list);
58
-                node = node->next)
57
+             node != &(information->object_list);
58
+             node = node->next)
59 59
         {
60 60
             object = rt_list_entry(node, struct rt_object, list);
61 61
             rt_thread_t thread = (rt_thread_t)object;
@@ -72,7 +72,7 @@ static int32_t rtthread_thr_cnts(struct thread_info_ops *ops)
72 72
         }
73 73
 
74 74
         priv->thr_cnts = idx;
75
-        
75
+
76 76
         /* If current thread not found, default to 0 */
77 77
         if (priv->cur_idx == -1)
78 78
         {
@@ -84,22 +84,22 @@ static int32_t rtthread_thr_cnts(struct thread_info_ops *ops)
84 84
     return priv->thr_cnts;
85 85
 }
86 86
 
87
-static int32_t rtthread_cur_idx(struct thread_info_ops *ops)
87
+static int32_t rtthread_cur_index(struct thread_info_ops *ops)
88 88
 {
89 89
     rtthread_ti_priv_t *priv = (rtthread_ti_priv_t *)ops->priv;
90 90
 
91 91
     if (-1 == priv->cur_idx)
92
-        rtthread_thr_cnts(ops);
92
+        rtthread_thread_cnts(ops);
93 93
 
94 94
     return priv->cur_idx;
95 95
 }
96 96
 
97
-static void rtthread_thr_rset(struct thread_info_ops *ops, int32_t idx,
98
-                              core_regset_type *core_regset,
99
-                              fp_regset_type *fp_regset)
97
+static void rtthread_thread_register(struct thread_info_ops *ops, int32_t idx,
98
+                                     core_regset_type *core_regset,
99
+                                     fp_regset_type *fp_regset)
100 100
 {
101 101
     rt_int32_t idx_l = 0;
102
-    rt_int32_t current_idx = rtthread_cur_idx(ops);
102
+    rt_int32_t current_idx = rtthread_cur_index(ops);
103 103
     struct rt_object_information *information;
104 104
     struct rt_object *object;
105 105
     struct rt_list_node *node;
@@ -107,9 +107,7 @@ static void rtthread_thr_rset(struct thread_info_ops *ops, int32_t idx,
107 107
     information = rt_object_get_information(RT_Object_Class_Thread);
108 108
     mcd_assert(information != RT_NULL);
109 109
 
110
-    for (node = information->object_list.next;
111
-            node != &(information->object_list);
112
-            node = node->next)
110
+    for (node = information->object_list.next; node != &(information->object_list); node = node->next)
113 111
     {
114 112
         object = rt_list_entry(node, struct rt_object, list);
115 113
         rt_thread_t thread = (rt_thread_t)object;
@@ -121,7 +119,7 @@ static void rtthread_thr_rset(struct thread_info_ops *ops, int32_t idx,
121 119
                 /* If this is the current thread, use current registers */
122 120
                 if (idx_l == current_idx)
123 121
                 {
124
-                    mcd_memcpy(core_regset, get_cur_core_regset_address(), sizeof(core_regset_type));
122
+                    mcd_memcpy(core_regset, get_cur_core_regset_address(), sizeof(core_regset_type)); // 异常中填充
125 123
                     mcd_memcpy(fp_regset, get_cur_fp_regset_address(), sizeof(fp_regset_type));
126 124
                 }
127 125
                 else
@@ -138,14 +136,14 @@ static void rtthread_thr_rset(struct thread_info_ops *ops, int32_t idx,
138 136
 
139 137
 static int32_t rtthread_get_mem_cnts(struct thread_info_ops *ops)
140 138
 {
141
-    return rtthread_thr_cnts(ops);
139
+    return rtthread_thread_cnts(ops);
142 140
 }
143 141
 
144 142
 static int32_t rtthread_get_memarea(struct thread_info_ops *ops, int32_t idx,
145
-                                       uint32_t *addr, uint32_t *memlen)
143
+                                    uint32_t *addr, uint32_t *memlen)
146 144
 {
147
-    rt_int32_t         idx_l = 0;
148
-    rt_int32_t current_idx = rtthread_cur_idx(ops);
145
+    rt_int32_t idx_l = 0;
146
+    rt_int32_t current_idx = rtthread_cur_index(ops);
149 147
     struct rt_object_information *information;
150 148
     struct rt_object *object;
151 149
     struct rt_list_node *node;
@@ -153,9 +151,7 @@ static int32_t rtthread_get_memarea(struct thread_info_ops *ops, int32_t idx,
153 151
     information = rt_object_get_information(RT_Object_Class_Thread);
154 152
     mcd_assert(information != RT_NULL);
155 153
 
156
-    for (node = information->object_list.next;
157
-            node != &(information->object_list);
158
-            node = node->next)
154
+    for (node = information->object_list.next; node != &(information->object_list); node = node->next)
159 155
     {
160 156
         object = rt_list_entry(node, struct rt_object, list);
161 157
         rt_thread_t thread = (rt_thread_t)object;
@@ -167,8 +163,14 @@ static int32_t rtthread_get_memarea(struct thread_info_ops *ops, int32_t idx,
167 163
                 /* If this is the current thread, use current stack pointer */
168 164
                 if (idx_l == current_idx)
169 165
                 {
170
-                    *addr = get_cur_core_regset_address()->sp;
171
-                    *memlen = 1024;
166
+                    *addr = get_cur_core_regset_address()->sp;  // 异常中填充
167
+                    *memlen = (rt_uint32_t)thread->stack_addr + thread->stack_size - (rt_uint32_t)thread->sp;
168
+
169
+                    if (*memlen > thread->stack_size)
170
+                    {
171
+                        mcd_println("The stack may overflow!!!");
172
+                        *memlen = thread->stack_size;
173
+                    }
172 174
                 }
173 175
                 else
174 176
                 {
@@ -186,9 +188,9 @@ static int32_t rtthread_get_memarea(struct thread_info_ops *ops, int32_t idx,
186 188
 void mcd_rtos_thread_ops(struct thread_info_ops *ops)
187 189
 {
188 190
     static rtthread_ti_priv_t priv;
189
-    ops->get_threads_count = rtthread_thr_cnts;
190
-    ops->get_current_thread_idx = rtthread_cur_idx;
191
-    ops->get_thread_regset = rtthread_thr_rset;
191
+    ops->get_threads_count = rtthread_thread_cnts;
192
+    ops->get_current_thread_idx = rtthread_cur_index;
193
+    ops->get_thread_regset = rtthread_thread_register;
192 194
     ops->get_memarea_count = rtthread_get_mem_cnts;
193 195
     ops->get_memarea = rtthread_get_memarea;
194 196
     ops->priv = &priv;
@@ -217,7 +219,7 @@ MCD_WEAK void rtt_assert_hook(const char *ex, const char *func, rt_size_t line)
217 219
     while (_continue == 1);
218 220
 }
219 221
 
220
-static int mcd_coredump_init(void) 
222
+static int mcd_coredump_init(void)
221 223
 {
222 224
     static mcd_bool_t is_init = MCD_FALSE;
223 225
 
@@ -227,11 +229,11 @@ static int mcd_coredump_init(void)
227 229
     }
228 230
 
229 231
     //mcd_print_memoryinfo();
230
-    
232
+
231 233
     rt_hw_exception_install(rtt_hard_fault_exception_hook);
232 234
 
233 235
     //rt_assert_set_hook(rtt_assert_hook);
234
-    
236
+
235 237
     is_init = MCD_TRUE;
236 238
     return RT_EOK;
237 239
 }

+ 1
- 0
Middlewares/MCoreDump/src/coredump.c Parādīt failu

@@ -215,6 +215,7 @@ static void addr_align(uint32_t *addr, uint32_t *memlen)
215 215
     *addr &= CORE_MEM_LINE_MASK;
216 216
 }
217 217
 
218
+// 生成.elf文件
218 219
 void mcd_gen_coredump(struct thread_info_ops *ops)
219 220
 {
220 221
     int note_size;

+ 16
- 2
Middlewares/MCoreDump/src/faultdump.c Parādīt failu

@@ -327,7 +327,21 @@ int mcd_faultdump_ex(mcd_output_mode_t output_mode)
327 327
 {
328 328
     struct thread_info_ops ops;
329 329
 
330
-    if (output_mode == MCD_OUTPUT_SERIAL)
330
+    if (output_mode == MCD_OUTPUT_FAULT_SERIAL)
331
+    {
332
+        mcd_init(corefile_serial_write);
333
+        mcd_irq_state_t irq_save = mcd_irq_disable();
334
+        serial_crc32 = 0xFFFFFFFF;
335
+
336
+        mcd_print("FAULT coredump start : {\n");
337
+        mcd_hard_fault_exception_dump();
338
+        mcd_print("\n} coredump end\n");
339
+        serial_crc32 = ~serial_crc32;
340
+        mcd_print("crc32 : %08x\n", serial_crc32);
341
+        mcd_irq_enable(irq_save);
342
+
343
+    }
344
+    else if (output_mode == MCD_OUTPUT_SERIAL)
331 345
     {
332 346
         mcd_init(corefile_serial_write);
333 347
 
@@ -396,7 +410,7 @@ int mcd_faultdump_ex(mcd_output_mode_t output_mode)
396 410
  *
397 411
  * This is the main entry point for generating coredumps in MCoreDump system.
398 412
  * It supports multiple output modes to accommodate different debugging scenarios:
399
- * 
413
+ *
400 414
  * - MCD_OUTPUT_MEMORY: Saves coredump to static memory buffer (persistent across resets)
401 415
  * - MCD_OUTPUT_SERIAL: Outputs coredump data via serial port in hex format
402 416
  * - MCD_OUTPUT_FILESYSTEM: Saves coredump to filesystem as ELF file (if filesystem support is enabled)

+ 1
- 1
Middlewares/rtthread/libcpu/arm/cortex-m3/context_iar.S Parādīt failu

@@ -168,7 +168,7 @@ rt_hw_context_switch_to:
168 168
 rt_hw_interrupt_thread_switch:
169 169
     BX      lr
170 170
 
171
-#if 0
171
+#if 1
172 172
     IMPORT rt_hw_hard_fault_exception
173 173
     EXPORT HardFault_Handler
174 174
 HardFault_Handler:

Notiek ielāde…
Atcelt
Saglabāt