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.
 
 
 
 
 
 

347 lines
9.4 KiB

  1. /***************************************************************************
  2. * Copyright (C) 2012 by Matthias Blaicher *
  3. * Matthias Blaicher - matthias@blaicher.com *
  4. * *
  5. * Copyright (C) 2011 by Broadcom Corporation *
  6. * Evan Hunter - ehunter@broadcom.com *
  7. * *
  8. * This program is free software; you can redistribute it and/or modify *
  9. * it under the terms of the GNU General Public License as published by *
  10. * the Free Software Foundation; either version 2 of the License, or *
  11. * (at your option) any later version. *
  12. * *
  13. * This program is distributed in the hope that it will be useful, *
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  16. * GNU General Public License for more details. *
  17. * *
  18. * You should have received a copy of the GNU General Public License *
  19. * along with this program; if not, write to the *
  20. * Free Software Foundation, Inc., *
  21. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  22. ***************************************************************************/
  23. /*
  24. * ChangeLog:
  25. * 2016 changed by Sony Corporation
  26. */
  27. #ifdef HAVE_CONFIG_H
  28. #include "config.h"
  29. #endif
  30. #include <jtag/jtag.h>
  31. #include "target/target.h"
  32. #include "target/target_type.h"
  33. #include "target/armv7m.h"
  34. #include "target/cortex_m.h"
  35. #include "rtos.h"
  36. #include "helper/log.h"
  37. #include "helper/types.h"
  38. #include "server/gdb_server.h"
  39. #include "nuttx_header.h"
  40. int rtos_thread_packet(struct connection *connection, const char *packet, int packet_size);
  41. #ifdef CONFIG_DISABLE_SIGNALS
  42. #define SIG_QUEUE_NUM 0
  43. #else
  44. #define SIG_QUEUE_NUM 1
  45. #endif /* CONFIG_DISABLE_SIGNALS */
  46. #ifdef CONFIG_DISABLE_MQUEUE
  47. #define M_QUEUE_NUM 0
  48. #else
  49. #define M_QUEUE_NUM 2
  50. #endif /* CONFIG_DISABLE_MQUEUE */
  51. #ifdef CONFIG_PAGING
  52. #define PAGING_QUEUE_NUM 1
  53. #else
  54. #define PAGING_QUEUE_NUM 0
  55. #endif /* CONFIG_PAGING */
  56. #define TASK_QUEUE_NUM (6 + SIG_QUEUE_NUM + M_QUEUE_NUM + PAGING_QUEUE_NUM)
  57. /* see nuttx/sched/os_start.c */
  58. static char *nuttx_symbol_list[] = {
  59. "g_readytorun", /* 0: must be top of this array */
  60. "g_tasklisttable",
  61. NULL
  62. };
  63. /* see nuttx/include/nuttx/sched.h */
  64. struct tcb_s
  65. {
  66. uint32_t flink;
  67. uint32_t blink;
  68. uint8_t dat[256];
  69. };
  70. struct {
  71. uint32_t addr;
  72. uint32_t prio;
  73. } g_tasklist[TASK_QUEUE_NUM];
  74. static char *task_state_str[] =
  75. {
  76. "INVALID",
  77. "PENDING",
  78. "READYTORUN",
  79. "RUNNING",
  80. "INACTIVE",
  81. "WAIT_SEM",
  82. #ifndef CONFIG_DISABLE_SIGNALS
  83. "WAIT_SIG",
  84. #endif /* CONFIG_DISABLE_SIGNALS */
  85. #ifndef CONFIG_DISABLE_MQUEUE
  86. "WAIT_MQNOTEMPTY",
  87. "WAIT_MQNOTFULL",
  88. #endif /* CONFIG_DISABLE_MQUEUE */
  89. #ifdef CONFIG_PAGING
  90. "WAIT_PAGEFILL",
  91. #endif /* CONFIG_PAGING */
  92. };
  93. /* see arch/arm/include/armv7-m/irq_cmnvector.h */
  94. static const struct stack_register_offset nuttx_stack_offsets_cortex_m[] = {
  95. { 0x28, 32 }, /* r0 */
  96. { 0x2c, 32 }, /* r1 */
  97. { 0x30, 32 }, /* r2 */
  98. { 0x34, 32 }, /* r3 */
  99. { 0x08, 32 }, /* r4 */
  100. { 0x0c, 32 }, /* r5 */
  101. { 0x10, 32 }, /* r6 */
  102. { 0x14, 32 }, /* r7 */
  103. { 0x18, 32 }, /* r8 */
  104. { 0x1c, 32 }, /* r9 */
  105. { 0x20, 32 }, /* r10 */
  106. { 0x24, 32 }, /* r11 */
  107. { 0x38, 32 }, /* r12 */
  108. { 0, 32 }, /* sp */
  109. { 0x3c, 32 }, /* lr */
  110. { 0x40, 32 }, /* pc */
  111. { 0x44, 32 }, /* xPSR */
  112. };
  113. static const struct rtos_register_stacking nuttx_stacking_cortex_m = {
  114. 0x48, /* stack_registers_size */
  115. -1, /* stack_growth_direction */
  116. 17, /* num_output_registers */
  117. 0, /* stack_alignment */
  118. nuttx_stack_offsets_cortex_m /* register_offsets */
  119. };
  120. static uint8_t pid_offset = PID;
  121. static uint8_t state_offset = STATE;
  122. static uint8_t name_offset = NAME;
  123. static uint8_t xcpreg_offset = XCPREG;
  124. static uint8_t name_size = NAME_SIZE;
  125. static int rcmd_offset(const char *cmd, const char *name)
  126. {
  127. if (strncmp(cmd, name, strlen(name)))
  128. return -1;
  129. if (strlen(cmd) <= strlen(name) + 1)
  130. return -1;
  131. return atoi(cmd + strlen(name));
  132. }
  133. static int nuttx_thread_packet(struct connection *connection,
  134. char const *packet, int packet_size)
  135. {
  136. char cmd[GDB_BUFFER_SIZE / 2] = "";
  137. if (!strncmp(packet, "qRcmd", 5)) {
  138. int len = unhexify((uint8_t *)cmd, packet + 6, sizeof(cmd));
  139. int offset;
  140. if (len <= 0)
  141. goto pass;
  142. if ((offset = rcmd_offset(cmd, "nuttx.pid_offset")) >= 0) {
  143. LOG_INFO("pid_offset: %d", offset);
  144. pid_offset = offset;
  145. goto retok;
  146. }
  147. if ((offset = rcmd_offset(cmd, "nuttx.state_offset")) >= 0) {
  148. LOG_INFO("state_offset: %d", offset);
  149. state_offset = offset;
  150. goto retok;
  151. }
  152. if ((offset = rcmd_offset(cmd, "nuttx.name_offset")) >= 0) {
  153. LOG_INFO("name_offset: %d", offset);
  154. name_offset = offset;
  155. goto retok;
  156. }
  157. if ((offset = rcmd_offset(cmd, "nuttx.xcpreg_offset")) >= 0) {
  158. LOG_INFO("xcpreg_offset: %d", offset);
  159. xcpreg_offset = offset;
  160. goto retok;
  161. }
  162. if ((offset = rcmd_offset(cmd, "nuttx.name_size")) >= 0) {
  163. LOG_INFO("name_size: %d", offset);
  164. name_size = offset;
  165. goto retok;
  166. }
  167. }
  168. pass:
  169. return rtos_thread_packet(connection, packet, packet_size);
  170. retok:
  171. gdb_put_packet(connection, "OK", 2);
  172. return ERROR_OK;
  173. }
  174. static int nuttx_detect_rtos(struct target *target)
  175. {
  176. if ((target->rtos->symbols != NULL) &&
  177. (target->rtos->symbols[0].address != 0) &&
  178. (target->rtos->symbols[1].address != 0)) {
  179. LOG_OUTPUT("detect Nuttx");
  180. return 1;
  181. }
  182. return 0;
  183. }
  184. static int nuttx_create(struct target *target)
  185. {
  186. target->rtos->gdb_thread_packet = nuttx_thread_packet;
  187. LOG_INFO("target type name = %s", target->type->name);
  188. return 0;
  189. }
  190. static int nuttx_update_threads(struct rtos *rtos)
  191. {
  192. int thread_count;
  193. struct tcb_s tcb;
  194. int ret;
  195. uint32_t head;
  196. uint32_t tcb_addr;
  197. int i;
  198. thread_count = 0;
  199. /* free old thread info */
  200. if (rtos->thread_details) {
  201. for (i = 0; i < rtos->thread_count; i++) {
  202. if (rtos->thread_details[i].thread_name_str)
  203. free(rtos->thread_details[i].thread_name_str);
  204. }
  205. free(rtos->thread_details);
  206. rtos->thread_details = NULL;
  207. rtos->thread_count = 0;
  208. }
  209. ret = target_read_buffer(rtos->target, rtos->symbols[1].address,
  210. sizeof(g_tasklist), (uint8_t *)&g_tasklist);
  211. if (ret) {
  212. LOG_ERROR("target_read_buffer : ret = %d\n", ret);
  213. return ERROR_FAIL;
  214. }
  215. for (i = 0; i < (int)TASK_QUEUE_NUM; i++) {
  216. if (g_tasklist[i].addr == 0)
  217. continue;
  218. ret = target_read_u32(rtos->target, g_tasklist[i].addr,
  219. &head);
  220. if (ret) {
  221. LOG_ERROR("target_read_u32 : ret = %d\n", ret);
  222. return ERROR_FAIL;
  223. }
  224. /* readytorun head is current thread */
  225. if (g_tasklist[i].addr == rtos->symbols[0].address)
  226. rtos->current_thread = head;
  227. tcb_addr = head;
  228. while (tcb_addr) {
  229. struct thread_detail *thread;
  230. ret = target_read_buffer(rtos->target, tcb_addr,
  231. sizeof(tcb), (uint8_t *)&tcb);
  232. if (ret) {
  233. LOG_ERROR("target_read_buffer : ret = %d\n",
  234. ret);
  235. return ERROR_FAIL;
  236. }
  237. thread_count++;
  238. rtos->thread_details = realloc(rtos->thread_details,
  239. sizeof(struct thread_detail) * thread_count);
  240. thread = &rtos->thread_details[thread_count - 1];
  241. thread->threadid = tcb_addr;
  242. thread->exists = true;
  243. // thread->display_str = malloc(256);
  244. // snprintf(thread->display_str, 256, "pid:%d",
  245. // tcb.dat[pid_offset - 8] |
  246. // tcb.dat[pid_offset - 8 + 1] << 8);
  247. if (name_offset) {
  248. thread->thread_name_str = malloc(name_size + 1);
  249. snprintf(thread->thread_name_str, name_size,
  250. "%s", (char *)&tcb.dat[name_offset - 8]);
  251. } else
  252. thread->thread_name_str = NULL;
  253. thread->extra_info_str =
  254. task_state_str[tcb.dat[state_offset - 8]];
  255. tcb_addr = tcb.flink;
  256. }
  257. }
  258. rtos->thread_count = thread_count;
  259. return 0;
  260. }
  261. /*
  262. * thread_id = tcb address;
  263. */
  264. static int nuttx_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
  265. char **hex_reg_list) {
  266. LOG_DEBUG("*** thread_id=%ld (0x%08x)", thread_id, (int32_t)thread_id);
  267. *hex_reg_list = NULL;
  268. return rtos_generic_stack_read(rtos->target, &nuttx_stacking_cortex_m,
  269. (uint32_t)thread_id + xcpreg_offset, hex_reg_list);
  270. };
  271. static int nuttx_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
  272. {
  273. unsigned int i;
  274. *symbol_list = (symbol_table_elem_t *) calloc(1,
  275. sizeof(symbol_table_elem_t) * ARRAY_SIZE(nuttx_symbol_list));
  276. for (i = 0; i < ARRAY_SIZE(nuttx_symbol_list); i++)
  277. (*symbol_list)[i].symbol_name = nuttx_symbol_list[i];
  278. return 0;
  279. }
  280. struct rtos_type nuttx_rtos = {
  281. .name = "nuttx",
  282. .detect_rtos = nuttx_detect_rtos,
  283. .create = nuttx_create,
  284. .update_threads = nuttx_update_threads,
  285. .get_thread_reg_list = nuttx_get_thread_reg_list,
  286. .get_symbol_list_to_lookup = nuttx_get_symbol_list_to_lookup,
  287. };