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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  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_thr_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_idx(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_thr_cnts(ops);
  79. return priv->cur_idx;
  80. }
  81. static void rtthread_thr_rset(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_idx(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;
  93. node != &(information->object_list);
  94. node = node->next)
  95. {
  96. object = rt_list_entry(node, struct rt_object, list);
  97. rt_thread_t thread = (rt_thread_t)object;
  98. if (is_thread_object(thread))
  99. {
  100. if (idx == idx_l)
  101. {
  102. /* If this is the current thread, use current registers */
  103. if (idx_l == current_idx)
  104. {
  105. mcd_memcpy(core_regset, get_cur_core_regset_address(), sizeof(core_regset_type));
  106. mcd_memcpy(fp_regset, get_cur_fp_regset_address(), sizeof(fp_regset_type));
  107. }
  108. else
  109. {
  110. /* Debug: Dynamic thread for comparison */
  111. collect_registers((uint32_t *)thread->sp, core_regset, fp_regset);
  112. }
  113. return;
  114. }
  115. idx_l++;
  116. }
  117. }
  118. }
  119. static int32_t rtthread_get_mem_cnts(struct thread_info_ops *ops)
  120. {
  121. return rtthread_thr_cnts(ops);
  122. }
  123. static int32_t rtthread_get_memarea(struct thread_info_ops *ops, int32_t idx,
  124. uint32_t *addr, uint32_t *memlen)
  125. {
  126. rt_int32_t idx_l = 0;
  127. rt_int32_t current_idx = rtthread_cur_idx(ops);
  128. struct rt_object_information *information;
  129. struct rt_object *object;
  130. struct rt_list_node *node;
  131. information = rt_object_get_information(RT_Object_Class_Thread);
  132. mcd_assert(information != RT_NULL);
  133. for (node = information->object_list.next;
  134. node != &(information->object_list);
  135. node = node->next)
  136. {
  137. object = rt_list_entry(node, struct rt_object, list);
  138. rt_thread_t thread = (rt_thread_t)object;
  139. if (is_thread_object(thread))
  140. {
  141. if (idx == idx_l)
  142. {
  143. /* If this is the current thread, use current stack pointer */
  144. if (idx_l == current_idx)
  145. {
  146. *addr = get_cur_core_regset_address()->sp;
  147. *memlen = 1024;
  148. }
  149. else
  150. {
  151. *addr = (rt_uint32_t)thread->sp;
  152. *memlen = (rt_uint32_t)thread->stack_addr + thread->stack_size - (rt_uint32_t)thread->sp;
  153. }
  154. return 0;
  155. }
  156. idx_l++;
  157. }
  158. }
  159. return 0;
  160. }
  161. void mcd_rtos_thread_ops(struct thread_info_ops *ops)
  162. {
  163. static rtthread_ti_priv_t priv;
  164. ops->get_threads_count = rtthread_thr_cnts;
  165. ops->get_current_thread_idx = rtthread_cur_idx;
  166. ops->get_thread_regset = rtthread_thr_rset;
  167. ops->get_memarea_count = rtthread_get_mem_cnts;
  168. ops->get_memarea = rtthread_get_memarea;
  169. ops->priv = &priv;
  170. priv.cur_idx = -1;
  171. priv.thr_cnts = -1;
  172. }
  173. MCD_WEAK rt_err_t rtt_hard_fault_exception_hook(void *context)
  174. {
  175. arch_hard_fault_exception_hook(context);
  176. return -RT_ERROR;
  177. }
  178. MCD_WEAK void rtt_assert_hook(const char *ex, const char *func, rt_size_t line)
  179. {
  180. volatile uint8_t _continue = 1;
  181. rt_interrupt_enter();
  182. mcd_print("(%s) has assert failed at %s:%ld.\n", ex, func, line);
  183. mcd_faultdump(MCD_OUTPUT_SERIAL);
  184. rt_interrupt_leave();
  185. while (_continue == 1);
  186. }
  187. static int mcd_coredump_init(void)
  188. {
  189. static mcd_bool_t is_init = MCD_FALSE;
  190. if (is_init)
  191. {
  192. return 0;
  193. }
  194. //mcd_print_memoryinfo();
  195. rt_hw_exception_install(rtt_hard_fault_exception_hook);
  196. //rt_assert_set_hook(rtt_assert_hook);
  197. is_init = MCD_TRUE;
  198. return RT_EOK;
  199. }
  200. INIT_DEVICE_EXPORT(mcd_coredump_init);