add34b4f4db8b2c2da8cb3dd0032e8d74317422c
[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 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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_m", /* 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 rtos_free_threadlist(rtos);
159
160 /* read the current thread id */
161 retval = target_read_buffer(rtos->target,
162 rtos->symbols[ThreadX_VAL_tx_thread_current_ptr].address,
163 4,
164 (uint8_t *)&rtos->current_thread);
165
166 if (retval != ERROR_OK) {
167 LOG_ERROR("Could not read ThreadX current thread from target");
168 return retval;
169 }
170
171 if ((thread_list_size == 0) || (rtos->current_thread == 0)) {
172 /* Either : No RTOS threads - there is always at least the current execution though */
173 /* OR : No current thread - all threads suspended - show the current execution
174 * of idling */
175 char tmp_str[] = "Current Execution";
176 thread_list_size++;
177 tasks_found++;
178 rtos->thread_details = (struct thread_detail *) malloc(
179 sizeof(struct thread_detail) * thread_list_size);
180 rtos->thread_details->threadid = 1;
181 rtos->thread_details->exists = true;
182 rtos->thread_details->display_str = NULL;
183 rtos->thread_details->extra_info_str = NULL;
184 rtos->thread_details->thread_name_str = (char *) malloc(sizeof(tmp_str));
185 strcpy(rtos->thread_details->thread_name_str, tmp_str);
186
187 if (thread_list_size == 0) {
188 rtos->thread_count = 1;
189 return ERROR_OK;
190 }
191 } else {
192 /* create space for new thread details */
193 rtos->thread_details = (struct thread_detail *) malloc(
194 sizeof(struct thread_detail) * thread_list_size);
195 }
196
197 /* Read the pointer to the first thread */
198 int64_t thread_ptr = 0;
199 retval = target_read_buffer(rtos->target,
200 rtos->symbols[ThreadX_VAL_tx_thread_created_ptr].address,
201 param->pointer_width,
202 (uint8_t *)&thread_ptr);
203 if (retval != ERROR_OK) {
204 LOG_ERROR("Could not read ThreadX thread location from target");
205 return retval;
206 }
207
208 /* loop over all threads */
209 int64_t prev_thread_ptr = 0;
210 while ((thread_ptr != prev_thread_ptr) && (tasks_found < thread_list_size)) {
211
212 #define THREADX_THREAD_NAME_STR_SIZE (200)
213 char tmp_str[THREADX_THREAD_NAME_STR_SIZE];
214 unsigned int i = 0;
215 int64_t name_ptr = 0;
216
217 /* Save the thread pointer */
218 rtos->thread_details[tasks_found].threadid = thread_ptr;
219
220 /* read the name pointer */
221 retval = target_read_buffer(rtos->target,
222 thread_ptr + param->thread_name_offset,
223 param->pointer_width,
224 (uint8_t *)&name_ptr);
225 if (retval != ERROR_OK) {
226 LOG_ERROR("Could not read ThreadX thread name pointer from target");
227 return retval;
228 }
229
230 /* Read the thread name */
231 retval =
232 target_read_buffer(rtos->target,
233 name_ptr,
234 THREADX_THREAD_NAME_STR_SIZE,
235 (uint8_t *)&tmp_str);
236 if (retval != ERROR_OK) {
237 LOG_ERROR("Error reading thread name from ThreadX target");
238 return retval;
239 }
240 tmp_str[THREADX_THREAD_NAME_STR_SIZE-1] = '\x00';
241
242 if (tmp_str[0] == '\x00')
243 strcpy(tmp_str, "No Name");
244
245 rtos->thread_details[tasks_found].thread_name_str =
246 (char *)malloc(strlen(tmp_str)+1);
247 strcpy(rtos->thread_details[tasks_found].thread_name_str, tmp_str);
248
249 /* Read the thread status */
250 int64_t thread_status = 0;
251 retval = target_read_buffer(rtos->target,
252 thread_ptr + param->thread_state_offset,
253 4,
254 (uint8_t *)&thread_status);
255 if (retval != ERROR_OK) {
256 LOG_ERROR("Error reading thread state from ThreadX target");
257 return retval;
258 }
259
260 for (i = 0; (i < THREADX_NUM_STATES) &&
261 (ThreadX_thread_states[i].value != thread_status); i++) {
262 /* empty */
263 }
264
265 char *state_desc;
266 if (i < THREADX_NUM_STATES)
267 state_desc = ThreadX_thread_states[i].desc;
268 else
269 state_desc = "Unknown state";
270
271 rtos->thread_details[tasks_found].extra_info_str = (char *)malloc(strlen(
272 state_desc)+1);
273 strcpy(rtos->thread_details[tasks_found].extra_info_str, state_desc);
274
275 rtos->thread_details[tasks_found].exists = true;
276
277 rtos->thread_details[tasks_found].display_str = NULL;
278
279 tasks_found++;
280 prev_thread_ptr = thread_ptr;
281
282 /* Get the location of the next thread structure. */
283 thread_ptr = 0;
284 retval = target_read_buffer(rtos->target,
285 prev_thread_ptr + param->thread_next_offset,
286 param->pointer_width,
287 (uint8_t *) &thread_ptr);
288 if (retval != ERROR_OK) {
289 LOG_ERROR("Error reading next thread pointer in ThreadX thread list");
290 return retval;
291 }
292 }
293
294 rtos->thread_count = tasks_found;
295
296 return 0;
297 }
298
299 static int ThreadX_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char **hex_reg_list)
300 {
301 int retval;
302 const struct ThreadX_params *param;
303
304 *hex_reg_list = NULL;
305
306 if (rtos == NULL)
307 return -1;
308
309 if (thread_id == 0)
310 return -2;
311
312 if (rtos->rtos_specific_params == NULL)
313 return -3;
314
315 param = (const struct ThreadX_params *) rtos->rtos_specific_params;
316
317 /* Read the stack pointer */
318 int64_t stack_ptr = 0;
319 retval = target_read_buffer(rtos->target,
320 thread_id + param->thread_stack_offset,
321 param->pointer_width,
322 (uint8_t *)&stack_ptr);
323 if (retval != ERROR_OK) {
324 LOG_ERROR("Error reading stack frame from ThreadX thread");
325 return retval;
326 }
327
328 return rtos_generic_stack_read(rtos->target, param->stacking_info, stack_ptr, hex_reg_list);
329 }
330
331 static int ThreadX_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
332 {
333 unsigned int i;
334 *symbol_list = (symbol_table_elem_t *) malloc(
335 sizeof(symbol_table_elem_t) * ARRAY_SIZE(ThreadX_symbol_list));
336
337 for (i = 0; i < ARRAY_SIZE(ThreadX_symbol_list); i++)
338 (*symbol_list)[i].symbol_name = ThreadX_symbol_list[i];
339
340 return 0;
341 }
342
343 static int ThreadX_detect_rtos(struct target *target)
344 {
345 if ((target->rtos->symbols != NULL) &&
346 (target->rtos->symbols[ThreadX_VAL_tx_thread_created_ptr].address != 0)) {
347 /* looks like ThreadX */
348 return 1;
349 }
350 return 0;
351 }
352
353 #if 0
354
355 static int ThreadX_set_current_thread(struct rtos *rtos, threadid_t thread_id)
356 {
357 return 0;
358 }
359
360 static int ThreadX_get_thread_detail(struct rtos *rtos,
361 threadid_t thread_id,
362 struct thread_detail *detail)
363 {
364 unsigned int i = 0;
365 int retval;
366
367 #define THREADX_THREAD_NAME_STR_SIZE (200)
368 char tmp_str[THREADX_THREAD_NAME_STR_SIZE];
369
370 const struct ThreadX_params *param;
371
372 if (rtos == NULL)
373 return -1;
374
375 if (thread_id == 0)
376 return -2;
377
378 if (rtos->rtos_specific_params == NULL)
379 return -3;
380
381 param = (const struct ThreadX_params *) rtos->rtos_specific_params;
382
383 if (rtos->symbols == NULL) {
384 LOG_ERROR("No symbols for ThreadX");
385 return -3;
386 }
387
388 detail->threadid = thread_id;
389
390 int64_t name_ptr = 0;
391 /* read the name pointer */
392 retval = target_read_buffer(rtos->target,
393 thread_id + param->thread_name_offset,
394 param->pointer_width,
395 (uint8_t *)&name_ptr);
396 if (retval != ERROR_OK) {
397 LOG_ERROR("Could not read ThreadX thread name pointer from target");
398 return retval;
399 }
400
401 /* Read the thread name */
402 retval = target_read_buffer(rtos->target,
403 name_ptr,
404 THREADX_THREAD_NAME_STR_SIZE,
405 (uint8_t *)&tmp_str);
406 if (retval != ERROR_OK) {
407 LOG_ERROR("Error reading thread name from ThreadX target");
408 return retval;
409 }
410 tmp_str[THREADX_THREAD_NAME_STR_SIZE-1] = '\x00';
411
412 if (tmp_str[0] == '\x00')
413 strcpy(tmp_str, "No Name");
414
415 detail->thread_name_str = (char *)malloc(strlen(tmp_str)+1);
416
417 /* Read the thread status */
418 int64_t thread_status = 0;
419 retval =
420 target_read_buffer(rtos->target,
421 thread_id + param->thread_state_offset,
422 4,
423 (uint8_t *)&thread_status);
424 if (retval != ERROR_OK) {
425 LOG_ERROR("Error reading thread state from ThreadX target");
426 return retval;
427 }
428
429 for (i = 0; (i < THREADX_NUM_STATES) &&
430 (ThreadX_thread_states[i].value != thread_status); i++) {
431 /* empty */
432 }
433
434 char *state_desc;
435 if (i < THREADX_NUM_STATES)
436 state_desc = ThreadX_thread_states[i].desc;
437 else
438 state_desc = "Unknown state";
439
440 detail->extra_info_str = (char *)malloc(strlen(state_desc)+1);
441
442 detail->exists = true;
443
444 detail->display_str = NULL;
445
446 return 0;
447 }
448
449 #endif
450
451 static int ThreadX_create(struct target *target)
452 {
453 int i = 0;
454 while ((i < THREADX_NUM_PARAMS) &&
455 (0 != strcmp(ThreadX_params_list[i].target_name, target->type->name))) {
456 i++;
457 }
458 if (i >= THREADX_NUM_PARAMS) {
459 LOG_ERROR("Could not find target in ThreadX compatibility list");
460 return -1;
461 }
462
463 target->rtos->rtos_specific_params = (void *) &ThreadX_params_list[i];
464 target->rtos->current_thread = 0;
465 target->rtos->thread_details = NULL;
466 return 0;
467 }

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)