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 static const 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
{
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
;
74 static 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 const char * const 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
,
120 static int ThreadX_update_threads(struct rtos
*rtos
)
124 int thread_list_size
= 0;
125 const struct ThreadX_params
*param
;
130 if (rtos
->rtos_specific_params
== NULL
)
133 param
= (const struct ThreadX_params
*) rtos
->rtos_specific_params
;
135 if (rtos
->symbols
== NULL
) {
136 LOG_ERROR("No symbols for ThreadX");
140 if (rtos
->symbols
[ThreadX_VAL_tx_thread_created_count
].address
== 0) {
141 LOG_ERROR("Don't have the number of threads in ThreadX");
145 /* read the number of threads */
146 retval
= target_read_buffer(rtos
->target
,
147 rtos
->symbols
[ThreadX_VAL_tx_thread_created_count
].address
,
149 (uint8_t *)&thread_list_size
);
151 if (retval
!= ERROR_OK
) {
152 LOG_ERROR("Could not read ThreadX thread count from target");
156 /* wipe out previous thread details if any */
157 rtos_free_threadlist(rtos
);
159 /* read the current thread id */
160 retval
= target_read_buffer(rtos
->target
,
161 rtos
->symbols
[ThreadX_VAL_tx_thread_current_ptr
].address
,
163 (uint8_t *)&rtos
->current_thread
);
165 if (retval
!= ERROR_OK
) {
166 LOG_ERROR("Could not read ThreadX current thread from target");
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
174 char tmp_str
[] = "Current Execution";
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
);
186 if (thread_list_size
== 0) {
187 rtos
->thread_count
= 1;
191 /* create space for new thread details */
192 rtos
->thread_details
= malloc(
193 sizeof(struct thread_detail
) * thread_list_size
);
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");
207 /* loop over all threads */
208 int64_t prev_thread_ptr
= 0;
209 while ((thread_ptr
!= prev_thread_ptr
) && (tasks_found
< thread_list_size
)) {
211 #define THREADX_THREAD_NAME_STR_SIZE (200)
212 char tmp_str
[THREADX_THREAD_NAME_STR_SIZE
];
214 int64_t name_ptr
= 0;
216 /* Save the thread pointer */
217 rtos
->thread_details
[tasks_found
].threadid
= thread_ptr
;
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");
229 /* Read the thread name */
231 target_read_buffer(rtos
->target
,
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");
239 tmp_str
[THREADX_THREAD_NAME_STR_SIZE
-1] = '\x00';
241 if (tmp_str
[0] == '\x00')
242 strcpy(tmp_str
, "No Name");
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
);
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
,
253 (uint8_t *)&thread_status
);
254 if (retval
!= ERROR_OK
) {
255 LOG_ERROR("Error reading thread state from ThreadX target");
259 for (i
= 0; (i
< THREADX_NUM_STATES
) &&
260 (ThreadX_thread_states
[i
].value
!= thread_status
); i
++) {
264 const char *state_desc
;
265 if (i
< THREADX_NUM_STATES
)
266 state_desc
= ThreadX_thread_states
[i
].desc
;
268 state_desc
= "Unknown state";
270 rtos
->thread_details
[tasks_found
].extra_info_str
= malloc(strlen(
272 strcpy(rtos
->thread_details
[tasks_found
].extra_info_str
, state_desc
);
274 rtos
->thread_details
[tasks_found
].exists
= true;
276 rtos
->thread_details
[tasks_found
].display_str
= NULL
;
279 prev_thread_ptr
= thread_ptr
;
281 /* Get the location of the next thread structure. */
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");
293 rtos
->thread_count
= tasks_found
;
298 static int ThreadX_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
)
301 const struct ThreadX_params
*param
;
303 *hex_reg_list
= NULL
;
311 if (rtos
->rtos_specific_params
== NULL
)
314 param
= (const struct ThreadX_params
*) rtos
->rtos_specific_params
;
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");
327 return rtos_generic_stack_read(rtos
->target
, param
->stacking_info
, stack_ptr
, hex_reg_list
);
330 static int ThreadX_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
333 *symbol_list
= calloc(
334 ARRAY_SIZE(ThreadX_symbol_list
), sizeof(symbol_table_elem_t
));
336 for (i
= 0; i
< ARRAY_SIZE(ThreadX_symbol_list
); i
++)
337 (*symbol_list
)[i
].symbol_name
= ThreadX_symbol_list
[i
];
342 static int ThreadX_detect_rtos(struct target
*target
)
344 if ((target
->rtos
->symbols
!= NULL
) &&
345 (target
->rtos
->symbols
[ThreadX_VAL_tx_thread_created_ptr
].address
!= 0)) {
346 /* looks like ThreadX */
354 static int ThreadX_set_current_thread(struct rtos
*rtos
, threadid_t thread_id
)
359 static int ThreadX_get_thread_detail(struct rtos
*rtos
,
360 threadid_t thread_id
,
361 struct thread_detail
*detail
)
366 #define THREADX_THREAD_NAME_STR_SIZE (200)
367 char tmp_str
[THREADX_THREAD_NAME_STR_SIZE
];
369 const struct ThreadX_params
*param
;
377 if (rtos
->rtos_specific_params
== NULL
)
380 param
= (const struct ThreadX_params
*) rtos
->rtos_specific_params
;
382 if (rtos
->symbols
== NULL
) {
383 LOG_ERROR("No symbols for ThreadX");
387 detail
->threadid
= thread_id
;
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");
400 /* Read the thread name */
401 retval
= target_read_buffer(rtos
->target
,
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");
409 tmp_str
[THREADX_THREAD_NAME_STR_SIZE
-1] = '\x00';
411 if (tmp_str
[0] == '\x00')
412 strcpy(tmp_str
, "No Name");
414 detail
->thread_name_str
= malloc(strlen(tmp_str
)+1);
416 /* Read the thread status */
417 int64_t thread_status
= 0;
419 target_read_buffer(rtos
->target
,
420 thread_id
+ param
->thread_state_offset
,
422 (uint8_t *)&thread_status
);
423 if (retval
!= ERROR_OK
) {
424 LOG_ERROR("Error reading thread state from ThreadX target");
428 for (i
= 0; (i
< THREADX_NUM_STATES
) &&
429 (ThreadX_thread_states
[i
].value
!= thread_status
); i
++) {
434 if (i
< THREADX_NUM_STATES
)
435 state_desc
= ThreadX_thread_states
[i
].desc
;
437 state_desc
= "Unknown state";
439 detail
->extra_info_str
= malloc(strlen(state_desc
)+1);
441 detail
->exists
= true;
443 detail
->display_str
= NULL
;
450 static int ThreadX_create(struct target
*target
)
453 while ((i
< THREADX_NUM_PARAMS
) &&
454 (0 != strcmp(ThreadX_params_list
[i
].target_name
, target
->type
->name
))) {
457 if (i
>= THREADX_NUM_PARAMS
) {
458 LOG_ERROR("Could not find target in ThreadX compatibility list");
462 target
->rtos
->rtos_specific_params
= (void *) &ThreadX_params_list
[i
];
463 target
->rtos
->current_thread
= 0;
464 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)