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 #define FREERTOS_MAX_PRIORITIES 63
36 #define FreeRTOS_STRUCT(int_type, ptr_type, list_prev_offset)
38 struct FreeRTOS_params
{
39 const char *target_name
;
40 const unsigned char thread_count_width
;
41 const unsigned char pointer_width
;
42 const unsigned char list_next_offset
;
43 const unsigned char list_width
;
44 const unsigned char list_elem_next_offset
;
45 const unsigned char list_elem_content_offset
;
46 const unsigned char thread_stack_offset
;
47 const unsigned char thread_name_offset
;
48 const struct rtos_register_stacking
*stacking_info
;
51 const struct FreeRTOS_params FreeRTOS_params_list
[] = {
53 "cortex_m3", /* target_name */
54 4, /* thread_count_width; */
55 4, /* pointer_width; */
56 16, /* list_next_offset; */
58 8, /* list_elem_next_offset; */
59 12, /* list_elem_content_offset */
60 0, /* thread_stack_offset; */
61 52, /* thread_name_offset; */
62 &rtos_standard_Cortex_M3_stacking
, /* stacking_info */
65 "hla_target", /* target_name */
66 4, /* thread_count_width; */
67 4, /* pointer_width; */
68 16, /* list_next_offset; */
70 8, /* list_elem_next_offset; */
71 12, /* list_elem_content_offset */
72 0, /* thread_stack_offset; */
73 52, /* thread_name_offset; */
74 &rtos_standard_Cortex_M3_stacking
, /* stacking_info */
78 #define FREERTOS_NUM_PARAMS ((int)(sizeof(FreeRTOS_params_list)/sizeof(struct FreeRTOS_params)))
80 static int FreeRTOS_detect_rtos(struct target
*target
);
81 static int FreeRTOS_create(struct target
*target
);
82 static int FreeRTOS_update_threads(struct rtos
*rtos
);
83 static int FreeRTOS_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
);
84 static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[]);
86 struct rtos_type FreeRTOS_rtos
= {
89 .detect_rtos
= FreeRTOS_detect_rtos
,
90 .create
= FreeRTOS_create
,
91 .update_threads
= FreeRTOS_update_threads
,
92 .get_thread_reg_list
= FreeRTOS_get_thread_reg_list
,
93 .get_symbol_list_to_lookup
= FreeRTOS_get_symbol_list_to_lookup
,
96 enum FreeRTOS_symbol_values
{
97 FreeRTOS_VAL_pxCurrentTCB
= 0,
98 FreeRTOS_VAL_pxReadyTasksLists
= 1,
99 FreeRTOS_VAL_xDelayedTaskList1
= 2,
100 FreeRTOS_VAL_xDelayedTaskList2
= 3,
101 FreeRTOS_VAL_pxDelayedTaskList
= 4,
102 FreeRTOS_VAL_pxOverflowDelayedTaskList
= 5,
103 FreeRTOS_VAL_xPendingReadyList
= 6,
104 FreeRTOS_VAL_xTasksWaitingTermination
= 7,
105 FreeRTOS_VAL_xSuspendedTaskList
= 8,
106 FreeRTOS_VAL_uxCurrentNumberOfTasks
= 9,
107 FreeRTOS_VAL_uxTopUsedPriority
= 10,
110 static char *FreeRTOS_symbol_list
[] = {
116 "pxOverflowDelayedTaskList",
118 "xTasksWaitingTermination",
119 "xSuspendedTaskList",
120 "uxCurrentNumberOfTasks",
126 /* this is not safe for little endian yet */
127 /* may be problems reading if sizes are not 32 bit long integers. */
128 /* test mallocs for failure */
130 static int FreeRTOS_update_threads(struct rtos
*rtos
)
135 const struct FreeRTOS_params
*param
;
137 if (rtos
->rtos_specific_params
== NULL
)
140 param
= (const struct FreeRTOS_params
*) rtos
->rtos_specific_params
;
142 if (rtos
->symbols
== NULL
) {
143 LOG_ERROR("No symbols for FreeRTOS");
147 if (rtos
->symbols
[FreeRTOS_VAL_uxCurrentNumberOfTasks
].address
== 0) {
148 LOG_ERROR("Don't have the number of threads in FreeRTOS");
152 int thread_list_size
= 0;
153 retval
= target_read_buffer(rtos
->target
,
154 rtos
->symbols
[FreeRTOS_VAL_uxCurrentNumberOfTasks
].address
,
155 param
->thread_count_width
,
156 (uint8_t *)&thread_list_size
);
158 if (retval
!= ERROR_OK
) {
159 LOG_ERROR("Could not read FreeRTOS thread count from target");
163 /* wipe out previous thread details if any */
164 if (rtos
->thread_details
!= NULL
) {
166 for (j
= 0; j
< rtos
->thread_count
; j
++) {
167 if (rtos
->thread_details
[j
].display_str
!= NULL
) {
168 free(rtos
->thread_details
[j
].display_str
);
169 rtos
->thread_details
[j
].display_str
= NULL
;
171 if (rtos
->thread_details
[j
].thread_name_str
!= NULL
) {
172 free(rtos
->thread_details
[j
].thread_name_str
);
173 rtos
->thread_details
[j
].thread_name_str
= NULL
;
175 if (rtos
->thread_details
[j
].extra_info_str
!= NULL
) {
176 free(rtos
->thread_details
[j
].extra_info_str
);
177 rtos
->thread_details
[j
].extra_info_str
= NULL
;
180 free(rtos
->thread_details
);
181 rtos
->thread_details
= NULL
;
184 /* read the current thread */
185 retval
= target_read_buffer(rtos
->target
,
186 rtos
->symbols
[FreeRTOS_VAL_pxCurrentTCB
].address
,
187 param
->pointer_width
,
188 (uint8_t *)&rtos
->current_thread
);
189 if (retval
!= ERROR_OK
) {
190 LOG_ERROR("Error reading current thread in FreeRTOS thread list");
194 if ((thread_list_size
== 0) || (rtos
->current_thread
== 0)) {
195 /* Either : No RTOS threads - there is always at least the current execution though */
196 /* OR : No current thread - all threads suspended - show the current execution
198 char tmp_str
[] = "Current Execution";
201 rtos
->thread_details
= (struct thread_detail
*) malloc(
202 sizeof(struct thread_detail
) * thread_list_size
);
203 if (!rtos
->thread_details
) {
204 LOG_ERROR("Error allocating memory for %d threads", thread_list_size
);
207 rtos
->thread_details
->threadid
= 1;
208 rtos
->thread_details
->exists
= true;
209 rtos
->thread_details
->display_str
= NULL
;
210 rtos
->thread_details
->extra_info_str
= NULL
;
211 rtos
->thread_details
->thread_name_str
= (char *) malloc(sizeof(tmp_str
));
212 strcpy(rtos
->thread_details
->thread_name_str
, tmp_str
);
214 if (thread_list_size
== 1) {
215 rtos
->thread_count
= 1;
219 /* create space for new thread details */
220 rtos
->thread_details
= (struct thread_detail
*) malloc(
221 sizeof(struct thread_detail
) * thread_list_size
);
222 if (!rtos
->thread_details
) {
223 LOG_ERROR("Error allocating memory for %d threads", thread_list_size
);
228 /* Find out how many lists are needed to be read from pxReadyTasksLists, */
229 int64_t max_used_priority
= 0;
230 retval
= target_read_buffer(rtos
->target
,
231 rtos
->symbols
[FreeRTOS_VAL_uxTopUsedPriority
].address
,
232 param
->pointer_width
,
233 (uint8_t *)&max_used_priority
);
234 if (retval
!= ERROR_OK
)
236 if (max_used_priority
> FREERTOS_MAX_PRIORITIES
) {
237 LOG_ERROR("FreeRTOS maximum used priority is unreasonably big, not proceeding: %" PRId64
"",
242 symbol_address_t
*list_of_lists
=
243 (symbol_address_t
*)malloc(sizeof(symbol_address_t
) *
244 (max_used_priority
+1 + 5));
245 if (!list_of_lists
) {
246 LOG_ERROR("Error allocating memory for %" PRId64
" priorities", max_used_priority
);
251 for (num_lists
= 0; num_lists
<= max_used_priority
; num_lists
++)
252 list_of_lists
[num_lists
] = rtos
->symbols
[FreeRTOS_VAL_pxReadyTasksLists
].address
+
253 num_lists
* param
->list_width
;
255 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xDelayedTaskList1
].address
;
256 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xDelayedTaskList2
].address
;
257 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xPendingReadyList
].address
;
258 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xSuspendedTaskList
].address
;
259 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xTasksWaitingTermination
].address
;
261 for (i
= 0; i
< num_lists
; i
++) {
262 if (list_of_lists
[i
] == 0)
265 /* Read the number of threads in this list */
266 int64_t list_thread_count
= 0;
267 retval
= target_read_buffer(rtos
->target
,
269 param
->thread_count_width
,
270 (uint8_t *)&list_thread_count
);
271 if (retval
!= ERROR_OK
) {
272 LOG_ERROR("Error reading number of threads in FreeRTOS thread list");
277 if (list_thread_count
== 0)
280 /* Read the location of first list item */
281 uint64_t prev_list_elem_ptr
= -1;
282 uint64_t list_elem_ptr
= 0;
283 retval
= target_read_buffer(rtos
->target
,
284 list_of_lists
[i
] + param
->list_next_offset
,
285 param
->pointer_width
,
286 (uint8_t *)&list_elem_ptr
);
287 if (retval
!= ERROR_OK
) {
288 LOG_ERROR("Error reading first thread item location in FreeRTOS thread list");
293 while ((list_thread_count
> 0) && (list_elem_ptr
!= 0) &&
294 (list_elem_ptr
!= prev_list_elem_ptr
) &&
295 (tasks_found
< thread_list_size
)) {
296 /* Get the location of the thread structure. */
297 rtos
->thread_details
[tasks_found
].threadid
= 0;
298 retval
= target_read_buffer(rtos
->target
,
299 list_elem_ptr
+ param
->list_elem_content_offset
,
300 param
->pointer_width
,
301 (uint8_t *)&(rtos
->thread_details
[tasks_found
].threadid
));
302 if (retval
!= ERROR_OK
) {
303 LOG_ERROR("Error reading thread list item object in FreeRTOS thread list");
308 /* get thread name */
310 #define FREERTOS_THREAD_NAME_STR_SIZE (200)
311 char tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
];
313 /* Read the thread name */
314 retval
= target_read_buffer(rtos
->target
,
315 rtos
->thread_details
[tasks_found
].threadid
+ param
->thread_name_offset
,
316 FREERTOS_THREAD_NAME_STR_SIZE
,
317 (uint8_t *)&tmp_str
);
318 if (retval
!= ERROR_OK
) {
319 LOG_ERROR("Error reading first thread item location in FreeRTOS thread list");
323 tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
-1] = '\x00';
325 if (tmp_str
[0] == '\x00')
326 strcpy(tmp_str
, "No Name");
328 rtos
->thread_details
[tasks_found
].thread_name_str
=
329 (char *)malloc(strlen(tmp_str
)+1);
330 strcpy(rtos
->thread_details
[tasks_found
].thread_name_str
, tmp_str
);
331 rtos
->thread_details
[tasks_found
].display_str
= NULL
;
332 rtos
->thread_details
[tasks_found
].exists
= true;
334 if (rtos
->thread_details
[tasks_found
].threadid
== rtos
->current_thread
) {
335 char running_str
[] = "Running";
336 rtos
->thread_details
[tasks_found
].extra_info_str
= (char *) malloc(
337 sizeof(running_str
));
338 strcpy(rtos
->thread_details
[tasks_found
].extra_info_str
,
341 rtos
->thread_details
[tasks_found
].extra_info_str
= NULL
;
346 prev_list_elem_ptr
= list_elem_ptr
;
348 retval
= target_read_buffer(rtos
->target
,
349 prev_list_elem_ptr
+ param
->list_elem_next_offset
,
350 param
->pointer_width
,
351 (uint8_t *)&list_elem_ptr
);
352 if (retval
!= ERROR_OK
) {
353 LOG_ERROR("Error reading next thread item location in FreeRTOS thread list");
361 rtos
->thread_count
= tasks_found
;
365 static int FreeRTOS_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
)
368 const struct FreeRTOS_params
*param
;
369 int64_t stack_ptr
= 0;
371 *hex_reg_list
= NULL
;
378 if (rtos
->rtos_specific_params
== NULL
)
381 param
= (const struct FreeRTOS_params
*) rtos
->rtos_specific_params
;
383 /* Read the stack pointer */
384 retval
= target_read_buffer(rtos
->target
,
385 thread_id
+ param
->thread_stack_offset
,
386 param
->pointer_width
,
387 (uint8_t *)&stack_ptr
);
388 if (retval
!= ERROR_OK
) {
389 LOG_ERROR("Error reading stack frame from FreeRTOS thread");
393 return rtos_generic_stack_read(rtos
->target
, param
->stacking_info
, stack_ptr
, hex_reg_list
);
396 static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
399 *symbol_list
= (symbol_table_elem_t
*) malloc(
400 sizeof(symbol_table_elem_t
) * ARRAY_SIZE(FreeRTOS_symbol_list
));
402 for (i
= 0; i
< ARRAY_SIZE(FreeRTOS_symbol_list
); i
++)
403 (*symbol_list
)[i
].symbol_name
= FreeRTOS_symbol_list
[i
];
410 static int FreeRTOS_set_current_thread(struct rtos
*rtos
, threadid_t thread_id
)
415 static int FreeRTOS_get_thread_ascii_info(struct rtos
*rtos
, threadid_t thread_id
, char **info
)
418 const struct FreeRTOS_params
*param
;
426 if (rtos
->rtos_specific_params
== NULL
)
429 param
= (const struct FreeRTOS_params
*) rtos
->rtos_specific_params
;
431 #define FREERTOS_THREAD_NAME_STR_SIZE (200)
432 char tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
];
434 /* Read the thread name */
435 retval
= target_read_buffer(rtos
->target
,
436 thread_id
+ param
->thread_name_offset
,
437 FREERTOS_THREAD_NAME_STR_SIZE
,
438 (uint8_t *)&tmp_str
);
439 if (retval
!= ERROR_OK
) {
440 LOG_ERROR("Error reading first thread item location in FreeRTOS thread list");
443 tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
-1] = '\x00';
445 if (tmp_str
[0] == '\x00')
446 strcpy(tmp_str
, "No Name");
448 *info
= (char *)malloc(strlen(tmp_str
)+1);
449 strcpy(*info
, tmp_str
);
455 static int FreeRTOS_detect_rtos(struct target
*target
)
457 if ((target
->rtos
->symbols
!= NULL
) &&
458 (target
->rtos
->symbols
[FreeRTOS_VAL_pxReadyTasksLists
].address
!= 0)) {
459 /* looks like FreeRTOS */
465 static int FreeRTOS_create(struct target
*target
)
468 while ((i
< FREERTOS_NUM_PARAMS
) &&
469 (0 != strcmp(FreeRTOS_params_list
[i
].target_name
, target
->type
->name
))) {
472 if (i
>= FREERTOS_NUM_PARAMS
) {
473 LOG_ERROR("Could not find target in FreeRTOS compatibility list");
477 target
->rtos
->rtos_specific_params
= (void *) &FreeRTOS_params_list
[i
];
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)