Bläddra i källkod

[add] MCoreDump

rtthread_MCoreDump
huangyulong 2 månader sedan
förälder
incheckning
e09cdf62eb

+ 39
- 0
EWARM/stm32_broad_mini.ewp Visa fil

@@ -220,6 +220,8 @@
220 220
                     <name>CCDefines</name>
221 221
                     <state>USE_HAL_DRIVER</state>
222 222
                     <state>STM32F103xB</state>
223
+                    <state>__RTTHREAD__</state>
224
+                    <state>PKG_USING_MCOREDUMP_ARCH_ARMV7M</state>
223 225
                 </option>
224 226
                 <option>
225 227
                     <name>CCPreprocFile</name>
@@ -353,6 +355,10 @@
353 355
                     <state>$PROJ_DIR$/../Middlewares/rtthread/include</state>
354 356
                     <state>$PROJ_DIR$/../Middlewares/rtthread/include/libc</state>
355 357
                     <state>$PROJ_DIR$/../Middlewares/rtthread/finsh</state>
358
+                    <state>$PROJ_DIR$/../Middlewares/MCoreDump/src/arm</state>
359
+                    <state>$PROJ_DIR$/../Middlewares/MCoreDump/inc</state>
360
+                    <state>$PROJ_DIR$/../Middlewares/MCoreDump/arch</state>
361
+                    <state>$PROJ_DIR$/../Middlewares/MCoreDump/arch/armv7m</state>
356 362
                 </option>
357 363
                 <option>
358 364
                     <name>CCStdIncCheck</name>
@@ -1176,6 +1182,9 @@
1176 1182
         <name>Middlewares</name>
1177 1183
         <group>
1178 1184
             <name>coredump</name>
1185
+            <excluded>
1186
+                <configuration>stm32_broad_mini</configuration>
1187
+            </excluded>
1179 1188
             <file>
1180 1189
                 <name>$PROJ_DIR$\..\Middlewares\coredump\coredump.c</name>
1181 1190
             </file>
@@ -1222,6 +1231,36 @@
1222 1231
                 <name>$PROJ_DIR$\..\Middlewares\Third_Party\FreeRTOS\Source\timers.c</name>
1223 1232
             </file>
1224 1233
         </group>
1234
+        <group>
1235
+            <name>MCoreDump</name>
1236
+            <group>
1237
+                <name>arch</name>
1238
+                <file>
1239
+                    <name>$PROJ_DIR$\..\Middlewares\MCoreDump\arch\armv7m\armv7m.c</name>
1240
+                </file>
1241
+            </group>
1242
+            <group>
1243
+                <name>osal</name>
1244
+                <file>
1245
+                    <name>$PROJ_DIR$\..\Middlewares\MCoreDump\osal\rtthread.c</name>
1246
+                </file>
1247
+            </group>
1248
+            <group>
1249
+                <name>src</name>
1250
+                <file>
1251
+                    <name>$PROJ_DIR$\..\Middlewares\MCoreDump\src\coredump.c</name>
1252
+                </file>
1253
+                <file>
1254
+                    <name>$PROJ_DIR$\..\Middlewares\MCoreDump\src\faultdump.c</name>
1255
+                </file>
1256
+                <file>
1257
+                    <name>$PROJ_DIR$\..\Middlewares\MCoreDump\src\arm\mcd_arm.c</name>
1258
+                </file>
1259
+            </group>
1260
+            <file>
1261
+                <name>$PROJ_DIR$\..\Middlewares\MCoreDump\example\mcd_example.c</name>
1262
+            </file>
1263
+        </group>
1225 1264
         <group>
1226 1265
             <name>RTT</name>
1227 1266
             <file>

+ 379
- 0
Middlewares/MCoreDump/arch/armv7m/armv7m.c Visa fil

@@ -0,0 +1,379 @@
1
+/*
2
+ * Copyright (c) 2025, RT-Thread Development Team
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ *
6
+ * Change Logs:
7
+ * Date           Author       Notes
8
+ * 2025-08-16     Rbb666       first version
9
+ */
10
+
11
+#include "coredump.h"
12
+#include "registers.h"
13
+
14
+#define FPU_CPACR 0xE000ED88
15
+
16
+int is_vfp_addressable(void)
17
+{
18
+    uint32_t reg_cpacr = *((volatile uint32_t *)FPU_CPACR);
19
+    if (reg_cpacr & 0x00F00000)
20
+        return 1;
21
+    else
22
+        return 0;
23
+}
24
+
25
+#if defined(__CC_ARM)
26
+
27
+/* clang-format off */
28
+__asm void mcd_mini_dump()
29
+{
30
+    extern get_cur_core_regset_address;
31
+    extern get_cur_fp_regset_address;
32
+    extern mcd_mini_dump_ops;
33
+    extern mcd_gen_coredump;
34
+    extern is_vfp_addressable;
35
+
36
+    PRESERVE8
37
+
38
+    push {r7, lr}
39
+    sub sp, sp, #24
40
+    add r7, sp, #0
41
+
42
+get_regset
43
+    bl get_cur_core_regset_address
44
+    str r0, [r0, #0]
45
+    add r0, r0, #4
46
+    stmia r0!, {r1 - r12}
47
+    mov r1, sp
48
+    add r1, #32
49
+    str r1, [r0, #0]
50
+    ldr r1, [sp, #28]
51
+    str r1, [r0, #4]
52
+    mov r1, pc
53
+    str r1, [r0, #8]
54
+    mrs r1, xpsr
55
+    str r1, [r0, #12]
56
+
57
+    bl is_vfp_addressable
58
+    cmp r0, #0
59
+    beq get_reg_done
60
+
61
+    bl get_cur_fp_regset_address
62
+    vstmia r0!, {d0 - d15}
63
+    vmrs r1, fpscr
64
+    str r1, [r0, #0]
65
+
66
+get_reg_done
67
+    mov r0, r7
68
+    bl mcd_mini_dump_ops
69
+    mov r0, r7
70
+    bl mcd_gen_coredump
71
+    nop
72
+    adds r7, r7, #24
73
+    mov sp, r7
74
+    pop {r7, pc}
75
+    nop
76
+    nop
77
+}
78
+
79
+__asm void mcd_multi_dump(void)
80
+{
81
+    extern get_cur_core_regset_address;
82
+    extern get_cur_fp_regset_address;
83
+    extern mcd_rtos_thread_ops;
84
+    extern mcd_gen_coredump;
85
+    extern is_vfp_addressable;
86
+
87
+    PRESERVE8
88
+
89
+    push {r7, lr}
90
+    sub sp, sp, #24
91
+    add r7, sp, #0
92
+
93
+get_regset1
94
+    bl get_cur_core_regset_address
95
+    str r0, [r0, #0]
96
+    add r0, r0, #4
97
+    stmia r0!, {r1 - r12}
98
+    mov r1, sp
99
+    add r1, #32
100
+    str r1, [r0, #0]
101
+    ldr r1, [sp, #28]
102
+    str r1, [r0, #4]
103
+    mov r1, pc
104
+    str r1, [r0, #8]
105
+    mrs r1, xpsr
106
+    str r1, [r0, #12]
107
+
108
+    bl is_vfp_addressable
109
+    cmp r0, #0
110
+    beq get_reg_done
111
+
112
+    bl get_cur_fp_regset_address
113
+    vstmia r0!, {d0 - d15}
114
+    vmrs r1, fpscr
115
+    str r1, [r0, #0]
116
+
117
+get_reg_done1
118
+    mov r0, r7
119
+    bl mcd_rtos_thread_ops
120
+    mov r0, r7
121
+    bl mcd_gen_coredump
122
+    nop
123
+    adds r7, r7, #24
124
+    mov sp, r7
125
+    pop {r7, pc}
126
+    nop
127
+    nop
128
+}
129
+
130
+#elif 1//defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) || defined(__GNUC__)
131
+
132
+#define mcd_get_regset(regset)                                              \
133
+    __asm volatile("  mov r0, %0                \n"                         \
134
+                   "  str r0, [r0 , #0]         \n"                         \
135
+                   "  add r0, r0, #4            \n"                         \
136
+                   "  stmia  r0!, {r1 - r12}    \n"                         \
137
+                   "  mov r1, sp                \n"                         \
138
+                   "  str  r1, [r0, #0]         \n"                         \
139
+                   "  mov r1, lr                \n"                         \
140
+                   "  str  r1, [r0, #4]         \n"                         \
141
+                   "  mov r1, pc                \n"                         \
142
+                   "  str  r1, [r0, #8]         \n"                         \
143
+                   "  mrs r1, xpsr              \n"                         \
144
+                   "  str  r1, [r0, #12]        \n" ::"r"(regset)           \
145
+                   : "memory", "cc");
146
+
147
+#define mcd_get_fpregset(regset)                                            \
148
+    __asm volatile(" mov r0, %0                 \n"                         \
149
+                   " vstmia r0!, {d0 - d15}     \n"                         \
150
+                   " vmrs r1, fpscr             \n"                         \
151
+                   " str  r1, [r0, #0]          \n" ::"r"(regset)           \
152
+                   : "memory", "cc");
153
+
154
+void mcd_mini_dump(void)
155
+{
156
+    struct thread_info_ops ops;
157
+
158
+    mcd_get_regset((uint32_t *)get_cur_core_regset_address());
159
+
160
+#if MCD_FPU_SUPPORT
161
+    if (is_vfp_addressable())
162
+        mcd_get_fpregset((uint32_t *)get_cur_fp_regset_address());
163
+#endif
164
+
165
+    mcd_mini_dump_ops(&ops);
166
+    mcd_gen_coredump(&ops);
167
+}
168
+
169
+void mcd_multi_dump(void)
170
+{
171
+    struct thread_info_ops ops;
172
+
173
+    mcd_get_regset((uint32_t *)get_cur_core_regset_address());
174
+
175
+#if MCD_FPU_SUPPORT
176
+    if (is_vfp_addressable())
177
+        mcd_get_fpregset((uint32_t *)get_cur_fp_regset_address());
178
+#endif
179
+
180
+    mcd_rtos_thread_ops(&ops);
181
+    mcd_gen_coredump(&ops);
182
+}
183
+
184
+#endif
185
+
186
+/**
187
+ * @brief Collect ARM Cortex-M4 registers from RT-Thread stack frame
188
+ *
189
+ * This function extracts register values from the stack frame created by
190
+ * RT-Thread's context switch mechanism (PendSV_Handler) or exception handling.
191
+ *
192
+ * RT-Thread Stack Frame Layout (from low to high memory address):
193
+ * +-------------------+  <- stack_top (input parameter)
194
+ * | FPU flag          |  (4 bytes, if MCD_FPU_SUPPORT enabled)
195
+ * +-------------------+
196
+ * | r4                |  (4 bytes, software saved)
197
+ * | r5                |  (4 bytes, software saved)
198
+ * | r6                |  (4 bytes, software saved)
199
+ * | r7                |  (4 bytes, software saved)
200
+ * | r8                |  (4 bytes, software saved)
201
+ * | r9                |  (4 bytes, software saved)
202
+ * | r10               |  (4 bytes, software saved)
203
+ * | r11               |  (4 bytes, software saved)
204
+ * +-------------------+
205
+ * | FPU s16-s31       |  (64 bytes, if FPU context active)
206
+ * +-------------------+
207
+ * | r0                |  (4 bytes, hardware saved)
208
+ * | r1                |  (4 bytes, hardware saved)
209
+ * | r2                |  (4 bytes, hardware saved)
210
+ * | r3                |  (4 bytes, hardware saved)
211
+ * | r12               |  (4 bytes, hardware saved)
212
+ * | lr                |  (4 bytes, hardware saved)
213
+ * | pc                |  (4 bytes, hardware saved)
214
+ * | xpsr              |  (4 bytes, hardware saved)
215
+ * +-------------------+
216
+ * | FPU s0-s15        |  (64 bytes, if FPU context active)
217
+ * | FPSCR             |  (4 bytes, if FPU context active)
218
+ * | NO_NAME           |  (4 bytes, if FPU context active)
219
+ * +-------------------+  <- current SP after context save
220
+ *
221
+ * @param stack_top Pointer to the beginning of the stack frame (FPU flag position)
222
+ * @param core_regset Pointer to structure for storing ARM core registers
223
+ * @param fp_regset Pointer to structure for storing FPU registers
224
+ */
225
+void collect_registers_armv7m(uint32_t *stack_top,
226
+                                    core_regset_type *core_regset,
227
+                                    fp_regset_type *fp_regset)
228
+{
229
+    /*
230
+     * This function uses the same stack frame parsing approach as collect_registers_armv7ms
231
+     * for consistency. Both PendSV_Handler and HardFault_Handler now use identical
232
+     * stacking order after the modifications.
233
+     *
234
+     * Expected stack layout starting from stack_top:
235
+     * [FPU flag] -> [r4-r11] -> [FPU s16-s31] -> [exception frame] -> [FPU s0-s15,FPSCR]
236
+     */
237
+    uint32_t *current_ptr = stack_top;
238
+
239
+    /* Clear both register sets first to ensure clean state */
240
+    mcd_memset(core_regset, 0, sizeof(core_regset_type));
241
+    mcd_memset(fp_regset, 0, sizeof(fp_regset_type));
242
+
243
+#if MCD_FPU_SUPPORT
244
+    /* Read FPU flag first - indicates if FPU context was saved */
245
+    uint32_t fpu_flag = *current_ptr++;
246
+#endif
247
+
248
+    /* Extract core registers r4-r11 (software saved by RT-Thread) */
249
+    core_regset->r4 = *current_ptr++;
250
+    core_regset->r5 = *current_ptr++;
251
+    core_regset->r6 = *current_ptr++;
252
+    core_regset->r7 = *current_ptr++;
253
+    core_regset->r8 = *current_ptr++;
254
+    core_regset->r9 = *current_ptr++;
255
+    core_regset->r10 = *current_ptr++;
256
+    core_regset->r11 = *current_ptr++;
257
+
258
+#if MCD_FPU_SUPPORT
259
+    /* If FPU context is active, s16-s31 registers are saved after r4-r11 */
260
+    if (fpu_flag)
261
+    {
262
+        /* Copy FPU s16-s31 registers (software saved by RT-Thread) */
263
+        for (int i = 16; i < 32; i++)
264
+        {
265
+            ((uint32_t *)fp_regset)[i] = *current_ptr++;
266
+        }
267
+    }
268
+#endif
269
+
270
+    /* Extract hardware exception frame (automatically saved by ARM Cortex-M) */
271
+    core_regset->r0 = *current_ptr++;
272
+    core_regset->r1 = *current_ptr++;
273
+    core_regset->r2 = *current_ptr++;
274
+    core_regset->r3 = *current_ptr++;
275
+    core_regset->r12 = *current_ptr++;
276
+    core_regset->lr = *current_ptr++;
277
+    core_regset->pc = *current_ptr++;
278
+    core_regset->xpsr = *current_ptr++;
279
+
280
+#if MCD_FPU_SUPPORT
281
+    /* If FPU context is active, s0-s15 and FPSCR are saved after exception frame */
282
+    if (fpu_flag)
283
+    {
284
+        /* Copy FPU s0-s15 registers (hardware saved by ARM Cortex-M) */
285
+        for (int i = 0; i < 16; i++)
286
+        {
287
+            ((uint32_t *)fp_regset)[i] = *current_ptr++;
288
+        }
289
+
290
+        /* Copy FPSCR register (FPU status and control) */
291
+        fp_regset->fpscr = *current_ptr++;
292
+
293
+        /* Skip NO_NAME field (reserved/alignment) */
294
+        current_ptr++;
295
+    }
296
+#endif
297
+
298
+    /* SP should point to the current stack pointer position after all saved data */
299
+    core_regset->sp = (uintptr_t)current_ptr;
300
+}
301
+
302
+/**
303
+ * @brief ARM Cortex-M specific hard fault exception handler for MCoreDump
304
+ *
305
+ * This function handles ARM Cortex-M specific stack frame processing when a
306
+ * hard fault occurs. It calculates the proper stack pointer position and
307
+ * extracts register context for coredump generation.
308
+ *
309
+ * HardFault Stack Frame Layout (created by HardFault_Handler):
310
+ * +-------------------+  <- Exception occurs here
311
+ * | Hardware Exception|  (32 bytes: r0,r1,r2,r3,r12,lr,pc,xpsr)
312
+ * | Stack Frame       |  (+ optional 72 bytes FPU: s0-s15,FPSCR,NO_NAME)
313
+ * +-------------------+  <- context parameter points here
314
+ * | r11               |  (4 bytes, software saved in HardFault_Handler)
315
+ * | r10               |  (4 bytes, software saved in HardFault_Handler)
316
+ * | ...               |  (...)
317
+ * | r4                |  (4 bytes, software saved in HardFault_Handler)
318
+ * +-------------------+
319
+ * | FPU s31           |  (4 bytes, if FPU context active)
320
+ * | FPU s30           |  (4 bytes, if FPU context active)
321
+ * | ...               |  (...)
322
+ * | FPU s16           |  (4 bytes, if FPU context active)
323
+ * +-------------------+
324
+ * | FPU flag          |  (4 bytes, if MCD_FPU_SUPPORT enabled)
325
+ * +-------------------+
326
+ * | EXC_RETURN        |  (4 bytes, contains exception return information)
327
+ * +-------------------+  <- Final stack pointer position
328
+ *
329
+ * @param context Pointer to exception_stack_frame from HardFault_Handler
330
+ * @return int Always returns -1 to indicate fault condition
331
+ */
332
+int armv7m_hard_fault_exception_hook(void *context)
333
+{
334
+    /*
335
+     * context points to exception_stack_frame created by HardFault_Handler.
336
+     * We need to calculate the complete stack frame position to extract all registers.
337
+     * Since HardFault_Handler now uses the same stacking order as PendSV_Handler,
338
+     * we can directly use collect_registers_armv7m function.
339
+     */
340
+
341
+    struct exception_stack_frame *exception_stack = (struct exception_stack_frame *)context;
342
+
343
+    /* Calculate stack pointer to the beginning of the saved context */
344
+    uint32_t *stack_ptr = (uint32_t *)exception_stack;
345
+
346
+#ifdef RT_USING_FINSH
347
+    extern long list_thread(void);
348
+    list_thread();
349
+#endif
350
+
351
+    /*
352
+     * Move backward through the stack to reach the beginning of saved context.
353
+     * Stack layout (working backwards from exception_stack):
354
+     * exception_stack -> r4-r11 (8 words) -> [s16-s31] -> [fpu_flag] -> [exc_return]
355
+     */
356
+    stack_ptr -= 8; /* Move backward 8 uint32_t positions to reach r4 */
357
+
358
+#if MCD_FPU_SUPPORT
359
+    /* Point to FPU flag position (collect_registers_armv7m expects this as start) */
360
+    stack_ptr -= 1; /* fpu flag */
361
+#else
362
+    /* If no FPU support, skip EXC_RETURN and point to r4 directly */
363
+    stack_ptr -= 1; /* exc_return */
364
+#endif
365
+
366
+    /*
367
+     * Now stack_ptr points to where collect_registers_armv7m expects:
368
+     * - With FPU: points to FPU flag (first field to be read)
369
+     * - Without FPU: points to r4 (first register to be read)
370
+     */
371
+    collect_registers_armv7m(stack_ptr,
372
+                           get_cur_core_regset_address(),
373
+                           get_cur_fp_regset_address());
374
+
375
+    /* Generate coredump using memory mode */
376
+    mcd_faultdump(MCD_OUTPUT_MEMORY);
377
+
378
+    return 0;
379
+}

+ 69
- 0
Middlewares/MCoreDump/arch/armv7m/registers.h Visa fil

@@ -0,0 +1,69 @@
1
+/*
2
+ * Copyright (c) 2025, RT-Thread Development Team
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ *
6
+ * Change Logs:
7
+ * Date           Author       Notes
8
+ * 2025-08-16     Rbb666       first version
9
+ */
10
+
11
+#ifndef __REGISTERS_H__
12
+#define __REGISTERS_H__
13
+
14
+#include <stdint.h>
15
+
16
+#ifdef __cplusplus
17
+extern "C" {
18
+#endif
19
+
20
+struct armv7m_core_regset
21
+{
22
+    uint32_t r0;
23
+    uint32_t r1;
24
+    uint32_t r2;
25
+    uint32_t r3;
26
+    uint32_t r4;
27
+    uint32_t r5;
28
+    uint32_t r6;
29
+    uint32_t r7;
30
+    uint32_t r8;
31
+    uint32_t r9;
32
+    uint32_t r10;
33
+    uint32_t r11;
34
+    uint32_t r12;
35
+    uint32_t sp;
36
+    uint32_t lr;
37
+    uint32_t pc;
38
+    uint32_t xpsr;
39
+};
40
+
41
+struct arm_vfpv2_regset
42
+{
43
+    uint64_t d0;
44
+    uint64_t d1;
45
+    uint64_t d2;
46
+    uint64_t d3;
47
+    uint64_t d4;
48
+    uint64_t d5;
49
+    uint64_t d6;
50
+    uint64_t d7;
51
+    uint64_t d8;
52
+    uint64_t d9;
53
+    uint64_t d10;
54
+    uint64_t d11;
55
+    uint64_t d12;
56
+    uint64_t d13;
57
+    uint64_t d14;
58
+    uint64_t d15;
59
+    uint32_t fpscr;
60
+};
61
+
62
+typedef struct armv7m_core_regset    core_regset_type;
63
+typedef struct arm_vfpv2_regset      fp_regset_type;
64
+
65
+#ifdef __cplusplus
66
+}
67
+#endif
68
+
69
+#endif /* __MCD_REGISTERS_H__ */

+ 394
- 0
Middlewares/MCoreDump/arch/armv8m/armv8m.c Visa fil

@@ -0,0 +1,394 @@
1
+/*
2
+ * Copyright (c) 2025, RT-Thread Development Team
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ *
6
+ * Change Logs:
7
+ * Date           Author       Notes
8
+ * 2025-08-16     Rbb666       first version
9
+ */
10
+
11
+#include "coredump.h"
12
+#include "registers.h"
13
+
14
+#define FPU_CPACR 0xE000ED88
15
+
16
+int is_vfp_addressable(void)
17
+{
18
+    uint32_t reg_cpacr = *((volatile uint32_t *)FPU_CPACR);
19
+    if (reg_cpacr & 0x00F00000)
20
+        return 1;
21
+    else
22
+        return 0;
23
+}
24
+
25
+#if defined(__CC_ARM)
26
+
27
+/* clang-format off */
28
+__asm void mcd_mini_dump()
29
+{
30
+    extern get_cur_core_regset_address;
31
+    extern get_cur_fp_regset_address;
32
+    extern mcd_mini_dump_ops;
33
+    extern mcd_gen_coredump;
34
+    extern is_vfp_addressable;
35
+
36
+    PRESERVE8
37
+
38
+    push {r7, lr}
39
+    sub sp, sp, #24
40
+    add r7, sp, #0
41
+
42
+get_regset
43
+    bl get_cur_core_regset_address
44
+    str r0, [r0, #0]
45
+    add r0, r0, #4
46
+    stmia r0!, {r1 - r12}
47
+    mov r1, sp
48
+    add r1, #32
49
+    str r1, [r0, #0]
50
+    ldr r1, [sp, #28]
51
+    str r1, [r0, #4]
52
+    mov r1, pc
53
+    str r1, [r0, #8]
54
+    mrs r1, xpsr
55
+    str r1, [r0, #12]
56
+
57
+    bl is_vfp_addressable
58
+    cmp r0, #0
59
+    beq get_reg_done
60
+
61
+    bl get_cur_fp_regset_address
62
+    vstmia r0!, {d0 - d15}
63
+    vmrs r1, fpscr
64
+    str r1, [r0, #0]
65
+
66
+get_reg_done
67
+    mov r0, r7
68
+    bl mcd_mini_dump_ops
69
+    mov r0, r7
70
+    bl mcd_gen_coredump
71
+    nop
72
+    adds r7, r7, #24
73
+    mov sp, r7
74
+    pop {r7, pc}
75
+    nop
76
+    nop
77
+}
78
+
79
+__asm void mcd_multi_dump(void)
80
+{
81
+    extern get_cur_core_regset_address;
82
+    extern get_cur_fp_regset_address;
83
+    extern mcd_rtos_thread_ops;
84
+    extern mcd_gen_coredump;
85
+    extern is_vfp_addressable;
86
+
87
+    PRESERVE8
88
+
89
+    push {r7, lr}
90
+    sub sp, sp, #24
91
+    add r7, sp, #0
92
+
93
+get_regset1
94
+    bl get_cur_core_regset_address
95
+    str r0, [r0, #0]
96
+    add r0, r0, #4
97
+    stmia r0!, {r1 - r12}
98
+    mov r1, sp
99
+    add r1, #32
100
+    str r1, [r0, #0]
101
+    ldr r1, [sp, #28]
102
+    str r1, [r0, #4]
103
+    mov r1, pc
104
+    str r1, [r0, #8]
105
+    mrs r1, xpsr
106
+    str r1, [r0, #12]
107
+
108
+    bl is_vfp_addressable
109
+    cmp r0, #0
110
+    beq get_reg_done
111
+
112
+    bl get_cur_fp_regset_address
113
+    vstmia r0!, {d0 - d15}
114
+    vmrs r1, fpscr
115
+    str r1, [r0, #0]
116
+
117
+get_reg_done1
118
+    mov r0, r7
119
+    bl mcd_rtos_thread_ops
120
+    mov r0, r7
121
+    bl mcd_gen_coredump
122
+    nop
123
+    adds r7, r7, #24
124
+    mov sp, r7
125
+    pop {r7, pc}
126
+    nop
127
+    nop
128
+}
129
+
130
+#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) || defined(__GNUC__)
131
+
132
+#define mcd_get_regset(regset)                                              \
133
+    __asm volatile("  mov r0, %0                \n"                         \
134
+                   "  str r0, [r0 , #0]         \n"                         \
135
+                   "  add r0, r0, #4            \n"                         \
136
+                   "  stmia  r0!, {r1 - r12}    \n"                         \
137
+                   "  mov r1, sp                \n"                         \
138
+                   "  str  r1, [r0, #0]         \n"                         \
139
+                   "  mov r1, lr                \n"                         \
140
+                   "  str  r1, [r0, #4]         \n"                         \
141
+                   "  mov r1, pc                \n"                         \
142
+                   "  str  r1, [r0, #8]         \n"                         \
143
+                   "  mrs r1, xpsr              \n"                         \
144
+                   "  str  r1, [r0, #12]        \n" ::"r"(regset)           \
145
+                   : "memory", "cc");
146
+
147
+#define mcd_get_fpregset(regset)                                            \
148
+    __asm volatile(" mov r0, %0                 \n"                         \
149
+                   " vstmia r0!, {d0 - d15}     \n"                         \
150
+                   " vmrs r1, fpscr             \n"                         \
151
+                   " str  r1, [r0, #0]          \n" ::"r"(regset)           \
152
+                   : "memory", "cc");
153
+
154
+void mcd_mini_dump(void)
155
+{
156
+    struct thread_info_ops ops;
157
+
158
+    mcd_get_regset((uint32_t *)get_cur_core_regset_address());
159
+
160
+#if MCD_FPU_SUPPORT
161
+    if (is_vfp_addressable())
162
+        mcd_get_fpregset((uint32_t *)get_cur_fp_regset_address());
163
+#endif
164
+
165
+    mcd_mini_dump_ops(&ops);
166
+    mcd_gen_coredump(&ops);
167
+}
168
+
169
+void mcd_multi_dump(void)
170
+{
171
+    struct thread_info_ops ops;
172
+
173
+    mcd_get_regset((uint32_t *)get_cur_core_regset_address());
174
+
175
+#if MCD_FPU_SUPPORT
176
+    if (is_vfp_addressable())
177
+        mcd_get_fpregset((uint32_t *)get_cur_fp_regset_address());
178
+#endif
179
+
180
+    mcd_rtos_thread_ops(&ops);
181
+    mcd_gen_coredump(&ops);
182
+}
183
+
184
+#endif
185
+
186
+/**
187
+ * @brief Collect ARM Cortex-M33 registers from RT-Thread stack frame
188
+ *
189
+ * This function extracts register values from the stack frame created by
190
+ * RT-Thread's HardFault_Handler for ARMv8-M architecture.
191
+ * 
192
+ * ARMv8-M Stack Frame Layout (based on HardFault_Handler in context_gcc.S):
193
+ * +-------------------+  <- stack_top (input parameter)
194
+ * | EXC_RETURN        |  (4 bytes, contains exception return information)
195
+ * +-------------------+
196
+ * | tz                |  (4 bytes, TrustZone context)
197
+ * | lr                |  (4 bytes, saved link register)
198
+ * | psplim            |  (4 bytes, stack pointer limit)
199
+ * | control           |  (4 bytes, control register)
200
+ * +-------------------+
201
+ * | r4                |  (4 bytes, software saved)
202
+ * | r5                |  (4 bytes, software saved)
203
+ * | r6                |  (4 bytes, software saved)
204
+ * | r7                |  (4 bytes, software saved)
205
+ * | r8                |  (4 bytes, software saved)
206
+ * | r9                |  (4 bytes, software saved)
207
+ * | r10               |  (4 bytes, software saved)
208
+ * | r11               |  (4 bytes, software saved)
209
+ * +-------------------+
210
+ * | FPU d8-d15        |  (64 bytes, if FPU context active)
211
+ * +-------------------+
212
+ * | r0                |  (4 bytes, hardware saved)
213
+ * | r1                |  (4 bytes, hardware saved)
214
+ * | r2                |  (4 bytes, hardware saved)
215
+ * | r3                |  (4 bytes, hardware saved)
216
+ * | r12               |  (4 bytes, hardware saved)
217
+ * | lr                |  (4 bytes, hardware saved)
218
+ * | pc                |  (4 bytes, hardware saved)
219
+ * | xpsr              |  (4 bytes, hardware saved)
220
+ * +-------------------+
221
+ * | FPU d0-d7         |  (64 bytes, if FPU context active)
222
+ * | FPSCR             |  (4 bytes, if FPU context active)
223
+ * | NO_NAME           |  (4 bytes, if FPU context active)
224
+ * +-------------------+  <- current SP after context save
225
+ *
226
+ * @param stack_top Pointer to the beginning of the stack frame (EXC_RETURN position)
227
+ * @param core_regset Pointer to structure for storing ARM core registers
228
+ * @param fp_regset Pointer to structure for storing FPU registers
229
+ */
230
+void collect_registers_armv8m(uint32_t *stack_top,
231
+                                    core_regset_type *core_regset,
232
+                                    fp_regset_type *fp_regset)
233
+{    
234
+    /* 
235
+     * ARMv8-M has two different stack layouts:
236
+     * 1. Exception context (HardFault_Handler): [EXC_RETURN] -> [tz,lr,psplim,control] -> [r4-r11] -> [FPU d8-d15] -> [exception frame] -> [FPU d0-d7,FPSCR]
237
+     * 2. Normal thread context (PendSV_Handler): [tz,lr,psplim,control] -> [r4-r11] -> [hardware exception frame]
238
+     */
239
+    uint32_t *current_ptr = stack_top;
240
+    
241
+    /* Clear both register sets first to ensure clean state */ 
242
+    mcd_memset(core_regset, 0, sizeof(core_regset_type));
243
+    mcd_memset(fp_regset, 0, sizeof(fp_regset_type));
244
+
245
+    /* Read first word to determine context type */
246
+    uint32_t first_word = *current_ptr;
247
+    uint32_t fpu_flag = 0;  // Default to no FPU context
248
+    
249
+    /* Check if this is a valid EXC_RETURN value (starts with 0xFF) */
250
+    if ((first_word & 0xFF000000) == 0xFF000000) 
251
+    {
252
+        /* Valid EXC_RETURN - this is an exception context */
253
+        uint32_t exc_return = *current_ptr++;
254
+        fpu_flag = !(exc_return & 0x10);
255
+        /* Skip tz, lr, psplim, control fields (4 words) */
256
+        current_ptr += 4;
257
+    }
258
+    else 
259
+    {
260
+        /* Not a valid EXC_RETURN - this is normal thread context from PendSV_Handler */
261
+        fpu_flag = 0;
262
+        /* For normal thread context, stack_top points to [tz,lr,psplim,control] */
263
+        /* Skip tz, lr, psplim, control fields (4 words) */
264
+        current_ptr += 4;
265
+    }
266
+
267
+    /* Extract core registers r4-r11 (software saved by RT-Thread) */
268
+    core_regset->r4 = *current_ptr++;
269
+    core_regset->r5 = *current_ptr++;
270
+    core_regset->r6 = *current_ptr++;
271
+    core_regset->r7 = *current_ptr++;
272
+    core_regset->r8 = *current_ptr++;
273
+    core_regset->r9 = *current_ptr++;
274
+    core_regset->r10 = *current_ptr++;
275
+    core_regset->r11 = *current_ptr++;
276
+
277
+#if MCD_FPU_SUPPORT
278
+    /* If FPU context is active, d8-d15 registers are saved after r4-r11 */
279
+    if (fpu_flag)
280
+    {
281
+        /* Copy FPU d8-d15 registers (software saved by HardFault_Handler) */
282
+        /* Each double precision register is 64 bits = 2 words */
283
+        uint64_t *fp_d_ptr = (uint64_t *)current_ptr;
284
+        for (int i = 0; i < 8; i++)  /* d8-d15 = 8 registers */
285
+        {
286
+            (&fp_regset->d8)[i] = *fp_d_ptr++;
287
+        }
288
+        current_ptr = (uint32_t *)fp_d_ptr;
289
+    }
290
+#endif
291
+
292
+    /* Extract hardware exception frame (automatically saved by ARM Cortex-M) */
293
+    core_regset->r0 = *current_ptr++;
294
+    core_regset->r1 = *current_ptr++;
295
+    core_regset->r2 = *current_ptr++;
296
+    core_regset->r3 = *current_ptr++;
297
+    core_regset->r12 = *current_ptr++;
298
+    core_regset->lr = *current_ptr++;
299
+    core_regset->pc = *current_ptr++;
300
+    core_regset->xpsr = *current_ptr++;
301
+
302
+#if MCD_FPU_SUPPORT
303
+    /* If FPU context is active, d0-d7 and FPSCR are saved after exception frame */
304
+    if (fpu_flag)
305
+    {
306
+        /* Copy FPU d0-d7 registers (hardware saved by ARM Cortex-M) */
307
+        /* Each double precision register is 64 bits = 2 words */
308
+        uint64_t *fp_d_ptr = (uint64_t *)current_ptr;
309
+        for (int i = 0; i < 8; i++)  /* d0-d7 = 8 registers */
310
+        {
311
+            (&fp_regset->d0)[i] = *fp_d_ptr++;
312
+        }
313
+        current_ptr = (uint32_t *)fp_d_ptr;
314
+        
315
+        /* Copy FPSCR register (FPU status and control) */
316
+        fp_regset->fpscr = *current_ptr++;
317
+        
318
+        /* Skip NO_NAME field (reserved/alignment) */
319
+        current_ptr++;
320
+    }
321
+#endif
322
+
323
+    /* SP should point to the current stack pointer position after all saved data */
324
+    core_regset->sp = (uintptr_t)current_ptr;
325
+}
326
+
327
+/**
328
+ * @brief ARM Cortex-M33 specific hard fault exception handler for MCoreDump
329
+ * 
330
+ * This function handles ARM Cortex-M33 specific stack frame processing when a 
331
+ * hard fault occurs. It follows the armv7m approach for simple and reliable
332
+ * stack pointer calculation.
333
+ * 
334
+ * HardFault Stack Frame Layout (created by HardFault_Handler):
335
+ * +-------------------+  <- Exception occurs here
336
+ * | Hardware Exception|  (32 bytes: r0,r1,r2,r3,r12,lr,pc,xpsr)
337
+ * | Stack Frame       |  (+ optional 72 bytes FPU: s0-s15,FPSCR,NO_NAME)
338
+ * +-------------------+  <- context parameter points here
339
+ * | r11               |  (4 bytes, software saved in HardFault_Handler)
340
+ * | r10               |  (4 bytes, software saved in HardFault_Handler)
341
+ * | ...               |  (...)
342
+ * | r4                |  (4 bytes, software saved in HardFault_Handler)
343
+ * +-------------------+
344
+ * | FPU s31           |  (4 bytes, if FPU context active)
345
+ * | FPU s30           |  (4 bytes, if FPU context active)
346
+ * | ...               |  (...)
347
+ * | FPU s16           |  (4 bytes, if FPU context active)
348
+ * +-------------------+
349
+ * | FPU flag          |  (4 bytes, if MCD_FPU_SUPPORT enabled)
350
+ * +-------------------+  <- Target position for collect_registers_armv8m
351
+ *
352
+ * @param context Pointer to exception_stack_frame from HardFault_Handler
353
+ * @return int Always returns 0 after processing coredump
354
+ */
355
+int armv8m_hard_fault_exception_hook(void *context)
356
+{
357
+    /* Add debug output to confirm we reach this function */
358
+    mcd_print("armv8m_hard_fault_exception_hook called, context = 0x%08x\n", (uint32_t)context);
359
+    
360
+    /* 
361
+     * Based on HardFault_Handler implementation in context_gcc.S:
362
+     * 
363
+     * For EXCEPTION context (HardFault_Handler):
364
+     * Stack layout from context (exception_stack_frame) backwards:
365
+     * context -> [r0,r1,r2,r3,r12,lr,pc,xpsr] (exception frame)
366
+     * context-32 -> [r11,r10,r9,r8,r7,r6,r5,r4] (8 words, STMFD r0!, {r4-r11})
367
+     * context-48 -> [tz,lr,psplim,control] (4 words, STMFD r0!, {r2-r5})  
368
+     * context-52 -> [EXC_RETURN] (1 word, STMFD r0!, {lr})
369
+     * 
370
+     * We need to point to EXC_RETURN for collect_registers_armv8m
371
+     */
372
+
373
+    uint32_t *stack_ptr = (uint32_t *)context;
374
+    
375
+    /* Move backwards to find EXC_RETURN position */
376
+    stack_ptr -= 8;  /* r4-r11 (8 registers) */
377
+    stack_ptr -= 4;  /* tz, lr, psplim, control (4 fields) */  
378
+    stack_ptr -= 1;  /* EXC_RETURN */
379
+
380
+#ifdef RT_USING_FINSH
381
+    extern long list_thread(void);
382
+    list_thread();
383
+#endif
384
+
385
+    /* Now stack_ptr points to EXC_RETURN, which is what collect_registers_armv8m expects */
386
+    collect_registers_armv8m(stack_ptr,
387
+                           get_cur_core_regset_address(),
388
+                           get_cur_fp_regset_address());
389
+
390
+    /* Generate coredump using memory mode */
391
+    mcd_faultdump(MCD_OUTPUT_MEMORY);
392
+
393
+    return 0;
394
+}

+ 69
- 0
Middlewares/MCoreDump/arch/armv8m/registers.h Visa fil

@@ -0,0 +1,69 @@
1
+/*
2
+ * Copyright (c) 2025, RT-Thread Development Team
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ *
6
+ * Change Logs:
7
+ * Date           Author       Notes
8
+ * 2025-08-16     Rbb666       first version
9
+ */
10
+
11
+#ifndef __REGISTERS_H__
12
+#define __REGISTERS_H__
13
+
14
+#include <stdint.h>
15
+
16
+#ifdef __cplusplus
17
+extern "C" {
18
+#endif
19
+
20
+struct armv8m_core_regset
21
+{
22
+    uint32_t r0;
23
+    uint32_t r1;
24
+    uint32_t r2;
25
+    uint32_t r3;
26
+    uint32_t r4;
27
+    uint32_t r5;
28
+    uint32_t r6;
29
+    uint32_t r7;
30
+    uint32_t r8;
31
+    uint32_t r9;
32
+    uint32_t r10;
33
+    uint32_t r11;
34
+    uint32_t r12;
35
+    uint32_t sp;
36
+    uint32_t lr;
37
+    uint32_t pc;
38
+    uint32_t xpsr;
39
+};
40
+
41
+struct arm_vfpv2_regset
42
+{
43
+    uint64_t d0;
44
+    uint64_t d1;
45
+    uint64_t d2;
46
+    uint64_t d3;
47
+    uint64_t d4;
48
+    uint64_t d5;
49
+    uint64_t d6;
50
+    uint64_t d7;
51
+    uint64_t d8;
52
+    uint64_t d9;
53
+    uint64_t d10;
54
+    uint64_t d11;
55
+    uint64_t d12;
56
+    uint64_t d13;
57
+    uint64_t d14;
58
+    uint64_t d15;
59
+    uint32_t fpscr;
60
+};
61
+
62
+typedef struct armv8m_core_regset    core_regset_type;
63
+typedef struct arm_vfpv2_regset      fp_regset_type;
64
+
65
+#ifdef __cplusplus
66
+}
67
+#endif
68
+
69
+#endif /* __MCD_REGISTERS_H__ */

+ 67
- 0
Middlewares/MCoreDump/arch/mcd_arch_interface.h Visa fil

@@ -0,0 +1,67 @@
1
+/*
2
+ * Copyright (c) 2025, RT-Thread Development Team
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ *
6
+ * Change Logs:
7
+ * Date           Author       Notes
8
+ * 2025-08-16     Rbb666       first version
9
+ */
10
+
11
+#ifndef __MCD_ARCH_INTERFACE_H__
12
+#define __MCD_ARCH_INTERFACE_H__
13
+
14
+#include <stdint.h>
15
+
16
+/**
17
+ * @brief Architecture-specific hard fault exception handler
18
+ * 
19
+ * This function should be implemented by each supported architecture
20
+ * to handle the architecture-specific stack frame processing.
21
+ * 
22
+ * @param context Pointer to exception context (architecture-specific format)
23
+ * @return int Always returns -1 to indicate fault condition
24
+ */
25
+#ifdef PKG_USING_MCOREDUMP_ARCH_ARMV7M
26
+int armv7m_hard_fault_exception_hook(void *context);
27
+
28
+/**
29
+ * @brief Architecture-specific register collection function
30
+ * 
31
+ * This function extracts register values from the architecture-specific
32
+ * stack frame format and stores them in the standard register sets.
33
+ * 
34
+ * @param stack_top Pointer to the stack frame
35
+ * @param core_regset Pointer to store ARM core registers  
36
+ * @param fp_regset Pointer to store FPU registers
37
+ */
38
+void collect_registers_armv7m(uint32_t *stack_top,
39
+                             core_regset_type *core_regset,
40
+                             fp_regset_type *fp_regset);
41
+
42
+/* Generic interface macro for architecture-agnostic code */
43
+#define collect_registers collect_registers_armv7m
44
+#endif
45
+
46
+#ifdef PKG_USING_MCOREDUMP_ARCH_ARMV8M
47
+int armv8m_hard_fault_exception_hook(void *context);
48
+
49
+/**
50
+ * @brief Architecture-specific register collection function
51
+ * 
52
+ * This function extracts register values from the architecture-specific
53
+ * stack frame format and stores them in the standard register sets.
54
+ * 
55
+ * @param stack_top Pointer to the stack frame
56
+ * @param core_regset Pointer to store ARM core registers  
57
+ * @param fp_regset Pointer to store FPU registers
58
+ */
59
+void collect_registers_armv8m(uint32_t *stack_top,
60
+                             core_regset_type *core_regset,
61
+                             fp_regset_type *fp_regset);
62
+
63
+/* Generic interface macro for architecture-agnostic code */
64
+#define collect_registers collect_registers_armv8m
65
+#endif
66
+
67
+#endif /* __MCD_ARCH_INTERFACE_H__ */

+ 69
- 0
Middlewares/MCoreDump/example/mcd_example.c Visa fil

@@ -0,0 +1,69 @@
1
+/*
2
+ * Copyright (c) 2025, RT-Thread Development Team
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ *
6
+ * Change Logs:
7
+ * Date           Author       Notes
8
+ * 2025-08-16     Rbb666       first version
9
+ */
10
+
11
+#include <math.h>
12
+#include <stdlib.h>
13
+#include <string.h>
14
+#include "coredump.h"
15
+
16
+typedef void (*fault_func)(float);
17
+
18
+static int mcd_test(int argc, char **argv)
19
+{
20
+    int x, y;
21
+    const char * sx = "84597";
22
+    const char * sy = "35268";
23
+
24
+    float a, b, c;
25
+    const char * fsa = "1.1322";
26
+    const char * fsb = "45.2547";
27
+    const char * fsc = "7854.2";
28
+
29
+    if (argc < 2)
30
+    {
31
+        rt_kprintf("Please input 'mcd_test <COREDUMP|ASSERT|FAULT>' \n");
32
+        return 0;
33
+    }
34
+
35
+    if (!strcmp(argv[1], "COREDUMP"))
36
+    {
37
+        mcd_faultdump(MCD_OUTPUT_SERIAL);
38
+        return 0;
39
+    }
40
+    else if (!strcmp(argv[1], "ASSERT"))
41
+    {
42
+        a = atof(&fsa[0]);
43
+        b = atof(&fsb[0]);
44
+        c = atof(&fsc[0]);
45
+
46
+        x = atoi(&sx[0]);
47
+        y = atoi(&sy[0]);
48
+
49
+        mcd_assert(x * a == y * b * c);
50
+        return 0;
51
+    }
52
+    else if (!strcmp(argv[1], "FAULT"))
53
+    {
54
+        fault_func func = (fault_func)0xFFFF0000;
55
+        
56
+        a = atof(&fsa[0]);
57
+        b = atof(&fsb[0]);
58
+        c = atof(&fsc[0]);
59
+
60
+        x = atoi(&sx[0]);
61
+        y = atoi(&sy[0]);
62
+
63
+        func(x * a + y * b * c);
64
+        return 0;
65
+    }
66
+    
67
+    return 0;
68
+}
69
+MCD_CMD_EXPORT(mcd_test, mCoreDump test: mcd_test <COREDUMP|FLOAT|ASSERT|FAULT>);

+ 245
- 0
Middlewares/MCoreDump/inc/coredump.h Visa fil

@@ -0,0 +1,245 @@
1
+/*
2
+ * Copyright (c) 2025, RT-Thread Development Team
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ *
6
+ * Change Logs:
7
+ * Date           Author       Notes
8
+ * 2025-08-16     Rbb666       first version
9
+ */
10
+
11
+#ifndef __COREDUMP_H__
12
+#define __COREDUMP_H__
13
+
14
+#include "mcd_cfg.h"
15
+#include "mcd_arm_define.h"
16
+
17
+/**
18
+ * @brief Function pointer type for coredump data output
19
+ * 
20
+ * This function pointer type defines the interface for writing coredump data
21
+ * to different output destinations (memory, serial, filesystem, etc.).
22
+ * 
23
+ * @param data Pointer to the data buffer to be written
24
+ * @param len Length of the data buffer in bytes
25
+ * 
26
+ * @note The implementation should handle the data appropriately based on the
27
+ *       chosen output mode and ensure data integrity.
28
+ */
29
+typedef void (*mcd_writeout_func_t)(uint8_t *, int);
30
+
31
+/**
32
+ * @brief Thread information operations structure
33
+ * 
34
+ * This structure contains function pointers for retrieving thread information
35
+ * in a RTOS environment. It's designed to avoid dynamic memory allocation
36
+ * during fault handling, as malloc operations may fail during hard faults.
37
+ * 
38
+ * The structure provides a generic interface for different RTOS systems
39
+ * to supply thread information for multi-threaded coredump generation.
40
+ */
41
+struct thread_info_ops
42
+{
43
+    /**
44
+     * @brief Get total number of threads in the system
45
+     * @param ops Pointer to this operations structure
46
+     * @return Total thread count
47
+     */
48
+    int32_t (*get_threads_count)(struct thread_info_ops *);
49
+    
50
+    /**
51
+     * @brief Get current executing thread index
52
+     * @param ops Pointer to this operations structure  
53
+     * @return Current thread index
54
+     */
55
+    int32_t (*get_current_thread_idx)(struct thread_info_ops *);
56
+    
57
+    /**
58
+     * @brief Get register set for a specific thread
59
+     * @param ops Pointer to this operations structure
60
+     * @param thread_idx Thread index to get registers for
61
+     * @param core_regset Pointer to store ARM core registers
62
+     * @param fp_regset Pointer to store FPU registers
63
+     */
64
+    void (*get_thread_regset)(struct thread_info_ops *, int32_t,
65
+                              core_regset_type *core_regset,
66
+                              fp_regset_type *fp_regset);
67
+    
68
+    /**
69
+     * @brief Get number of memory areas to dump
70
+     * @param ops Pointer to this operations structure
71
+     * @return Number of memory areas
72
+     */
73
+    int32_t (*get_memarea_count)(struct thread_info_ops *);
74
+    
75
+    /**
76
+     * @brief Get memory area information
77
+     * @param ops Pointer to this operations structure
78
+     * @param area_idx Memory area index
79
+     * @param addr Pointer to store memory area start address
80
+     * @param size Pointer to store memory area size
81
+     * @return 0 on success, negative on error
82
+     */
83
+    int32_t (*get_memarea)(struct thread_info_ops *, int32_t,
84
+                           uint32_t *, uint32_t *);
85
+    
86
+    /** Private data for RTOS-specific implementations */
87
+    void *priv;
88
+};
89
+
90
+/**
91
+ * @brief Initialize the mCoreDump system
92
+ *
93
+ * This function initializes the mCoreDump system with automatic FPU detection.
94
+ * It must be called before any coredump generation operations.
95
+ *
96
+ * FPU support is automatically detected based on compiler definitions:
97
+ * - Enabled if __VFP_FP__ is defined and __SOFTFP__ is not defined
98
+ * - Disabled if no hardware FPU support is detected
99
+ *
100
+ * @param func Function pointer to write the coredump data out.
101
+ *             This callback will be called repeatedly with chunks of coredump data.
102
+ *
103
+ * @note The writeout function should handle data appropriately based on the
104
+ *       chosen output mode (memory, serial, filesystem).
105
+ *
106
+ * @warning This function should be called from a safe context, preferably
107
+ *          during system initialization or before fault occurs.
108
+ *
109
+ * @see mcd_writeout_func_t for callback function requirements
110
+ */
111
+void mcd_init(mcd_writeout_func_t func);
112
+
113
+/**
114
+ * @brief Generate coredump for current call chain only
115
+ *
116
+ * This function generates a minimal coredump containing only the current
117
+ * execution context (single thread). It's faster and uses less memory
118
+ * compared to multi-threaded coredump generation.
119
+ *
120
+ * Use this function when:
121
+ * - Quick fault analysis is needed
122
+ * - Memory is limited
123
+ * - Only current thread context is relevant
124
+ *
125
+ * @note This function captures the current thread's register state and
126
+ *       stack information at the point of call.
127
+ *
128
+ * @warning Must call mcd_init() before using this function.
129
+ *
130
+ * @see mcd_multi_dump() for full system coredump
131
+ */
132
+void mcd_mini_dump(void);
133
+
134
+/**
135
+ * @brief Generate coredump with all threads information
136
+ *
137
+ * This function generates a comprehensive coredump containing information
138
+ * about all threads in the system, including their register states,
139
+ * stack contents, and memory areas.
140
+ *
141
+ * Use this function when:
142
+ * - Complete system state analysis is needed
143
+ * - Multi-threading issues need to be debugged
144
+ * - Full context switch information is required
145
+ *
146
+ * @note This function may take longer to execute and use more memory
147
+ *       compared to mcd_mini_dump().
148
+ *
149
+ * @warning Must call mcd_init() before using this function.
150
+ *          Should be used carefully in interrupt context due to execution time.
151
+ *
152
+ * @see mcd_mini_dump() for single thread coredump
153
+ */
154
+void mcd_multi_dump(void);
155
+
156
+/**
157
+ * @brief Generate coredump using provided thread operations
158
+ *
159
+ * This is the core coredump generation function that uses the provided
160
+ * thread_info_ops structure to gather system information and generate
161
+ * the ELF format coredump.
162
+ *
163
+ * @param ops Pointer to thread information operations structure.
164
+ *            Contains function pointers for retrieving thread and memory information.
165
+ *
166
+ * @note This is a low-level function typically called by mcd_mini_dump()
167
+ *       and mcd_multi_dump() after setting up appropriate ops structure.
168
+ *
169
+ * @warning The ops structure must be properly initialized with valid
170
+ *          function pointers before calling this function.
171
+ */
172
+void mcd_gen_coredump(struct thread_info_ops *ops);
173
+
174
+/**
175
+ * @brief Setup thread operations for RTOS environment
176
+ *
177
+ * This function initializes the thread_info_ops structure with function
178
+ * pointers appropriate for the current RTOS environment (RT-Thread).
179
+ *
180
+ * @param ops Pointer to thread operations structure to be initialized
181
+ *
182
+ * @note This function is typically called internally by mcd_multi_dump()
183
+ *       to set up multi-threaded coredump generation.
184
+ */
185
+void mcd_rtos_thread_ops(struct thread_info_ops *ops);
186
+
187
+/**
188
+ * @brief Setup thread operations for single thread dump
189
+ *
190
+ * This function initializes the thread_info_ops structure for minimal
191
+ * coredump generation (current thread only).
192
+ *
193
+ * @param ops Pointer to thread operations structure to be initialized
194
+ *
195
+ * @note This function is typically called internally by mcd_mini_dump()
196
+ *       to set up single-threaded coredump generation.
197
+ */
198
+void mcd_mini_dump_ops(struct thread_info_ops *ops);
199
+
200
+/**
201
+ * @brief           Generate coredump and save to specified output.
202
+ *
203
+ * @param[in]       output_mode Output mode (MCD_OUTPUT_SERIAL, MCD_OUTPUT_MEMORY, or MCD_OUTPUT_FILESYSTEM).
204
+ *
205
+ * @return          Whether save operation success.
206
+ * @retval          MCD_OK      success.
207
+ * @retval          MCD_ERROR   failed.
208
+ */
209
+int mcd_faultdump(mcd_output_mode_t output_mode);
210
+
211
+/**
212
+ * @brief Print coredump memory information at startup
213
+ *
214
+ * This function should be called during system initialization
215
+ */
216
+void mcd_print_memoryinfo(void);
217
+
218
+/**
219
+ * @brief Get address of current core register set
220
+ *
221
+ * This function returns a pointer to the current thread's core register
222
+ * set storage area. The register values are captured during fault handling.
223
+ *
224
+ * @return Pointer to core register set structure
225
+ *
226
+ * @note The returned pointer points to static storage that gets updated
227
+ *       each time a fault occurs or registers are captured.
228
+ */
229
+core_regset_type *get_cur_core_regset_address(void);
230
+
231
+/**
232
+ * @brief Get address of current floating-point register set
233
+ *
234
+ * This function returns a pointer to the current thread's floating-point
235
+ * register set storage area. The register values are captured during fault handling.
236
+ *
237
+ * @return Pointer to floating-point register set structure
238
+ *
239
+ * @note The returned pointer points to static storage that gets updated
240
+ *       each time a fault occurs or registers are captured.
241
+ *       Returns valid data only if FPU is available and enabled.
242
+ */
243
+fp_regset_type *get_cur_fp_regset_address(void);
244
+
245
+#endif /* __MCOREDUMP_H__ */

+ 229
- 0
Middlewares/MCoreDump/inc/mcd_cfg.h Visa fil

@@ -0,0 +1,229 @@
1
+/*
2
+ * Copyright (c) 2025, RT-Thread Development Team
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ *
6
+ * Change Logs:
7
+ * Date           Author       Notes
8
+ * 2025-08-16     Rbb666       Configuration file for mCoreDump
9
+ */
10
+
11
+#ifndef __MCD_CFG_H__
12
+#define __MCD_CFG_H__
13
+
14
+/*
15
+ * ===============================================================
16
+ * Operating System Detection and Abstraction Layer
17
+ * ===============================================================
18
+ */
19
+
20
+/* Auto-detect operating system */
21
+#ifdef __RTTHREAD__
22
+    #define MCD_OS_RTTHREAD    1
23
+    #include <rtthread.h>
24
+#else
25
+    #define MCD_OS_BAREMETAL   1
26
+    #include <stdint.h>
27
+    #include <stdbool.h>
28
+#endif
29
+
30
+#define MCD_ALIGN(x, y)  (((x - 1) / y + 1) * y)
31
+
32
+/*
33
+ * ===============================================================
34
+ * Print configuration - Printf function abstraction
35
+ * ===============================================================
36
+ */
37
+
38
+/* OS-specific print function abstraction */
39
+#ifdef MCD_OS_RTTHREAD
40
+/* RT-Thread print functions */
41
+#ifndef RT_USING_ULOG
42
+/* Use rt_kprintf directly */
43
+#define mcd_println(...)               rt_kprintf(__VA_ARGS__);rt_kprintf("\r\n")
44
+#define mcd_print(...)                 rt_kprintf(__VA_ARGS__)
45
+#else /* RT_USING_ULOG */
46
+/* Use ulog for unified logging */
47
+#include <ulog.h>
48
+#define MCD_LOG_TAG                    "mcd"
49
+#define mcd_println(...)               ulog_e(MCD_LOG_TAG, __VA_ARGS__);ulog_flush()
50
+#define mcd_print(...)                 ulog_raw(__VA_ARGS__)
51
+#endif /* RT_USING_ULOG */
52
+#else
53
+/* Bare metal - use standard printf or define custom */
54
+#include <stdio.h>
55
+#define mcd_println(...)               printf(__VA_ARGS__);printf("\r\n")
56
+#define mcd_print(...)                 printf(__VA_ARGS__)
57
+#endif /* MCD_OS_RTTHREAD */
58
+
59
+/*
60
+ * ===============================================================
61
+ * Memory management abstraction
62
+ * ===============================================================
63
+ */
64
+
65
+#ifdef MCD_OS_RTTHREAD
66
+#define mcd_malloc(size)               rt_malloc(size)
67
+#define mcd_free(ptr)                  rt_free(ptr)
68
+#define mcd_memset(ptr, val, size)     rt_memset(ptr, val, size)
69
+#define mcd_memcpy(dst, src, size)     rt_memcpy(dst, src, size)
70
+#else
71
+/* Standard C library */
72
+#include <stdlib.h>
73
+#include <string.h>
74
+#define mcd_malloc(size)               malloc(size)
75
+#define mcd_free(ptr)                  free(ptr)
76
+#define mcd_memset(ptr, val, size)     memset(ptr, val, size)
77
+#define mcd_memcpy(dst, src, size)     memcpy(dst, src, size)
78
+#endif
79
+
80
+/*
81
+ * ===============================================================
82
+ * Interrupt control abstraction
83
+ * ===============================================================
84
+ */
85
+
86
+#ifdef MCD_OS_RTTHREAD
87
+typedef rt_base_t mcd_irq_state_t;
88
+#define mcd_irq_disable()              rt_hw_interrupt_disable()
89
+#define mcd_irq_enable(state)          rt_hw_interrupt_enable(state)
90
+#else
91
+/* Bare metal - define as needed for specific platform */
92
+typedef uint32_t mcd_irq_state_t;
93
+#define mcd_irq_disable()              __disable_irq();
94
+#define mcd_irq_enable(state)          __enable_irq()
95
+#endif
96
+
97
+/*
98
+ * ===============================================================
99
+ * Command export abstraction
100
+ * ===============================================================
101
+ */
102
+
103
+#ifdef MCD_OS_RTTHREAD
104
+#define MCD_CMD_EXPORT(cmd, desc)      MSH_CMD_EXPORT(cmd, desc)
105
+#else
106
+/* Other OS or bare metal */
107
+#define MCD_CMD_EXPORT(cmd, desc)      /* No command export */
108
+#endif
109
+
110
+/*
111
+ * ===============================================================
112
+ * Boolean type abstraction
113
+ * ===============================================================
114
+ */
115
+
116
+#ifdef MCD_OS_RTTHREAD
117
+#define mcd_bool_t                     rt_bool_t
118
+#define MCD_TRUE                       RT_TRUE
119
+#define MCD_FALSE                      RT_FALSE
120
+#else
121
+#include <stdbool.h>
122
+#define mcd_bool_t                     bool
123
+#define MCD_TRUE                       true
124
+#define MCD_FALSE                      false
125
+#endif
126
+
127
+/*
128
+ * ===============================================================
129
+ * ASSERT type abstraction
130
+ * ===============================================================
131
+ */
132
+
133
+#ifdef MCD_OS_RTTHREAD
134
+#define mcd_assert(expr)               RT_ASSERT(expr)
135
+#else
136
+#include <assert.h>
137
+#define mcd_assert(expr)               assert(expr)
138
+#endif /* MCD_OS_RTTHREAD */
139
+
140
+/*
141
+ * ===============================================================
142
+ * Weak attribute abstraction
143
+ * ===============================================================
144
+ */
145
+
146
+#ifdef MCD_OS_RTTHREAD
147
+#ifndef RT_WEAK
148
+#define MCD_WEAK                   rt_weak
149
+#else
150
+#define MCD_WEAK                   RT_WEAK
151
+#endif /* RT_WEAK */
152
+#else
153
+/* Standard GCC weak attribute */
154
+#define MCD_WEAK                       __attribute__((weak))
155
+#endif /* MCD_OS_RTTHREAD */
156
+
157
+/*
158
+ * ===============================================================
159
+ * Floating Point Unit (FPU) configuration
160
+ * ===============================================================
161
+ */
162
+
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__)) )
168
+#define MCD_FPU_SUPPORT          1    /* FPU supported and enabled */
169
+#else
170
+#define MCD_FPU_SUPPORT          0    /* No FPU support */
171
+#endif
172
+
173
+/*
174
+ * ===============================================================
175
+ * Memory configuration
176
+ * ===============================================================
177
+ */
178
+
179
+/* Default memory buffer size (can be overridden by Kconfig) */
180
+#ifndef PKG_MCOREDUMP_MEMORY_SIZE
181
+#define MCD_DEFAULT_MEMORY_SIZE           (8 * 1024)    /* Default 8KB */
182
+#else
183
+#define MCD_DEFAULT_MEMORY_SIZE           PKG_MCOREDUMP_MEMORY_SIZE
184
+#endif /* PKG_MCOREDUMP_MEMORY_SIZE */
185
+
186
+/*
187
+ * ===============================================================
188
+ * Filesystem configuration
189
+ * ===============================================================
190
+ */
191
+
192
+#ifdef PKG_USING_MCOREDUMP_FILESYSTEM
193
+/* Default filesystem settings */
194
+#ifndef PKG_MCOREDUMP_FILESYSTEM_DIR
195
+#define MCD_DEFAULT_COREDUMP_DIR      "/sdcard"
196
+#else
197
+#define MCD_DEFAULT_COREDUMP_DIR      PKG_MCOREDUMP_FILESYSTEM_DIR
198
+#endif /* PKG_MCOREDUMP_FILESYSTEM_DIR*/
199
+
200
+#ifndef PKG_MCOREDUMP_FILESYSTEM_PREFIX
201
+#define MCD_DEFAULT_COREDUMP_PREFIX   "core_"
202
+#else
203
+#define MCD_DEFAULT_COREDUMP_PREFIX   PKG_MCOREDUMP_FILESYSTEM_PREFIX
204
+#endif /* PKG_MCOREDUMP_FILESYSTEM_PREFIX */
205
+
206
+#define MCD_DEFAULT_COREDUMP_EXT          ".elf"
207
+#endif /* PKG_USING_MCOREDUMP_FILESYSTEM */
208
+
209
+/*
210
+ * ===============================================================
211
+ * Output mode definitions
212
+ * ===============================================================
213
+ */
214
+
215
+/* Coredump output modes */
216
+typedef enum {
217
+    MCD_OUTPUT_SERIAL = 0,                /* Output via serial port */
218
+    MCD_OUTPUT_MEMORY,                    /* Store in memory buffer */
219
+    MCD_OUTPUT_FILESYSTEM,                /* Save to filesystem */
220
+    MCD_OUTPUT_FLASH                      /* Store in flash (reserved) */
221
+} mcd_output_mode_t;
222
+
223
+/* Return codes */
224
+enum {
225
+    MCD_ERROR = -1,
226
+    MCD_OK = 0,
227
+};
228
+
229
+#endif /* __MCD_CFG_H__ */

+ 472
- 0
Middlewares/MCoreDump/inc/mcd_elf_define.h Visa fil

@@ -0,0 +1,472 @@
1
+/*
2
+ * Copyright (c) 2025, RT-Thread Development Team
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ *
6
+ * Change Logs:
7
+ * Date           Author       Notes
8
+ * 2025-08-16     Rbb666       first version
9
+ */
10
+
11
+#ifndef __MCD_ELF_DEFINE_H__
12
+#define __MCD_ELF_DEFINE_H__
13
+
14
+/* Fields in e_ident[].  */
15
+#define EI_MAG0 0    /* File identification byte 0 index */
16
+#define ELFMAG0 0x7F /* Magic number byte 0 */
17
+
18
+#define EI_MAG1 1   /* File identification byte 1 index */
19
+#define ELFMAG1 'E' /* Magic number byte 1 */
20
+
21
+#define EI_MAG2 2   /* File identification byte 2 index */
22
+#define ELFMAG2 'L' /* Magic number byte 2 */
23
+
24
+#define EI_MAG3 3   /* File identification byte 3 index */
25
+#define ELFMAG3 'F' /* Magic number byte 3 */
26
+
27
+#define EI_CLASS 4     /* File class */
28
+#define ELFCLASSNONE 0 /* Invalid class */
29
+#define ELFCLASS32 1   /* 32-bit objects */
30
+#define ELFCLASS64 2   /* 64-bit objects */
31
+
32
+#define EI_DATA 5     /* Data encoding */
33
+#define ELFDATANONE 0 /* Invalid data encoding */
34
+#define ELFDATA2LSB 1 /* 2's complement, little endian */
35
+#define ELFDATA2MSB 2 /* 2's complement, big endian */
36
+
37
+#define EI_VERSION 6 /* File version */
38
+
39
+#define EI_OSABI 7           /* Operating System/ABI indication */
40
+#define ELFOSABI_NONE 0      /* UNIX System V ABI */
41
+#define ELFOSABI_HPUX 1      /* HP-UX operating system */
42
+#define ELFOSABI_NETBSD 2    /* NetBSD */
43
+#define ELFOSABI_GNU 3       /* GNU */
44
+#define ELFOSABI_LINUX 3     /* Alias for ELFOSABI_GNU */
45
+#define ELFOSABI_SOLARIS 6   /* Solaris */
46
+#define ELFOSABI_AIX 7       /* AIX */
47
+#define ELFOSABI_IRIX 8      /* IRIX */
48
+#define ELFOSABI_FREEBSD 9   /* FreeBSD */
49
+#define ELFOSABI_TRU64 10    /* TRU64 UNIX */
50
+#define ELFOSABI_MODESTO 11  /* Novell Modesto */
51
+#define ELFOSABI_OPENBSD 12  /* OpenBSD */
52
+#define ELFOSABI_OPENVMS 13  /* OpenVMS */
53
+#define ELFOSABI_NSK 14      /* Hewlett-Packard Non-Stop Kernel */
54
+#define ELFOSABI_AROS 15     /* AROS */
55
+#define ELFOSABI_FENIXOS 16  /* FenixOS */
56
+#define ELFOSABI_CLOUDABI 17 /* Nuxi CloudABI */
57
+#define ELFOSABI_OPENVOS 18  /* Stratus Technologies OpenVOS */
58
+
59
+#define ELFOSABI_C6000_ELFABI 64 /* Bare-metal TMS320C6000 */
60
+#define ELFOSABI_C6000_LINUX 65  /* Linux TMS320C6000 */
61
+#define ELFOSABI_ARM_FDPIC 65    /* ARM FDPIC */
62
+#define ELFOSABI_ARM 97          /* ARM */
63
+#define ELFOSABI_STANDALONE 255  /* Standalone (embedded) application */
64
+
65
+#define EI_ABIVERSION 8 /* ABI version */
66
+
67
+#define EI_PAD 9 /* Start of padding bytes */
68
+
69
+#define EI_NIDENT 16
70
+
71
+/* Values for e_type, which identifies the object file type.  */
72
+
73
+#define ET_NONE 0 /* No file type */
74
+#define ET_REL 1  /* Relocatable file */
75
+#define ET_EXEC 2 /* Position-dependent executable file */
76
+#define ET_DYN                                                                 \
77
+  3                      /* Position-independent executable or                 \
78
+                    shared object file */
79
+#define ET_CORE 4        /* Core file */
80
+#define ET_LOOS 0xFE00   /* Operating system-specific */
81
+#define ET_HIOS 0xFEFF   /* Operating system-specific */
82
+#define ET_LOPROC 0xFF00 /* Processor-specific */
83
+#define ET_HIPROC 0xFFFF /* Processor-specific */
84
+
85
+/* Values for e_machine, which identifies the architecture.  These numbers
86
+   are officially assigned by registry@sco.com.  See below for a list of
87
+   ad-hoc numbers used during initial development.  */
88
+
89
+#define EM_NONE 0  /* No machine */
90
+#define EM_M32 1   /* AT&T WE 32100 */
91
+#define EM_SPARC 2 /* SUN SPARC */
92
+#define EM_386 3   /* Intel 80386 */
93
+#define EM_68K 4   /* Motorola m68k family */
94
+#define EM_88K 5   /* Motorola m88k family */
95
+#define EM_IAMCU 6 /* Intel MCU */
96
+#define EM_860 7   /* Intel 80860 */
97
+#define EM_MIPS 8  /* MIPS R3000 (officially, big-endian only) */
98
+#define EM_S370 9  /* IBM System/370 */
99
+#define EM_MIPS_RS3_LE                                                         \
100
+  10 /* MIPS R3000 little-endian (Oct 4 1999 Draft).  Deprecated.  */
101
+#define EM_OLD_SPARCV9                                                         \
102
+  11 /* Old version of Sparc v9, from before the ABI.  Deprecated.  */
103
+#define EM_res011 11      /* Reserved */
104
+#define EM_res012 12      /* Reserved */
105
+#define EM_res013 13      /* Reserved */
106
+#define EM_res014 14      /* Reserved */
107
+#define EM_PARISC 15      /* HPPA */
108
+#define EM_res016 16      /* Reserved */
109
+#define EM_PPC_OLD 17     /* Old version of PowerPC.  Deprecated.  */
110
+#define EM_VPP550 17      /* Fujitsu VPP500 */
111
+#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */
112
+#define EM_960 19         /* Intel 80960 */
113
+#define EM_PPC 20         /* PowerPC */
114
+#define EM_PPC64 21       /* 64-bit PowerPC */
115
+#define EM_S390 22        /* IBM S/390 */
116
+#define EM_SPU 23         /* Sony/Toshiba/IBM SPU */
117
+#define EM_res024 24      /* Reserved */
118
+#define EM_res025 25      /* Reserved */
119
+#define EM_res026 26      /* Reserved */
120
+#define EM_res027 27      /* Reserved */
121
+#define EM_res028 28      /* Reserved */
122
+#define EM_res029 29      /* Reserved */
123
+#define EM_res030 30      /* Reserved */
124
+#define EM_res031 31      /* Reserved */
125
+#define EM_res032 32      /* Reserved */
126
+#define EM_res033 33      /* Reserved */
127
+#define EM_res034 34      /* Reserved */
128
+#define EM_res035 35      /* Reserved */
129
+#define EM_V800 36        /* NEC V800 series */
130
+#define EM_FR20 37        /* Fujitsu FR20 */
131
+#define EM_RH32 38        /* TRW RH32 */
132
+#define EM_MCORE                                                               \
133
+  39 /* Motorola M*Core */ /* May also be taken by Fujitsu MMA                 \
134
+                            */
135
+#define EM_RCE 39          /* Old name for MCore */
136
+#define EM_ARM 40          /* ARM */
137
+#define EM_OLD_ALPHA 41    /* Digital Alpha */
138
+#define EM_SH 42           /* Renesas (formerly Hitachi) / SuperH SH */
139
+#define EM_SPARCV9 43      /* SPARC v9 64-bit */
140
+#define EM_TRICORE 44      /* Siemens Tricore embedded processor */
141
+#define EM_ARC 45          /* ARC Cores */
142
+#define EM_H8_300 46       /* Renesas (formerly Hitachi) H8/300 */
143
+#define EM_H8_300H 47      /* Renesas (formerly Hitachi) H8/300H */
144
+#define EM_H8S 48          /* Renesas (formerly Hitachi) H8S */
145
+#define EM_H8_500 49       /* Renesas (formerly Hitachi) H8/500 */
146
+#define EM_IA_64 50        /* Intel IA-64 Processor */
147
+#define EM_MIPS_X 51       /* Stanford MIPS-X */
148
+#define EM_COLDFIRE 52     /* Motorola Coldfire */
149
+#define EM_68HC12 53       /* Motorola M68HC12 */
150
+#define EM_MMA 54          /* Fujitsu Multimedia Accelerator */
151
+#define EM_PCP 55          /* Siemens PCP */
152
+#define EM_NCPU 56         /* Sony nCPU embedded RISC processor */
153
+#define EM_NDR1 57         /* Denso NDR1 microprocessor */
154
+#define EM_STARCORE 58     /* Motorola Star*Core processor */
155
+#define EM_ME16 59         /* Toyota ME16 processor */
156
+#define EM_ST100 60        /* STMicroelectronics ST100 processor */
157
+#define EM_TINYJ 61        /* Advanced Logic Corp. TinyJ embedded processor */
158
+#define EM_X86_64 62       /* Advanced Micro Devices X86-64 processor */
159
+#define EM_PDSP 63         /* Sony DSP Processor */
160
+#define EM_PDP10 64        /* Digital Equipment Corp. PDP-10 */
161
+#define EM_PDP11 65        /* Digital Equipment Corp. PDP-11 */
162
+#define EM_FX66 66         /* Siemens FX66 microcontroller */
163
+#define EM_ST9PLUS 67     /* STMicroelectronics ST9+ 8/16 bit microcontroller */
164
+#define EM_ST7 68         /* STMicroelectronics ST7 8-bit microcontroller */
165
+#define EM_68HC16 69      /* Motorola MC68HC16 Microcontroller */
166
+#define EM_68HC11 70      /* Motorola MC68HC11 Microcontroller */
167
+#define EM_68HC08 71      /* Motorola MC68HC08 Microcontroller */
168
+#define EM_68HC05 72      /* Motorola MC68HC05 Microcontroller */
169
+#define EM_SVX 73         /* Silicon Graphics SVx */
170
+#define EM_ST19 74        /* STMicroelectronics ST19 8-bit cpu */
171
+#define EM_VAX 75         /* Digital VAX */
172
+#define EM_CRIS 76        /* Axis Communications 32-bit embedded processor */
173
+#define EM_JAVELIN 77     /* Infineon Technologies 32-bit embedded cpu */
174
+#define EM_FIREPATH 78    /* Element 14 64-bit DSP processor */
175
+#define EM_ZSP 79         /* LSI Logic's 16-bit DSP processor */
176
+#define EM_MMIX 80        /* Donald Knuth's educational 64-bit processor */
177
+#define EM_HUANY 81       /* Harvard's machine-independent format */
178
+#define EM_PRISM 82       /* SiTera Prism */
179
+#define EM_AVR 83         /* Atmel AVR 8-bit microcontroller */
180
+#define EM_FR30 84        /* Fujitsu FR30 */
181
+#define EM_D10V 85        /* Mitsubishi D10V */
182
+#define EM_D30V 86        /* Mitsubishi D30V */
183
+#define EM_V850 87        /* Renesas V850 (formerly NEC V850) */
184
+#define EM_M32R 88        /* Renesas M32R (formerly Mitsubishi M32R) */
185
+#define EM_MN10300 89     /* Matsushita MN10300 */
186
+#define EM_MN10200 90     /* Matsushita MN10200 */
187
+#define EM_PJ 91          /* picoJava */
188
+#define EM_OR1K 92        /* OpenRISC 1000 32-bit embedded processor */
189
+#define EM_ARC_COMPACT 93 /* ARC International ARCompact processor */
190
+#define EM_XTENSA 94      /* Tensilica Xtensa Architecture */
191
+#define EM_SCORE_OLD                                                           \
192
+  95 /* Old Sunplus S+core7 backend magic number. Written in the absence of    \
193
+        an ABI.  */
194
+#define EM_VIDEOCORE 95 /* Alphamosaic VideoCore processor */
195
+#define EM_TMM_GPP 96   /* Thompson Multimedia General Purpose Processor */
196
+#define EM_NS32K 97     /* National Semiconductor 32000 series */
197
+#define EM_TPC 98       /* Tenor Network TPC processor */
198
+#define EM_PJ_OLD 99    /* Old value for picoJava.  Deprecated.  */
199
+#define EM_SNP1K 99     /* Trebia SNP 1000 processor */
200
+#define EM_ST200 100    /* STMicroelectronics ST200 microcontroller */
201
+#define EM_IP2K 101     /* Ubicom IP2022 micro controller */
202
+#define EM_MAX 102      /* MAX Processor */
203
+#define EM_CR 103       /* National Semiconductor CompactRISC */
204
+#define EM_F2MC16 104   /* Fujitsu F2MC16 */
205
+#define EM_MSP430 105   /* TI msp430 micro controller */
206
+#define EM_BLACKFIN 106 /* ADI Blackfin */
207
+#define EM_SE_C33 107   /* S1C33 Family of Seiko Epson processors */
208
+#define EM_SEP 108      /* Sharp embedded microprocessor */
209
+#define EM_ARCA 109     /* Arca RISC Microprocessor */
210
+#define EM_UNICORE                                                             \
211
+  110 /* Microprocessor series from PKU-Unity Ltd. and MPRC of Peking          \
212
+         University */
213
+#define EM_EXCESS 111 /* eXcess: 16/32/64-bit configurable embedded CPU */
214
+#define EM_DXP 112    /* Icera Semiconductor Inc. Deep Execution Processor */
215
+#define EM_ALTERA_NIOS2 113 /* Altera Nios II soft-core processor */
216
+#define EM_CRX 114          /* National Semiconductor CRX */
217
+#define EM_CR16_OLD                                                            \
218
+  115 /* Old, value for National Semiconductor CompactRISC.  Deprecated.  */
219
+#define EM_XGATE 115 /* Motorola XGATE embedded processor */
220
+#define EM_C166 116  /* Infineon C16x/XC16x processor */
221
+#define EM_M16C 117  /* Renesas M16C series microprocessors */
222
+#define EM_DSPIC30F                                                            \
223
+  118             /* Microchip Technology dsPIC30F Digital Signal Controller */
224
+#define EM_CE 119 /* Freescale Communication Engine RISC core */
225
+#define EM_M32C 120       /* Renesas M32C series microprocessors */
226
+#define EM_res121 121     /* Reserved */
227
+#define EM_res122 122     /* Reserved */
228
+#define EM_res123 123     /* Reserved */
229
+#define EM_res124 124     /* Reserved */
230
+#define EM_res125 125     /* Reserved */
231
+#define EM_res126 126     /* Reserved */
232
+#define EM_res127 127     /* Reserved */
233
+#define EM_res128 128     /* Reserved */
234
+#define EM_res129 129     /* Reserved */
235
+#define EM_res130 130     /* Reserved */
236
+#define EM_TSK3000 131    /* Altium TSK3000 core */
237
+#define EM_RS08 132       /* Freescale RS08 embedded processor */
238
+#define EM_res133 133     /* Reserved */
239
+#define EM_ECOG2 134      /* Cyan Technology eCOG2 microprocessor */
240
+#define EM_SCORE 135      /* Sunplus Score */
241
+#define EM_SCORE7 135     /* Sunplus S+core7 RISC processor */
242
+#define EM_DSP24 136      /* New Japan Radio (NJR) 24-bit DSP Processor */
243
+#define EM_VIDEOCORE3 137 /* Broadcom VideoCore III processor */
244
+#define EM_LATTICEMICO32                                                       \
245
+  138                   /* RISC processor for Lattice FPGA architecture        \
246
+                         */
247
+#define EM_SE_C17 139   /* Seiko Epson C17 family */
248
+#define EM_TI_C6000 140 /* Texas Instruments TMS320C6000 DSP family */
249
+#define EM_TI_C2000 141 /* Texas Instruments TMS320C2000 DSP family */
250
+#define EM_TI_C5500 142 /* Texas Instruments TMS320C55x DSP family */
251
+#define EM_res143 143   /* Reserved */
252
+#define EM_TI_PRU 144   /* Texas Instruments Programmable Realtime Unit */
253
+#define EM_res145 145   /* Reserved */
254
+#define EM_res146 146   /* Reserved */
255
+#define EM_res147 147   /* Reserved */
256
+#define EM_res148 148   /* Reserved */
257
+#define EM_res149 149   /* Reserved */
258
+#define EM_res150 150   /* Reserved */
259
+#define EM_res151 151   /* Reserved */
260
+#define EM_res152 152   /* Reserved */
261
+#define EM_res153 153   /* Reserved */
262
+#define EM_res154 154   /* Reserved */
263
+#define EM_res155 155   /* Reserved */
264
+#define EM_res156 156   /* Reserved */
265
+#define EM_res157 157   /* Reserved */
266
+#define EM_res158 158   /* Reserved */
267
+#define EM_res159 159   /* Reserved */
268
+#define EM_MMDSP_PLUS                                                          \
269
+  160 /* STMicroelectronics 64bit VLIW Data Signal Processor */
270
+#define EM_CYPRESS_M8C 161 /* Cypress M8C microprocessor */
271
+#define EM_R32C 162        /* Renesas R32C series microprocessors */
272
+#define EM_TRIMEDIA 163    /* NXP Semiconductors TriMedia architecture family */
273
+#define EM_QDSP6 164       /* QUALCOMM DSP6 Processor */
274
+#define EM_8051 165        /* Intel 8051 and variants */
275
+#define EM_STXP7X 166      /* STMicroelectronics STxP7x family */
276
+#define EM_NDS32                                                               \
277
+  167 /* Andes Technology compact code size embedded RISC processor family */
278
+#define EM_ECOG1 168  /* Cyan Technology eCOG1X family */
279
+#define EM_ECOG1X 168 /* Cyan Technology eCOG1X family */
280
+#define EM_MAXQ30                                                              \
281
+  169                  /* Dallas Semiconductor MAXQ30 Core Micro-controllers   \
282
+                        */
283
+#define EM_XIMO16 170  /* New Japan Radio (NJR) 16-bit DSP Processor */
284
+#define EM_MANIK 171   /* M2000 Reconfigurable RISC Microprocessor */
285
+#define EM_CRAYNV2 172 /* Cray Inc. NV2 vector architecture */
286
+#define EM_RX 173      /* Renesas RX family */
287
+#define EM_METAG                                                               \
288
+  174 /* Imagination Technologies Meta processor architecture                  \
289
+       */
290
+#define EM_MCST_ELBRUS                                                         \
291
+  175                 /* MCST Elbrus general purpose hardware architecture */
292
+#define EM_ECOG16 176 /* Cyan Technology eCOG16 family */
293
+#define EM_CR16 177   /* National Semiconductor CompactRISC 16-bit processor */
294
+#define EM_ETPU 178   /* Freescale Extended Time Processing Unit */
295
+#define EM_SLE9X 179  /* Infineon Technologies SLE9X core */
296
+#define EM_L1OM 180   /* Intel L1OM */
297
+#define EM_K1OM 181   /* Intel K1OM */
298
+#define EM_INTEL182 182 /* Reserved by Intel */
299
+#define EM_AARCH64 183  /* ARM 64-bit architecture */
300
+#define EM_ARM184 184   /* Reserved by ARM */
301
+#define EM_AVR32 185    /* Atmel Corporation 32-bit microprocessor family */
302
+#define EM_STM8 186     /* STMicroeletronics STM8 8-bit microcontroller */
303
+#define EM_TILE64 187   /* Tilera TILE64 multicore architecture family */
304
+#define EM_TILEPRO 188  /* Tilera TILEPro multicore architecture family */
305
+#define EM_MICROBLAZE                                                          \
306
+  189                 /* Xilinx MicroBlaze 32-bit RISC soft processor core */
307
+#define EM_CUDA 190   /* NVIDIA CUDA architecture */
308
+#define EM_TILEGX 191 /* Tilera TILE-Gx multicore architecture family */
309
+#define EM_CLOUDSHIELD 192 /* CloudShield architecture family */
310
+#define EM_COREA_1ST                                                           \
311
+  193 /* KIPO-KAIST Core-A 1st generation processor family                     \
312
+       */
313
+#define EM_COREA_2ND                                                           \
314
+  194 /* KIPO-KAIST Core-A 2nd generation processor family                     \
315
+       */
316
+#define EM_ARC_COMPACT2 195 /* Synopsys ARCompact V2 */
317
+#define EM_OPEN8 196        /* Open8 8-bit RISC soft processor core */
318
+#define EM_RL78 197         /* Renesas RL78 family.  */
319
+#define EM_VIDEOCORE5 198   /* Broadcom VideoCore V processor */
320
+#define EM_78K0R 199        /* Renesas 78K0R.  */
321
+#define EM_56800EX                                                             \
322
+  200                   /* Freescale 56800EX Digital Signal Controller (DSC)   \
323
+                         */
324
+#define EM_BA1 201      /* Beyond BA1 CPU architecture */
325
+#define EM_BA2 202      /* Beyond BA2 CPU architecture */
326
+#define EM_XCORE 203    /* XMOS xCORE processor family */
327
+#define EM_MCHP_PIC 204 /* Microchip 8-bit PIC(r) family */
328
+#define EM_INTEL205 205 /* Reserved by Intel */
329
+#define EM_INTEL206 206 /* Reserved by Intel */
330
+#define EM_INTEL207 207 /* Reserved by Intel */
331
+#define EM_INTEL208 208 /* Reserved by Intel */
332
+#define EM_INTEL209 209 /* Reserved by Intel */
333
+#define EM_KM32 210     /* KM211 KM32 32-bit processor */
334
+#define EM_KMX32 211    /* KM211 KMX32 32-bit processor */
335
+#define EM_KMX16 212    /* KM211 KMX16 16-bit processor */
336
+#define EM_KMX8 213     /* KM211 KMX8 8-bit processor */
337
+#define EM_KVARC 214    /* KM211 KVARC processor */
338
+#define EM_CDP 215      /* Paneve CDP architecture family */
339
+#define EM_COGE 216     /* Cognitive Smart Memory Processor */
340
+#define EM_COOL 217     /* Bluechip Systems CoolEngine */
341
+#define EM_NORC 218     /* Nanoradio Optimized RISC */
342
+#define EM_CSR_KALIMBA 219 /* CSR Kalimba architecture family */
343
+#define EM_Z80 220         /* Zilog Z80 */
344
+#define EM_VISIUM 221      /* Controls and Data Services VISIUMcore processor */
345
+#define EM_FT32                                                                \
346
+  222 /* FTDI Chip FT32 high performance 32-bit RISC architecture */
347
+#define EM_MOXIE 223  /* Moxie processor family */
348
+#define EM_AMDGPU 224 /* AMD GPU architecture */
349
+#define EM_RISCV 243  /* RISC-V */
350
+#define EM_LANAI 244  /* Lanai 32-bit processor.  */
351
+#define EM_BPF 247    /* Linux BPF – in-kernel virtual machine.  */
352
+#define EM_NFP 250    /* Netronome Flow Processor.  */
353
+#define EM_CSKY 252   /* C-SKY processor family.  */
354
+
355
+/* Values of note segment descriptor types for core files.  */
356
+
357
+#define NT_PRSTATUS    1        /* Contains copy of prstatus struct */
358
+#define NT_FPREGSET    2        /* Contains copy of fpregset struct */
359
+#define NT_PRPSINFO    3        /* Contains copy of prpsinfo struct */
360
+#define NT_TASKSTRUCT    4        /* Contains copy of task struct */
361
+#define NT_AUXV        6        /* Contains copy of Elfxx_auxv_t */
362
+#define NT_PRXFPREG    0x46e62b7f    /* Contains a user_xfpregs_struct; */
363
+/*   note name must be "LINUX".  */
364
+#define NT_PPC_VMX    0x100        /* PowerPC Altivec/VMX registers */
365
+/*   note name must be "LINUX".  */
366
+#define NT_PPC_VSX    0x102        /* PowerPC VSX registers */
367
+/*   note name must be "LINUX".  */
368
+#define NT_PPC_TAR    0x103        /* PowerPC Target Address Register */
369
+/*   note name must be "LINUX".  */
370
+#define NT_PPC_PPR    0x104        /* PowerPC Program Priority Register */
371
+/*   note name must be "LINUX".  */
372
+#define NT_PPC_DSCR    0x105        /* PowerPC Data Stream Control Register */
373
+/*   note name must be "LINUX".  */
374
+#define NT_PPC_EBB    0x106        /* PowerPC Event Based Branch Registers */
375
+/*   note name must be "LINUX".  */
376
+#define NT_PPC_PMU    0x107        /* PowerPC Performance Monitor Registers */
377
+/*   note name must be "LINUX".  */
378
+#define NT_PPC_TM_CGPR    0x108        /* PowerPC TM checkpointed GPR Registers */
379
+/*   note name must be "LINUX".  */
380
+#define NT_PPC_TM_CFPR    0x109        /* PowerPC TM checkpointed FPR Registers */
381
+/*   note name must be "LINUX".  */
382
+#define NT_PPC_TM_CVMX    0x10a        /* PowerPC TM checkpointed VMX Registers */
383
+/*   note name must be "LINUX".  */
384
+#define NT_PPC_TM_CVSX    0x10b        /* PowerPC TM checkpointed VSX Registers */
385
+/*   note name must be "LINUX".  */
386
+#define NT_PPC_TM_SPR    0x10c        /* PowerPC TM Special Purpose Registers */
387
+/*   note name must be "LINUX".  */
388
+#define NT_PPC_TM_CTAR    0x10d        /* PowerPC TM checkpointed TAR */
389
+/*   note name must be "LINUX".  */
390
+#define NT_PPC_TM_CPPR    0x10e        /* PowerPC TM checkpointed PPR */
391
+/*   note name must be "LINUX".  */
392
+#define NT_PPC_TM_CDSCR    0x10f        /* PowerPC TM checkpointed Data SCR */
393
+/*   note name must be "LINUX".  */
394
+#define NT_386_TLS    0x200        /* x86 TLS information */
395
+/*   note name must be "LINUX".  */
396
+#define NT_386_IOPERM    0x201        /* x86 io permissions */
397
+/*   note name must be "LINUX".  */
398
+#define NT_X86_XSTATE    0x202        /* x86 XSAVE extended state */
399
+/*   note name must be "LINUX".  */
400
+#define NT_X86_CET    0x203        /* x86 CET state.  */
401
+/*   note name must be "LINUX".  */
402
+#define NT_S390_HIGH_GPRS 0x300        /* S/390 upper halves of GPRs  */
403
+/*   note name must be "LINUX".  */
404
+#define NT_S390_TIMER    0x301        /* S390 timer */
405
+/*   note name must be "LINUX".  */
406
+#define NT_S390_TODCMP    0x302        /* S390 TOD clock comparator */
407
+/*   note name must be "LINUX".  */
408
+#define NT_S390_TODPREG    0x303        /* S390 TOD programmable register */
409
+/*   note name must be "LINUX".  */
410
+#define NT_S390_CTRS    0x304        /* S390 control registers */
411
+/*   note name must be "LINUX".  */
412
+#define NT_S390_PREFIX    0x305        /* S390 prefix register */
413
+/*   note name must be "LINUX".  */
414
+#define NT_S390_LAST_BREAK      0x306   /* S390 breaking event address */
415
+/*   note name must be "LINUX".  */
416
+#define NT_S390_SYSTEM_CALL     0x307   /* S390 system call restart data */
417
+/*   note name must be "LINUX".  */
418
+#define NT_S390_TDB    0x308        /* S390 transaction diagnostic block */
419
+/*   note name must be "LINUX".  */
420
+#define NT_S390_VXRS_LOW    0x309    /* S390 vector registers 0-15 upper half */
421
+/*   note name must be "LINUX".  */
422
+#define NT_S390_VXRS_HIGH    0x30a    /* S390 vector registers 16-31 */
423
+/*   note name must be "LINUX".  */
424
+#define NT_S390_GS_CB    0x30b        /* s390 guarded storage registers */
425
+/*   note name must be "LINUX".  */
426
+#define NT_S390_GS_BC    0x30c        /* s390 guarded storage broadcast control block */
427
+/*   note name must be "LINUX".  */
428
+#define NT_ARM_VFP    0x400        /* ARM VFP registers */
429
+/* The following definitions should really use NT_AARCH_..., but defined
430
+   this way for compatibility with Linux.  */
431
+#define NT_ARM_TLS    0x401        /* AArch TLS registers */
432
+/*   note name must be "LINUX".  */
433
+#define NT_ARM_HW_BREAK    0x402        /* AArch hardware breakpoint registers */
434
+/*   note name must be "LINUX".  */
435
+#define NT_ARM_HW_WATCH    0x403        /* AArch hardware watchpoint registers */
436
+/*   note name must be "LINUX".  */
437
+#define NT_ARM_SVE    0x405        /* AArch SVE registers.  */
438
+/*   note name must be "LINUX".  */
439
+#define NT_ARM_PAC_MASK    0x406        /* AArch pointer authentication code masks */
440
+/*   note name must be "LINUX".  */
441
+#define NT_ARC_V2    0x600        /* ARC HS accumulator/extra registers.  */
442
+/*   note name must be "LINUX".  */
443
+#define NT_SIGINFO    0x53494749    /* Fields of siginfo_t.  */
444
+#define NT_FILE        0x46494c45    /* Description of mapped files.  */
445
+
446
+/* Values for program header, p_type field.  */
447
+
448
+#define PT_NULL        0        /* Program header table entry unused */
449
+#define PT_LOAD        1        /* Loadable program segment */
450
+#define PT_DYNAMIC    2        /* Dynamic linking information */
451
+#define PT_INTERP    3        /* Program interpreter */
452
+#define PT_NOTE        4        /* Auxiliary information */
453
+#define PT_SHLIB    5        /* Reserved, unspecified semantics */
454
+#define PT_PHDR        6        /* Entry for header table itself */
455
+#define PT_TLS        7        /* Thread local storage segment */
456
+#define PT_LOOS        0x60000000    /* OS-specific */
457
+#define PT_HIOS        0x6fffffff    /* OS-specific */
458
+#define PT_LOPROC    0x70000000    /* Processor-specific */
459
+#define PT_HIPROC    0x7FFFFFFF    /* Processor-specific */
460
+
461
+/* Program segment permissions, in program header p_flags field.  */
462
+
463
+#define PF_X        (1 << 0)    /* Segment is executable */
464
+#define PF_W        (1 << 1)    /* Segment is writable */
465
+#define PF_R        (1 << 2)    /* Segment is readable */
466
+/* #define PF_MASKOS    0x0F000000    *//* OS-specific reserved bits */
467
+#define PF_MASKOS    0x0FF00000    /* New value, Oct 4, 1999 Draft */
468
+#define PF_MASKPROC    0xF0000000    /* Processor-specific reserved bits */
469
+
470
+#define CORE_MEM_LINE_MASK  0xFFFFFFC0
471
+
472
+#endif /* __MCD_ELF_DEFINE_H__ */

+ 238
- 0
Middlewares/MCoreDump/osal/rtthread.c Visa fil

@@ -0,0 +1,238 @@
1
+/*
2
+ * Copyright (c) 2025, RT-Thread Development Team
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ *
6
+ * Change Logs:
7
+ * Date           Author       Notes
8
+ * 2025-08-16     Rbb666       first version
9
+ */
10
+
11
+#include <rtthread.h>
12
+#include "coredump.h"
13
+#include "mcd_arch_interface.h"
14
+
15
+/*
16
+ * RT-Thread OS abstraction layer implementation for MCoreDump
17
+ */
18
+typedef struct
19
+{
20
+    rt_int32_t thr_cnts;
21
+    rt_int32_t cur_idx;
22
+} rtthread_ti_priv_t;
23
+
24
+/* Architecture-specific exception hook function */
25
+#ifdef PKG_USING_MCOREDUMP_ARCH_ARMV7M
26
+#define arch_hard_fault_exception_hook armv7m_hard_fault_exception_hook
27
+#elif defined(PKG_USING_MCOREDUMP_ARCH_ARMV8M)
28
+#define arch_hard_fault_exception_hook armv8m_hard_fault_exception_hook
29
+#else
30
+#error "MCoredump does not support this architecture"
31
+#endif
32
+
33
+static rt_int32_t is_thread_object(rt_thread_t thread)
34
+{
35
+    /* Check if the object is a thread (both static and dynamic) */
36
+    return ((thread->type & ~RT_Object_Class_Static) == RT_Object_Class_Thread);
37
+}
38
+
39
+static int32_t rtthread_thr_cnts(struct thread_info_ops *ops)
40
+{
41
+    rtthread_ti_priv_t *priv = (rtthread_ti_priv_t *)ops->priv;
42
+    rt_int32_t idx = 0;
43
+    struct rt_object_information *information;
44
+    struct rt_object *object;
45
+    struct rt_list_node *node;
46
+    rt_thread_t current_thread;
47
+
48
+    if (-1 == priv->thr_cnts)
49
+    {
50
+        information = rt_object_get_information(RT_Object_Class_Thread);
51
+        mcd_assert(information != RT_NULL);
52
+        
53
+        current_thread = rt_thread_self();
54
+        priv->cur_idx = -1;  /* Initialize current thread index */
55
+
56
+        for (node = information->object_list.next;
57
+                node != &(information->object_list);
58
+                node = node->next)
59
+        {
60
+            object = rt_list_entry(node, struct rt_object, list);
61
+            rt_thread_t thread = (rt_thread_t)object;
62
+
63
+            if (is_thread_object(thread))
64
+            {
65
+                /* Check if this is the current thread */
66
+                if (thread == current_thread)
67
+                {
68
+                    priv->cur_idx = idx;
69
+                }
70
+                idx++;
71
+            }
72
+        }
73
+
74
+        priv->thr_cnts = idx;
75
+        
76
+        /* If current thread not found, default to 0 */
77
+        if (priv->cur_idx == -1)
78
+        {
79
+            priv->cur_idx = 0;
80
+            mcd_print("MCD DEBUG: Current thread not found, defaulting to index 0\n");
81
+        }
82
+    }
83
+
84
+    return priv->thr_cnts;
85
+}
86
+
87
+static int32_t rtthread_cur_idx(struct thread_info_ops *ops)
88
+{
89
+    rtthread_ti_priv_t *priv = (rtthread_ti_priv_t *)ops->priv;
90
+
91
+    if (-1 == priv->cur_idx)
92
+        rtthread_thr_cnts(ops);
93
+
94
+    return priv->cur_idx;
95
+}
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)
100
+{
101
+    rt_int32_t idx_l = 0;
102
+    rt_int32_t current_idx = rtthread_cur_idx(ops);
103
+    struct rt_object_information *information;
104
+    struct rt_object *object;
105
+    struct rt_list_node *node;
106
+
107
+    information = rt_object_get_information(RT_Object_Class_Thread);
108
+    mcd_assert(information != RT_NULL);
109
+
110
+    for (node = information->object_list.next;
111
+            node != &(information->object_list);
112
+            node = node->next)
113
+    {
114
+        object = rt_list_entry(node, struct rt_object, list);
115
+        rt_thread_t thread = (rt_thread_t)object;
116
+
117
+        if (is_thread_object(thread))
118
+        {
119
+            if (idx == idx_l)
120
+            {
121
+                /* If this is the current thread, use current registers */
122
+                if (idx_l == current_idx)
123
+                {
124
+                    mcd_memcpy(core_regset, get_cur_core_regset_address(), sizeof(core_regset_type));
125
+                    mcd_memcpy(fp_regset, get_cur_fp_regset_address(), sizeof(fp_regset_type));
126
+                }
127
+                else
128
+                {
129
+                    /* Debug: Dynamic thread for comparison */
130
+                    collect_registers((uint32_t *)thread->sp, core_regset, fp_regset);
131
+                }
132
+                return;
133
+            }
134
+            idx_l++;
135
+        }
136
+    }
137
+}
138
+
139
+static int32_t rtthread_get_mem_cnts(struct thread_info_ops *ops)
140
+{
141
+    return rtthread_thr_cnts(ops);
142
+}
143
+
144
+static int32_t rtthread_get_memarea(struct thread_info_ops *ops, int32_t idx,
145
+                                       uint32_t *addr, uint32_t *memlen)
146
+{
147
+    rt_int32_t         idx_l = 0;
148
+    rt_int32_t current_idx = rtthread_cur_idx(ops);
149
+    struct rt_object_information *information;
150
+    struct rt_object *object;
151
+    struct rt_list_node *node;
152
+
153
+    information = rt_object_get_information(RT_Object_Class_Thread);
154
+    mcd_assert(information != RT_NULL);
155
+
156
+    for (node = information->object_list.next;
157
+            node != &(information->object_list);
158
+            node = node->next)
159
+    {
160
+        object = rt_list_entry(node, struct rt_object, list);
161
+        rt_thread_t thread = (rt_thread_t)object;
162
+
163
+        if (is_thread_object(thread))
164
+        {
165
+            if (idx == idx_l)
166
+            {
167
+                /* If this is the current thread, use current stack pointer */
168
+                if (idx_l == current_idx)
169
+                {
170
+                    *addr = get_cur_core_regset_address()->sp;
171
+                    *memlen = 1024;
172
+                }
173
+                else
174
+                {
175
+                    *addr = (rt_uint32_t)thread->sp;
176
+                    *memlen = (rt_uint32_t)thread->stack_addr + thread->stack_size - (rt_uint32_t)thread->sp;
177
+                }
178
+                return 0;
179
+            }
180
+            idx_l++;
181
+        }
182
+    }
183
+    return 0;
184
+}
185
+
186
+void mcd_rtos_thread_ops(struct thread_info_ops *ops)
187
+{
188
+    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;
192
+    ops->get_memarea_count = rtthread_get_mem_cnts;
193
+    ops->get_memarea = rtthread_get_memarea;
194
+    ops->priv = &priv;
195
+    priv.cur_idx = -1;
196
+    priv.thr_cnts = -1;
197
+}
198
+
199
+MCD_WEAK rt_err_t rtt_hard_fault_exception_hook(void *context)
200
+{
201
+    arch_hard_fault_exception_hook(context);
202
+    return -RT_ERROR;
203
+}
204
+
205
+MCD_WEAK void rtt_assert_hook(const char *ex, const char *func, rt_size_t line)
206
+{
207
+    volatile uint8_t _continue = 1;
208
+
209
+    rt_interrupt_enter();
210
+
211
+    mcd_print("(%s) has assert failed at %s:%ld.\n", ex, func, line);
212
+
213
+    mcd_faultdump(MCD_OUTPUT_SERIAL);
214
+
215
+    rt_interrupt_leave();
216
+
217
+    while (_continue == 1);
218
+}
219
+
220
+static int mcd_coredump_init(void) 
221
+{
222
+    static mcd_bool_t is_init = MCD_FALSE;
223
+
224
+    if (is_init)
225
+    {
226
+        return 0;
227
+    }
228
+
229
+    //mcd_print_memoryinfo();
230
+    
231
+    rt_hw_exception_install(rtt_hard_fault_exception_hook);
232
+
233
+    //rt_assert_set_hook(rtt_assert_hook);
234
+    
235
+    is_init = MCD_TRUE;
236
+    return RT_EOK;
237
+}
238
+INIT_DEVICE_EXPORT(mcd_coredump_init);

+ 102
- 0
Middlewares/MCoreDump/src/arm/mcd_arm.c Visa fil

@@ -0,0 +1,102 @@
1
+/*
2
+ * Copyright (c) 2025, RT-Thread Development Team
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ *
6
+ * Change Logs:
7
+ * Date           Author       Notes
8
+ * 2025-08-16     Rbb666       Unified ARM architecture implementation
9
+ */
10
+
11
+#include <stdint.h>
12
+#include "mcd_cfg.h"
13
+#include "mcd_arm_define.h"
14
+
15
+/* Global task ID counter for note generation */
16
+static uint32_t task_id_counter = 3539;
17
+
18
+#if MCD_ARM_ARCH_32BIT
19
+/**
20
+ * @brief Fill prstatus note description for ARM32
21
+ * 
22
+ * @param desc Pointer to description buffer
23
+ * @param regset Pointer to core register set
24
+ */
25
+void arm32_fill_note_prstatus_desc(uint8_t *desc, core_regset_type *regset)
26
+{
27
+    uint16_t *signal = (uint16_t *)&desc[12];
28
+    uint32_t *lwpid = (uint32_t *)&desc[24];
29
+
30
+    mcd_memset(desc, 0, MCOREDUMP_PRSTATUS_SIZE);
31
+    *signal = 0;
32
+    *lwpid = task_id_counter++;
33
+    
34
+    /* Copy ARM32 registers to offset 72 */
35
+    mcd_memcpy(desc + MCD_PRSTATUS_REG_OFFSET, regset, sizeof(core_regset_type));
36
+}
37
+
38
+/**
39
+ * @brief Fill fpregset note description for ARM32
40
+ * 
41
+ * @param desc Pointer to description buffer
42
+ * @param regset Pointer to floating point register set
43
+ */
44
+void arm32_fill_note_fpregset_desc(uint8_t *desc, fp_regset_type *regset)
45
+{
46
+    if (regset != 0)
47
+    {
48
+        /* Copy VFP registers (32 * 8 bytes = 256 bytes) */
49
+        mcd_memcpy(desc, regset, sizeof(fp_regset_type) - sizeof(uint32_t));
50
+        /* Copy FPSCR at the end */
51
+        mcd_memcpy(desc + 32 * 8, &regset->fpscr, sizeof(uint32_t));
52
+    }
53
+    else
54
+    {
55
+        mcd_memset(desc, 0, MCOREDUMP_FPREGSET_SIZE);
56
+    }
57
+}
58
+#endif /* MCD_ARM_ARCH_32BIT */
59
+
60
+#if MCD_ARM_ARCH_64BIT
61
+/**
62
+ * @brief Fill prstatus note description for ARM64
63
+ * 
64
+ * @param desc Pointer to description buffer
65
+ * @param regset Pointer to core register set
66
+ */
67
+void arm64_fill_note_prstatus_desc(uint8_t *desc, core_regset_type *regset)
68
+{
69
+    uint16_t *signal = (uint16_t *)&desc[12];
70
+    uint32_t *lwpid = (uint32_t *)&desc[32];
71
+
72
+    mcd_memset(desc, 0, MCOREDUMP_PRSTATUS_SIZE);
73
+    *signal = 0;
74
+    *lwpid = task_id_counter++;
75
+    
76
+    /* Copy ARM64 registers to offset 112 */
77
+    mcd_memcpy(desc + MCD_PRSTATUS_REG_OFFSET, regset, sizeof(core_regset_type));
78
+}
79
+
80
+/**
81
+ * @brief Fill fpregset note description for ARM64
82
+ * 
83
+ * @param desc Pointer to description buffer  
84
+ * @param regset Pointer to floating point register set
85
+ */
86
+void arm64_fill_note_fpregset_desc(uint8_t *desc, fp_regset_type *regset)
87
+{
88
+    if (regset != NULL)
89
+    {
90
+        /* Copy SIMD/FP registers (32 * 16 bytes = 512 bytes) */
91
+        mcd_memcpy(desc, regset, sizeof(fp_regset_type) - 8);
92
+        
93
+        /* Copy FPSR and FPCR at the end */
94
+        mcd_memcpy(desc + 32 * 16, &regset->fpsr, sizeof(uint32_t));
95
+        mcd_memcpy(desc + 32 * 16 + 4, &regset->fpcr, sizeof(uint32_t));
96
+    }
97
+    else
98
+    {
99
+        mcd_memset(desc, 0, MCOREDUMP_FPREGSET_SIZE);
100
+    }
101
+}
102
+#endif /* MCD_ARM_ARCH_64BIT */

+ 68
- 0
Middlewares/MCoreDump/src/arm/mcd_arm_define.h Visa fil

@@ -0,0 +1,68 @@
1
+/*
2
+ * Copyright (c) 2025, RT-Thread Development Team
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ *
6
+ * Change Logs:
7
+ * Date           Author       Notes
8
+ * 2025-08-16     Rbb666       Unified ARM architecture definitions
9
+ */
10
+
11
+#ifndef __MCD_ARM_DEFINE_H__
12
+#define __MCD_ARM_DEFINE_H__
13
+
14
+#include "registers.h"
15
+
16
+/* ARM Architecture Detection */
17
+#if defined(__aarch64__) || defined(_M_ARM64)
18
+#define MCD_ARM_ARCH_64BIT          1
19
+#define MCD_ARM_ARCH_32BIT          0
20
+#elif defined(__arm__) || defined(_M_ARM) || defined(__ARM_ARCH)
21
+#define MCD_ARM_ARCH_64BIT          0
22
+#define MCD_ARM_ARCH_32BIT          1
23
+#else
24
+#error "Unsupported ARM architecture"
25
+#endif
26
+
27
+/* Architecture-specific ELF definitions */
28
+#if MCD_ARM_ARCH_64BIT
29
+/* ARM64 (AArch64) definitions */
30
+#define MCOREDUMP_ELF_CLASS         ELFCLASS64
31
+#define MCOREDUMP_ELF_ENDIAN        ELFDATA2LSB
32
+#define MCOREDUMP_MACHINE           EM_AARCH64
33
+#define MCOREDUMP_OSABI             ELFOSABI_NONE
34
+#define MCOREDUMP_PRSTATUS_SIZE     392
35
+#define MCOREDUMP_FPREGSET_SIZE     (32 * 16 + 8)
36
+#define MCD_PRSTATUS_REG_OFFSET     112
37
+
38
+/* Function mappings */
39
+#define fill_note_prstatus_desc     arm64_fill_note_prstatus_desc
40
+#define fill_note_fpregset_desc     arm64_fill_note_fpregset_desc
41
+    
42
+#elif MCD_ARM_ARCH_32BIT
43
+/* ARM32 (AArch32) definitions */
44
+#define MCOREDUMP_ELF_CLASS         ELFCLASS32
45
+#define MCOREDUMP_ELF_ENDIAN        ELFDATA2LSB
46
+#define MCOREDUMP_MACHINE           EM_ARM
47
+#define MCOREDUMP_OSABI             ELFOSABI_ARM
48
+#define MCOREDUMP_PRSTATUS_SIZE     148
49
+#define MCOREDUMP_FPREGSET_SIZE     (32 * 8 + 4)
50
+#define MCD_PRSTATUS_REG_OFFSET     72
51
+
52
+/* Function mappings */
53
+#define fill_note_prstatus_desc     arm32_fill_note_prstatus_desc
54
+#define fill_note_fpregset_desc     arm32_fill_note_fpregset_desc
55
+#endif /* MCD_ARM_ARCH_32BIT */
56
+
57
+/* Function declarations */
58
+#if MCD_ARM_ARCH_32BIT
59
+void arm32_fill_note_prstatus_desc(uint8_t *desc, core_regset_type *regset);
60
+void arm32_fill_note_fpregset_desc(uint8_t *desc, fp_regset_type *regset);
61
+#endif
62
+
63
+#if MCD_ARM_ARCH_64BIT
64
+void arm64_fill_note_prstatus_desc(uint8_t *desc, core_regset_type *regset);
65
+void arm64_fill_note_fpregset_desc(uint8_t *desc, fp_regset_type *regset);
66
+#endif
67
+
68
+#endif /* __MCD_ARM_DEFINE_H__ */

+ 355
- 0
Middlewares/MCoreDump/src/coredump.c Visa fil

@@ -0,0 +1,355 @@
1
+/*
2
+ * Copyright (c) 2025, RT-Thread Development Team
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ *
6
+ * Change Logs:
7
+ * Date           Author       Notes
8
+ * 2025-08-16     Rbb666       first version
9
+ */
10
+
11
+#include <string.h>
12
+#include "coredump.h"
13
+#include "mcd_elf_define.h"
14
+#include "mcd_arm_define.h"
15
+
16
+typedef uint16_t elf_half;
17
+typedef uint32_t elf_word;
18
+
19
+#if MCOREDUMP_ELF_CLASS == ELFCLASS32
20
+typedef uint32_t elf_addr;
21
+typedef uint32_t elf_off;
22
+typedef struct elf32_phdr elf_phdr_t;
23
+#else
24
+typedef uint64_t elf_addr;
25
+typedef uint64_t elf_off;
26
+typedef struct elf64_phdr elf_phdr_t;
27
+#endif
28
+
29
+/* Elf file header type */
30
+typedef struct
31
+{
32
+    unsigned char e_ident[EI_NIDENT];
33
+    elf_half e_type;
34
+    elf_half e_machine;
35
+    elf_word e_version;
36
+    elf_addr e_entry;
37
+    elf_off e_phoff;
38
+    elf_off e_shoff;
39
+    elf_word e_flags;
40
+    elf_half e_ehsize;
41
+    elf_half e_phentsize;
42
+    elf_half e_phnum;
43
+    elf_half e_shentsize;
44
+    elf_half e_shnum;
45
+    elf_half e_shstrndx;
46
+} elf_ehdr_t;
47
+
48
+/* Segment header type for 32bit arch */
49
+struct elf32_phdr
50
+{
51
+    elf_word p_type;
52
+    elf_off p_offset;
53
+    elf_addr p_vaddr;
54
+    elf_addr p_paddr;
55
+    elf_off p_filesz;
56
+    elf_off p_memsz;
57
+    elf_word p_flags;
58
+    elf_off p_align;
59
+};
60
+
61
+/* Segment header type for 64bit arch */
62
+struct elf64_phdr
63
+{
64
+    elf_word p_type;  /* Identifies program segment type */
65
+    elf_word p_flags; /* Segment flags */
66
+    elf_off p_offset; /* Segment file offset */
67
+    elf_addr p_vaddr; /* Segment virtual address */
68
+    elf_addr p_paddr; /* Segment physical address */
69
+    elf_off p_filesz; /* Segment size in file */
70
+    elf_off p_memsz;  /* Segment size in memory */
71
+    elf_off p_align;  /* Segment alignment, file & memory */
72
+};
73
+
74
+typedef struct
75
+{
76
+    elf_word namesz;                       /* Size of entry's owner string */
77
+    elf_word descsz;                       /* Size of the note descriptor */
78
+    elf_word type;                         /* Interpretation of the descriptor */
79
+    char name[1];
80
+} elf_note_base_t;
81
+
82
+typedef struct
83
+{
84
+    elf_word namesz;                       /* Size of entry's owner string */
85
+    elf_word descsz;                       /* Size of the note descriptor */
86
+    elf_word type;                         /* Interpretation of the descriptor */
87
+    char name[MCD_ALIGN(sizeof("CORE"), 4)]; /* The only support name is "CORE" */
88
+    uint8_t desc[MCOREDUMP_PRSTATUS_SIZE];    /* descriptor of this note entry type */
89
+} elf_note_prstatus_t;
90
+
91
+typedef struct
92
+{
93
+    elf_word namesz;                        /* Size of entry's owner string */
94
+    elf_word descsz;                        /* Size of the note descriptor */
95
+    elf_word type;                          /* Interpretation of the descriptor */
96
+    char name[MCD_ALIGN(sizeof("LINUX"), 4)]; /* The only support name is "LINUX" */
97
+    uint8_t desc[MCOREDUMP_FPREGSET_SIZE];     /* descriptor of this note entry type */
98
+} elf_note_fpreg_entry_t;
99
+
100
+typedef struct
101
+{
102
+    elf_off file_off;
103
+    uint32_t with_fp;
104
+    uint32_t stack_size;
105
+    mcd_writeout_func_t writeout_func;
106
+    union
107
+    {
108
+        elf_ehdr_t elf_header;
109
+        elf_phdr_t program_header;
110
+        elf_note_prstatus_t prstatus;
111
+        elf_note_fpreg_entry_t note_fp;
112
+    } tmp;
113
+    core_regset_type tmp_core_rset;
114
+    fp_regset_type tmp_fp_rset;
115
+} mcd_instance_t;
116
+
117
+static core_regset_type current_core_regset;
118
+static fp_regset_type current_fp_regset;
119
+
120
+static mcd_instance_t m_ctx;
121
+
122
+static void fill_core_file_header(elf_ehdr_t *elf_header, uint16_t num)
123
+{
124
+    memset(elf_header, 0, sizeof(elf_ehdr_t));
125
+
126
+    elf_header->e_ident[EI_MAG0] = ELFMAG0;
127
+    elf_header->e_ident[EI_MAG1] = ELFMAG1;
128
+    elf_header->e_ident[EI_MAG2] = ELFMAG2;
129
+    elf_header->e_ident[EI_MAG3] = ELFMAG3;
130
+    elf_header->e_ident[EI_CLASS] = MCOREDUMP_ELF_CLASS;
131
+    elf_header->e_ident[EI_DATA] = MCOREDUMP_ELF_ENDIAN;
132
+    elf_header->e_ident[EI_VERSION] = 1;
133
+    elf_header->e_ident[EI_OSABI] = MCOREDUMP_OSABI;
134
+    elf_header->e_type = ET_CORE;
135
+    elf_header->e_machine = MCOREDUMP_MACHINE;
136
+    elf_header->e_version = 1;
137
+    elf_header->e_entry = 0;
138
+    elf_header->e_phoff = sizeof(elf_ehdr_t);
139
+    elf_header->e_shoff = 0;
140
+    elf_header->e_flags = 0;
141
+    elf_header->e_ehsize = sizeof(elf_ehdr_t);
142
+    elf_header->e_phentsize = sizeof(elf_phdr_t);
143
+    elf_header->e_phnum = num;
144
+    elf_header->e_shentsize = 0;
145
+    elf_header->e_shnum = 0;
146
+    elf_header->e_shstrndx = 0;
147
+}
148
+
149
+static void fill_program_header(elf_phdr_t *program_header, elf_word type,
150
+                                elf_addr vaddr, elf_off filesz, elf_off memsz,
151
+                                elf_word flag)
152
+{
153
+    program_header->p_type = type;
154
+    program_header->p_offset = m_ctx.file_off;
155
+    program_header->p_vaddr = vaddr;
156
+    program_header->p_paddr = 0;
157
+    program_header->p_filesz = filesz;
158
+    program_header->p_memsz = memsz;
159
+    program_header->p_flags = flag;
160
+    program_header->p_align = 1;
161
+
162
+    m_ctx.file_off += filesz;
163
+}
164
+
165
+static void fill_note_base(elf_note_base_t *note, const char *note_name,
166
+                           elf_word type, elf_word descsz)
167
+{
168
+    note->namesz = strlen(note_name) + 1;
169
+    note->descsz = descsz;
170
+    note->type = type;
171
+    mcd_memcpy(note->name, note_name, note->namesz);
172
+    if (note->namesz & 3)
173
+        memset(&note->name[note->namesz], 0, note->namesz & 3);
174
+}
175
+
176
+/*  fill prstatus struct in note segment */
177
+static void fill_note_prstatus(elf_note_prstatus_t *prstatus, core_regset_type *regset)
178
+{
179
+    fill_note_base((elf_note_base_t *)prstatus, "CORE", NT_PRSTATUS, sizeof(prstatus->desc));
180
+    fill_note_prstatus_desc(&prstatus->desc[0], regset);
181
+}
182
+
183
+/*  fill FP registers struct in note segment */
184
+static void fill_note_vfp_regset(elf_note_fpreg_entry_t *prstatus, fp_regset_type *regset)
185
+{
186
+    fill_note_base((elf_note_base_t *)prstatus, "LINUX", NT_ARM_VFP, sizeof(prstatus->desc));
187
+    fill_note_fpregset_desc(&prstatus->desc[0], regset);
188
+}
189
+
190
+void mcd_init(mcd_writeout_func_t func)
191
+{
192
+    memset(&m_ctx, 0, sizeof(mcd_instance_t));
193
+    m_ctx.stack_size = 1536;
194
+    m_ctx.writeout_func = func;
195
+    
196
+    /* Automatically detect FPU support based on compiler definitions */
197
+    m_ctx.with_fp = MCD_FPU_SUPPORT;
198
+}
199
+
200
+static void fill_one_threads_regset(core_regset_type *core_regset, fp_regset_type *fp_regset)
201
+{
202
+    fill_note_prstatus(&m_ctx.tmp.prstatus, core_regset);
203
+    m_ctx.writeout_func((uint8_t *)&m_ctx.tmp.prstatus, sizeof(elf_note_prstatus_t));
204
+
205
+    if (m_ctx.with_fp)
206
+    {
207
+        fill_note_vfp_regset(&m_ctx.tmp.note_fp, fp_regset);
208
+        m_ctx.writeout_func((uint8_t *)&m_ctx.tmp.note_fp, sizeof(elf_note_fpreg_entry_t));
209
+    }
210
+}
211
+
212
+static void addr_align(uint32_t *addr, uint32_t *memlen)
213
+{
214
+    *memlen += ((*addr) & (~CORE_MEM_LINE_MASK));
215
+    *addr &= CORE_MEM_LINE_MASK;
216
+}
217
+
218
+void mcd_gen_coredump(struct thread_info_ops *ops)
219
+{
220
+    int note_size;
221
+    uint32_t addr, memlen;
222
+
223
+    int segment_count = ops->get_memarea_count(ops) + 1;
224
+    fill_core_file_header(&m_ctx.tmp.elf_header, segment_count);
225
+    m_ctx.writeout_func((uint8_t *)&m_ctx.tmp.elf_header, sizeof(elf_ehdr_t));
226
+
227
+    m_ctx.file_off = sizeof(elf_ehdr_t) + segment_count * sizeof(elf_phdr_t);
228
+
229
+    if (m_ctx.with_fp)
230
+        note_size = (sizeof(elf_note_prstatus_t)
231
+                     + sizeof(elf_note_fpreg_entry_t))
232
+                    * ops->get_threads_count(ops);
233
+    else
234
+        note_size = sizeof(elf_note_prstatus_t)
235
+                    * ops->get_threads_count(ops);
236
+    fill_program_header(&m_ctx.tmp.program_header, PT_NOTE, 0, note_size, 0, PF_R);
237
+    m_ctx.writeout_func((uint8_t *)&m_ctx.tmp.program_header, sizeof(elf_phdr_t));
238
+
239
+    for (int i = 0; i < ops->get_memarea_count(ops); i++)
240
+    {
241
+        ops->get_memarea(ops, i, &addr, &memlen);
242
+        addr_align(&addr, &memlen);
243
+        fill_program_header(&m_ctx.tmp.program_header, PT_LOAD, addr,
244
+                            memlen, memlen,
245
+                            PF_R | PF_W);
246
+        m_ctx.writeout_func((uint8_t *)&m_ctx.tmp.program_header, sizeof(elf_phdr_t));
247
+    }
248
+
249
+    /* Write all threads in index order */
250
+    for (int i = 0; i < ops->get_threads_count(ops); i++)
251
+    {
252
+        ops->get_thread_regset(ops, i,
253
+                               &m_ctx.tmp_core_rset, &m_ctx.tmp_fp_rset);
254
+        fill_one_threads_regset(&m_ctx.tmp_core_rset, &m_ctx.tmp_fp_rset);
255
+    }
256
+
257
+    for (int i = 0; i < ops->get_memarea_count(ops); i++)
258
+    {
259
+        ops->get_memarea(ops, i, &addr, &memlen);
260
+        addr_align(&addr, &memlen);
261
+        m_ctx.writeout_func((uint8_t *)addr, memlen);
262
+    }
263
+}
264
+
265
+int32_t mcd_corefile_size(struct thread_info_ops *ops)
266
+{
267
+    int elf_size = 0;
268
+    int segment_count;
269
+    uint32_t addr, memlen;
270
+
271
+    segment_count = ops->get_memarea_count(ops) + 1;
272
+    elf_size = sizeof(elf_ehdr_t) + segment_count * sizeof(elf_phdr_t);
273
+
274
+    if (m_ctx.with_fp)
275
+        elf_size += (sizeof(elf_note_prstatus_t)
276
+                     + sizeof(elf_note_fpreg_entry_t))
277
+                    * ops->get_threads_count(ops);
278
+    else
279
+        elf_size += sizeof(elf_note_prstatus_t)
280
+                    * ops->get_threads_count(ops);
281
+
282
+    for (int i = 0; i < ops->get_memarea_count(ops); i++)
283
+    {
284
+        ops->get_memarea(ops, i, &addr, &memlen);
285
+        addr_align(&addr, &memlen);
286
+        elf_size += memlen;
287
+    }
288
+
289
+    return elf_size;
290
+}
291
+
292
+int32_t mcd_mini_dump_size(void)
293
+{
294
+    struct thread_info_ops ops;
295
+    mcd_mini_dump_ops(&ops);
296
+    return mcd_corefile_size(&ops);
297
+}
298
+
299
+int32_t mcd_multi_dump_size(void)
300
+{
301
+    struct thread_info_ops ops;
302
+    mcd_rtos_thread_ops(&ops);
303
+    return mcd_corefile_size(&ops);
304
+}
305
+
306
+static int32_t minidump_thr_cnts(struct thread_info_ops *ops)
307
+{
308
+    return 1;
309
+}
310
+
311
+static int32_t minidump_cur_idx(struct thread_info_ops *ops)
312
+{
313
+    return 0;
314
+}
315
+
316
+static void minidump_thr_rset(struct thread_info_ops *ops, int32_t idx,
317
+                              core_regset_type *core_regset,
318
+                              fp_regset_type *fp_regset)
319
+{
320
+    mcd_memcpy(core_regset, get_cur_core_regset_address(), sizeof(core_regset_type));
321
+    mcd_memcpy(fp_regset, get_cur_fp_regset_address(), sizeof(fp_regset_type));
322
+}
323
+
324
+static int32_t minidump_mem_cnts(struct thread_info_ops *ops)
325
+{
326
+    return 1;
327
+}
328
+
329
+static int32_t minidump_memarea(struct thread_info_ops *ops, int32_t idx,
330
+                                uint32_t *addr, uint32_t *memlen)
331
+{
332
+    *addr = current_core_regset.sp;
333
+    *memlen = m_ctx.stack_size;
334
+    return 0;
335
+}
336
+
337
+void mcd_mini_dump_ops(struct thread_info_ops *ops)
338
+{
339
+    ops->get_threads_count = minidump_thr_cnts;
340
+    ops->get_current_thread_idx = minidump_cur_idx;
341
+    ops->get_thread_regset = minidump_thr_rset;
342
+    ops->get_memarea_count = minidump_mem_cnts;
343
+    ops->get_memarea = minidump_memarea;
344
+    ops->priv = NULL;
345
+}
346
+
347
+core_regset_type *get_cur_core_regset_address(void)
348
+{
349
+    return &current_core_regset;
350
+}
351
+
352
+fp_regset_type *get_cur_fp_regset_address(void)
353
+{
354
+    return &current_fp_regset;
355
+}

+ 492
- 0
Middlewares/MCoreDump/src/faultdump.c Visa fil

@@ -0,0 +1,492 @@
1
+/*
2
+ * Copyright (c) 2025, RT-Thread Development Team
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ *
6
+ * Change Logs:
7
+ * Date           Author       Notes
8
+ * 2025-08-16     Rbb666       first version
9
+ */
10
+
11
+#include <stdbool.h>
12
+#include <stdint.h>
13
+#include <rtconfig.h>
14
+#ifdef PKG_USING_MCOREDUMP_FILESYSTEM
15
+#include <dfs_file.h>
16
+#include <unistd.h>
17
+#include <sys/time.h>
18
+#endif /* PKG_USING_MCOREDUMP_FILESYSTEM */
19
+#include "coredump.h"
20
+
21
+#define COREDUMP_MEMORY_MAGIC       (0x434D4450)  /* "CMDP" */
22
+
23
+/* Static memory buffer for coredump storage */
24
+#ifndef PKG_MCOREDUMP_MEMORY_SIZE
25
+#define COREDUMP_MEMORY_SIZE        (8 * 1024)    /* Default 8KB buffer size */
26
+#else
27
+#define COREDUMP_MEMORY_SIZE        PKG_MCOREDUMP_MEMORY_SIZE
28
+#endif
29
+
30
+typedef struct
31
+{
32
+    uint32_t magic;                     /* Magic number to identify valid coredump */
33
+    uint32_t data_size;                 /* Actual coredump data size */
34
+    uint32_t crc32;                     /* CRC32 checksum */
35
+    uint8_t data[COREDUMP_MEMORY_SIZE]; /* Coredump data buffer */
36
+} coredump_memory_t;
37
+
38
+/* Static memory buffer for coredump storage - must persist across resets */
39
+#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
40
+/* ARM Compiler V6 (armclang) - use custom section with UNINIT attribute in scatter file */
41
+static coredump_memory_t coredump_memory_buffer __attribute__((section(".bss.NoInit")));
42
+#elif defined(__GNUC__)
43
+/* GCC - use .noinit section (not initialized by startup code) */
44
+static coredump_memory_t coredump_memory_buffer __attribute__((section(".noinit")));
45
+#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 6010050)
46
+/* ARM Compiler 5 (armcc) - use custom section */
47
+static coredump_memory_t coredump_memory_buffer __attribute__((section(".bss.NoInit"), zero_init));
48
+#else
49
+/* Fallback for other compilers - normal static allocation */
50
+#warning "MCoreDump: Unknown compiler, coredump buffer may not persist across resets"
51
+#warning "MCoreDump: Data will be lost after system reset"
52
+static coredump_memory_t coredump_memory_buffer;
53
+#endif
54
+
55
+/* Memory write context */
56
+static struct
57
+{
58
+    uint32_t offset;
59
+    bool overflow;
60
+} memory_write_ctx;
61
+
62
+#ifdef PKG_USING_MCOREDUMP_FILESYSTEM
63
+/* Internal function declarations */
64
+static int create_coredump_filename(void);
65
+static int prepare_coredump_filesystem(void);
66
+#endif /* PKG_USING_MCOREDUMP_FILESYSTEM */
67
+
68
+/* Global variables for serial output */
69
+static uint32_t serial_crc32;
70
+static uint32_t serial_byte_count;
71
+
72
+#ifdef PKG_USING_MCOREDUMP_FILESYSTEM
73
+/* Global variables for filesystem output */
74
+static int coredump_fd = -1;
75
+static char coredump_filename[64];
76
+
77
+#ifndef PKG_MCOREDUMP_FILESYSTEM_DIR
78
+#define COREDUMP_DIR "/sdcard"
79
+#else
80
+#define COREDUMP_DIR PKG_MCOREDUMP_FILESYSTEM_DIR
81
+#endif
82
+
83
+#ifndef PKG_MCOREDUMP_FILESYSTEM_PREFIX
84
+#define COREDUMP_PREFIX "core_"
85
+#else
86
+#define COREDUMP_PREFIX PKG_MCOREDUMP_FILESYSTEM_PREFIX
87
+#endif
88
+
89
+#define COREDUMP_EXT ".elf"
90
+#endif /* PKG_USING_MCOREDUMP_FILESYSTEM */
91
+
92
+typedef struct
93
+{
94
+    uint16_t magic;
95
+    uint16_t page_size;
96
+    uint32_t file_size;
97
+    uint8_t corefile[1];
98
+} persistent_format_t;
99
+
100
+static uint32_t mcd_crc32b(const uint8_t *message, int32_t megLen, uint32_t initCrc)
101
+{
102
+    int i, j;
103
+    uint32_t byte, crc, mask;
104
+
105
+    i = 0;
106
+    crc = initCrc;
107
+    for (i = 0; i < megLen; i++)
108
+    {
109
+        byte = message[i];            /* Get next byte. */
110
+        crc = crc ^ byte;
111
+        for (j = 7; j >= 0; j--)      /* Do eight times. */
112
+        {
113
+            mask = -(crc & 1);
114
+            crc = (crc >> 1) ^ (0xEDB88320 & mask);
115
+        }
116
+    }
117
+
118
+    return ~crc;
119
+}
120
+
121
+static void corefile_serial_write(uint8_t *data, int len)
122
+{
123
+    for (int i = 0; i < len; i++)
124
+    {
125
+        uint8_t b = data[i];
126
+        serial_crc32 = mcd_crc32b(&b, 1, serial_crc32) ^ 0xFFFFFFFF;
127
+        mcd_print("%02x", b);
128
+        serial_byte_count++;
129
+    }
130
+}
131
+
132
+static void corefile_memory_write(uint8_t *data, int len)
133
+{
134
+    if (memory_write_ctx.overflow)
135
+        return;
136
+
137
+    /* Check if we have enough space */
138
+    if (memory_write_ctx.offset + len > COREDUMP_MEMORY_SIZE)
139
+    {
140
+        memory_write_ctx.overflow = true;
141
+        mcd_println("WARNING: Coredump memory buffer overflow! Data truncated.");
142
+        len = COREDUMP_MEMORY_SIZE - memory_write_ctx.offset;
143
+        if (len <= 0)
144
+            return;
145
+    }
146
+
147
+    /* Copy data to memory buffer */
148
+    mcd_memcpy(&coredump_memory_buffer.data[memory_write_ctx.offset], data, len);
149
+    memory_write_ctx.offset += len;
150
+}
151
+
152
+/**
153
+ * @brief Check if there's a valid coredump in memory buffer
154
+ *
155
+ * @return bool true if valid coredump exists, false otherwise
156
+ */
157
+mcd_bool_t mcd_check_memory_coredump(void)
158
+{
159
+    return (coredump_memory_buffer.magic == COREDUMP_MEMORY_MAGIC &&
160
+            coredump_memory_buffer.data_size > 0 &&
161
+            coredump_memory_buffer.data_size <= COREDUMP_MEMORY_SIZE);
162
+}
163
+
164
+/**
165
+ * @brief Print coredump memory information at startup
166
+ *
167
+ * This function should be called during system initialization
168
+ */
169
+void mcd_print_memoryinfo(void)
170
+{
171
+    mcd_print("\n=== MCoreDump Memory Check ===\n");
172
+    mcd_print("Memory buffer address: 0x%08X\n", (uint32_t)&coredump_memory_buffer);
173
+    mcd_print("Buffer size: %d bytes\n", sizeof(coredump_memory_t));
174
+
175
+    if (mcd_check_memory_coredump())
176
+    {
177
+        mcd_print("*** COREDUMP FOUND IN MEMORY ***\n");
178
+        mcd_print("Data size: %d bytes\n", coredump_memory_buffer.data_size);
179
+#ifdef PKG_USING_MCOREDUMP_FILESYSTEM
180
+        mcd_print("Use 'mcd_dump_filesystem' command to save to filesystem.\n");
181
+#endif /* PKG_USING_MCOREDUMP_FILESYSTEM */
182
+        mcd_print("Use 'mcd_dump_memory' command to dump memory to terminal.\n");
183
+    }
184
+    else
185
+    {
186
+        mcd_print("No valid coredump found in memory.\n");
187
+    }
188
+    mcd_print("============================\n\n");
189
+}
190
+
191
+#ifdef PKG_USING_MCOREDUMP_FILESYSTEM
192
+/**
193
+ * @brief Save coredump from memory buffer to filesystem
194
+ *
195
+ * @return int MCD_OK on success, error code on failure
196
+ */
197
+int mcd_dump_filesystem(void)
198
+{
199
+    if (!mcd_check_memory_coredump())
200
+    {
201
+        mcd_print("No valid coredump found in memory buffer.\n");
202
+        return MCD_ERROR;
203
+    }
204
+
205
+    /* Verify CRC32 */
206
+    uint32_t calculated_crc = mcd_crc32b(coredump_memory_buffer.data,
207
+                                         coredump_memory_buffer.data_size,
208
+                                         0xFFFFFFFF) ^ 0xFFFFFFFF;
209
+
210
+    if (calculated_crc != coredump_memory_buffer.crc32)
211
+    {
212
+        mcd_print("ERROR: Coredump data corruption detected (CRC mismatch)!\n");
213
+        mcd_print("Expected: 0x%08X, Calculated: 0x%08X\n",
214
+                   coredump_memory_buffer.crc32, calculated_crc);
215
+        return MCD_ERROR;
216
+    }
217
+
218
+    /* Prepare filesystem */
219
+    if (prepare_coredump_filesystem() != 0)
220
+    {
221
+        mcd_print("ERROR: Failed to prepare filesystem for coredump\n");
222
+        return MCD_ERROR;
223
+    }
224
+
225
+    mcd_print("Saving coredump from memory to file: %s\n", coredump_filename);
226
+
227
+    /* Write coredump data directly (pure ELF format without custom header) */
228
+    if (write(coredump_fd, coredump_memory_buffer.data, coredump_memory_buffer.data_size) < 0)
229
+    {
230
+        mcd_print("ERROR: Failed to write coredump data\n");
231
+        close(coredump_fd);
232
+        return MCD_ERROR;
233
+    }
234
+
235
+    close(coredump_fd);
236
+    coredump_fd = -1;
237
+
238
+    mcd_print("Coredump saved successfully to: %s\n", coredump_filename);
239
+
240
+    /* Clear memory buffer after successful save */
241
+    mcd_memset(&coredump_memory_buffer, 0, sizeof(coredump_memory_t));
242
+
243
+    return MCD_OK;
244
+}
245
+MCD_CMD_EXPORT(mcd_dump_filesystem, Save coredump from memory to filesystem);
246
+
247
+static int create_coredump_filename(void)
248
+{
249
+    struct timeval tv;
250
+    struct tm *tm_info;
251
+
252
+    /* Get current time */
253
+    if (gettimeofday(&tv, NULL) != 0)
254
+    {
255
+        /* If time is not available, use a simple counter-based name */
256
+        static int file_counter = 0;
257
+        file_counter++;
258
+        snprintf(coredump_filename, sizeof(coredump_filename),
259
+                 "%s/%s%04d%s",
260
+                 COREDUMP_DIR, COREDUMP_PREFIX, file_counter, COREDUMP_EXT);
261
+    }
262
+    else
263
+    {
264
+        tm_info = localtime(&tv.tv_sec);
265
+
266
+        /* Create filename with timestamp */
267
+        snprintf(coredump_filename, sizeof(coredump_filename),
268
+                 "%s/%s%04d%02d%02d_%02d%02d%02d%s",
269
+                 COREDUMP_DIR, COREDUMP_PREFIX,
270
+                 tm_info->tm_year + 1900, tm_info->tm_mon + 1, tm_info->tm_mday,
271
+                 tm_info->tm_hour, tm_info->tm_min, tm_info->tm_sec,
272
+                 COREDUMP_EXT);
273
+    }
274
+
275
+    return 0;
276
+}
277
+
278
+static int prepare_coredump_filesystem(void)
279
+{
280
+    struct stat st;
281
+
282
+    /* Check if coredump directory exists first */
283
+    if (stat(COREDUMP_DIR, &st) != 0)
284
+    {
285
+        mcd_print("ERROR: %s directory not found. Please mount filesystem first.\n", COREDUMP_DIR);
286
+        return -1;
287
+    }
288
+
289
+    /* Create coredump directory if it doesn't exist */
290
+    if (stat(COREDUMP_DIR, &st) != 0)
291
+    {
292
+        mcd_print("Creating directory: %s\n", COREDUMP_DIR);
293
+        if (mkdir(COREDUMP_DIR, 0x777) != 0)
294
+        {
295
+            mcd_print("ERROR: Failed to create coredump directory: %s\n", COREDUMP_DIR);
296
+            mcd_print("Please check if filesystem is mounted and writable.\n");
297
+            return -1;
298
+        }
299
+        mcd_print("Directory created successfully: %s\n", COREDUMP_DIR);
300
+    }
301
+
302
+    /* Generate filename */
303
+    create_coredump_filename();
304
+
305
+    mcd_print("Creating coredump file: %s\n", coredump_filename);
306
+
307
+    /* Open file for writing */
308
+    coredump_fd = open(coredump_filename, O_WRONLY | O_CREAT);
309
+    if (coredump_fd < 0)
310
+    {
311
+        mcd_print("ERROR: Failed to create coredump file: %s\n", coredump_filename);
312
+        return -1;
313
+    }
314
+
315
+    mcd_print("Coredump file opened successfully (fd: %d)\n", coredump_fd);
316
+    return 0;
317
+}
318
+#endif /* PKG_USING_MCOREDUMP_FILESYSTEM */
319
+
320
+/**
321
+ * @brief Core dump with output mode selection
322
+ *
323
+ * @param output_mode MCD_OUTPUT_FLASH for flash storage, MCD_OUTPUT_SERIAL for serial output, MCD_OUTPUT_MEMORY for memory storage
324
+ * @return int MCD_OK on success, error code on failure
325
+ */
326
+int mcd_faultdump_ex(mcd_output_mode_t output_mode)
327
+{
328
+    struct thread_info_ops ops;
329
+
330
+    if (output_mode == MCD_OUTPUT_SERIAL)
331
+    {
332
+        mcd_init(corefile_serial_write);
333
+
334
+        mcd_irq_state_t irq_save = mcd_irq_disable();
335
+
336
+        serial_crc32 = 0xFFFFFFFF;
337
+
338
+        mcd_print("coredump start : {\n");
339
+        mcd_multi_dump();
340
+        mcd_print("\n} coredump end\n");
341
+
342
+        serial_crc32 = ~serial_crc32;
343
+
344
+        mcd_print("crc32 : %08x\n", serial_crc32);
345
+
346
+        mcd_irq_enable(irq_save);
347
+    }
348
+    else if (output_mode == MCD_OUTPUT_MEMORY)
349
+    {
350
+        /* Memory buffer output mode - for exception handling */
351
+        mcd_print("\n=== MCoreDump Memory Storage Started ===\n");
352
+
353
+        /* Initialize memory write context */
354
+        memory_write_ctx.offset = 0;
355
+        memory_write_ctx.overflow = false;
356
+
357
+        /* Clear memory buffer */
358
+        mcd_memset(&coredump_memory_buffer, 0, sizeof(coredump_memory_t));
359
+
360
+        /* Initialize mcd with memory write function */
361
+        mcd_init(corefile_memory_write);
362
+
363
+        /* Generate and write coredump to memory */
364
+        mcd_rtos_thread_ops(&ops);
365
+        mcd_gen_coredump(&ops);
366
+
367
+        /* Finalize memory buffer */
368
+        if (!memory_write_ctx.overflow && memory_write_ctx.offset > 0)
369
+        {
370
+            coredump_memory_buffer.magic = COREDUMP_MEMORY_MAGIC;
371
+            coredump_memory_buffer.data_size = memory_write_ctx.offset;
372
+            coredump_memory_buffer.crc32 = mcd_crc32b(coredump_memory_buffer.data,
373
+                                           memory_write_ctx.offset,
374
+                                           0xFFFFFFFF) ^ 0xFFFFFFFF;
375
+
376
+            mcd_println("Coredump saved to memory buffer:\n");
377
+            mcd_println("  Address: 0x%08X", (uint32_t)&coredump_memory_buffer);
378
+            mcd_println("  Size: %d bytes", memory_write_ctx.offset);
379
+            mcd_println("  CRC32: 0x%08X", coredump_memory_buffer.crc32);
380
+        }
381
+        else
382
+        {
383
+            mcd_println("ERROR: Memory buffer overflow or no data written");
384
+            mcd_println("=== MCoreDump Memory Storage Failed ===\n");
385
+            return MCD_ERROR;
386
+        }
387
+    }
388
+
389
+    mcd_println("=== MCoreDump Memory Storage Completed ===\n");
390
+
391
+    return MCD_OK;
392
+}
393
+
394
+/**
395
+ * @brief Generate coredump with specified output mode
396
+ *
397
+ * This is the main entry point for generating coredumps in MCoreDump system.
398
+ * It supports multiple output modes to accommodate different debugging scenarios:
399
+ * 
400
+ * - MCD_OUTPUT_MEMORY: Saves coredump to static memory buffer (persistent across resets)
401
+ * - MCD_OUTPUT_SERIAL: Outputs coredump data via serial port in hex format
402
+ * - MCD_OUTPUT_FILESYSTEM: Saves coredump to filesystem as ELF file (if filesystem support is enabled)
403
+ *
404
+ * The function is designed to be called from exception handlers, assert hooks,
405
+ * or user applications when fault analysis is needed.
406
+ *
407
+ * @param output_mode Output destination for coredump data:
408
+ *                    - MCD_OUTPUT_MEMORY: Store in memory buffer (recommended for fault handlers)
409
+ *                    - MCD_OUTPUT_SERIAL: Output via serial port (for immediate analysis)
410
+ *                    - MCD_OUTPUT_FILESYSTEM: Save to file (requires filesystem support)
411
+ *
412
+ * @return int Status code:
413
+ *             - MCD_OK: Coredump generated successfully
414
+ *             - MCD_ERROR: Failed to generate coredump (memory overflow, filesystem error, etc.)
415
+ *
416
+ * @note This function calls mcd_faultdump_ex() internally, which contains the actual implementation.
417
+ *       The memory buffer mode is particularly useful for hard fault handlers as the data
418
+ *       persists across system resets when power is maintained.
419
+ *
420
+ * @warning When called from interrupt context (e.g., hard fault handler), avoid using
421
+ *          filesystem mode as it may involve complex I/O operations.
422
+ *
423
+ * @see mcd_faultdump_ex() for detailed implementation
424
+ * @see mcd_check_memory_coredump() to check for existing coredumps in memory
425
+ * @see mcd_dump_filesystem() to save memory coredump to filesystem
426
+ */
427
+int mcd_faultdump(mcd_output_mode_t output_mode)
428
+{
429
+    /* Default to memory storage mode for exception handling */
430
+    return mcd_faultdump_ex(output_mode);
431
+}
432
+
433
+/**
434
+ * @brief Print coredump from memory buffer via serial output
435
+ *
436
+ * This function reads coredump data from memory buffer and prints it via serial port
437
+ *
438
+ * @return int MCD_OK on success, error code on failure
439
+ */
440
+static int mcd_dump_memory(void)
441
+{
442
+    if (!mcd_check_memory_coredump())
443
+    {
444
+        mcd_print("No valid coredump found in memory buffer.\n");
445
+        return MCD_ERROR;
446
+    }
447
+
448
+    /* Verify CRC32 */
449
+    uint32_t calculated_crc = mcd_crc32b(coredump_memory_buffer.data,
450
+                                         coredump_memory_buffer.data_size,
451
+                                         0xFFFFFFFF) ^ 0xFFFFFFFF;
452
+
453
+    if (calculated_crc != coredump_memory_buffer.crc32)
454
+    {
455
+        mcd_print("ERROR: Coredump data corruption detected (CRC mismatch)!\n");
456
+        mcd_print("Expected: 0x%08X, Calculated: 0x%08X\n",
457
+                   coredump_memory_buffer.crc32, calculated_crc);
458
+        return MCD_ERROR;
459
+    }
460
+
461
+    mcd_print("\n=== MCoreDump Memory Data Serial Output ===\n");
462
+    mcd_print("Coredump found in memory buffer:\n");
463
+    mcd_print("  Address: 0x%08X\n", (uint32_t)&coredump_memory_buffer);
464
+    mcd_print("  Size: %d bytes\n", coredump_memory_buffer.data_size);
465
+    mcd_print("  CRC32: 0x%08X\n", coredump_memory_buffer.crc32);
466
+    mcd_print("\n");
467
+
468
+    /* Calculate and display CRC32 for serial output */
469
+    uint32_t serial_crc = 0xFFFFFFFF;
470
+    uint32_t byte_count = 0;
471
+
472
+    mcd_print("coredump start : {\n");
473
+
474
+    /* Print coredump data in hex format */
475
+    for (uint32_t i = 0; i < coredump_memory_buffer.data_size; i++)
476
+    {
477
+        uint8_t b = coredump_memory_buffer.data[i];
478
+        serial_crc = mcd_crc32b(&b, 1, serial_crc) ^ 0xFFFFFFFF;
479
+        mcd_print("%02x", b);
480
+        byte_count++;
481
+    }
482
+
483
+    mcd_print("\n} coredump end\n");
484
+
485
+    serial_crc = ~serial_crc;
486
+    mcd_print("crc32 : %08x\n", serial_crc);
487
+    mcd_print("bytes : %d\n", byte_count);
488
+    mcd_print("=== MCoreDump Memory Data Serial Output Completed ===\n\n");
489
+
490
+    return MCD_OK;
491
+}
492
+MCD_CMD_EXPORT(mcd_dump_memory, Print memory coredump via serial);

Laddar…
Avbryt
Spara