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 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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_m3", /* 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 */
86 #define THREADX_NUM_PARAMS ((int)(sizeof(ThreadX_params_list)/sizeof(struct ThreadX_params)))
88 enum ThreadX_symbol_values
{
89 ThreadX_VAL_tx_thread_current_ptr
= 0,
90 ThreadX_VAL_tx_thread_created_ptr
= 1,
91 ThreadX_VAL_tx_thread_created_count
= 2,
94 static char *ThreadX_symbol_list
[] = {
95 "_tx_thread_current_ptr",
96 "_tx_thread_created_ptr",
97 "_tx_thread_created_count",
101 const struct rtos_type ThreadX_rtos
= {
104 .detect_rtos
= ThreadX_detect_rtos
,
105 .create
= ThreadX_create
,
106 .update_threads
= ThreadX_update_threads
,
107 .get_thread_reg_list
= ThreadX_get_thread_reg_list
,
108 .get_symbol_list_to_lookup
= ThreadX_get_symbol_list_to_lookup
,
112 static int ThreadX_update_threads(struct rtos
*rtos
)
116 int thread_list_size
= 0;
117 const struct ThreadX_params
*param
;
122 if (rtos
->rtos_specific_params
== NULL
)
125 param
= (const struct ThreadX_params
*) rtos
->rtos_specific_params
;
127 if (rtos
->symbols
== NULL
) {
128 LOG_OUTPUT("No symbols for ThreadX\r\n");
132 if (rtos
->symbols
[ThreadX_VAL_tx_thread_created_count
].address
== 0) {
133 LOG_OUTPUT("Don't have the number of threads in ThreadX \r\n");
137 /* read the number of threads */
138 retval
= target_read_buffer(rtos
->target
,
139 rtos
->symbols
[ThreadX_VAL_tx_thread_created_count
].address
,
141 (uint8_t *)&thread_list_size
);
143 if (retval
!= ERROR_OK
) {
144 LOG_OUTPUT("Could not read ThreadX thread count from target\r\n");
148 /* wipe out previous thread details if any */
149 if (rtos
->thread_details
!= NULL
) {
151 for (j
= 0; j
< rtos
->thread_count
; j
++) {
152 if (rtos
->thread_details
[j
].display_str
!= NULL
) {
153 free(rtos
->thread_details
[j
].display_str
);
154 rtos
->thread_details
[j
].display_str
= NULL
;
156 if (rtos
->thread_details
[j
].thread_name_str
!= NULL
) {
157 free(rtos
->thread_details
[j
].thread_name_str
);
158 rtos
->thread_details
[j
].thread_name_str
= NULL
;
160 if (rtos
->thread_details
[j
].extra_info_str
!= NULL
) {
161 free(rtos
->thread_details
[j
].extra_info_str
);
162 rtos
->thread_details
[j
].extra_info_str
= NULL
;
165 free(rtos
->thread_details
);
166 rtos
->thread_details
= NULL
;
169 /* read the current thread id */
170 retval
= target_read_buffer(rtos
->target
,
171 rtos
->symbols
[ThreadX_VAL_tx_thread_current_ptr
].address
,
173 (uint8_t *)&rtos
->current_thread
);
175 if (retval
!= ERROR_OK
) {
176 LOG_OUTPUT("Could not read ThreadX current thread from target\r\n");
180 if ((thread_list_size
== 0) || (rtos
->current_thread
== 0)) {
181 /* Either : No RTOS threads - there is always at least the current execution though */
182 /* OR : No current thread - all threads suspended - show the current execution
184 char tmp_str
[] = "Current Execution";
187 rtos
->thread_details
= (struct thread_detail
*) malloc(
188 sizeof(struct thread_detail
) * thread_list_size
);
189 rtos
->thread_details
->threadid
= 1;
190 rtos
->thread_details
->exists
= true;
191 rtos
->thread_details
->display_str
= NULL
;
192 rtos
->thread_details
->extra_info_str
= NULL
;
193 rtos
->thread_details
->thread_name_str
= (char *) malloc(sizeof(tmp_str
));
194 strcpy(rtos
->thread_details
->thread_name_str
, tmp_str
);
196 if (thread_list_size
== 0) {
197 rtos
->thread_count
= 1;
201 /* create space for new thread details */
202 rtos
->thread_details
= (struct thread_detail
*) malloc(
203 sizeof(struct thread_detail
) * thread_list_size
);
206 /* Read the pointer to the first thread */
207 int64_t thread_ptr
= 0;
208 retval
= target_read_buffer(rtos
->target
,
209 rtos
->symbols
[ThreadX_VAL_tx_thread_created_ptr
].address
,
210 param
->pointer_width
,
211 (uint8_t *)&thread_ptr
);
212 if (retval
!= ERROR_OK
) {
213 LOG_OUTPUT("Could not read ThreadX thread location from target\r\n");
217 /* loop over all threads */
218 int64_t prev_thread_ptr
= 0;
219 while ((thread_ptr
!= prev_thread_ptr
) && (tasks_found
< thread_list_size
)) {
221 #define THREADX_THREAD_NAME_STR_SIZE (200)
222 char tmp_str
[THREADX_THREAD_NAME_STR_SIZE
];
224 int64_t name_ptr
= 0;
226 /* Save the thread pointer */
227 rtos
->thread_details
[tasks_found
].threadid
= thread_ptr
;
229 /* read the name pointer */
230 retval
= target_read_buffer(rtos
->target
,
231 thread_ptr
+ param
->thread_name_offset
,
232 param
->pointer_width
,
233 (uint8_t *)&name_ptr
);
234 if (retval
!= ERROR_OK
) {
235 LOG_OUTPUT("Could not read ThreadX thread name pointer from target\r\n");
239 /* Read the thread name */
241 target_read_buffer(rtos
->target
,
243 THREADX_THREAD_NAME_STR_SIZE
,
244 (uint8_t *)&tmp_str
);
245 if (retval
!= ERROR_OK
) {
246 LOG_OUTPUT("Error reading thread name from ThreadX target\r\n");
249 tmp_str
[THREADX_THREAD_NAME_STR_SIZE
-1] = '\x00';
251 if (tmp_str
[0] == '\x00')
252 strcpy(tmp_str
, "No Name");
254 rtos
->thread_details
[tasks_found
].thread_name_str
=
255 (char *)malloc(strlen(tmp_str
)+1);
256 strcpy(rtos
->thread_details
[tasks_found
].thread_name_str
, tmp_str
);
258 /* Read the thread status */
259 int64_t thread_status
= 0;
260 retval
= target_read_buffer(rtos
->target
,
261 thread_ptr
+ param
->thread_state_offset
,
263 (uint8_t *)&thread_status
);
264 if (retval
!= ERROR_OK
) {
265 LOG_OUTPUT("Error reading thread state from ThreadX target\r\n");
269 for (i
= 0; (i
< THREADX_NUM_STATES
) &&
270 (ThreadX_thread_states
[i
].value
!= thread_status
); i
++) {
275 if (i
< THREADX_NUM_STATES
)
276 state_desc
= ThreadX_thread_states
[i
].desc
;
278 state_desc
= "Unknown state";
280 rtos
->thread_details
[tasks_found
].extra_info_str
= (char *)malloc(strlen(
282 strcpy(rtos
->thread_details
[tasks_found
].extra_info_str
, state_desc
);
284 rtos
->thread_details
[tasks_found
].exists
= true;
286 rtos
->thread_details
[tasks_found
].display_str
= NULL
;
289 prev_thread_ptr
= thread_ptr
;
291 /* Get the location of the next thread structure. */
293 retval
= target_read_buffer(rtos
->target
,
294 prev_thread_ptr
+ param
->thread_next_offset
,
295 param
->pointer_width
,
296 (uint8_t *) &thread_ptr
);
297 if (retval
!= ERROR_OK
) {
298 LOG_OUTPUT("Error reading next thread pointer in ThreadX thread list\r\n");
303 rtos
->thread_count
= tasks_found
;
308 static int ThreadX_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
)
311 const struct ThreadX_params
*param
;
313 *hex_reg_list
= NULL
;
321 if (rtos
->rtos_specific_params
== NULL
)
324 param
= (const struct ThreadX_params
*) rtos
->rtos_specific_params
;
326 /* Read the stack pointer */
327 int64_t stack_ptr
= 0;
328 retval
= target_read_buffer(rtos
->target
,
329 thread_id
+ param
->thread_stack_offset
,
330 param
->pointer_width
,
331 (uint8_t *)&stack_ptr
);
332 if (retval
!= ERROR_OK
) {
333 LOG_OUTPUT("Error reading stack frame from ThreadX thread\r\n");
337 return rtos_generic_stack_read(rtos
->target
, param
->stacking_info
, stack_ptr
, hex_reg_list
);
340 static int ThreadX_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
343 *symbol_list
= (symbol_table_elem_t
*) malloc(
344 sizeof(symbol_table_elem_t
) * ARRAY_SIZE(ThreadX_symbol_list
));
346 for (i
= 0; i
< ARRAY_SIZE(ThreadX_symbol_list
); i
++)
347 (*symbol_list
)[i
].symbol_name
= ThreadX_symbol_list
[i
];
352 static int ThreadX_detect_rtos(struct target
*target
)
354 if ((target
->rtos
->symbols
!= NULL
) &&
355 (target
->rtos
->symbols
[ThreadX_VAL_tx_thread_created_ptr
].address
!= 0)) {
356 /* looks like ThreadX */
364 static int ThreadX_set_current_thread(struct rtos
*rtos
, threadid_t thread_id
)
369 static int ThreadX_get_thread_detail(struct rtos
*rtos
,
370 threadid_t thread_id
,
371 struct thread_detail
*detail
)
376 #define THREADX_THREAD_NAME_STR_SIZE (200)
377 char tmp_str
[THREADX_THREAD_NAME_STR_SIZE
];
379 const struct ThreadX_params
*param
;
387 if (rtos
->rtos_specific_params
== NULL
)
390 param
= (const struct ThreadX_params
*) rtos
->rtos_specific_params
;
392 if (rtos
->symbols
== NULL
) {
393 LOG_OUTPUT("No symbols for ThreadX\r\n");
397 detail
->threadid
= thread_id
;
399 int64_t name_ptr
= 0;
400 /* read the name pointer */
401 retval
= target_read_buffer(rtos
->target
,
402 thread_id
+ param
->thread_name_offset
,
403 param
->pointer_width
,
404 (uint8_t *)&name_ptr
);
405 if (retval
!= ERROR_OK
) {
406 LOG_OUTPUT("Could not read ThreadX thread name pointer from target\r\n");
410 /* Read the thread name */
411 retval
= target_read_buffer(rtos
->target
,
413 THREADX_THREAD_NAME_STR_SIZE
,
414 (uint8_t *)&tmp_str
);
415 if (retval
!= ERROR_OK
) {
416 LOG_OUTPUT("Error reading thread name from ThreadX target\r\n");
419 tmp_str
[THREADX_THREAD_NAME_STR_SIZE
-1] = '\x00';
421 if (tmp_str
[0] == '\x00')
422 strcpy(tmp_str
, "No Name");
424 detail
->thread_name_str
= (char *)malloc(strlen(tmp_str
)+1);
426 /* Read the thread status */
427 int64_t thread_status
= 0;
429 target_read_buffer(rtos
->target
,
430 thread_id
+ param
->thread_state_offset
,
432 (uint8_t *)&thread_status
);
433 if (retval
!= ERROR_OK
) {
434 LOG_OUTPUT("Error reading thread state from ThreadX target\r\n");
438 for (i
= 0; (i
< THREADX_NUM_STATES
) &&
439 (ThreadX_thread_states
[i
].value
!= thread_status
); i
++) {
444 if (i
< THREADX_NUM_STATES
)
445 state_desc
= ThreadX_thread_states
[i
].desc
;
447 state_desc
= "Unknown state";
449 detail
->extra_info_str
= (char *)malloc(strlen(state_desc
)+1);
451 detail
->exists
= true;
453 detail
->display_str
= NULL
;
460 static int ThreadX_create(struct target
*target
)
463 while ((i
< THREADX_NUM_PARAMS
) &&
464 (0 != strcmp(ThreadX_params_list
[i
].target_name
, target
->type
->name
))) {
467 if (i
>= THREADX_NUM_PARAMS
) {
468 LOG_OUTPUT("Could not find target in ThreadX compatibility list\r\n");
472 target
->rtos
->rtos_specific_params
= (void *) &ThreadX_params_list
[i
];
473 target
->rtos
->current_thread
= 0;
474 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)