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 if (rtos
->thread_details
!= NULL
) {
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
;
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
;
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
;
174 free(rtos
->thread_details
);
175 rtos
->thread_details
= NULL
;
178 /* read the current thread id */
179 retval
= target_read_buffer(rtos
->target
,
180 rtos
->symbols
[ThreadX_VAL_tx_thread_current_ptr
].address
,
182 (uint8_t *)&rtos
->current_thread
);
184 if (retval
!= ERROR_OK
) {
185 LOG_ERROR("Could not read ThreadX current thread from target");
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
193 char tmp_str
[] = "Current Execution";
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
);
205 if (thread_list_size
== 0) {
206 rtos
->thread_count
= 1;
210 /* create space for new thread details */
211 rtos
->thread_details
= (struct thread_detail
*) malloc(
212 sizeof(struct thread_detail
) * thread_list_size
);
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");
226 /* loop over all threads */
227 int64_t prev_thread_ptr
= 0;
228 while ((thread_ptr
!= prev_thread_ptr
) && (tasks_found
< thread_list_size
)) {
230 #define THREADX_THREAD_NAME_STR_SIZE (200)
231 char tmp_str
[THREADX_THREAD_NAME_STR_SIZE
];
233 int64_t name_ptr
= 0;
235 /* Save the thread pointer */
236 rtos
->thread_details
[tasks_found
].threadid
= thread_ptr
;
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");
248 /* Read the thread name */
250 target_read_buffer(rtos
->target
,
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");
258 tmp_str
[THREADX_THREAD_NAME_STR_SIZE
-1] = '\x00';
260 if (tmp_str
[0] == '\x00')
261 strcpy(tmp_str
, "No Name");
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
);
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
,
272 (uint8_t *)&thread_status
);
273 if (retval
!= ERROR_OK
) {
274 LOG_ERROR("Error reading thread state from ThreadX target");
278 for (i
= 0; (i
< THREADX_NUM_STATES
) &&
279 (ThreadX_thread_states
[i
].value
!= thread_status
); i
++) {
284 if (i
< THREADX_NUM_STATES
)
285 state_desc
= ThreadX_thread_states
[i
].desc
;
287 state_desc
= "Unknown state";
289 rtos
->thread_details
[tasks_found
].extra_info_str
= (char *)malloc(strlen(
291 strcpy(rtos
->thread_details
[tasks_found
].extra_info_str
, state_desc
);
293 rtos
->thread_details
[tasks_found
].exists
= true;
295 rtos
->thread_details
[tasks_found
].display_str
= NULL
;
298 prev_thread_ptr
= thread_ptr
;
300 /* Get the location of the next thread structure. */
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");
312 rtos
->thread_count
= tasks_found
;
317 static int ThreadX_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
)
320 const struct ThreadX_params
*param
;
322 *hex_reg_list
= NULL
;
330 if (rtos
->rtos_specific_params
== NULL
)
333 param
= (const struct ThreadX_params
*) rtos
->rtos_specific_params
;
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");
346 return rtos_generic_stack_read(rtos
->target
, param
->stacking_info
, stack_ptr
, hex_reg_list
);
349 static int ThreadX_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
352 *symbol_list
= (symbol_table_elem_t
*) malloc(
353 sizeof(symbol_table_elem_t
) * ARRAY_SIZE(ThreadX_symbol_list
));
355 for (i
= 0; i
< ARRAY_SIZE(ThreadX_symbol_list
); i
++)
356 (*symbol_list
)[i
].symbol_name
= ThreadX_symbol_list
[i
];
361 static int ThreadX_detect_rtos(struct target
*target
)
363 if ((target
->rtos
->symbols
!= NULL
) &&
364 (target
->rtos
->symbols
[ThreadX_VAL_tx_thread_created_ptr
].address
!= 0)) {
365 /* looks like ThreadX */
373 static int ThreadX_set_current_thread(struct rtos
*rtos
, threadid_t thread_id
)
378 static int ThreadX_get_thread_detail(struct rtos
*rtos
,
379 threadid_t thread_id
,
380 struct thread_detail
*detail
)
385 #define THREADX_THREAD_NAME_STR_SIZE (200)
386 char tmp_str
[THREADX_THREAD_NAME_STR_SIZE
];
388 const struct ThreadX_params
*param
;
396 if (rtos
->rtos_specific_params
== NULL
)
399 param
= (const struct ThreadX_params
*) rtos
->rtos_specific_params
;
401 if (rtos
->symbols
== NULL
) {
402 LOG_ERROR("No symbols for ThreadX");
406 detail
->threadid
= thread_id
;
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");
419 /* Read the thread name */
420 retval
= target_read_buffer(rtos
->target
,
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");
428 tmp_str
[THREADX_THREAD_NAME_STR_SIZE
-1] = '\x00';
430 if (tmp_str
[0] == '\x00')
431 strcpy(tmp_str
, "No Name");
433 detail
->thread_name_str
= (char *)malloc(strlen(tmp_str
)+1);
435 /* Read the thread status */
436 int64_t thread_status
= 0;
438 target_read_buffer(rtos
->target
,
439 thread_id
+ param
->thread_state_offset
,
441 (uint8_t *)&thread_status
);
442 if (retval
!= ERROR_OK
) {
443 LOG_ERROR("Error reading thread state from ThreadX target");
447 for (i
= 0; (i
< THREADX_NUM_STATES
) &&
448 (ThreadX_thread_states
[i
].value
!= thread_status
); i
++) {
453 if (i
< THREADX_NUM_STATES
)
454 state_desc
= ThreadX_thread_states
[i
].desc
;
456 state_desc
= "Unknown state";
458 detail
->extra_info_str
= (char *)malloc(strlen(state_desc
)+1);
460 detail
->exists
= true;
462 detail
->display_str
= NULL
;
469 static int ThreadX_create(struct target
*target
)
472 while ((i
< THREADX_NUM_PARAMS
) &&
473 (0 != strcmp(ThreadX_params_list
[i
].target_name
, target
->type
->name
))) {
476 if (i
>= THREADX_NUM_PARAMS
) {
477 LOG_ERROR("Could not find target in ThreadX compatibility list");
481 target
->rtos
->rtos_specific_params
= (void *) &ThreadX_params_list
[i
];
482 target
->rtos
->current_thread
= 0;
483 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)