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.
 
 
 
 
 
 

537 lines
14 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. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "rtos_standard_stackings.h"
  30. static int ThreadX_detect_rtos( struct target* target );
  31. static int ThreadX_create( struct target* target );
  32. static int ThreadX_update_threads( struct rtos* rtos);
  33. static int ThreadX_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char ** hex_reg_list );
  34. static int ThreadX_get_symbol_list_to_lookup(symbol_table_elem_t * symbol_list[]);
  35. struct ThreadX_thread_state
  36. {
  37. int value;
  38. char * desc;
  39. };
  40. struct ThreadX_thread_state ThreadX_thread_states[] =
  41. {
  42. { 0, "Ready" },
  43. { 1, "Completed" },
  44. { 2, "Terminated" },
  45. { 3, "Suspended" },
  46. { 4, "Sleeping" },
  47. { 5, "Waiting - Queue" },
  48. { 6, "Waiting - Semaphore" },
  49. { 7, "Waiting - Event flag" },
  50. { 8, "Waiting - Memory" },
  51. { 9, "Waiting - Memory" },
  52. { 10, "Waiting - I/O" },
  53. { 11, "Waiting - Filesystem" },
  54. { 12, "Waiting - Network" },
  55. { 13, "Waiting - Mutex" },
  56. };
  57. #define THREADX_NUM_STATES (sizeof(ThreadX_thread_states)/sizeof(struct ThreadX_thread_state))
  58. struct ThreadX_params
  59. {
  60. char * target_name;
  61. unsigned char pointer_width;
  62. unsigned char thread_stack_offset;
  63. unsigned char thread_name_offset;
  64. unsigned char thread_state_offset;
  65. unsigned char thread_next_offset;
  66. const struct rtos_register_stacking* stacking_info;
  67. };
  68. const struct ThreadX_params ThreadX_params_list[] =
  69. {
  70. { "cortex_m3", // target_name
  71. 4, // pointer_width;
  72. 8, // thread_stack_offset;
  73. 40, // thread_name_offset;
  74. 48, // thread_state_offset;
  75. 136, // thread_next_offset
  76. &rtos_standard_Cortex_M3_stacking, // stacking_info
  77. }
  78. };
  79. #define THREADX_NUM_PARAMS ((int)(sizeof(ThreadX_params_list)/sizeof(struct ThreadX_params)))
  80. enum ThreadX_symbol_values
  81. {
  82. ThreadX_VAL_tx_thread_current_ptr = 0,
  83. ThreadX_VAL_tx_thread_created_ptr = 1,
  84. ThreadX_VAL_tx_thread_created_count = 2,
  85. };
  86. static char* ThreadX_symbol_list[] =
  87. {
  88. "_tx_thread_current_ptr",
  89. "_tx_thread_created_ptr",
  90. "_tx_thread_created_count",
  91. NULL
  92. };
  93. #define THREADX_NUM_SYMBOLS (sizeof(ThreadX_symbol_list)/sizeof(char*))
  94. const struct rtos_type ThreadX_rtos =
  95. {
  96. .name = "ThreadX",
  97. .detect_rtos = ThreadX_detect_rtos,
  98. .create = ThreadX_create,
  99. .update_threads = ThreadX_update_threads,
  100. .get_thread_reg_list = ThreadX_get_thread_reg_list,
  101. .get_symbol_list_to_lookup = ThreadX_get_symbol_list_to_lookup,
  102. };
  103. static int ThreadX_update_threads( struct rtos* rtos)
  104. {
  105. int retval;
  106. int tasks_found = 0;
  107. int thread_list_size = 0;
  108. const struct ThreadX_params* param;
  109. if ( rtos == NULL )
  110. {
  111. return -1;
  112. }
  113. if (rtos->rtos_specific_params == NULL )
  114. {
  115. return -3;
  116. }
  117. param = (const struct ThreadX_params*) rtos->rtos_specific_params;
  118. if ( rtos->symbols == NULL )
  119. {
  120. LOG_OUTPUT("No symbols for ThreadX\r\n");
  121. return -4;
  122. }
  123. if ( rtos->symbols[ThreadX_VAL_tx_thread_created_count].address == 0 )
  124. {
  125. LOG_OUTPUT("Don't have the number of threads in ThreadX \r\n");
  126. return -2;
  127. }
  128. // read the number of threads
  129. retval = target_read_buffer( rtos->target, rtos->symbols[ThreadX_VAL_tx_thread_created_count].address, 4, (uint8_t *)&thread_list_size);
  130. if ( retval != ERROR_OK )
  131. {
  132. LOG_OUTPUT("Could not read ThreadX thread count from target\r\n");
  133. return retval;
  134. }
  135. // wipe out previous thread details if any
  136. if ( rtos->thread_details != NULL )
  137. {
  138. int j;
  139. for( j = 0; j < rtos->thread_count; j++ )
  140. {
  141. if ( rtos->thread_details[j].display_str != NULL )
  142. {
  143. free( rtos->thread_details[j].display_str );
  144. rtos->thread_details[j].display_str = NULL;
  145. }
  146. if ( rtos->thread_details[j].thread_name_str != NULL )
  147. {
  148. free( rtos->thread_details[j].thread_name_str );
  149. rtos->thread_details[j].thread_name_str = NULL;
  150. }
  151. if ( rtos->thread_details[j].extra_info_str != NULL )
  152. {
  153. free( rtos->thread_details[j].extra_info_str );
  154. rtos->thread_details[j].extra_info_str = NULL;
  155. }
  156. }
  157. free( rtos->thread_details );
  158. rtos->thread_details = NULL;
  159. }
  160. // read the current thread id
  161. retval = target_read_buffer( rtos->target, rtos->symbols[ThreadX_VAL_tx_thread_current_ptr].address, 4, (uint8_t *)&rtos->current_thread);
  162. if ( retval != ERROR_OK )
  163. {
  164. LOG_OUTPUT("Could not read ThreadX current thread from target\r\n");
  165. return retval;
  166. }
  167. if ( ( thread_list_size == 0 ) || ( rtos->current_thread == 0 ) )
  168. {
  169. // Either : No RTOS threads - there is always at least the current execution though
  170. // OR : No current thread - all threads suspended - show the current execution of idling
  171. char tmp_str[] = "Current Execution";
  172. thread_list_size++;
  173. tasks_found++;
  174. rtos->thread_details = (struct thread_detail*) malloc( sizeof( struct thread_detail ) * thread_list_size );
  175. rtos->thread_details->threadid = 1;
  176. rtos->thread_details->exists = true;
  177. rtos->thread_details->display_str = NULL;
  178. rtos->thread_details->extra_info_str = NULL;
  179. rtos->thread_details->thread_name_str = (char*) malloc( sizeof(tmp_str) );
  180. strcpy( rtos->thread_details->thread_name_str, tmp_str );
  181. if ( thread_list_size == 0 )
  182. {
  183. rtos->thread_count = 1;
  184. return ERROR_OK;
  185. }
  186. }
  187. else
  188. {
  189. // create space for new thread details
  190. rtos->thread_details = (struct thread_detail*) malloc( sizeof( struct thread_detail ) * thread_list_size );
  191. }
  192. // Read the pointer to the first thread
  193. int64_t thread_ptr = 0;
  194. retval = target_read_buffer( rtos->target, rtos->symbols[ThreadX_VAL_tx_thread_created_ptr].address, param->pointer_width, (uint8_t *)&thread_ptr);
  195. if ( retval != ERROR_OK )
  196. {
  197. LOG_OUTPUT("Could not read ThreadX thread location from target\r\n");
  198. return retval;
  199. }
  200. // loop over all threads
  201. int64_t prev_thread_ptr = 0;
  202. while ( ( thread_ptr != prev_thread_ptr ) && ( tasks_found < thread_list_size ) )
  203. {
  204. #define THREADX_THREAD_NAME_STR_SIZE (200)
  205. char tmp_str[THREADX_THREAD_NAME_STR_SIZE];
  206. unsigned int i = 0;
  207. int64_t name_ptr = 0;
  208. // Save the thread pointer
  209. rtos->thread_details[tasks_found].threadid = thread_ptr;
  210. // read the name pointer
  211. retval = target_read_buffer( rtos->target, thread_ptr + param->thread_name_offset, param->pointer_width, (uint8_t *)&name_ptr);
  212. if ( retval != ERROR_OK )
  213. {
  214. LOG_OUTPUT("Could not read ThreadX thread name pointer from target\r\n");
  215. return retval;
  216. }
  217. // Read the thread name
  218. retval = target_read_buffer( rtos->target, name_ptr, THREADX_THREAD_NAME_STR_SIZE, (uint8_t *)&tmp_str);
  219. if ( retval != ERROR_OK )
  220. {
  221. LOG_OUTPUT("Error reading thread name from ThreadX target\r\n");
  222. return retval;
  223. }
  224. tmp_str[THREADX_THREAD_NAME_STR_SIZE-1] = '\x00';
  225. if ( tmp_str[0] == '\x00' )
  226. {
  227. strcpy(tmp_str,"No Name");
  228. }
  229. rtos->thread_details[tasks_found].thread_name_str = (char*)malloc( strlen(tmp_str)+1 );
  230. strcpy( rtos->thread_details[tasks_found].thread_name_str, tmp_str );
  231. // Read the thread status
  232. int64_t thread_status = 0;
  233. retval = target_read_buffer( rtos->target, thread_ptr + param->thread_state_offset, 4, (uint8_t *)&thread_status);
  234. if ( retval != ERROR_OK )
  235. {
  236. LOG_OUTPUT("Error reading thread state from ThreadX target\r\n");
  237. return retval;
  238. }
  239. for( i = 0; (i < THREADX_NUM_STATES) && (ThreadX_thread_states[i].value!=thread_status); i++ )
  240. {
  241. }
  242. char * state_desc;
  243. if (i < THREADX_NUM_STATES)
  244. {
  245. state_desc = ThreadX_thread_states[i].desc;
  246. }
  247. else
  248. {
  249. state_desc = "Unknown state";
  250. }
  251. rtos->thread_details[tasks_found].extra_info_str = (char*)malloc( strlen(state_desc)+1 );
  252. strcpy( rtos->thread_details[tasks_found].extra_info_str, state_desc );
  253. rtos->thread_details[tasks_found].exists = true;
  254. rtos->thread_details[tasks_found].display_str = NULL;
  255. tasks_found++;
  256. prev_thread_ptr = thread_ptr;
  257. // Get the location of the next thread structure.
  258. thread_ptr = 0;
  259. retval = target_read_buffer( rtos->target, prev_thread_ptr + param->thread_next_offset, param->pointer_width, (uint8_t *) &thread_ptr );
  260. if ( retval != ERROR_OK )
  261. {
  262. LOG_OUTPUT("Error reading next thread pointer in ThreadX thread list\r\n");
  263. return retval;
  264. }
  265. }
  266. rtos->thread_count = tasks_found;
  267. return 0;
  268. }
  269. static int ThreadX_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char ** hex_reg_list )
  270. {
  271. int retval;
  272. const struct ThreadX_params* param;
  273. *hex_reg_list = NULL;
  274. if ( rtos == NULL )
  275. {
  276. return -1;
  277. }
  278. if ( thread_id == 0 )
  279. {
  280. return -2;
  281. }
  282. if (rtos->rtos_specific_params == NULL )
  283. {
  284. return -3;
  285. }
  286. param = (const struct ThreadX_params*) rtos->rtos_specific_params;
  287. // Read the stack pointer
  288. int64_t stack_ptr = 0;
  289. retval = target_read_buffer( rtos->target, thread_id + param->thread_stack_offset, param->pointer_width, (uint8_t*)&stack_ptr);
  290. if ( retval != ERROR_OK )
  291. {
  292. LOG_OUTPUT("Error reading stack frame from ThreadX thread\r\n");
  293. return retval;
  294. }
  295. return rtos_generic_stack_read( rtos->target, param->stacking_info, stack_ptr, hex_reg_list );
  296. }
  297. static int ThreadX_get_symbol_list_to_lookup(symbol_table_elem_t * symbol_list[])
  298. {
  299. unsigned int i;
  300. *symbol_list = (symbol_table_elem_t *) malloc( sizeof( symbol_table_elem_t ) * THREADX_NUM_SYMBOLS );
  301. for( i = 0; i < THREADX_NUM_SYMBOLS; i++ )
  302. {
  303. (*symbol_list)[i].symbol_name = ThreadX_symbol_list[i];
  304. }
  305. return 0;
  306. }
  307. static int ThreadX_detect_rtos( struct target* target )
  308. {
  309. if ( ( target->rtos->symbols != NULL ) &&
  310. ( target->rtos->symbols[ThreadX_VAL_tx_thread_created_ptr].address != 0 ) )
  311. {
  312. // looks like ThreadX
  313. return 1;
  314. }
  315. return 0;
  316. }
  317. #if 0
  318. static int ThreadX_set_current_thread(struct rtos *rtos, threadid_t thread_id)
  319. {
  320. return 0;
  321. }
  322. static int ThreadX_get_thread_detail( struct rtos* rtos, threadid_t thread_id, struct thread_detail* detail )
  323. {
  324. unsigned int i = 0;
  325. int retval;
  326. #define THREADX_THREAD_NAME_STR_SIZE (200)
  327. char tmp_str[THREADX_THREAD_NAME_STR_SIZE];
  328. const struct ThreadX_params* param;
  329. if ( rtos == NULL )
  330. {
  331. return -1;
  332. }
  333. if ( thread_id == 0 )
  334. {
  335. return -2;
  336. }
  337. if (rtos->rtos_specific_params == NULL )
  338. {
  339. return -3;
  340. }
  341. param = (const struct ThreadX_params*) rtos->rtos_specific_params;
  342. if ( rtos->symbols == NULL )
  343. {
  344. LOG_OUTPUT("No symbols for ThreadX\r\n");
  345. return -3;
  346. }
  347. detail->threadid = thread_id;
  348. int64_t name_ptr = 0;
  349. // read the name pointer
  350. retval = target_read_buffer( rtos->target, thread_id + param->thread_name_offset, param->pointer_width, (uint8_t *)&name_ptr);
  351. if ( retval != ERROR_OK )
  352. {
  353. LOG_OUTPUT("Could not read ThreadX thread name pointer from target\r\n");
  354. return retval;
  355. }
  356. // Read the thread name
  357. retval = target_read_buffer( rtos->target, name_ptr, THREADX_THREAD_NAME_STR_SIZE, (uint8_t *)&tmp_str);
  358. if ( retval != ERROR_OK )
  359. {
  360. LOG_OUTPUT("Error reading thread name from ThreadX target\r\n");
  361. return retval;
  362. }
  363. tmp_str[THREADX_THREAD_NAME_STR_SIZE-1] = '\x00';
  364. if ( tmp_str[0] == '\x00' )
  365. {
  366. strcpy(tmp_str,"No Name");
  367. }
  368. detail->thread_name_str = (char*)malloc( strlen(tmp_str)+1 );
  369. // Read the thread status
  370. int64_t thread_status = 0;
  371. retval = target_read_buffer( rtos->target, thread_id + param->thread_state_offset, 4, (uint8_t *)&thread_status);
  372. if ( retval != ERROR_OK )
  373. {
  374. LOG_OUTPUT("Error reading thread state from ThreadX target\r\n");
  375. return retval;
  376. }
  377. for( i = 0; (i < THREADX_NUM_STATES) && (ThreadX_thread_states[i].value!=thread_status); i++ )
  378. {
  379. }
  380. char * state_desc;
  381. if (i < THREADX_NUM_STATES)
  382. {
  383. state_desc = ThreadX_thread_states[i].desc;
  384. }
  385. else
  386. {
  387. state_desc = "Unknown state";
  388. }
  389. detail->extra_info_str = (char*)malloc( strlen(state_desc)+1 );
  390. detail->exists = true;
  391. detail->display_str = NULL;
  392. return 0;
  393. }
  394. #endif
  395. static int ThreadX_create( struct target* target )
  396. {
  397. int i = 0;
  398. while ( ( i < THREADX_NUM_PARAMS ) && ( 0 != strcmp( ThreadX_params_list[i].target_name, target->type->name ) ) )
  399. {
  400. i++;
  401. }
  402. if ( i >= THREADX_NUM_PARAMS )
  403. {
  404. LOG_OUTPUT("Could not find target in ThreadX compatibility list\r\n");
  405. return -1;
  406. }
  407. target->rtos->rtos_specific_params = (void*) &ThreadX_params_list[i];
  408. target->rtos->current_thread = 0;
  409. target->rtos->thread_details = NULL;
  410. return 0;
  411. }