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.
 
 
 
 
 
 

499 lines
16 KiB

  1. /***************************************************************************
  2. * Copyright (C) 2011 by Broadcom Corporation *
  3. * Evan Hunter - ehunter@broadcom.com *
  4. * *
  5. * This program is free software; you can redistribute it and/or modify *
  6. * it under the terms of the GNU General Public License as published by *
  7. * the Free Software Foundation; either version 2 of the License, or *
  8. * (at your option) any later version. *
  9. * *
  10. * This program is distributed in the hope that it will be useful, *
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  13. * GNU General Public License for more details. *
  14. * *
  15. * You should have received a copy of the GNU General Public License *
  16. * along with this program; if not, write to the *
  17. * Free Software Foundation, Inc., *
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
  19. ***************************************************************************/
  20. #ifdef HAVE_CONFIG_H
  21. #include "config.h"
  22. #endif
  23. #include <helper/time_support.h>
  24. #include <jtag/jtag.h>
  25. #include "target/target.h"
  26. #include "target/target_type.h"
  27. #include "rtos.h"
  28. #include "helper/log.h"
  29. #include "helper/types.h"
  30. #include "rtos_standard_stackings.h"
  31. #define FREERTOS_MAX_PRIORITIES 63
  32. #define FreeRTOS_STRUCT(int_type, ptr_type, list_prev_offset)
  33. struct FreeRTOS_params {
  34. const char *target_name;
  35. const unsigned char thread_count_width;
  36. const unsigned char pointer_width;
  37. const unsigned char list_next_offset;
  38. const unsigned char list_width;
  39. const unsigned char list_elem_next_offset;
  40. const unsigned char list_elem_content_offset;
  41. const unsigned char thread_stack_offset;
  42. const unsigned char thread_name_offset;
  43. const struct rtos_register_stacking *stacking_info;
  44. };
  45. static const struct FreeRTOS_params FreeRTOS_params_list[] = {
  46. {
  47. "cortex_m", /* target_name */
  48. 4, /* thread_count_width; */
  49. 4, /* pointer_width; */
  50. 16, /* list_next_offset; */
  51. 20, /* list_width; */
  52. 8, /* list_elem_next_offset; */
  53. 12, /* list_elem_content_offset */
  54. 0, /* thread_stack_offset; */
  55. 52, /* thread_name_offset; */
  56. &rtos_standard_Cortex_M3_stacking, /* stacking_info */
  57. },
  58. {
  59. "hla_target", /* target_name */
  60. 4, /* thread_count_width; */
  61. 4, /* pointer_width; */
  62. 16, /* list_next_offset; */
  63. 20, /* list_width; */
  64. 8, /* list_elem_next_offset; */
  65. 12, /* list_elem_content_offset */
  66. 0, /* thread_stack_offset; */
  67. 52, /* thread_name_offset; */
  68. &rtos_standard_Cortex_M3_stacking, /* stacking_info */
  69. },
  70. {
  71. "nds32_v3", /* target_name */
  72. 4, /* thread_count_width; */
  73. 4, /* pointer_width; */
  74. 16, /* list_next_offset; */
  75. 20, /* list_width; */
  76. 8, /* list_elem_next_offset; */
  77. 12, /* list_elem_content_offset */
  78. 0, /* thread_stack_offset; */
  79. 52, /* thread_name_offset; */
  80. &rtos_standard_NDS32_N1068_stacking, /* stacking_info */
  81. },
  82. };
  83. #define FREERTOS_NUM_PARAMS ((int)(sizeof(FreeRTOS_params_list)/sizeof(struct FreeRTOS_params)))
  84. static int FreeRTOS_detect_rtos(struct target *target);
  85. static int FreeRTOS_create(struct target *target);
  86. static int FreeRTOS_update_threads(struct rtos *rtos);
  87. static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list);
  88. static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]);
  89. struct rtos_type FreeRTOS_rtos = {
  90. .name = "FreeRTOS",
  91. .detect_rtos = FreeRTOS_detect_rtos,
  92. .create = FreeRTOS_create,
  93. .update_threads = FreeRTOS_update_threads,
  94. .get_thread_reg_list = FreeRTOS_get_thread_reg_list,
  95. .get_symbol_list_to_lookup = FreeRTOS_get_symbol_list_to_lookup,
  96. };
  97. enum FreeRTOS_symbol_values {
  98. FreeRTOS_VAL_pxCurrentTCB = 0,
  99. FreeRTOS_VAL_pxReadyTasksLists = 1,
  100. FreeRTOS_VAL_xDelayedTaskList1 = 2,
  101. FreeRTOS_VAL_xDelayedTaskList2 = 3,
  102. FreeRTOS_VAL_pxDelayedTaskList = 4,
  103. FreeRTOS_VAL_pxOverflowDelayedTaskList = 5,
  104. FreeRTOS_VAL_xPendingReadyList = 6,
  105. FreeRTOS_VAL_xTasksWaitingTermination = 7,
  106. FreeRTOS_VAL_xSuspendedTaskList = 8,
  107. FreeRTOS_VAL_uxCurrentNumberOfTasks = 9,
  108. FreeRTOS_VAL_uxTopUsedPriority = 10,
  109. };
  110. static const char * const FreeRTOS_symbol_list[] = {
  111. "pxCurrentTCB",
  112. "pxReadyTasksLists",
  113. "xDelayedTaskList1",
  114. "xDelayedTaskList2",
  115. "pxDelayedTaskList",
  116. "pxOverflowDelayedTaskList",
  117. "xPendingReadyList",
  118. "xTasksWaitingTermination",
  119. "xSuspendedTaskList",
  120. "uxCurrentNumberOfTasks",
  121. "uxTopUsedPriority",
  122. NULL
  123. };
  124. /* TODO: */
  125. /* this is not safe for little endian yet */
  126. /* may be problems reading if sizes are not 32 bit long integers. */
  127. /* test mallocs for failure */
  128. static int FreeRTOS_update_threads(struct rtos *rtos)
  129. {
  130. int i = 0;
  131. int retval;
  132. int tasks_found = 0;
  133. const struct FreeRTOS_params *param;
  134. if (rtos->rtos_specific_params == NULL)
  135. return -1;
  136. param = (const struct FreeRTOS_params *) rtos->rtos_specific_params;
  137. if (rtos->symbols == NULL) {
  138. LOG_ERROR("No symbols for FreeRTOS");
  139. return -3;
  140. }
  141. if (rtos->symbols[FreeRTOS_VAL_uxCurrentNumberOfTasks].address == 0) {
  142. LOG_ERROR("Don't have the number of threads in FreeRTOS");
  143. return -2;
  144. }
  145. int thread_list_size = 0;
  146. retval = target_read_buffer(rtos->target,
  147. rtos->symbols[FreeRTOS_VAL_uxCurrentNumberOfTasks].address,
  148. param->thread_count_width,
  149. (uint8_t *)&thread_list_size);
  150. LOG_DEBUG("FreeRTOS: Read uxCurrentNumberOfTasks at 0x%" PRIx64 ", value %d\r\n",
  151. rtos->symbols[FreeRTOS_VAL_uxCurrentNumberOfTasks].address,
  152. thread_list_size);
  153. if (retval != ERROR_OK) {
  154. LOG_ERROR("Could not read FreeRTOS thread count from target");
  155. return retval;
  156. }
  157. /* wipe out previous thread details if any */
  158. rtos_free_threadlist(rtos);
  159. /* read the current thread */
  160. retval = target_read_buffer(rtos->target,
  161. rtos->symbols[FreeRTOS_VAL_pxCurrentTCB].address,
  162. param->pointer_width,
  163. (uint8_t *)&rtos->current_thread);
  164. if (retval != ERROR_OK) {
  165. LOG_ERROR("Error reading current thread in FreeRTOS thread list");
  166. return retval;
  167. }
  168. LOG_DEBUG("FreeRTOS: Read pxCurrentTCB at 0x%" PRIx64 ", value 0x%" PRIx64 "\r\n",
  169. rtos->symbols[FreeRTOS_VAL_pxCurrentTCB].address,
  170. rtos->current_thread);
  171. if ((thread_list_size == 0) || (rtos->current_thread == 0)) {
  172. /* Either : No RTOS threads - there is always at least the current execution though */
  173. /* OR : No current thread - all threads suspended - show the current execution
  174. * of idling */
  175. char tmp_str[] = "Current Execution";
  176. thread_list_size++;
  177. tasks_found++;
  178. rtos->thread_details = malloc(
  179. sizeof(struct thread_detail) * thread_list_size);
  180. if (!rtos->thread_details) {
  181. LOG_ERROR("Error allocating memory for %d threads", thread_list_size);
  182. return ERROR_FAIL;
  183. }
  184. rtos->thread_details->threadid = 1;
  185. rtos->thread_details->exists = true;
  186. rtos->thread_details->display_str = NULL;
  187. rtos->thread_details->extra_info_str = NULL;
  188. rtos->thread_details->thread_name_str = malloc(sizeof(tmp_str));
  189. strcpy(rtos->thread_details->thread_name_str, tmp_str);
  190. if (thread_list_size == 1) {
  191. rtos->thread_count = 1;
  192. return ERROR_OK;
  193. }
  194. } else {
  195. /* create space for new thread details */
  196. rtos->thread_details = malloc(
  197. sizeof(struct thread_detail) * thread_list_size);
  198. if (!rtos->thread_details) {
  199. LOG_ERROR("Error allocating memory for %d threads", thread_list_size);
  200. return ERROR_FAIL;
  201. }
  202. }
  203. /* Find out how many lists are needed to be read from pxReadyTasksLists, */
  204. int64_t max_used_priority = 0;
  205. retval = target_read_buffer(rtos->target,
  206. rtos->symbols[FreeRTOS_VAL_uxTopUsedPriority].address,
  207. param->pointer_width,
  208. (uint8_t *)&max_used_priority);
  209. if (retval != ERROR_OK)
  210. return retval;
  211. LOG_DEBUG("FreeRTOS: Read uxTopUsedPriority at 0x%" PRIx64 ", value %" PRId64 "\r\n",
  212. rtos->symbols[FreeRTOS_VAL_uxTopUsedPriority].address,
  213. max_used_priority);
  214. if (max_used_priority > FREERTOS_MAX_PRIORITIES) {
  215. LOG_ERROR("FreeRTOS maximum used priority is unreasonably big, not proceeding: %" PRId64 "",
  216. max_used_priority);
  217. return ERROR_FAIL;
  218. }
  219. symbol_address_t *list_of_lists =
  220. malloc(sizeof(symbol_address_t) *
  221. (max_used_priority+1 + 5));
  222. if (!list_of_lists) {
  223. LOG_ERROR("Error allocating memory for %" PRId64 " priorities", max_used_priority);
  224. return ERROR_FAIL;
  225. }
  226. int num_lists;
  227. for (num_lists = 0; num_lists <= max_used_priority; num_lists++)
  228. list_of_lists[num_lists] = rtos->symbols[FreeRTOS_VAL_pxReadyTasksLists].address +
  229. num_lists * param->list_width;
  230. list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xDelayedTaskList1].address;
  231. list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xDelayedTaskList2].address;
  232. list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xPendingReadyList].address;
  233. list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xSuspendedTaskList].address;
  234. list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xTasksWaitingTermination].address;
  235. for (i = 0; i < num_lists; i++) {
  236. if (list_of_lists[i] == 0)
  237. continue;
  238. /* Read the number of threads in this list */
  239. int64_t list_thread_count = 0;
  240. retval = target_read_buffer(rtos->target,
  241. list_of_lists[i],
  242. param->thread_count_width,
  243. (uint8_t *)&list_thread_count);
  244. if (retval != ERROR_OK) {
  245. LOG_ERROR("Error reading number of threads in FreeRTOS thread list");
  246. free(list_of_lists);
  247. return retval;
  248. }
  249. LOG_DEBUG("FreeRTOS: Read thread count for list %d at 0x%" PRIx64 ", value %" PRId64 "\r\n",
  250. i, list_of_lists[i], list_thread_count);
  251. if (list_thread_count == 0)
  252. continue;
  253. /* Read the location of first list item */
  254. uint64_t prev_list_elem_ptr = -1;
  255. uint64_t list_elem_ptr = 0;
  256. retval = target_read_buffer(rtos->target,
  257. list_of_lists[i] + param->list_next_offset,
  258. param->pointer_width,
  259. (uint8_t *)&list_elem_ptr);
  260. if (retval != ERROR_OK) {
  261. LOG_ERROR("Error reading first thread item location in FreeRTOS thread list");
  262. free(list_of_lists);
  263. return retval;
  264. }
  265. LOG_DEBUG("FreeRTOS: Read first item for list %d at 0x%" PRIx64 ", value 0x%" PRIx64 "\r\n",
  266. i, list_of_lists[i] + param->list_next_offset, list_elem_ptr);
  267. while ((list_thread_count > 0) && (list_elem_ptr != 0) &&
  268. (list_elem_ptr != prev_list_elem_ptr) &&
  269. (tasks_found < thread_list_size)) {
  270. /* Get the location of the thread structure. */
  271. rtos->thread_details[tasks_found].threadid = 0;
  272. retval = target_read_buffer(rtos->target,
  273. list_elem_ptr + param->list_elem_content_offset,
  274. param->pointer_width,
  275. (uint8_t *)&(rtos->thread_details[tasks_found].threadid));
  276. if (retval != ERROR_OK) {
  277. LOG_ERROR("Error reading thread list item object in FreeRTOS thread list");
  278. free(list_of_lists);
  279. return retval;
  280. }
  281. LOG_DEBUG("FreeRTOS: Read Thread ID at 0x%" PRIx64 ", value 0x%" PRIx64 "\r\n",
  282. list_elem_ptr + param->list_elem_content_offset,
  283. rtos->thread_details[tasks_found].threadid);
  284. /* get thread name */
  285. #define FREERTOS_THREAD_NAME_STR_SIZE (200)
  286. char tmp_str[FREERTOS_THREAD_NAME_STR_SIZE];
  287. /* Read the thread name */
  288. retval = target_read_buffer(rtos->target,
  289. rtos->thread_details[tasks_found].threadid + param->thread_name_offset,
  290. FREERTOS_THREAD_NAME_STR_SIZE,
  291. (uint8_t *)&tmp_str);
  292. if (retval != ERROR_OK) {
  293. LOG_ERROR("Error reading first thread item location in FreeRTOS thread list");
  294. free(list_of_lists);
  295. return retval;
  296. }
  297. tmp_str[FREERTOS_THREAD_NAME_STR_SIZE-1] = '\x00';
  298. LOG_DEBUG("FreeRTOS: Read Thread Name at 0x%" PRIx64 ", value \"%s\"\r\n",
  299. rtos->thread_details[tasks_found].threadid + param->thread_name_offset,
  300. tmp_str);
  301. if (tmp_str[0] == '\x00')
  302. strcpy(tmp_str, "No Name");
  303. rtos->thread_details[tasks_found].thread_name_str =
  304. malloc(strlen(tmp_str)+1);
  305. strcpy(rtos->thread_details[tasks_found].thread_name_str, tmp_str);
  306. rtos->thread_details[tasks_found].display_str = NULL;
  307. rtos->thread_details[tasks_found].exists = true;
  308. if (rtos->thread_details[tasks_found].threadid == rtos->current_thread) {
  309. char running_str[] = "Running";
  310. rtos->thread_details[tasks_found].extra_info_str = malloc(
  311. sizeof(running_str));
  312. strcpy(rtos->thread_details[tasks_found].extra_info_str,
  313. running_str);
  314. } else
  315. rtos->thread_details[tasks_found].extra_info_str = NULL;
  316. tasks_found++;
  317. list_thread_count--;
  318. prev_list_elem_ptr = list_elem_ptr;
  319. list_elem_ptr = 0;
  320. retval = target_read_buffer(rtos->target,
  321. prev_list_elem_ptr + param->list_elem_next_offset,
  322. param->pointer_width,
  323. (uint8_t *)&list_elem_ptr);
  324. if (retval != ERROR_OK) {
  325. LOG_ERROR("Error reading next thread item location in FreeRTOS thread list");
  326. free(list_of_lists);
  327. return retval;
  328. }
  329. LOG_DEBUG("FreeRTOS: Read next thread location at 0x%" PRIx64 ", value 0x%" PRIx64 "\r\n",
  330. prev_list_elem_ptr + param->list_elem_next_offset,
  331. list_elem_ptr);
  332. }
  333. }
  334. free(list_of_lists);
  335. rtos->thread_count = tasks_found;
  336. return 0;
  337. }
  338. static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list)
  339. {
  340. int retval;
  341. const struct FreeRTOS_params *param;
  342. int64_t stack_ptr = 0;
  343. *hex_reg_list = NULL;
  344. if (rtos == NULL)
  345. return -1;
  346. if (thread_id == 0)
  347. return -2;
  348. if (rtos->rtos_specific_params == NULL)
  349. return -1;
  350. param = (const struct FreeRTOS_params *) rtos->rtos_specific_params;
  351. /* Read the stack pointer */
  352. retval = target_read_buffer(rtos->target,
  353. thread_id + param->thread_stack_offset,
  354. param->pointer_width,
  355. (uint8_t *)&stack_ptr);
  356. if (retval != ERROR_OK) {
  357. LOG_ERROR("Error reading stack frame from FreeRTOS thread");
  358. return retval;
  359. }
  360. LOG_DEBUG("FreeRTOS: Read stack pointer at 0x%" PRIx64 ", value 0x%" PRIx64 "\r\n",
  361. thread_id + param->thread_stack_offset,
  362. stack_ptr);
  363. return rtos_generic_stack_read(rtos->target, param->stacking_info, stack_ptr, hex_reg_list);
  364. }
  365. static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
  366. {
  367. unsigned int i;
  368. *symbol_list = calloc(
  369. ARRAY_SIZE(FreeRTOS_symbol_list), sizeof(symbol_table_elem_t));
  370. for (i = 0; i < ARRAY_SIZE(FreeRTOS_symbol_list); i++)
  371. (*symbol_list)[i].symbol_name = FreeRTOS_symbol_list[i];
  372. return 0;
  373. }
  374. #if 0
  375. static int FreeRTOS_set_current_thread(struct rtos *rtos, threadid_t thread_id)
  376. {
  377. return 0;
  378. }
  379. static int FreeRTOS_get_thread_ascii_info(struct rtos *rtos, threadid_t thread_id, char **info)
  380. {
  381. int retval;
  382. const struct FreeRTOS_params *param;
  383. if (rtos == NULL)
  384. return -1;
  385. if (thread_id == 0)
  386. return -2;
  387. if (rtos->rtos_specific_params == NULL)
  388. return -3;
  389. param = (const struct FreeRTOS_params *) rtos->rtos_specific_params;
  390. #define FREERTOS_THREAD_NAME_STR_SIZE (200)
  391. char tmp_str[FREERTOS_THREAD_NAME_STR_SIZE];
  392. /* Read the thread name */
  393. retval = target_read_buffer(rtos->target,
  394. thread_id + param->thread_name_offset,
  395. FREERTOS_THREAD_NAME_STR_SIZE,
  396. (uint8_t *)&tmp_str);
  397. if (retval != ERROR_OK) {
  398. LOG_ERROR("Error reading first thread item location in FreeRTOS thread list");
  399. return retval;
  400. }
  401. tmp_str[FREERTOS_THREAD_NAME_STR_SIZE-1] = '\x00';
  402. if (tmp_str[0] == '\x00')
  403. strcpy(tmp_str, "No Name");
  404. *info = malloc(strlen(tmp_str)+1);
  405. strcpy(*info, tmp_str);
  406. return 0;
  407. }
  408. #endif
  409. static int FreeRTOS_detect_rtos(struct target *target)
  410. {
  411. if ((target->rtos->symbols != NULL) &&
  412. (target->rtos->symbols[FreeRTOS_VAL_pxReadyTasksLists].address != 0)) {
  413. /* looks like FreeRTOS */
  414. return 1;
  415. }
  416. return 0;
  417. }
  418. static int FreeRTOS_create(struct target *target)
  419. {
  420. int i = 0;
  421. while ((i < FREERTOS_NUM_PARAMS) &&
  422. (0 != strcmp(FreeRTOS_params_list[i].target_name, target->type->name))) {
  423. i++;
  424. }
  425. if (i >= FREERTOS_NUM_PARAMS) {
  426. LOG_ERROR("Could not find target in FreeRTOS compatibility list");
  427. return -1;
  428. }
  429. target->rtos->rtos_specific_params = (void *) &FreeRTOS_params_list[i];
  430. return 0;
  431. }