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

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)