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 #define FREERTOS_MAX_PRIORITIES 63
35 #define FreeRTOS_STRUCT(int_type, ptr_type, list_prev_offset)
37 struct FreeRTOS_params
{
38 const char *target_name
;
39 const unsigned char thread_count_width
;
40 const unsigned char pointer_width
;
41 const unsigned char list_next_offset
;
42 const unsigned char list_width
;
43 const unsigned char list_elem_next_offset
;
44 const unsigned char list_elem_content_offset
;
45 const unsigned char thread_stack_offset
;
46 const unsigned char thread_name_offset
;
47 const struct rtos_register_stacking
*stacking_info
;
50 const struct FreeRTOS_params FreeRTOS_params_list
[] = {
52 "cortex_m3", /* target_name */
53 4, /* thread_count_width; */
54 4, /* pointer_width; */
55 16, /* list_next_offset; */
57 8, /* list_elem_next_offset; */
58 12, /* list_elem_content_offset */
59 0, /* thread_stack_offset; */
60 52, /* thread_name_offset; */
61 &rtos_standard_Cortex_M3_stacking
, /* stacking_info */
65 #define FREERTOS_NUM_PARAMS ((int)(sizeof(FreeRTOS_params_list)/sizeof(struct FreeRTOS_params)))
67 static int FreeRTOS_detect_rtos(struct target
*target
);
68 static int FreeRTOS_create(struct target
*target
);
69 static int FreeRTOS_update_threads(struct rtos
*rtos
);
70 static int FreeRTOS_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
);
71 static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[]);
73 struct rtos_type FreeRTOS_rtos
= {
76 .detect_rtos
= FreeRTOS_detect_rtos
,
77 .create
= FreeRTOS_create
,
78 .update_threads
= FreeRTOS_update_threads
,
79 .get_thread_reg_list
= FreeRTOS_get_thread_reg_list
,
80 .get_symbol_list_to_lookup
= FreeRTOS_get_symbol_list_to_lookup
,
83 enum FreeRTOS_symbol_values
{
84 FreeRTOS_VAL_pxCurrentTCB
= 0,
85 FreeRTOS_VAL_pxReadyTasksLists
= 1,
86 FreeRTOS_VAL_xDelayedTaskList1
= 2,
87 FreeRTOS_VAL_xDelayedTaskList2
= 3,
88 FreeRTOS_VAL_pxDelayedTaskList
= 4,
89 FreeRTOS_VAL_pxOverflowDelayedTaskList
= 5,
90 FreeRTOS_VAL_xPendingReadyList
= 6,
91 FreeRTOS_VAL_xTasksWaitingTermination
= 7,
92 FreeRTOS_VAL_xSuspendedTaskList
= 8,
93 FreeRTOS_VAL_uxCurrentNumberOfTasks
= 9,
94 FreeRTOS_VAL_uxTopUsedPriority
= 10,
97 static char *FreeRTOS_symbol_list
[] = {
103 "pxOverflowDelayedTaskList",
105 "xTasksWaitingTermination",
106 "xSuspendedTaskList",
107 "uxCurrentNumberOfTasks",
112 #define FREERTOS_NUM_SYMBOLS (sizeof(FreeRTOS_symbol_list)/sizeof(char *))
115 /* this is not safe for little endian yet */
116 /* may be problems reading if sizes are not 32 bit long integers. */
117 /* test mallocs for failure */
119 static int FreeRTOS_update_threads(struct rtos
*rtos
)
124 const struct FreeRTOS_params
*param
;
126 if (rtos
->rtos_specific_params
== NULL
)
129 param
= (const struct FreeRTOS_params
*) rtos
->rtos_specific_params
;
131 if (rtos
->symbols
== NULL
) {
132 LOG_OUTPUT("No symbols for FreeRTOS\r\n");
136 if (rtos
->symbols
[FreeRTOS_VAL_uxCurrentNumberOfTasks
].address
== 0) {
137 LOG_OUTPUT("Don't have the number of threads in FreeRTOS \r\n");
141 int thread_list_size
= 0;
142 retval
= target_read_buffer(rtos
->target
,
143 rtos
->symbols
[FreeRTOS_VAL_uxCurrentNumberOfTasks
].address
,
144 param
->thread_count_width
,
145 (uint8_t *)&thread_list_size
);
147 if (retval
!= ERROR_OK
) {
148 LOG_OUTPUT("Could not read FreeRTOS thread count from target\r\n");
152 /* wipe out previous thread details if any */
153 if (rtos
->thread_details
!= NULL
) {
155 for (j
= 0; j
< rtos
->thread_count
; j
++) {
156 if (rtos
->thread_details
[j
].display_str
!= NULL
) {
157 free(rtos
->thread_details
[j
].display_str
);
158 rtos
->thread_details
[j
].display_str
= NULL
;
160 if (rtos
->thread_details
[j
].thread_name_str
!= NULL
) {
161 free(rtos
->thread_details
[j
].thread_name_str
);
162 rtos
->thread_details
[j
].thread_name_str
= NULL
;
164 if (rtos
->thread_details
[j
].extra_info_str
!= NULL
) {
165 free(rtos
->thread_details
[j
].extra_info_str
);
166 rtos
->thread_details
[j
].extra_info_str
= NULL
;
169 free(rtos
->thread_details
);
170 rtos
->thread_details
= NULL
;
173 /* read the current thread */
174 retval
= target_read_buffer(rtos
->target
,
175 rtos
->symbols
[FreeRTOS_VAL_pxCurrentTCB
].address
,
176 param
->pointer_width
,
177 (uint8_t *)&rtos
->current_thread
);
178 if (retval
!= ERROR_OK
) {
179 LOG_OUTPUT("Error reading current thread in FreeRTOS thread list\r\n");
183 if ((thread_list_size
== 0) || (rtos
->current_thread
== 0)) {
184 /* Either : No RTOS threads - there is always at least the current execution though */
185 /* OR : No current thread - all threads suspended - show the current execution
187 char tmp_str
[] = "Current Execution";
190 rtos
->thread_details
= (struct thread_detail
*) malloc(
191 sizeof(struct thread_detail
) * thread_list_size
);
192 if (!rtos
->thread_details
) {
193 LOG_ERROR("Error allocating memory for %d threads", thread_list_size
);
196 rtos
->thread_details
->threadid
= 1;
197 rtos
->thread_details
->exists
= true;
198 rtos
->thread_details
->display_str
= NULL
;
199 rtos
->thread_details
->extra_info_str
= NULL
;
200 rtos
->thread_details
->thread_name_str
= (char *) malloc(sizeof(tmp_str
));
201 strcpy(rtos
->thread_details
->thread_name_str
, tmp_str
);
203 if (thread_list_size
== 1) {
204 rtos
->thread_count
= 1;
208 /* create space for new thread details */
209 rtos
->thread_details
= (struct thread_detail
*) malloc(
210 sizeof(struct thread_detail
) * thread_list_size
);
211 if (!rtos
->thread_details
) {
212 LOG_ERROR("Error allocating memory for %d threads", thread_list_size
);
217 /* Find out how many lists are needed to be read from pxReadyTasksLists, */
218 int64_t max_used_priority
= 0;
219 retval
= target_read_buffer(rtos
->target
,
220 rtos
->symbols
[FreeRTOS_VAL_uxTopUsedPriority
].address
,
221 param
->pointer_width
,
222 (uint8_t *)&max_used_priority
);
223 if (retval
!= ERROR_OK
)
225 if (max_used_priority
> FREERTOS_MAX_PRIORITIES
) {
226 LOG_ERROR("FreeRTOS maximum used priority is unreasonably big, not proceeding: %" PRId64
"",
231 symbol_address_t
*list_of_lists
=
232 (symbol_address_t
*)malloc(sizeof(symbol_address_t
) *
233 (max_used_priority
+1 + 5));
234 if (!list_of_lists
) {
235 LOG_ERROR("Error allocating memory for %" PRId64
" priorities", max_used_priority
);
240 for (num_lists
= 0; num_lists
<= max_used_priority
; num_lists
++)
241 list_of_lists
[num_lists
] = rtos
->symbols
[FreeRTOS_VAL_pxReadyTasksLists
].address
+
242 num_lists
* param
->list_width
;
244 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xDelayedTaskList1
].address
;
245 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xDelayedTaskList2
].address
;
246 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xPendingReadyList
].address
;
247 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xSuspendedTaskList
].address
;
248 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xTasksWaitingTermination
].address
;
250 for (i
= 0; i
< num_lists
; i
++) {
251 if (list_of_lists
[i
] == 0)
254 /* Read the number of threads in this list */
255 int64_t list_thread_count
= 0;
256 retval
= target_read_buffer(rtos
->target
,
258 param
->thread_count_width
,
259 (uint8_t *)&list_thread_count
);
260 if (retval
!= ERROR_OK
) {
261 LOG_OUTPUT("Error reading number of threads in FreeRTOS thread list\r\n");
265 if (list_thread_count
== 0)
268 /* Read the location of first list item */
269 uint64_t prev_list_elem_ptr
= -1;
270 uint64_t list_elem_ptr
= 0;
271 retval
= target_read_buffer(rtos
->target
,
272 list_of_lists
[i
] + param
->list_next_offset
,
273 param
->pointer_width
,
274 (uint8_t *)&list_elem_ptr
);
275 if (retval
!= ERROR_OK
) {
277 "Error reading first thread item location in FreeRTOS thread list\r\n");
281 while ((list_thread_count
> 0) && (list_elem_ptr
!= 0) &&
282 (list_elem_ptr
!= prev_list_elem_ptr
) &&
283 (tasks_found
< thread_list_size
)) {
284 /* Get the location of the thread structure. */
285 rtos
->thread_details
[tasks_found
].threadid
= 0;
286 retval
= target_read_buffer(rtos
->target
,
287 list_elem_ptr
+ param
->list_elem_content_offset
,
288 param
->pointer_width
,
289 (uint8_t *)&(rtos
->thread_details
[tasks_found
].threadid
));
290 if (retval
!= ERROR_OK
) {
292 "Error reading thread list item object in FreeRTOS thread list\r\n");
296 /* get thread name */
298 #define FREERTOS_THREAD_NAME_STR_SIZE (200)
299 char tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
];
301 /* Read the thread name */
302 retval
= target_read_buffer(rtos
->target
,
303 rtos
->thread_details
[tasks_found
].threadid
+ param
->thread_name_offset
,
304 FREERTOS_THREAD_NAME_STR_SIZE
,
305 (uint8_t *)&tmp_str
);
306 if (retval
!= ERROR_OK
) {
308 "Error reading first thread item location in FreeRTOS thread list\r\n");
311 tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
-1] = '\x00';
313 if (tmp_str
[0] == '\x00')
314 strcpy(tmp_str
, "No Name");
316 rtos
->thread_details
[tasks_found
].thread_name_str
=
317 (char *)malloc(strlen(tmp_str
)+1);
318 strcpy(rtos
->thread_details
[tasks_found
].thread_name_str
, tmp_str
);
319 rtos
->thread_details
[tasks_found
].display_str
= NULL
;
320 rtos
->thread_details
[tasks_found
].exists
= true;
322 if (rtos
->thread_details
[tasks_found
].threadid
== rtos
->current_thread
) {
323 char running_str
[] = "Running";
324 rtos
->thread_details
[tasks_found
].extra_info_str
= (char *) malloc(
325 sizeof(running_str
));
326 strcpy(rtos
->thread_details
[tasks_found
].extra_info_str
,
329 rtos
->thread_details
[tasks_found
].extra_info_str
= NULL
;
334 prev_list_elem_ptr
= list_elem_ptr
;
336 retval
= target_read_buffer(rtos
->target
,
337 prev_list_elem_ptr
+ param
->list_elem_next_offset
,
338 param
->pointer_width
,
339 (uint8_t *)&list_elem_ptr
);
340 if (retval
!= ERROR_OK
) {
342 "Error reading next thread item location in FreeRTOS thread list\r\n");
348 rtos
->thread_count
= tasks_found
;
352 static int FreeRTOS_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
)
355 const struct FreeRTOS_params
*param
;
356 int64_t stack_ptr
= 0;
358 *hex_reg_list
= NULL
;
365 if (rtos
->rtos_specific_params
== NULL
)
368 param
= (const struct FreeRTOS_params
*) rtos
->rtos_specific_params
;
370 /* Read the stack pointer */
371 retval
= target_read_buffer(rtos
->target
,
372 thread_id
+ param
->thread_stack_offset
,
373 param
->pointer_width
,
374 (uint8_t *)&stack_ptr
);
375 if (retval
!= ERROR_OK
) {
376 LOG_OUTPUT("Error reading stack frame from FreeRTOS thread\r\n");
380 return rtos_generic_stack_read(rtos
->target
, param
->stacking_info
, stack_ptr
, hex_reg_list
);
384 static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
387 *symbol_list
= (symbol_table_elem_t
*) malloc(
388 sizeof(symbol_table_elem_t
) * FREERTOS_NUM_SYMBOLS
);
390 for (i
= 0; i
< FREERTOS_NUM_SYMBOLS
; i
++)
391 (*symbol_list
)[i
].symbol_name
= FreeRTOS_symbol_list
[i
];
398 static int FreeRTOS_set_current_thread(struct rtos
*rtos
, threadid_t thread_id
)
403 static int FreeRTOS_get_thread_ascii_info(struct rtos
*rtos
, threadid_t thread_id
, char **info
)
406 const struct FreeRTOS_params
*param
;
414 if (rtos
->rtos_specific_params
== NULL
)
417 param
= (const struct FreeRTOS_params
*) rtos
->rtos_specific_params
;
419 #define FREERTOS_THREAD_NAME_STR_SIZE (200)
420 char tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
];
422 /* Read the thread name */
423 retval
= target_read_buffer(rtos
->target
,
424 thread_id
+ param
->thread_name_offset
,
425 FREERTOS_THREAD_NAME_STR_SIZE
,
426 (uint8_t *)&tmp_str
);
427 if (retval
!= ERROR_OK
) {
428 LOG_OUTPUT("Error reading first thread item location in FreeRTOS thread list\r\n");
431 tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
-1] = '\x00';
433 if (tmp_str
[0] == '\x00')
434 strcpy(tmp_str
, "No Name");
436 *info
= (char *)malloc(strlen(tmp_str
)+1);
437 strcpy(*info
, tmp_str
);
443 static int FreeRTOS_detect_rtos(struct target
*target
)
445 if ((target
->rtos
->symbols
!= NULL
) &&
446 (target
->rtos
->symbols
[FreeRTOS_VAL_pxReadyTasksLists
].address
!= 0)) {
447 /* looks like FreeRTOS */
453 static int FreeRTOS_create(struct target
*target
)
456 while ((i
< FREERTOS_NUM_PARAMS
) &&
457 (0 != strcmp(FreeRTOS_params_list
[i
].target_name
, target
->type
->name
))) {
460 if (i
>= FREERTOS_NUM_PARAMS
) {
461 LOG_OUTPUT("Could not find target in FreeRTOS compatibility list\r\n");
465 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)