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_STRUCT(int_type, ptr_type, list_prev_offset)
35 struct FreeRTOS_params
{
36 const char *target_name
;
37 const unsigned char thread_count_width
;
38 const unsigned char pointer_width
;
39 const unsigned char list_next_offset
;
40 const unsigned char list_width
;
41 const unsigned char list_elem_next_offset
;
42 const unsigned char list_elem_content_offset
;
43 const unsigned char thread_stack_offset
;
44 const unsigned char thread_name_offset
;
45 const struct rtos_register_stacking
*stacking_info
;
48 const struct FreeRTOS_params FreeRTOS_params_list
[] = {
50 "cortex_m3", /* target_name */
51 4, /* thread_count_width; */
52 4, /* pointer_width; */
53 16, /* list_next_offset; */
55 8, /* list_elem_next_offset; */
56 12, /* list_elem_content_offset */
57 0, /* thread_stack_offset; */
58 52, /* thread_name_offset; */
59 &rtos_standard_Cortex_M3_stacking
, /* stacking_info */
63 #define FREERTOS_NUM_PARAMS ((int)(sizeof(FreeRTOS_params_list)/sizeof(struct FreeRTOS_params)))
65 static int FreeRTOS_detect_rtos(struct target
*target
);
66 static int FreeRTOS_create(struct target
*target
);
67 static int FreeRTOS_update_threads(struct rtos
*rtos
);
68 static int FreeRTOS_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
);
69 static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[]);
71 struct rtos_type FreeRTOS_rtos
= {
74 .detect_rtos
= FreeRTOS_detect_rtos
,
75 .create
= FreeRTOS_create
,
76 .update_threads
= FreeRTOS_update_threads
,
77 .get_thread_reg_list
= FreeRTOS_get_thread_reg_list
,
78 .get_symbol_list_to_lookup
= FreeRTOS_get_symbol_list_to_lookup
,
81 enum FreeRTOS_symbol_values
{
82 FreeRTOS_VAL_pxCurrentTCB
= 0,
83 FreeRTOS_VAL_pxReadyTasksLists
= 1,
84 FreeRTOS_VAL_xDelayedTaskList1
= 2,
85 FreeRTOS_VAL_xDelayedTaskList2
= 3,
86 FreeRTOS_VAL_pxDelayedTaskList
= 4,
87 FreeRTOS_VAL_pxOverflowDelayedTaskList
= 5,
88 FreeRTOS_VAL_xPendingReadyList
= 6,
89 FreeRTOS_VAL_xTasksWaitingTermination
= 7,
90 FreeRTOS_VAL_xSuspendedTaskList
= 8,
91 FreeRTOS_VAL_uxCurrentNumberOfTasks
= 9,
92 FreeRTOS_VAL_uxTopUsedPriority
= 10,
95 static char *FreeRTOS_symbol_list
[] = {
101 "pxOverflowDelayedTaskList",
103 "xTasksWaitingTermination",
104 "xSuspendedTaskList",
105 "uxCurrentNumberOfTasks",
110 #define FREERTOS_NUM_SYMBOLS (sizeof(FreeRTOS_symbol_list)/sizeof(char *))
113 /* this is not safe for little endian yet */
114 /* may be problems reading if sizes are not 32 bit long integers. */
115 /* test mallocs for failure */
117 static int FreeRTOS_update_threads(struct rtos
*rtos
)
122 const struct FreeRTOS_params
*param
;
124 if (rtos
->rtos_specific_params
== NULL
)
127 param
= (const struct FreeRTOS_params
*) rtos
->rtos_specific_params
;
129 if (rtos
->symbols
== NULL
) {
130 LOG_OUTPUT("No symbols for FreeRTOS\r\n");
134 if (rtos
->symbols
[FreeRTOS_VAL_uxCurrentNumberOfTasks
].address
== 0) {
135 LOG_OUTPUT("Don't have the number of threads in FreeRTOS \r\n");
139 int thread_list_size
= 0;
140 retval
= target_read_buffer(rtos
->target
,
141 rtos
->symbols
[FreeRTOS_VAL_uxCurrentNumberOfTasks
].address
,
142 param
->thread_count_width
,
143 (uint8_t *)&thread_list_size
);
145 if (retval
!= ERROR_OK
) {
146 LOG_OUTPUT("Could not read FreeRTOS thread count from target\r\n");
150 /* wipe out previous thread details if any */
151 if (rtos
->thread_details
!= NULL
) {
153 for (j
= 0; j
< rtos
->thread_count
; j
++) {
154 if (rtos
->thread_details
[j
].display_str
!= NULL
) {
155 free(rtos
->thread_details
[j
].display_str
);
156 rtos
->thread_details
[j
].display_str
= NULL
;
158 if (rtos
->thread_details
[j
].thread_name_str
!= NULL
) {
159 free(rtos
->thread_details
[j
].thread_name_str
);
160 rtos
->thread_details
[j
].thread_name_str
= NULL
;
162 if (rtos
->thread_details
[j
].extra_info_str
!= NULL
) {
163 free(rtos
->thread_details
[j
].extra_info_str
);
164 rtos
->thread_details
[j
].extra_info_str
= NULL
;
167 free(rtos
->thread_details
);
168 rtos
->thread_details
= NULL
;
171 /* read the current thread */
172 retval
= target_read_buffer(rtos
->target
,
173 rtos
->symbols
[FreeRTOS_VAL_pxCurrentTCB
].address
,
174 param
->pointer_width
,
175 (uint8_t *)&rtos
->current_thread
);
176 if (retval
!= ERROR_OK
) {
177 LOG_OUTPUT("Error reading current thread in FreeRTOS thread list\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 if (!rtos
->thread_details
) {
191 LOG_ERROR("Error allocating memory for %d threads", thread_list_size
);
194 rtos
->thread_details
->threadid
= 1;
195 rtos
->thread_details
->exists
= true;
196 rtos
->thread_details
->display_str
= NULL
;
197 rtos
->thread_details
->extra_info_str
= NULL
;
198 rtos
->thread_details
->thread_name_str
= (char *) malloc(sizeof(tmp_str
));
199 strcpy(rtos
->thread_details
->thread_name_str
, tmp_str
);
201 if (thread_list_size
== 1) {
202 rtos
->thread_count
= 1;
206 /* create space for new thread details */
207 rtos
->thread_details
= (struct thread_detail
*) malloc(
208 sizeof(struct thread_detail
) * thread_list_size
);
209 if (!rtos
->thread_details
) {
210 LOG_ERROR("Error allocating memory for %d threads", thread_list_size
);
215 /* Find out how many lists are needed to be read from pxReadyTasksLists, */
216 int64_t max_used_priority
= 0;
217 retval
= target_read_buffer(rtos
->target
,
218 rtos
->symbols
[FreeRTOS_VAL_uxTopUsedPriority
].address
,
219 param
->pointer_width
,
220 (uint8_t *)&max_used_priority
);
221 if (retval
!= ERROR_OK
)
224 symbol_address_t
*list_of_lists
=
225 (symbol_address_t
*)malloc(sizeof(symbol_address_t
) *
226 (max_used_priority
+1 + 5));
227 if (!list_of_lists
) {
228 LOG_ERROR("Error allocating memory for %" PRId64
" priorities", max_used_priority
);
233 for (num_lists
= 0; num_lists
<= max_used_priority
; num_lists
++)
234 list_of_lists
[num_lists
] = rtos
->symbols
[FreeRTOS_VAL_pxReadyTasksLists
].address
+
235 num_lists
* param
->list_width
;
237 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xDelayedTaskList1
].address
;
238 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xDelayedTaskList2
].address
;
239 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xPendingReadyList
].address
;
240 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xSuspendedTaskList
].address
;
241 list_of_lists
[num_lists
++] = rtos
->symbols
[FreeRTOS_VAL_xTasksWaitingTermination
].address
;
243 for (i
= 0; i
< num_lists
; i
++) {
244 if (list_of_lists
[i
] == 0)
247 /* Read the number of threads in this list */
248 int64_t list_thread_count
= 0;
249 retval
= target_read_buffer(rtos
->target
,
251 param
->thread_count_width
,
252 (uint8_t *)&list_thread_count
);
253 if (retval
!= ERROR_OK
) {
254 LOG_OUTPUT("Error reading number of threads in FreeRTOS thread list\r\n");
258 if (list_thread_count
== 0)
261 /* Read the location of first list item */
262 uint64_t prev_list_elem_ptr
= -1;
263 uint64_t list_elem_ptr
= 0;
264 retval
= target_read_buffer(rtos
->target
,
265 list_of_lists
[i
] + param
->list_next_offset
,
266 param
->pointer_width
,
267 (uint8_t *)&list_elem_ptr
);
268 if (retval
!= ERROR_OK
) {
270 "Error reading first thread item location in FreeRTOS thread list\r\n");
274 while ((list_thread_count
> 0) && (list_elem_ptr
!= 0) &&
275 (list_elem_ptr
!= prev_list_elem_ptr
) &&
276 (tasks_found
< thread_list_size
)) {
277 /* Get the location of the thread structure. */
278 rtos
->thread_details
[tasks_found
].threadid
= 0;
279 retval
= target_read_buffer(rtos
->target
,
280 list_elem_ptr
+ param
->list_elem_content_offset
,
281 param
->pointer_width
,
282 (uint8_t *)&(rtos
->thread_details
[tasks_found
].threadid
));
283 if (retval
!= ERROR_OK
) {
285 "Error reading thread list item object in FreeRTOS thread list\r\n");
289 /* get thread name */
291 #define FREERTOS_THREAD_NAME_STR_SIZE (200)
292 char tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
];
294 /* Read the thread name */
295 retval
= target_read_buffer(rtos
->target
,
296 rtos
->thread_details
[tasks_found
].threadid
+ param
->thread_name_offset
,
297 FREERTOS_THREAD_NAME_STR_SIZE
,
298 (uint8_t *)&tmp_str
);
299 if (retval
!= ERROR_OK
) {
301 "Error reading first thread item location in FreeRTOS thread list\r\n");
304 tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
-1] = '\x00';
306 if (tmp_str
[0] == '\x00')
307 strcpy(tmp_str
, "No Name");
309 rtos
->thread_details
[tasks_found
].thread_name_str
=
310 (char *)malloc(strlen(tmp_str
)+1);
311 strcpy(rtos
->thread_details
[tasks_found
].thread_name_str
, tmp_str
);
312 rtos
->thread_details
[tasks_found
].display_str
= NULL
;
313 rtos
->thread_details
[tasks_found
].exists
= true;
315 if (rtos
->thread_details
[tasks_found
].threadid
== rtos
->current_thread
) {
316 char running_str
[] = "Running";
317 rtos
->thread_details
[tasks_found
].extra_info_str
= (char *) malloc(
318 sizeof(running_str
));
319 strcpy(rtos
->thread_details
[tasks_found
].extra_info_str
,
322 rtos
->thread_details
[tasks_found
].extra_info_str
= NULL
;
327 prev_list_elem_ptr
= list_elem_ptr
;
329 retval
= target_read_buffer(rtos
->target
,
330 prev_list_elem_ptr
+ param
->list_elem_next_offset
,
331 param
->pointer_width
,
332 (uint8_t *)&list_elem_ptr
);
333 if (retval
!= ERROR_OK
) {
335 "Error reading next thread item location in FreeRTOS thread list\r\n");
341 rtos
->thread_count
= tasks_found
;
345 static int FreeRTOS_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
, char **hex_reg_list
)
348 const struct FreeRTOS_params
*param
;
349 int64_t stack_ptr
= 0;
351 *hex_reg_list
= NULL
;
358 if (rtos
->rtos_specific_params
== NULL
)
361 param
= (const struct FreeRTOS_params
*) rtos
->rtos_specific_params
;
363 /* Read the stack pointer */
364 retval
= target_read_buffer(rtos
->target
,
365 thread_id
+ param
->thread_stack_offset
,
366 param
->pointer_width
,
367 (uint8_t *)&stack_ptr
);
368 if (retval
!= ERROR_OK
) {
369 LOG_OUTPUT("Error reading stack frame from FreeRTOS thread\r\n");
373 return rtos_generic_stack_read(rtos
->target
, param
->stacking_info
, stack_ptr
, hex_reg_list
);
377 static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t
*symbol_list
[])
380 *symbol_list
= (symbol_table_elem_t
*) malloc(
381 sizeof(symbol_table_elem_t
) * FREERTOS_NUM_SYMBOLS
);
383 for (i
= 0; i
< FREERTOS_NUM_SYMBOLS
; i
++)
384 (*symbol_list
)[i
].symbol_name
= FreeRTOS_symbol_list
[i
];
391 static int FreeRTOS_set_current_thread(struct rtos
*rtos
, threadid_t thread_id
)
396 static int FreeRTOS_get_thread_ascii_info(struct rtos
*rtos
, threadid_t thread_id
, char **info
)
399 const struct FreeRTOS_params
*param
;
407 if (rtos
->rtos_specific_params
== NULL
)
410 param
= (const struct FreeRTOS_params
*) rtos
->rtos_specific_params
;
412 #define FREERTOS_THREAD_NAME_STR_SIZE (200)
413 char tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
];
415 /* Read the thread name */
416 retval
= target_read_buffer(rtos
->target
,
417 thread_id
+ param
->thread_name_offset
,
418 FREERTOS_THREAD_NAME_STR_SIZE
,
419 (uint8_t *)&tmp_str
);
420 if (retval
!= ERROR_OK
) {
421 LOG_OUTPUT("Error reading first thread item location in FreeRTOS thread list\r\n");
424 tmp_str
[FREERTOS_THREAD_NAME_STR_SIZE
-1] = '\x00';
426 if (tmp_str
[0] == '\x00')
427 strcpy(tmp_str
, "No Name");
429 *info
= (char *)malloc(strlen(tmp_str
)+1);
430 strcpy(*info
, tmp_str
);
436 static int FreeRTOS_detect_rtos(struct target
*target
)
438 if ((target
->rtos
->symbols
!= NULL
) &&
439 (target
->rtos
->symbols
[FreeRTOS_VAL_pxReadyTasksLists
].address
!= 0)) {
440 /* looks like FreeRTOS */
446 static int FreeRTOS_create(struct target
*target
)
449 while ((i
< FREERTOS_NUM_PARAMS
) &&
450 (0 != strcmp(FreeRTOS_params_list
[i
].target_name
, target
->type
->name
))) {
453 if (i
>= FREERTOS_NUM_PARAMS
) {
454 LOG_OUTPUT("Could not find target in FreeRTOS compatibility list\r\n");
458 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)