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 "rtos_standard_stackings.h"
33 static int ThreadX_detect_rtos(struct target
*target
);
34 static int ThreadX_create(struct target
*target
);
35 static int ThreadX_update_threads(struct rtos
*rtos
);
36 static int ThreadX_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
);
37 static int ThreadX_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[]);
39 struct ThreadX_thread_state
{
44 struct ThreadX_thread_state ThreadX_thread_states
[] = {
50 { 5, "Waiting - Queue" },
51 { 6, "Waiting - Semaphore" },
52 { 7, "Waiting - Event flag" },
53 { 8, "Waiting - Memory" },
54 { 9, "Waiting - Memory" },
55 { 10, "Waiting - I/O" },
56 { 11, "Waiting - Filesystem" },
57 { 12, "Waiting - Network" },
58 { 13, "Waiting - Mutex" },
61 #define THREADX_NUM_STATES (sizeof(ThreadX_thread_states)/sizeof(struct ThreadX_thread_state))
63 struct ThreadX_params
{
65 unsigned char pointer_width
;
66 unsigned char thread_stack_offset
;
67 unsigned char thread_name_offset
;
68 unsigned char thread_state_offset
;
69 unsigned char thread_next_offset
;
70 const struct rtos_register_stacking
*stacking_info
;
73 const struct ThreadX_params ThreadX_params_list
[] = {
75 "cortex_m3", /* target_name */
76 4, /* pointer_width; */
77 8, /* thread_stack_offset; */
78 40, /* thread_name_offset; */
79 48, /* thread_state_offset; */
80 136, /* thread_next_offset */
81 &rtos_standard_Cortex_M3_stacking
, /* stacking_info */
85 #define THREADX_NUM_PARAMS ((int)(sizeof(ThreadX_params_list)/sizeof(struct ThreadX_params)))
87 enum ThreadX_symbol_values
{
88 ThreadX_VAL_tx_thread_current_ptr
= 0,
89 ThreadX_VAL_tx_thread_created_ptr
= 1,
90 ThreadX_VAL_tx_thread_created_count
= 2,
93 static char *ThreadX_symbol_list
[] = {
94 "_tx_thread_current_ptr",
95 "_tx_thread_created_ptr",
96 "_tx_thread_created_count",
100 #define THREADX_NUM_SYMBOLS (sizeof(ThreadX_symbol_list)/sizeof(char *))
102 const struct rtos_type ThreadX_rtos
= {
105 .detect_rtos
= ThreadX_detect_rtos
,
106 .create
= ThreadX_create
,
107 .update_threads
= ThreadX_update_threads
,
108 .get_thread_reg_list
= ThreadX_get_thread_reg_list
,
109 .get_symbol_list_to_lookup
= ThreadX_get_symbol_list_to_lookup
,
113 static int ThreadX_update_threads(struct rtos
*rtos
)
117 int thread_list_size
= 0;
118 const struct ThreadX_params
*param
;
123 if (rtos
->rtos_specific_params
== NULL
)
126 param
= (const struct ThreadX_params
*) rtos
->rtos_specific_params
;
128 if (rtos
->symbols
== NULL
) {
129 LOG_OUTPUT("No symbols for ThreadX\r\n");
133 if (rtos
->symbols
[ThreadX_VAL_tx_thread_created_count
].address
== 0) {
134 LOG_OUTPUT("Don't have the number of threads in ThreadX \r\n");
138 /* read the number of threads */
139 retval
= target_read_buffer(rtos
->target
,
140 rtos
->symbols
[ThreadX_VAL_tx_thread_created_count
].address
,
142 (uint8_t *)&thread_list_size
);
144 if (retval
!= ERROR_OK
) {
145 LOG_OUTPUT("Could not read ThreadX thread count from target\r\n");
149 /* wipe out previous thread details if any */
150 if (rtos
->thread_details
!= NULL
) {
152 for (j
= 0; j
< rtos
->thread_count
; j
++) {
153 if (rtos
->thread_details
[j
].display_str
!= NULL
) {
154 free(rtos
->thread_details
[j
].display_str
);
155 rtos
->thread_details
[j
].display_str
= NULL
;
157 if (rtos
->thread_details
[j
].thread_name_str
!= NULL
) {
158 free(rtos
->thread_details
[j
].thread_name_str
);
159 rtos
->thread_details
[j
].thread_name_str
= NULL
;
161 if (rtos
->thread_details
[j
].extra_info_str
!= NULL
) {
162 free(rtos
->thread_details
[j
].extra_info_str
);
163 rtos
->thread_details
[j
].extra_info_str
= NULL
;
166 free(rtos
->thread_details
);
167 rtos
->thread_details
= NULL
;
170 /* read the current thread id */
171 retval
= target_read_buffer(rtos
->target
,
172 rtos
->symbols
[ThreadX_VAL_tx_thread_current_ptr
].address
,
174 (uint8_t *)&rtos
->current_thread
);
176 if (retval
!= ERROR_OK
) {
177 LOG_OUTPUT("Could not read ThreadX current thread from target\r\n");
181 if ((thread_list_size
== 0) || (rtos
->current_thread
== 0)) {
182 /* Either : No RTOS threads - there is always at least the current execution though */
183 /* OR : No current thread - all threads suspended - show the current execution
185 char tmp_str
[] = "Current Execution";
188 rtos
->thread_details
= (struct thread_detail
*) malloc(
189 sizeof(struct thread_detail
) * thread_list_size
);
190 rtos
->thread_details
->threadid
= 1;
191 rtos
->thread_details
->exists
= true;
192 rtos
->thread_details
->display_str
= NULL
;
193 rtos
->thread_details
->extra_info_str
= NULL
;
194 rtos
->thread_details
->thread_name_str
= (char *) malloc(sizeof(tmp_str
));
195 strcpy(rtos
->thread_details
->thread_name_str
, tmp_str
);
197 if (thread_list_size
== 0) {
198 rtos
->thread_count
= 1;
202 /* create space for new thread details */
203 rtos
->thread_details
= (struct thread_detail
*) malloc(
204 sizeof(struct thread_detail
) * thread_list_size
);
207 /* Read the pointer to the first thread */
208 int64_t thread_ptr
= 0;
209 retval
= target_read_buffer(rtos
->target
,
210 rtos
->symbols
[ThreadX_VAL_tx_thread_created_ptr
].address
,
211 param
->pointer_width
,
212 (uint8_t *)&thread_ptr
);
213 if (retval
!= ERROR_OK
) {
214 LOG_OUTPUT("Could not read ThreadX thread location from target\r\n");
218 /* loop over all threads */
219 int64_t prev_thread_ptr
= 0;
220 while ((thread_ptr
!= prev_thread_ptr
) && (tasks_found
< thread_list_size
)) {
222 #define THREADX_THREAD_NAME_STR_SIZE (200)
223 char tmp_str
[THREADX_THREAD_NAME_STR_SIZE
];
225 int64_t name_ptr
= 0;
227 /* Save the thread pointer */
228 rtos
->thread_details
[tasks_found
].threadid
= thread_ptr
;
230 /* read the name pointer */
231 retval
= target_read_buffer(rtos
->target
,
232 thread_ptr
+ param
->thread_name_offset
,
233 param
->pointer_width
,
234 (uint8_t *)&name_ptr
);
235 if (retval
!= ERROR_OK
) {
236 LOG_OUTPUT("Could not read ThreadX thread name pointer from target\r\n");
240 /* Read the thread name */
242 target_read_buffer(rtos
->target
,
244 THREADX_THREAD_NAME_STR_SIZE
,
245 (uint8_t *)&tmp_str
);
246 if (retval
!= ERROR_OK
) {
247 LOG_OUTPUT("Error reading thread name from ThreadX target\r\n");
250 tmp_str
[THREADX_THREAD_NAME_STR_SIZE
-1] = '\x00';
252 if (tmp_str
[0] == '\x00')
253 strcpy(tmp_str
, "No Name");
255 rtos
->thread_details
[tasks_found
].thread_name_str
=
256 (char *)malloc(strlen(tmp_str
)+1);
257 strcpy(rtos
->thread_details
[tasks_found
].thread_name_str
, tmp_str
);
259 /* Read the thread status */
260 int64_t thread_status
= 0;
261 retval
= target_read_buffer(rtos
->target
,
262 thread_ptr
+ param
->thread_state_offset
,
264 (uint8_t *)&thread_status
);
265 if (retval
!= ERROR_OK
) {
266 LOG_OUTPUT("Error reading thread state from ThreadX target\r\n");
270 for (i
= 0; (i
< THREADX_NUM_STATES
) &&
271 (ThreadX_thread_states
[i
].value
!= thread_status
); i
++) {
276 if (i
< THREADX_NUM_STATES
)
277 state_desc
= ThreadX_thread_states
[i
].desc
;
279 state_desc
= "Unknown state";
281 rtos
->thread_details
[tasks_found
].extra_info_str
= (char *)malloc(strlen(
283 strcpy(rtos
->thread_details
[tasks_found
].extra_info_str
, state_desc
);
285 rtos
->thread_details
[tasks_found
].exists
= true;
287 rtos
->thread_details
[tasks_found
].display_str
= NULL
;
290 prev_thread_ptr
= thread_ptr
;
292 /* Get the location of the next thread structure. */
294 retval
= target_read_buffer(rtos
->target
,
295 prev_thread_ptr
+ param
->thread_next_offset
,
296 param
->pointer_width
,
297 (uint8_t *) &thread_ptr
);
298 if (retval
!= ERROR_OK
) {
299 LOG_OUTPUT("Error reading next thread pointer in ThreadX thread list\r\n");
304 rtos
->thread_count
= tasks_found
;
309 static int ThreadX_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
)
312 const struct ThreadX_params
*param
;
314 *hex_reg_list
= NULL
;
322 if (rtos
->rtos_specific_params
== NULL
)
325 param
= (const struct ThreadX_params
*) rtos
->rtos_specific_params
;
327 /* Read the stack pointer */
328 int64_t stack_ptr
= 0;
329 retval
= target_read_buffer(rtos
->target
,
330 thread_id
+ param
->thread_stack_offset
,
331 param
->pointer_width
,
332 (uint8_t *)&stack_ptr
);
333 if (retval
!= ERROR_OK
) {
334 LOG_OUTPUT("Error reading stack frame from ThreadX thread\r\n");
338 return rtos_generic_stack_read(rtos
->target
, param
->stacking_info
, stack_ptr
, hex_reg_list
);
341 static int ThreadX_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
344 *symbol_list
= (symbol_table_elem_t
*) malloc(
345 sizeof(symbol_table_elem_t
) * THREADX_NUM_SYMBOLS
);
347 for (i
= 0; i
< THREADX_NUM_SYMBOLS
; i
++)
348 (*symbol_list
)[i
].symbol_name
= ThreadX_symbol_list
[i
];
353 static int ThreadX_detect_rtos(struct target
*target
)
355 if ((target
->rtos
->symbols
!= NULL
) &&
356 (target
->rtos
->symbols
[ThreadX_VAL_tx_thread_created_ptr
].address
!= 0)) {
357 /* looks like ThreadX */
365 static int ThreadX_set_current_thread(struct rtos
*rtos
, threadid_t thread_id
)
370 static int ThreadX_get_thread_detail(struct rtos
*rtos
,
371 threadid_t thread_id
,
372 struct thread_detail
*detail
)
377 #define THREADX_THREAD_NAME_STR_SIZE (200)
378 char tmp_str
[THREADX_THREAD_NAME_STR_SIZE
];
380 const struct ThreadX_params
*param
;
388 if (rtos
->rtos_specific_params
== NULL
)
391 param
= (const struct ThreadX_params
*) rtos
->rtos_specific_params
;
393 if (rtos
->symbols
== NULL
) {
394 LOG_OUTPUT("No symbols for ThreadX\r\n");
398 detail
->threadid
= thread_id
;
400 int64_t name_ptr
= 0;
401 /* read the name pointer */
402 retval
= target_read_buffer(rtos
->target
,
403 thread_id
+ param
->thread_name_offset
,
404 param
->pointer_width
,
405 (uint8_t *)&name_ptr
);
406 if (retval
!= ERROR_OK
) {
407 LOG_OUTPUT("Could not read ThreadX thread name pointer from target\r\n");
411 /* Read the thread name */
412 retval
= target_read_buffer(rtos
->target
,
414 THREADX_THREAD_NAME_STR_SIZE
,
415 (uint8_t *)&tmp_str
);
416 if (retval
!= ERROR_OK
) {
417 LOG_OUTPUT("Error reading thread name from ThreadX target\r\n");
420 tmp_str
[THREADX_THREAD_NAME_STR_SIZE
-1] = '\x00';
422 if (tmp_str
[0] == '\x00')
423 strcpy(tmp_str
, "No Name");
425 detail
->thread_name_str
= (char *)malloc(strlen(tmp_str
)+1);
427 /* Read the thread status */
428 int64_t thread_status
= 0;
430 target_read_buffer(rtos
->target
,
431 thread_id
+ param
->thread_state_offset
,
433 (uint8_t *)&thread_status
);
434 if (retval
!= ERROR_OK
) {
435 LOG_OUTPUT("Error reading thread state from ThreadX target\r\n");
439 for (i
= 0; (i
< THREADX_NUM_STATES
) &&
440 (ThreadX_thread_states
[i
].value
!= thread_status
); i
++) {
445 if (i
< THREADX_NUM_STATES
)
446 state_desc
= ThreadX_thread_states
[i
].desc
;
448 state_desc
= "Unknown state";
450 detail
->extra_info_str
= (char *)malloc(strlen(state_desc
)+1);
452 detail
->exists
= true;
454 detail
->display_str
= NULL
;
461 static int ThreadX_create(struct target
*target
)
464 while ((i
< THREADX_NUM_PARAMS
) &&
465 (0 != strcmp(ThreadX_params_list
[i
].target_name
, target
->type
->name
))) {
468 if (i
>= THREADX_NUM_PARAMS
) {
469 LOG_OUTPUT("Could not find target in ThreadX compatibility list\r\n");
473 target
->rtos
->rtos_specific_params
= (void *) &ThreadX_params_list
[i
];
474 target
->rtos
->current_thread
= 0;
475 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)