1 /***************************************************************************
2 * Copyright (C) 2011 by Broadcom Corporation *
3 * Evan Hunter - ehunter@broadcom.com *
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. *
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. *
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 ***************************************************************************/
25 #include <helper/time_support.h>
26 #include <jtag/jtag.h>
27 #include "target/target.h"
28 #include "target/target_type.h"
30 #include "helper/log.h"
31 #include "helper/types.h"
32 #include "rtos_standard_stackings.h"
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
[]);
40 struct ThreadX_thread_state
{
45 struct ThreadX_thread_state ThreadX_thread_states
[] = {
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" },
62 #define THREADX_NUM_STATES (sizeof(ThreadX_thread_states)/sizeof(struct ThreadX_thread_state))
64 struct ThreadX_params
{
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
;
74 const struct ThreadX_params ThreadX_params_list
[] = {
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 */
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 */
95 #define THREADX_NUM_PARAMS ((int)(sizeof(ThreadX_params_list)/sizeof(struct ThreadX_params)))
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,
103 static char *ThreadX_symbol_list
[] = {
104 "_tx_thread_current_ptr",
105 "_tx_thread_created_ptr",
106 "_tx_thread_created_count",
110 const struct rtos_type ThreadX_rtos
= {
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
,
121 static int ThreadX_update_threads(struct rtos
*rtos
)
125 int thread_list_size
= 0;
126 const struct ThreadX_params
*param
;
131 if (rtos
->rtos_specific_params
== NULL
)
134 param
= (const struct ThreadX_params
*) rtos
->rtos_specific_params
;
136 if (rtos
->symbols
== NULL
) {
137 LOG_ERROR("No symbols for ThreadX");
141 if (rtos
->symbols
[ThreadX_VAL_tx_thread_created_count
].address
== 0) {
142 LOG_ERROR("Don't have the number of threads in ThreadX");
146 /* read the number of threads */
147 retval
= target_read_buffer(rtos
->target
,
148 rtos
->symbols
[ThreadX_VAL_tx_thread_created_count
].address
,
150 (uint8_t *)&thread_list_size
);
152 if (retval
!= ERROR_OK
) {
153 LOG_ERROR("Could not read ThreadX thread count from target");
157 /* wipe out previous thread details if any */
158 rtos_free_threadlist(rtos
);
160 /* read the current thread id */
161 retval
= target_read_buffer(rtos
->target
,
162 rtos
->symbols
[ThreadX_VAL_tx_thread_current_ptr
].address
,
164 (uint8_t *)&rtos
->current_thread
);
166 if (retval
!= ERROR_OK
) {
167 LOG_ERROR("Could not read ThreadX current thread from target");
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
175 char tmp_str
[] = "Current Execution";
178 rtos
->thread_details
= 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
= malloc(sizeof(tmp_str
));
185 strcpy(rtos
->thread_details
->thread_name_str
, tmp_str
);
187 if (thread_list_size
== 0) {
188 rtos
->thread_count
= 1;
192 /* create space for new thread details */
193 rtos
->thread_details
= malloc(
194 sizeof(struct thread_detail
) * thread_list_size
);
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");
208 /* loop over all threads */
209 int64_t prev_thread_ptr
= 0;
210 while ((thread_ptr
!= prev_thread_ptr
) && (tasks_found
< thread_list_size
)) {
212 #define THREADX_THREAD_NAME_STR_SIZE (200)
213 char tmp_str
[THREADX_THREAD_NAME_STR_SIZE
];
215 int64_t name_ptr
= 0;
217 /* Save the thread pointer */
218 rtos
->thread_details
[tasks_found
].threadid
= thread_ptr
;
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");
230 /* Read the thread name */
232 target_read_buffer(rtos
->target
,
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");
240 tmp_str
[THREADX_THREAD_NAME_STR_SIZE
-1] = '\x00';
242 if (tmp_str
[0] == '\x00')
243 strcpy(tmp_str
, "No Name");
245 rtos
->thread_details
[tasks_found
].thread_name_str
=
246 malloc(strlen(tmp_str
)+1);
247 strcpy(rtos
->thread_details
[tasks_found
].thread_name_str
, tmp_str
);
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
,
254 (uint8_t *)&thread_status
);
255 if (retval
!= ERROR_OK
) {
256 LOG_ERROR("Error reading thread state from ThreadX target");
260 for (i
= 0; (i
< THREADX_NUM_STATES
) &&
261 (ThreadX_thread_states
[i
].value
!= thread_status
); i
++) {
266 if (i
< THREADX_NUM_STATES
)
267 state_desc
= ThreadX_thread_states
[i
].desc
;
269 state_desc
= "Unknown state";
271 rtos
->thread_details
[tasks_found
].extra_info_str
= malloc(strlen(
273 strcpy(rtos
->thread_details
[tasks_found
].extra_info_str
, state_desc
);
275 rtos
->thread_details
[tasks_found
].exists
= true;
277 rtos
->thread_details
[tasks_found
].display_str
= NULL
;
280 prev_thread_ptr
= thread_ptr
;
282 /* Get the location of the next thread structure. */
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");
294 rtos
->thread_count
= tasks_found
;
299 static int ThreadX_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
)
302 const struct ThreadX_params
*param
;
304 *hex_reg_list
= NULL
;
312 if (rtos
->rtos_specific_params
== NULL
)
315 param
= (const struct ThreadX_params
*) rtos
->rtos_specific_params
;
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");
328 return rtos_generic_stack_read(rtos
->target
, param
->stacking_info
, stack_ptr
, hex_reg_list
);
331 static int ThreadX_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
334 *symbol_list
= malloc(
335 sizeof(symbol_table_elem_t
) * ARRAY_SIZE(ThreadX_symbol_list
));
337 for (i
= 0; i
< ARRAY_SIZE(ThreadX_symbol_list
); i
++)
338 (*symbol_list
)[i
].symbol_name
= ThreadX_symbol_list
[i
];
343 static int ThreadX_detect_rtos(struct target
*target
)
345 if ((target
->rtos
->symbols
!= NULL
) &&
346 (target
->rtos
->symbols
[ThreadX_VAL_tx_thread_created_ptr
].address
!= 0)) {
347 /* looks like ThreadX */
355 static int ThreadX_set_current_thread(struct rtos
*rtos
, threadid_t thread_id
)
360 static int ThreadX_get_thread_detail(struct rtos
*rtos
,
361 threadid_t thread_id
,
362 struct thread_detail
*detail
)
367 #define THREADX_THREAD_NAME_STR_SIZE (200)
368 char tmp_str
[THREADX_THREAD_NAME_STR_SIZE
];
370 const struct ThreadX_params
*param
;
378 if (rtos
->rtos_specific_params
== NULL
)
381 param
= (const struct ThreadX_params
*) rtos
->rtos_specific_params
;
383 if (rtos
->symbols
== NULL
) {
384 LOG_ERROR("No symbols for ThreadX");
388 detail
->threadid
= thread_id
;
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");
401 /* Read the thread name */
402 retval
= target_read_buffer(rtos
->target
,
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");
410 tmp_str
[THREADX_THREAD_NAME_STR_SIZE
-1] = '\x00';
412 if (tmp_str
[0] == '\x00')
413 strcpy(tmp_str
, "No Name");
415 detail
->thread_name_str
= malloc(strlen(tmp_str
)+1);
417 /* Read the thread status */
418 int64_t thread_status
= 0;
420 target_read_buffer(rtos
->target
,
421 thread_id
+ param
->thread_state_offset
,
423 (uint8_t *)&thread_status
);
424 if (retval
!= ERROR_OK
) {
425 LOG_ERROR("Error reading thread state from ThreadX target");
429 for (i
= 0; (i
< THREADX_NUM_STATES
) &&
430 (ThreadX_thread_states
[i
].value
!= thread_status
); i
++) {
435 if (i
< THREADX_NUM_STATES
)
436 state_desc
= ThreadX_thread_states
[i
].desc
;
438 state_desc
= "Unknown state";
440 detail
->extra_info_str
= malloc(strlen(state_desc
)+1);
442 detail
->exists
= true;
444 detail
->display_str
= NULL
;
451 static int ThreadX_create(struct target
*target
)
454 while ((i
< THREADX_NUM_PARAMS
) &&
455 (0 != strcmp(ThreadX_params_list
[i
].target_name
, target
->type
->name
))) {
458 if (i
>= THREADX_NUM_PARAMS
) {
459 LOG_ERROR("Could not find target in ThreadX compatibility list");
463 target
->rtos
->rtos_specific_params
= (void *) &ThreadX_params_list
[i
];
464 target
->rtos
->current_thread
= 0;
465 target
->rtos
->thread_details
= NULL
;
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)