rtos: removed chSysInit from detection of ChibiOS (#121)
[openocd.git] / src / rtos / ThreadX.c
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
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
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
32 static const struct rtos_register_stacking *get_stacking_info(const struct rtos *rtos, int64_t stack_ptr);
33 static const struct rtos_register_stacking *get_stacking_info_arm926ejs(const struct rtos *rtos, int64_t stack_ptr);
34
35 static int is_thread_id_valid(const struct rtos *rtos, int64_t thread_id);
36 static int is_thread_id_valid_arm926ejs(const struct rtos *rtos, int64_t thread_id);
37
38 static int ThreadX_detect_rtos(struct target *target);
39 static int ThreadX_create(struct target *target);
40 static int ThreadX_update_threads(struct rtos *rtos);
41 static int ThreadX_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list);
42 static int ThreadX_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]);
43
44
45
46 struct ThreadX_thread_state {
47 int value;
48 const char *desc;
49 };
50
51 static const struct ThreadX_thread_state ThreadX_thread_states[] = {
52 { 0, "Ready" },
53 { 1, "Completed" },
54 { 2, "Terminated" },
55 { 3, "Suspended" },
56 { 4, "Sleeping" },
57 { 5, "Waiting - Queue" },
58 { 6, "Waiting - Semaphore" },
59 { 7, "Waiting - Event flag" },
60 { 8, "Waiting - Memory" },
61 { 9, "Waiting - Memory" },
62 { 10, "Waiting - I/O" },
63 { 11, "Waiting - Filesystem" },
64 { 12, "Waiting - Network" },
65 { 13, "Waiting - Mutex" },
66 };
67
68 #define THREADX_NUM_STATES (sizeof(ThreadX_thread_states)/sizeof(struct ThreadX_thread_state))
69
70 #define ARM926EJS_REGISTERS_SIZE_SOLICITED (11 * 4)
71 static const struct stack_register_offset rtos_threadx_arm926ejs_stack_offsets_solicited[] = {
72 { -1, 32 }, /* r0 */
73 { -1, 32 }, /* r1 */
74 { -1, 32 }, /* r2 */
75 { -1, 32 }, /* r3 */
76 { 0x08, 32 }, /* r4 */
77 { 0x0C, 32 }, /* r5 */
78 { 0x10, 32 }, /* r6 */
79 { 0x14, 32 }, /* r7 */
80 { 0x18, 32 }, /* r8 */
81 { 0x1C, 32 }, /* r9 */
82 { 0x20, 32 }, /* r10 */
83 { 0x24, 32 }, /* r11 */
84 { -1, 32 }, /* r12 */
85 { -2, 32 }, /* sp (r13) */
86 { 0x28, 32 }, /* lr (r14) */
87 { -1, 32 }, /* pc (r15) */
88 /*{ -1, 32 },*/ /* lr (r14) */
89 /*{ 0x28, 32 },*/ /* pc (r15) */
90 { 0x04, 32 }, /* xPSR */
91 };
92 #define ARM926EJS_REGISTERS_SIZE_INTERRUPT (17 * 4)
93 static const struct stack_register_offset rtos_threadx_arm926ejs_stack_offsets_interrupt[] = {
94 { 0x08, 32 }, /* r0 */
95 { 0x0C, 32 }, /* r1 */
96 { 0x10, 32 }, /* r2 */
97 { 0x14, 32 }, /* r3 */
98 { 0x18, 32 }, /* r4 */
99 { 0x1C, 32 }, /* r5 */
100 { 0x20, 32 }, /* r6 */
101 { 0x24, 32 }, /* r7 */
102 { 0x28, 32 }, /* r8 */
103 { 0x2C, 32 }, /* r9 */
104 { 0x30, 32 }, /* r10 */
105 { 0x34, 32 }, /* r11 */
106 { 0x38, 32 }, /* r12 */
107 { -2, 32 }, /* sp (r13) */
108 { 0x3C, 32 }, /* lr (r14) */
109 { 0x40, 32 }, /* pc (r15) */
110 { 0x04, 32 }, /* xPSR */
111 };
112
113 const struct rtos_register_stacking rtos_threadx_arm926ejs_stacking[] = {
114 {
115 ARM926EJS_REGISTERS_SIZE_SOLICITED, /* stack_registers_size */
116 -1, /* stack_growth_direction */
117 17, /* num_output_registers */
118 NULL, /* stack_alignment */
119 rtos_threadx_arm926ejs_stack_offsets_solicited /* register_offsets */
120 },
121 {
122 ARM926EJS_REGISTERS_SIZE_INTERRUPT, /* stack_registers_size */
123 -1, /* stack_growth_direction */
124 17, /* num_output_registers */
125 NULL, /* stack_alignment */
126 rtos_threadx_arm926ejs_stack_offsets_interrupt /* register_offsets */
127 },
128 };
129
130 struct ThreadX_params {
131 const char *target_name;
132 unsigned char pointer_width;
133 unsigned char thread_stack_offset;
134 unsigned char thread_name_offset;
135 unsigned char thread_state_offset;
136 unsigned char thread_next_offset;
137 const struct rtos_register_stacking *stacking_info;
138 size_t stacking_info_nb;
139 const struct rtos_register_stacking* (*fn_get_stacking_info)(const struct rtos *rtos, int64_t stack_ptr);
140 int (*fn_is_thread_id_valid)(const struct rtos *rtos, int64_t thread_id);
141 };
142
143 static const struct ThreadX_params ThreadX_params_list[] = {
144 {
145 "cortex_m", /* target_name */
146 4, /* pointer_width; */
147 8, /* thread_stack_offset; */
148 40, /* thread_name_offset; */
149 48, /* thread_state_offset; */
150 136, /* thread_next_offset */
151 &rtos_standard_Cortex_M3_stacking, /* stacking_info */
152 1, /* stacking_info_nb */
153 NULL, /* fn_get_stacking_info */
154 NULL, /* fn_is_thread_id_valid */
155 },
156 {
157 "cortex_r4", /* target_name */
158 4, /* pointer_width; */
159 8, /* thread_stack_offset; */
160 40, /* thread_name_offset; */
161 48, /* thread_state_offset; */
162 136, /* thread_next_offset */
163 &rtos_standard_Cortex_R4_stacking, /* stacking_info */
164 1, /* stacking_info_nb */
165 NULL, /* fn_get_stacking_info */
166 NULL, /* fn_is_thread_id_valid */
167 },
168 {
169 "arm926ejs", /* target_name */
170 4, /* pointer_width; */
171 8, /* thread_stack_offset; */
172 40, /* thread_name_offset; */
173 48, /* thread_state_offset; */
174 136, /* thread_next_offset */
175 rtos_threadx_arm926ejs_stacking, /* stacking_info */
176 2, /* stacking_info_nb */
177 get_stacking_info_arm926ejs, /* fn_get_stacking_info */
178 is_thread_id_valid_arm926ejs, /* fn_is_thread_id_valid */
179 },
180 };
181
182 #define THREADX_NUM_PARAMS ((int)(sizeof(ThreadX_params_list)/sizeof(struct ThreadX_params)))
183
184 enum ThreadX_symbol_values {
185 ThreadX_VAL_tx_thread_current_ptr = 0,
186 ThreadX_VAL_tx_thread_created_ptr = 1,
187 ThreadX_VAL_tx_thread_created_count = 2,
188 };
189
190 static const char * const ThreadX_symbol_list[] = {
191 "_tx_thread_current_ptr",
192 "_tx_thread_created_ptr",
193 "_tx_thread_created_count",
194 NULL
195 };
196
197 const struct rtos_type ThreadX_rtos = {
198 .name = "ThreadX",
199
200 .detect_rtos = ThreadX_detect_rtos,
201 .create = ThreadX_create,
202 .update_threads = ThreadX_update_threads,
203 .get_thread_reg_list = ThreadX_get_thread_reg_list,
204 .get_symbol_list_to_lookup = ThreadX_get_symbol_list_to_lookup,
205 };
206
207 static const struct rtos_register_stacking *get_stacking_info(const struct rtos *rtos, int64_t stack_ptr)
208 {
209 const struct ThreadX_params *param = (const struct ThreadX_params *) rtos->rtos_specific_params;
210
211 if (param->fn_get_stacking_info != NULL)
212 return param->fn_get_stacking_info(rtos, stack_ptr);
213
214 return param->stacking_info + 0;
215 }
216
217 static int is_thread_id_valid(const struct rtos *rtos, int64_t thread_id)
218 {
219 const struct ThreadX_params *param;
220
221 if (rtos->rtos_specific_params == NULL)
222 return 0; /* invalid */
223
224 param = (const struct ThreadX_params *) rtos->rtos_specific_params;
225
226 if (param->fn_is_thread_id_valid != NULL)
227 return param->fn_is_thread_id_valid(rtos, thread_id);
228
229 return (thread_id != 0);
230 }
231
232 static const struct rtos_register_stacking *get_stacking_info_arm926ejs(const struct rtos *rtos, int64_t stack_ptr)
233 {
234 const struct ThreadX_params *param = (const struct ThreadX_params *) rtos->rtos_specific_params;
235 int retval;
236 uint32_t flag;
237
238 retval = target_read_buffer(rtos->target,
239 stack_ptr,
240 sizeof(flag),
241 (uint8_t *)&flag);
242 if (retval != ERROR_OK) {
243 LOG_ERROR("Error reading stack data from ThreadX thread: stack_ptr=0x%" PRIx64, stack_ptr);
244 return NULL;
245 }
246
247 if (flag == 0) {
248 LOG_DEBUG(" solicited stack");
249 return param->stacking_info + 0;
250 } else {
251 LOG_DEBUG(" interrupt stack: %u", flag);
252 return param->stacking_info + 1;
253 }
254 }
255
256 static int is_thread_id_valid_arm926ejs(const struct rtos *rtos, int64_t thread_id)
257 {
258 return (thread_id != 0 && thread_id != 1);
259 }
260
261 static int ThreadX_update_threads(struct rtos *rtos)
262 {
263 int retval;
264 int tasks_found = 0;
265 int thread_list_size = 0;
266 const struct ThreadX_params *param;
267
268 if (rtos == NULL)
269 return -1;
270
271 if (rtos->rtos_specific_params == NULL)
272 return -3;
273
274 param = (const struct ThreadX_params *) rtos->rtos_specific_params;
275
276 if (rtos->symbols == NULL) {
277 LOG_ERROR("No symbols for ThreadX");
278 return -4;
279 }
280
281 if (rtos->symbols[ThreadX_VAL_tx_thread_created_count].address == 0) {
282 LOG_ERROR("Don't have the number of threads in ThreadX");
283 return -2;
284 }
285
286 /* read the number of threads */
287 retval = target_read_buffer(rtos->target,
288 rtos->symbols[ThreadX_VAL_tx_thread_created_count].address,
289 4,
290 (uint8_t *)&thread_list_size);
291
292 if (retval != ERROR_OK) {
293 LOG_ERROR("Could not read ThreadX thread count from target");
294 return retval;
295 }
296
297 /* wipe out previous thread details if any */
298 rtos_free_threadlist(rtos);
299
300 /* read the current thread id */
301 retval = target_read_buffer(rtos->target,
302 rtos->symbols[ThreadX_VAL_tx_thread_current_ptr].address,
303 4,
304 (uint8_t *)&rtos->current_thread);
305
306 if (retval != ERROR_OK) {
307 LOG_ERROR("Could not read ThreadX current thread from target");
308 return retval;
309 }
310
311 if ((thread_list_size == 0) || (rtos->current_thread == 0)) {
312 /* Either : No RTOS threads - there is always at least the current execution though */
313 /* OR : No current thread - all threads suspended - show the current execution
314 * of idling */
315 char tmp_str[] = "Current Execution";
316 thread_list_size++;
317 tasks_found++;
318 rtos->thread_details = malloc(
319 sizeof(struct thread_detail) * thread_list_size);
320 rtos->thread_details->threadid = 1;
321 rtos->thread_details->exists = true;
322 rtos->thread_details->display_str = NULL;
323 rtos->thread_details->extra_info_str = NULL;
324 rtos->thread_details->thread_name_str = malloc(sizeof(tmp_str));
325 strcpy(rtos->thread_details->thread_name_str, tmp_str);
326
327 if (thread_list_size == 0) {
328 rtos->thread_count = 1;
329 return ERROR_OK;
330 }
331 } else {
332 /* create space for new thread details */
333 rtos->thread_details = malloc(
334 sizeof(struct thread_detail) * thread_list_size);
335 }
336
337 /* Read the pointer to the first thread */
338 int64_t thread_ptr = 0;
339 retval = target_read_buffer(rtos->target,
340 rtos->symbols[ThreadX_VAL_tx_thread_created_ptr].address,
341 param->pointer_width,
342 (uint8_t *)&thread_ptr);
343 if (retval != ERROR_OK) {
344 LOG_ERROR("Could not read ThreadX thread location from target");
345 return retval;
346 }
347
348 /* loop over all threads */
349 int64_t prev_thread_ptr = 0;
350 while ((thread_ptr != prev_thread_ptr) && (tasks_found < thread_list_size)) {
351
352 #define THREADX_THREAD_NAME_STR_SIZE (200)
353 char tmp_str[THREADX_THREAD_NAME_STR_SIZE];
354 unsigned int i = 0;
355 int64_t name_ptr = 0;
356
357 /* Save the thread pointer */
358 rtos->thread_details[tasks_found].threadid = thread_ptr;
359
360 /* read the name pointer */
361 retval = target_read_buffer(rtos->target,
362 thread_ptr + param->thread_name_offset,
363 param->pointer_width,
364 (uint8_t *)&name_ptr);
365 if (retval != ERROR_OK) {
366 LOG_ERROR("Could not read ThreadX thread name pointer from target");
367 return retval;
368 }
369
370 /* Read the thread name */
371 retval =
372 target_read_buffer(rtos->target,
373 name_ptr,
374 THREADX_THREAD_NAME_STR_SIZE,
375 (uint8_t *)&tmp_str);
376 if (retval != ERROR_OK) {
377 LOG_ERROR("Error reading thread name from ThreadX target");
378 return retval;
379 }
380 tmp_str[THREADX_THREAD_NAME_STR_SIZE-1] = '\x00';
381
382 if (tmp_str[0] == '\x00')
383 strcpy(tmp_str, "No Name");
384
385 rtos->thread_details[tasks_found].thread_name_str =
386 malloc(strlen(tmp_str)+1);
387 strcpy(rtos->thread_details[tasks_found].thread_name_str, tmp_str);
388
389 /* Read the thread status */
390 int64_t thread_status = 0;
391 retval = target_read_buffer(rtos->target,
392 thread_ptr + param->thread_state_offset,
393 4,
394 (uint8_t *)&thread_status);
395 if (retval != ERROR_OK) {
396 LOG_ERROR("Error reading thread state from ThreadX target");
397 return retval;
398 }
399
400 for (i = 0; (i < THREADX_NUM_STATES) &&
401 (ThreadX_thread_states[i].value != thread_status); i++) {
402 /* empty */
403 }
404
405 const char *state_desc;
406 if (i < THREADX_NUM_STATES)
407 state_desc = ThreadX_thread_states[i].desc;
408 else
409 state_desc = "Unknown state";
410
411 rtos->thread_details[tasks_found].extra_info_str = malloc(strlen(
412 state_desc)+1);
413 strcpy(rtos->thread_details[tasks_found].extra_info_str, state_desc);
414
415 rtos->thread_details[tasks_found].exists = true;
416
417 rtos->thread_details[tasks_found].display_str = NULL;
418
419 tasks_found++;
420 prev_thread_ptr = thread_ptr;
421
422 /* Get the location of the next thread structure. */
423 thread_ptr = 0;
424 retval = target_read_buffer(rtos->target,
425 prev_thread_ptr + param->thread_next_offset,
426 param->pointer_width,
427 (uint8_t *) &thread_ptr);
428 if (retval != ERROR_OK) {
429 LOG_ERROR("Error reading next thread pointer in ThreadX thread list");
430 return retval;
431 }
432 }
433
434 rtos->thread_count = tasks_found;
435
436 return 0;
437 }
438
439 static int ThreadX_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list)
440 {
441 int retval;
442 const struct ThreadX_params *param;
443
444 *hex_reg_list = NULL;
445
446 if (rtos == NULL)
447 return -1;
448
449 if (!is_thread_id_valid(rtos, thread_id))
450 return -2;
451
452 if (rtos->rtos_specific_params == NULL)
453 return -3;
454
455 param = (const struct ThreadX_params *) rtos->rtos_specific_params;
456
457 /* Read the stack pointer */
458 int64_t stack_ptr = 0;
459 retval = target_read_buffer(rtos->target,
460 thread_id + param->thread_stack_offset,
461 param->pointer_width,
462 (uint8_t *)&stack_ptr);
463 if (retval != ERROR_OK) {
464 LOG_ERROR("Error reading stack frame from ThreadX thread");
465 return retval;
466 }
467
468 LOG_INFO("thread: 0x%" PRIx64 ", stack_ptr=0x%" PRIx64, (uint64_t)thread_id, (uint64_t)stack_ptr);
469
470 if (stack_ptr == 0) {
471 LOG_ERROR("null stack pointer in thread");
472 return -5;
473 }
474
475 const struct rtos_register_stacking *stacking_info =
476 get_stacking_info(rtos, stack_ptr);
477
478 if (stacking_info == NULL) {
479 LOG_ERROR("Unknown stacking info for thread id=0x%" PRIx64, (uint64_t)thread_id);
480 return -6;
481 }
482
483 return rtos_generic_stack_read(rtos->target, stacking_info, stack_ptr, hex_reg_list);
484 }
485
486 static int ThreadX_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
487 {
488 unsigned int i;
489 *symbol_list = calloc(
490 ARRAY_SIZE(ThreadX_symbol_list), sizeof(symbol_table_elem_t));
491
492 for (i = 0; i < ARRAY_SIZE(ThreadX_symbol_list); i++)
493 (*symbol_list)[i].symbol_name = ThreadX_symbol_list[i];
494
495 return 0;
496 }
497
498 static int ThreadX_detect_rtos(struct target *target)
499 {
500 if ((target->rtos->symbols != NULL) &&
501 (target->rtos->symbols[ThreadX_VAL_tx_thread_created_ptr].address != 0)) {
502 /* looks like ThreadX */
503 return 1;
504 }
505 return 0;
506 }
507
508 #if 0
509
510 static int ThreadX_set_current_thread(struct rtos *rtos, threadid_t thread_id)
511 {
512 return 0;
513 }
514
515 static int ThreadX_get_thread_detail(struct rtos *rtos,
516 threadid_t thread_id,
517 struct thread_detail *detail)
518 {
519 unsigned int i = 0;
520 int retval;
521
522 #define THREADX_THREAD_NAME_STR_SIZE (200)
523 char tmp_str[THREADX_THREAD_NAME_STR_SIZE];
524
525 const struct ThreadX_params *param;
526
527 if (rtos == NULL)
528 return -1;
529
530 if (thread_id == 0)
531 return -2;
532
533 if (rtos->rtos_specific_params == NULL)
534 return -3;
535
536 param = (const struct ThreadX_params *) rtos->rtos_specific_params;
537
538 if (rtos->symbols == NULL) {
539 LOG_ERROR("No symbols for ThreadX");
540 return -3;
541 }
542
543 detail->threadid = thread_id;
544
545 int64_t name_ptr = 0;
546 /* read the name pointer */
547 retval = target_read_buffer(rtos->target,
548 thread_id + param->thread_name_offset,
549 param->pointer_width,
550 (uint8_t *)&name_ptr);
551 if (retval != ERROR_OK) {
552 LOG_ERROR("Could not read ThreadX thread name pointer from target");
553 return retval;
554 }
555
556 /* Read the thread name */
557 retval = target_read_buffer(rtos->target,
558 name_ptr,
559 THREADX_THREAD_NAME_STR_SIZE,
560 (uint8_t *)&tmp_str);
561 if (retval != ERROR_OK) {
562 LOG_ERROR("Error reading thread name from ThreadX target");
563 return retval;
564 }
565 tmp_str[THREADX_THREAD_NAME_STR_SIZE-1] = '\x00';
566
567 if (tmp_str[0] == '\x00')
568 strcpy(tmp_str, "No Name");
569
570 detail->thread_name_str = malloc(strlen(tmp_str)+1);
571
572 /* Read the thread status */
573 int64_t thread_status = 0;
574 retval =
575 target_read_buffer(rtos->target,
576 thread_id + param->thread_state_offset,
577 4,
578 (uint8_t *)&thread_status);
579 if (retval != ERROR_OK) {
580 LOG_ERROR("Error reading thread state from ThreadX target");
581 return retval;
582 }
583
584 for (i = 0; (i < THREADX_NUM_STATES) &&
585 (ThreadX_thread_states[i].value != thread_status); i++) {
586 /* empty */
587 }
588
589 char *state_desc;
590 if (i < THREADX_NUM_STATES)
591 state_desc = ThreadX_thread_states[i].desc;
592 else
593 state_desc = "Unknown state";
594
595 detail->extra_info_str = malloc(strlen(state_desc)+1);
596
597 detail->exists = true;
598
599 detail->display_str = NULL;
600
601 return 0;
602 }
603
604 #endif
605
606 static int ThreadX_create(struct target *target)
607 {
608 int i = 0;
609 while ((i < THREADX_NUM_PARAMS) &&
610 (0 != strcmp(ThreadX_params_list[i].target_name, target->type->name))) {
611 i++;
612 }
613 if (i >= THREADX_NUM_PARAMS) {
614 LOG_ERROR("Could not find target in ThreadX compatibility list");
615 return -1;
616 }
617
618 target->rtos->rtos_specific_params = (void *) &ThreadX_params_list[i];
619 target->rtos->current_thread = 0;
620 target->rtos->thread_details = NULL;
621 return 0;
622 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)