You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

rtthread.c 6.9KB

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