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

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)