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.
 
 
 
 
 
 

343 lines
11 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, see <http://www.gnu.org/licenses/>. *
  17. ***************************************************************************/
  18. #ifdef HAVE_CONFIG_H
  19. #include "config.h"
  20. #endif
  21. #include <helper/time_support.h>
  22. #include <jtag/jtag.h>
  23. #include "target/target.h"
  24. #include "target/target_type.h"
  25. #include "rtos.h"
  26. #include "helper/log.h"
  27. #include "helper/types.h"
  28. #include "rtos_embkernel_stackings.h"
  29. #define EMBKERNEL_MAX_THREAD_NAME_STR_SIZE (64)
  30. static bool embkernel_detect_rtos(struct target *target);
  31. static int embkernel_create(struct target *target);
  32. static int embkernel_update_threads(struct rtos *rtos);
  33. static int embkernel_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
  34. struct rtos_reg **reg_list, int *num_regs);
  35. static int embkernel_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[]);
  36. struct rtos_type embkernel_rtos = {
  37. .name = "embKernel",
  38. .detect_rtos = embkernel_detect_rtos,
  39. .create = embkernel_create,
  40. .update_threads = embkernel_update_threads,
  41. .get_thread_reg_list =
  42. embkernel_get_thread_reg_list,
  43. .get_symbol_list_to_lookup = embkernel_get_symbol_list_to_lookup,
  44. };
  45. enum {
  46. SYMBOL_ID_S_CURRENT_TASK = 0,
  47. SYMBOL_ID_S_LIST_READY = 1,
  48. SYMBOL_ID_S_LIST_SLEEP = 2,
  49. SYMBOL_ID_S_LIST_SUSPENDED = 3,
  50. SYMBOL_ID_S_MAX_PRIORITIES = 4,
  51. SYMBOL_ID_S_CURRENT_TASK_COUNT = 5,
  52. };
  53. static const char * const embkernel_symbol_list[] = {
  54. "Rtos::sCurrentTask",
  55. "Rtos::sListReady",
  56. "Rtos::sListSleep",
  57. "Rtos::sListSuspended",
  58. "Rtos::sMaxPriorities",
  59. "Rtos::sCurrentTaskCount",
  60. NULL };
  61. struct embkernel_params {
  62. const char *target_name;
  63. const unsigned char pointer_width;
  64. const unsigned char thread_count_width;
  65. const unsigned char rtos_list_size;
  66. const unsigned char thread_stack_offset;
  67. const unsigned char thread_name_offset;
  68. const unsigned char thread_priority_offset;
  69. const unsigned char thread_priority_width;
  70. const unsigned char iterable_next_offset;
  71. const unsigned char iterable_task_owner_offset;
  72. const struct rtos_register_stacking *stacking_info;
  73. };
  74. static const struct embkernel_params embkernel_params_list[] = {
  75. {
  76. "cortex_m", /* target_name */
  77. 4, /* pointer_width */
  78. 4, /* thread_count_width */
  79. 8, /*rtos_list_size */
  80. 0, /*thread_stack_offset */
  81. 4, /*thread_name_offset */
  82. 8, /*thread_priority_offset */
  83. 4, /*thread_priority_width */
  84. 4, /*iterable_next_offset */
  85. 12, /*iterable_task_owner_offset */
  86. &rtos_embkernel_cortex_m_stacking, /* stacking_info*/
  87. },
  88. { "hla_target", /* target_name */
  89. 4, /* pointer_width */
  90. 4, /* thread_count_width */
  91. 8, /*rtos_list_size */
  92. 0, /*thread_stack_offset */
  93. 4, /*thread_name_offset */
  94. 8, /*thread_priority_offset */
  95. 4, /*thread_priority_width */
  96. 4, /*iterable_next_offset */
  97. 12, /*iterable_task_owner_offset */
  98. &rtos_embkernel_cortex_m_stacking, /* stacking_info */
  99. }
  100. };
  101. static bool embkernel_detect_rtos(struct target *target)
  102. {
  103. if (target->rtos->symbols) {
  104. if (target->rtos->symbols[SYMBOL_ID_S_CURRENT_TASK].address != 0)
  105. return true;
  106. }
  107. return false;
  108. }
  109. static int embkernel_create(struct target *target)
  110. {
  111. size_t i = 0;
  112. while ((i < ARRAY_SIZE(embkernel_params_list)) &&
  113. (0 != strcmp(embkernel_params_list[i].target_name, target->type->name)))
  114. i++;
  115. if (i >= ARRAY_SIZE(embkernel_params_list)) {
  116. LOG_WARNING("Could not find target \"%s\" in embKernel compatibility "
  117. "list", target->type->name);
  118. return -1;
  119. }
  120. target->rtos->rtos_specific_params = (void *) &embkernel_params_list[i];
  121. return 0;
  122. }
  123. static int embkernel_get_tasks_details(struct rtos *rtos, int64_t iterable, const struct embkernel_params *param,
  124. struct thread_detail *details, const char *state_str)
  125. {
  126. int64_t task = 0;
  127. int retval = target_read_buffer(rtos->target, iterable + param->iterable_task_owner_offset, param->pointer_width,
  128. (uint8_t *) &task);
  129. if (retval != ERROR_OK)
  130. return retval;
  131. details->threadid = (threadid_t) task;
  132. details->exists = true;
  133. int64_t name_ptr = 0;
  134. retval = target_read_buffer(rtos->target, task + param->thread_name_offset, param->pointer_width,
  135. (uint8_t *) &name_ptr);
  136. if (retval != ERROR_OK)
  137. return retval;
  138. details->thread_name_str = malloc(EMBKERNEL_MAX_THREAD_NAME_STR_SIZE);
  139. if (name_ptr) {
  140. retval = target_read_buffer(rtos->target, name_ptr, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE,
  141. (uint8_t *) details->thread_name_str);
  142. if (retval != ERROR_OK)
  143. return retval;
  144. details->thread_name_str[EMBKERNEL_MAX_THREAD_NAME_STR_SIZE - 1] = 0;
  145. } else {
  146. snprintf(details->thread_name_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "NoName:[0x%08X]", (unsigned int) task);
  147. }
  148. int64_t priority = 0;
  149. retval = target_read_buffer(rtos->target, task + param->thread_priority_offset, param->thread_priority_width,
  150. (uint8_t *) &priority);
  151. if (retval != ERROR_OK)
  152. return retval;
  153. details->extra_info_str = malloc(EMBKERNEL_MAX_THREAD_NAME_STR_SIZE);
  154. if (task == rtos->current_thread) {
  155. snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "State: Running, Priority: %u",
  156. (unsigned int) priority);
  157. } else {
  158. snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "State: %s, Priority: %u",
  159. state_str, (unsigned int) priority);
  160. }
  161. LOG_OUTPUT("Getting task details: iterable=0x%08X, task=0x%08X, name=%s\n", (unsigned int)iterable,
  162. (unsigned int)task, details->thread_name_str);
  163. return 0;
  164. }
  165. static int embkernel_update_threads(struct rtos *rtos)
  166. {
  167. /* int i = 0; */
  168. int retval;
  169. const struct embkernel_params *param;
  170. if (!rtos)
  171. return -1;
  172. if (!rtos->rtos_specific_params)
  173. return -3;
  174. if (!rtos->symbols) {
  175. LOG_ERROR("No symbols for embKernel");
  176. return -4;
  177. }
  178. if (rtos->symbols[SYMBOL_ID_S_CURRENT_TASK].address == 0) {
  179. LOG_ERROR("Don't have the thread list head");
  180. return -2;
  181. }
  182. /* wipe out previous thread details if any */
  183. rtos_free_threadlist(rtos);
  184. param = (const struct embkernel_params *) rtos->rtos_specific_params;
  185. retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_S_CURRENT_TASK].address, param->pointer_width,
  186. (uint8_t *) &rtos->current_thread);
  187. if (retval != ERROR_OK) {
  188. LOG_ERROR("Error reading current thread in embKernel thread list");
  189. return retval;
  190. }
  191. int64_t max_used_priority = 0;
  192. retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_S_MAX_PRIORITIES].address, param->pointer_width,
  193. (uint8_t *) &max_used_priority);
  194. if (retval != ERROR_OK)
  195. return retval;
  196. int thread_list_size = 0;
  197. retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_S_CURRENT_TASK_COUNT].address,
  198. param->thread_count_width, (uint8_t *) &thread_list_size);
  199. if (retval != ERROR_OK) {
  200. LOG_ERROR("Could not read embKernel thread count from target");
  201. return retval;
  202. }
  203. /* create space for new thread details */
  204. rtos->thread_details = malloc(sizeof(struct thread_detail) * thread_list_size);
  205. if (!rtos->thread_details) {
  206. LOG_ERROR("Error allocating memory for %d threads", thread_list_size);
  207. return ERROR_FAIL;
  208. }
  209. int thread_idx = 0;
  210. /* Look for ready tasks */
  211. for (int pri = 0; pri < max_used_priority; pri++) {
  212. /* Get first item in queue */
  213. int64_t iterable = 0;
  214. retval = target_read_buffer(rtos->target,
  215. rtos->symbols[SYMBOL_ID_S_LIST_READY].address + (pri * param->rtos_list_size), param->pointer_width,
  216. (uint8_t *) &iterable);
  217. if (retval != ERROR_OK)
  218. return retval;
  219. for (; iterable && thread_idx < thread_list_size; thread_idx++) {
  220. /* Get info from this iterable item */
  221. retval = embkernel_get_tasks_details(rtos, iterable, param, &rtos->thread_details[thread_idx], "Ready");
  222. if (retval != ERROR_OK)
  223. return retval;
  224. /* Get next iterable item */
  225. retval = target_read_buffer(rtos->target, iterable + param->iterable_next_offset, param->pointer_width,
  226. (uint8_t *) &iterable);
  227. if (retval != ERROR_OK)
  228. return retval;
  229. }
  230. }
  231. /* Look for sleeping tasks */
  232. int64_t iterable = 0;
  233. retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_S_LIST_SLEEP].address, param->pointer_width,
  234. (uint8_t *) &iterable);
  235. if (retval != ERROR_OK)
  236. return retval;
  237. for (; iterable && thread_idx < thread_list_size; thread_idx++) {
  238. /*Get info from this iterable item */
  239. retval = embkernel_get_tasks_details(rtos, iterable, param, &rtos->thread_details[thread_idx], "Sleeping");
  240. if (retval != ERROR_OK)
  241. return retval;
  242. /*Get next iterable item */
  243. retval = target_read_buffer(rtos->target, iterable + param->iterable_next_offset, param->pointer_width,
  244. (uint8_t *) &iterable);
  245. if (retval != ERROR_OK)
  246. return retval;
  247. }
  248. /* Look for suspended tasks */
  249. iterable = 0;
  250. retval = target_read_buffer(rtos->target, rtos->symbols[SYMBOL_ID_S_LIST_SUSPENDED].address, param->pointer_width,
  251. (uint8_t *) &iterable);
  252. if (retval != ERROR_OK)
  253. return retval;
  254. for (; iterable && thread_idx < thread_list_size; thread_idx++) {
  255. /* Get info from this iterable item */
  256. retval = embkernel_get_tasks_details(rtos, iterable, param, &rtos->thread_details[thread_idx], "Suspended");
  257. if (retval != ERROR_OK)
  258. return retval;
  259. /*Get next iterable item */
  260. retval = target_read_buffer(rtos->target, iterable + param->iterable_next_offset, param->pointer_width,
  261. (uint8_t *) &iterable);
  262. if (retval != ERROR_OK)
  263. return retval;
  264. }
  265. rtos->thread_count = 0;
  266. rtos->thread_count = thread_idx;
  267. LOG_OUTPUT("Found %u tasks\n", (unsigned int)thread_idx);
  268. return 0;
  269. }
  270. static int embkernel_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
  271. struct rtos_reg **reg_list, int *num_regs)
  272. {
  273. int retval;
  274. const struct embkernel_params *param;
  275. int64_t stack_ptr = 0;
  276. if (!rtos)
  277. return -1;
  278. if (thread_id == 0)
  279. return -2;
  280. if (!rtos->rtos_specific_params)
  281. return -1;
  282. param = (const struct embkernel_params *) rtos->rtos_specific_params;
  283. /* Read the stack pointer */
  284. retval = target_read_buffer(rtos->target, thread_id + param->thread_stack_offset, param->pointer_width,
  285. (uint8_t *) &stack_ptr);
  286. if (retval != ERROR_OK) {
  287. LOG_ERROR("Error reading stack frame from embKernel thread");
  288. return retval;
  289. }
  290. return rtos_generic_stack_read(rtos->target, param->stacking_info, stack_ptr, reg_list, num_regs);
  291. }
  292. static int embkernel_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
  293. {
  294. unsigned int i;
  295. *symbol_list = calloc(ARRAY_SIZE(embkernel_symbol_list), sizeof(struct symbol_table_elem));
  296. for (i = 0; i < ARRAY_SIZE(embkernel_symbol_list); i++)
  297. (*symbol_list)[i].symbol_name = embkernel_symbol_list[i];
  298. return 0;
  299. }