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.
 
 
 
 
 
 

482 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. #define FreeRTOS_STRUCT( int_type, ptr_type, list_prev_offset )
  31. struct FreeRTOS_params
  32. {
  33. const char * target_name;
  34. const unsigned char thread_count_width;
  35. const unsigned char pointer_width;
  36. const unsigned char list_next_offset;
  37. const unsigned char list_width;
  38. const unsigned char list_elem_next_offset;
  39. const unsigned char list_elem_content_offset;
  40. const unsigned char thread_stack_offset;
  41. const unsigned char thread_name_offset;
  42. const struct rtos_register_stacking* stacking_info;
  43. };
  44. const struct FreeRTOS_params FreeRTOS_params_list[] =
  45. {
  46. { "cortex_m3", // target_name
  47. 4, // thread_count_width;
  48. 4, // pointer_width;
  49. 16, // list_next_offset;
  50. 20, // list_width;
  51. 8, // list_elem_next_offset;
  52. 12, // list_elem_content_offset
  53. 0, // thread_stack_offset;
  54. 52, // thread_name_offset;
  55. &rtos_standard_Cortex_M3_stacking, // stacking_info
  56. }
  57. };
  58. #define FREERTOS_NUM_PARAMS ((int)(sizeof(FreeRTOS_params_list)/sizeof(struct FreeRTOS_params)))
  59. static int FreeRTOS_detect_rtos( struct target* target );
  60. static int FreeRTOS_create( struct target* target );
  61. static int FreeRTOS_update_threads( struct rtos *rtos );
  62. static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char ** hex_reg_list );
  63. static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t * symbol_list[]);
  64. struct rtos_type FreeRTOS_rtos =
  65. {
  66. .name = "FreeRTOS",
  67. .detect_rtos = FreeRTOS_detect_rtos,
  68. .create = FreeRTOS_create,
  69. .update_threads = FreeRTOS_update_threads,
  70. .get_thread_reg_list = FreeRTOS_get_thread_reg_list,
  71. .get_symbol_list_to_lookup = FreeRTOS_get_symbol_list_to_lookup,
  72. };
  73. enum FreeRTOS_symbol_values
  74. {
  75. FreeRTOS_VAL_pxCurrentTCB = 0,
  76. FreeRTOS_VAL_pxReadyTasksLists = 1,
  77. FreeRTOS_VAL_xDelayedTaskList1 = 2,
  78. FreeRTOS_VAL_xDelayedTaskList2 = 3,
  79. FreeRTOS_VAL_pxDelayedTaskList = 4,
  80. FreeRTOS_VAL_pxOverflowDelayedTaskList = 5,
  81. FreeRTOS_VAL_xPendingReadyList = 6,
  82. FreeRTOS_VAL_xTasksWaitingTermination = 7,
  83. FreeRTOS_VAL_xSuspendedTaskList = 8,
  84. FreeRTOS_VAL_uxCurrentNumberOfTasks = 9,
  85. };
  86. static char* FreeRTOS_symbol_list[] =
  87. {
  88. "pxCurrentTCB",
  89. "pxReadyTasksLists",
  90. "xDelayedTaskList1",
  91. "xDelayedTaskList2",
  92. "pxDelayedTaskList",
  93. "pxOverflowDelayedTaskList",
  94. "xPendingReadyList",
  95. "xTasksWaitingTermination",
  96. "xSuspendedTaskList",
  97. "uxCurrentNumberOfTasks",
  98. NULL
  99. };
  100. #define FREERTOS_NUM_SYMBOLS (sizeof(FreeRTOS_symbol_list)/sizeof(char*))
  101. // TODO:
  102. // this is not safe for little endian yet
  103. // may be problems reading if sizes are not 32 bit long integers.
  104. // test mallocs for failure
  105. static int FreeRTOS_update_threads( struct rtos *rtos )
  106. {
  107. int i = 0;
  108. int retval;
  109. int tasks_found = 0;
  110. const struct FreeRTOS_params* param;
  111. if (rtos->rtos_specific_params == NULL )
  112. {
  113. return -1;
  114. }
  115. param = (const struct FreeRTOS_params*) rtos->rtos_specific_params;
  116. if ( rtos->symbols == NULL )
  117. {
  118. LOG_OUTPUT("No symbols for FreeRTOS\r\n");
  119. return -3;
  120. }
  121. if ( rtos->symbols[FreeRTOS_VAL_uxCurrentNumberOfTasks].address == 0 )
  122. {
  123. LOG_OUTPUT("Don't have the number of threads in FreeRTOS \r\n");
  124. return -2;
  125. }
  126. int thread_list_size = 0;
  127. retval = target_read_buffer( rtos->target, rtos->symbols[FreeRTOS_VAL_uxCurrentNumberOfTasks].address, param->thread_count_width, (uint8_t *)&thread_list_size);
  128. if ( retval != ERROR_OK )
  129. {
  130. LOG_OUTPUT("Could not read FreeRTOS thread count from target\r\n");
  131. return retval;
  132. }
  133. // wipe out previous thread details if any
  134. if ( rtos->thread_details != NULL )
  135. {
  136. int j;
  137. for( j = 0; j < rtos->thread_count; j++ )
  138. {
  139. if ( rtos->thread_details[j].display_str != NULL )
  140. {
  141. free( rtos->thread_details[j].display_str );
  142. rtos->thread_details[j].display_str = NULL;
  143. }
  144. if ( rtos->thread_details[j].thread_name_str != NULL )
  145. {
  146. free( rtos->thread_details[j].thread_name_str );
  147. rtos->thread_details[j].thread_name_str = NULL;
  148. }
  149. if ( rtos->thread_details[j].extra_info_str != NULL )
  150. {
  151. free( rtos->thread_details[j].extra_info_str );
  152. rtos->thread_details[j].extra_info_str = NULL;
  153. }
  154. }
  155. free( rtos->thread_details );
  156. rtos->thread_details = NULL;
  157. }
  158. // read the current thread
  159. retval = target_read_buffer( rtos->target, rtos->symbols[FreeRTOS_VAL_pxCurrentTCB].address, param->pointer_width, (uint8_t *)&rtos->current_thread );
  160. if ( retval != ERROR_OK )
  161. {
  162. LOG_OUTPUT("Error reading current thread in FreeRTOS thread list\r\n");
  163. return retval;
  164. }
  165. if ( ( thread_list_size == 0 ) || ( rtos->current_thread == 0 ) )
  166. {
  167. // Either : No RTOS threads - there is always at least the current execution though
  168. // OR : No current thread - all threads suspended - show the current execution of idling
  169. char tmp_str[] = "Current Execution";
  170. thread_list_size++;
  171. tasks_found++;
  172. rtos->thread_details = (struct thread_detail*) malloc( sizeof( struct thread_detail ) * thread_list_size );
  173. rtos->thread_details->threadid = 1;
  174. rtos->thread_details->exists = true;
  175. rtos->thread_details->display_str = NULL;
  176. rtos->thread_details->extra_info_str = NULL;
  177. rtos->thread_details->thread_name_str = (char*) malloc( sizeof(tmp_str) );
  178. strcpy( rtos->thread_details->thread_name_str, tmp_str );
  179. if ( thread_list_size == 1 )
  180. {
  181. rtos->thread_count = 1;
  182. return ERROR_OK;
  183. }
  184. }
  185. else
  186. {
  187. // create space for new thread details
  188. rtos->thread_details = (struct thread_detail*) malloc( sizeof( struct thread_detail ) * thread_list_size );
  189. }
  190. // Unfortunately, we can't know how many lists there are for pxReadyTasksLists,
  191. // So figure it out via other variables
  192. int num_ready_task_lists = (rtos->symbols[FreeRTOS_VAL_xDelayedTaskList1].address - rtos->symbols[FreeRTOS_VAL_pxReadyTasksLists].address) / param->list_width;
  193. symbol_address_t* list_of_lists = (symbol_address_t *)malloc( sizeof( symbol_address_t ) * ( num_ready_task_lists + 5 ) );
  194. int num_lists;
  195. for( num_lists = 0; num_lists < num_ready_task_lists; num_lists++ )
  196. {
  197. list_of_lists[num_lists] = rtos->symbols[FreeRTOS_VAL_pxReadyTasksLists].address + num_lists * param->list_width;
  198. }
  199. list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xDelayedTaskList1].address;
  200. list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xDelayedTaskList2].address;
  201. list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xPendingReadyList].address;
  202. list_of_lists[num_lists++] = rtos->symbols[FreeRTOS_VAL_xTasksWaitingTermination].address;
  203. for( i = 0; i < num_lists; i++ )
  204. {
  205. if ( list_of_lists[i] == 0 )
  206. {
  207. continue;
  208. }
  209. // Read the number of threads in this list
  210. int64_t list_thread_count = 0;
  211. retval = target_read_buffer( rtos->target, list_of_lists[i], param->thread_count_width, (uint8_t *)&list_thread_count);
  212. if ( retval != ERROR_OK )
  213. {
  214. LOG_OUTPUT("Error reading number of threads in FreeRTOS thread list\r\n");
  215. return retval;
  216. }
  217. if ( list_thread_count == 0 )
  218. {
  219. continue;
  220. }
  221. // Read the location of first list item
  222. uint64_t prev_list_elem_ptr = -1;
  223. uint64_t list_elem_ptr = 0;
  224. retval = target_read_buffer( rtos->target, list_of_lists[i] + param->list_next_offset, param->pointer_width, (uint8_t *)&list_elem_ptr);
  225. if ( retval != ERROR_OK )
  226. {
  227. LOG_OUTPUT("Error reading first thread item location in FreeRTOS thread list\r\n");
  228. return retval;
  229. }
  230. while ( (list_thread_count > 0) && ( list_elem_ptr != 0) && ( list_elem_ptr != prev_list_elem_ptr ) && ( tasks_found < thread_list_size ) )
  231. {
  232. // Get the location of the thread structure.
  233. rtos->thread_details[tasks_found].threadid = 0;
  234. retval = target_read_buffer( rtos->target, list_elem_ptr + param->list_elem_content_offset, param->pointer_width, (uint8_t *)&(rtos->thread_details[tasks_found].threadid));
  235. if ( retval != ERROR_OK )
  236. {
  237. LOG_OUTPUT("Error reading thread list item object in FreeRTOS thread list\r\n");
  238. return retval;
  239. }
  240. // get thread name
  241. #define FREERTOS_THREAD_NAME_STR_SIZE (200)
  242. char tmp_str[FREERTOS_THREAD_NAME_STR_SIZE];
  243. // Read the thread name
  244. retval = target_read_buffer( rtos->target, rtos->thread_details[tasks_found].threadid + param->thread_name_offset, FREERTOS_THREAD_NAME_STR_SIZE, (uint8_t *)&tmp_str);
  245. if ( retval != ERROR_OK )
  246. {
  247. LOG_OUTPUT("Error reading first thread item location in FreeRTOS thread list\r\n");
  248. return retval;
  249. }
  250. tmp_str[FREERTOS_THREAD_NAME_STR_SIZE-1] = '\x00';
  251. if ( tmp_str[0] == '\x00' )
  252. {
  253. strcpy(tmp_str,"No Name");
  254. }
  255. rtos->thread_details[tasks_found].thread_name_str = (char*)malloc( strlen(tmp_str)+1 );
  256. strcpy( rtos->thread_details[tasks_found].thread_name_str, tmp_str );
  257. rtos->thread_details[tasks_found].display_str = NULL;
  258. rtos->thread_details[tasks_found].exists = true;
  259. if ( rtos->thread_details[tasks_found].threadid == rtos->current_thread )
  260. {
  261. char running_str[] = "Running";
  262. rtos->thread_details[tasks_found].extra_info_str = (char*) malloc( sizeof(running_str) );
  263. strcpy( rtos->thread_details[tasks_found].extra_info_str, running_str );
  264. }
  265. else
  266. {
  267. rtos->thread_details[tasks_found].extra_info_str = NULL;
  268. }
  269. tasks_found++;
  270. list_thread_count--;
  271. prev_list_elem_ptr = list_elem_ptr;
  272. list_elem_ptr = 0;
  273. retval = target_read_buffer( rtos->target, prev_list_elem_ptr + param->list_elem_next_offset, param->pointer_width, (uint8_t *)&list_elem_ptr);
  274. if ( retval != ERROR_OK )
  275. {
  276. LOG_OUTPUT("Error reading next thread item location in FreeRTOS thread list\r\n");
  277. return retval;
  278. }
  279. }
  280. }
  281. free( list_of_lists );
  282. rtos->thread_count = tasks_found;
  283. return 0;
  284. }
  285. static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char ** hex_reg_list )
  286. {
  287. int retval;
  288. const struct FreeRTOS_params* param;
  289. int64_t stack_ptr = 0;
  290. *hex_reg_list = NULL;
  291. if ( rtos == NULL )
  292. {
  293. return -1;
  294. }
  295. if ( thread_id == 0 )
  296. {
  297. return -2;
  298. }
  299. if (rtos->rtos_specific_params == NULL )
  300. {
  301. return -1;
  302. }
  303. param = (const struct FreeRTOS_params*) rtos->rtos_specific_params;
  304. // Read the stack pointer
  305. retval = target_read_buffer( rtos->target, thread_id + param->thread_stack_offset, param->pointer_width, (uint8_t*)&stack_ptr);
  306. if ( retval != ERROR_OK )
  307. {
  308. LOG_OUTPUT("Error reading stack frame from FreeRTOS thread\r\n");
  309. return retval;
  310. }
  311. return rtos_generic_stack_read( rtos->target, param->stacking_info, stack_ptr, hex_reg_list );
  312. }
  313. static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t * symbol_list[])
  314. {
  315. unsigned int i;
  316. *symbol_list = (symbol_table_elem_t *) malloc( sizeof( symbol_table_elem_t ) * FREERTOS_NUM_SYMBOLS );
  317. for( i = 0; i < FREERTOS_NUM_SYMBOLS; i++ )
  318. {
  319. (*symbol_list)[i].symbol_name = FreeRTOS_symbol_list[i];
  320. }
  321. return 0;
  322. }
  323. #if 0
  324. static int FreeRTOS_set_current_thread(struct rtos *rtos, threadid_t thread_id)
  325. {
  326. return 0;
  327. }
  328. static int FreeRTOS_get_thread_ascii_info( struct rtos* rtos, threadid_t thread_id, char ** info )
  329. {
  330. int retval;
  331. const struct FreeRTOS_params* param;
  332. if ( rtos == NULL )
  333. {
  334. return -1;
  335. }
  336. if ( thread_id == 0 )
  337. {
  338. return -2;
  339. }
  340. if (rtos->rtos_specific_params == NULL )
  341. {
  342. return -3;
  343. }
  344. param = (const struct FreeRTOS_params*) rtos->rtos_specific_params;
  345. #define FREERTOS_THREAD_NAME_STR_SIZE (200)
  346. char tmp_str[FREERTOS_THREAD_NAME_STR_SIZE];
  347. // Read the thread name
  348. retval = target_read_buffer( rtos->target, thread_id + param->thread_name_offset, FREERTOS_THREAD_NAME_STR_SIZE, (uint8_t *)&tmp_str);
  349. if ( retval != ERROR_OK )
  350. {
  351. LOG_OUTPUT("Error reading first thread item location in FreeRTOS thread list\r\n");
  352. return retval;
  353. }
  354. tmp_str[FREERTOS_THREAD_NAME_STR_SIZE-1] = '\x00';
  355. if ( tmp_str[0] == '\x00' )
  356. {
  357. strcpy(tmp_str,"No Name");
  358. }
  359. *info = (char*)malloc( strlen(tmp_str)+1 );
  360. strcpy( *info, tmp_str );
  361. return 0;
  362. }
  363. #endif
  364. static int FreeRTOS_detect_rtos( struct target* target )
  365. {
  366. if ( ( target->rtos->symbols != NULL ) &&
  367. ( target->rtos->symbols[FreeRTOS_VAL_pxReadyTasksLists].address != 0 ) )
  368. {
  369. // looks like FreeRTOS
  370. return 1;
  371. }
  372. return 0;
  373. return 0;
  374. }
  375. static int FreeRTOS_create( struct target* target )
  376. {
  377. int i = 0;
  378. while ( ( i < FREERTOS_NUM_PARAMS ) && ( 0 != strcmp( FreeRTOS_params_list[i].target_name, target->type->name ) ) )
  379. {
  380. i++;
  381. }
  382. if ( i >= FREERTOS_NUM_PARAMS )
  383. {
  384. LOG_OUTPUT("Could not find target in FreeRTOS compatibility list\r\n");
  385. return -1;
  386. }
  387. target->rtos->rtos_specific_params = (void*) &FreeRTOS_params_list[i];
  388. return 0;
  389. }