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

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)